package uk.ac.lkl.common.util;
/**
* An object that can be locked with a key.
*
* This object implements a simple mechanism for setting a boolean 'locked' with
* a key. This key can be kept hidden by the locking class so that only it can
* have access to the appropriate methods. Note that using a key of null locks
* the class permanently.
*
* This class can either be sub-classed or an instance of it can be used as
* instance data. In either case, relevant instance-data-modifying methods must
* check to see whether it is locked before continuing.
*
* @author $Author: darren.pearce $
* @version $Revision: 714 $
* @version $Date: 2008-05-17 05:38:27 -0700 (Sat, 17 May 2008) $
*
*/
public class LockableObject implements Lockable {
/**
* Indicates whether or not this instance is currently locked.
*
*/
private boolean locked;
/**
* If <code>locked</code> is <code>true</code>, this is the key that
* the instance was locked with. A key of <code>null</code> locks the
* instance forever. When <code>locked</code> is <code>false</code>,
* the key is always <code>null</code> (unused).
*
*/
private Object key;
/**
* Create a new initially-unlocked instance.
*
*/
public LockableObject() {
setUnlocked();
}
/**
* Return whether this class is currently locked.
*
* @return <code>true</code> if this instance is locked;
* <code>false</code> otherwise
*
*/
public boolean isLocked() {
return locked;
}
/**
* Lock this instance permanently.
*
* This is equivalent to locking with a key of <code>null</code>.
*
* @return <code>true</code> if this instance is locked successfully as a
* result of this method; <code>false</code> otherwise
*
*/
public boolean lock() {
return lock(null);
}
// can't lock twice even with same key
/**
* Lock this instance using the given key.
*
* A key of null locks this class permanently. Note that if this instance is
* locked, calling this method even with the current key will return
* <code>false</code>.
*
* @param key
* the key to use
*
* @return <code>true</code> if this instance is locked successfully as a
* result of this method; <code>false</code> otherwise
*/
public boolean lock(Object key) {
if (isLocked())
return false;
setLocked(key);
return true;
}
/**
* Unlock this instance using the given key.
*
* Note that unlocking with a key of <code>null</code> does nothing.
*
* @param key
* the key to use
*
* @return <code>true</code> if this instance is unlocked successfully as
* a result of this method; <code>false</code> otherwise
*
*/
public boolean unlock(Object key) {
if (this.key == null)
return false;
if (key != this.key)
return false;
setUnlocked();
return true;
}
public void checkLocked() {
if (isLocked())
throw new UnsupportedOperationException();
}
/**
* Set the instance data of this class to a locked state.
*
* This method is used internally.
*
* @param key
* the key to use
*
*/
private void setLocked(Object key) {
this.locked = true;
this.key = key;
}
/**
* Set the instance data of this class to an unlocked state.
*
* This method is used internally.
*
*/
private void setUnlocked() {
locked = false;
key = null;
}
}
|