package org.freehep.util.parameterdatabase;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class ParameterValue {
/**
* The value associated with this parameter.
*/
private Object value;
/**
* This monitors the state of this ParameterValue. If this key has been
* cleared, then this ParameterValue is invalid and most user-visible calls
* will return an IllegalStateException.
*/
private boolean isValid;
/**
* This contains the maximum number of recycled keys.
*/
static private int inventoryLimit = 10000;
/**
* This linked list contains the set of recycled keys.
*/
static private LinkedList inventory = new LinkedList();
/**
* The object which keeps the list of PropertyChangeListeners.
*/
private LinkedList propertyChangeListeners;
/**
* This protected constructor creates a new ParameterValue with the given
* parameters. Users should not create ParameterValues via this constructor,
* but should instead use the static factory method createParameterValue().
*/
protected ParameterValue(Object value) {
this.value = value;
isValid = true;
propertyChangeListeners = new LinkedList();
}
/**
* This static factory method returns a ParameterValue using the given
* arguments. This method will try to use a recycled ParameterValue if one
* is available.
*/
static public ParameterValue createParameterValue(Object value) {
// Check the validity of the input parameter.
if (value == null) {
throw new IllegalArgumentException();
}
ParameterValue newValue = null;
// First check to see if a value is already available. This
// must be synchronized to guarantee that the same value isn't
// given out twice by accident.
synchronized (inventory) {
if (!inventory.isEmpty()) {
newValue = (ParameterValue) inventory.removeFirst();
newValue.value = value;
newValue.isValid = true;
}
}
// If we couldn't find an existing key, then make a new one.
if (newValue == null) {
newValue = new ParameterValue(value);
}
return newValue;
}
/**
* Return the value associated with this ParameterValue.
*/
public Object getValue() {
if (!isValid)
throw new IllegalStateException();
return value;
}
/**
* Set the value associated with the parameter name.
*/
public void setValue(Object value) {
if (!isValid)
throw new IllegalStateException();
if (value == null)
throw new IllegalArgumentException();
this.value = value;
}
/**
* This method will recycle this ParameterValue. Any further user method
* calls on this object will result in an IllegalStateException being
* thrown. This object will be available for reuse only after the JVM
* determines that there are no more outstanding references to this
* ParameterValue and the JVM runs the finalize() method.
*/
protected void recycle() {
isValid = false;
value = null;
propertyChangeListeners.clear();
}
/**
* Equality for two ParameterValues is determined by whether the underlying
* value objects are equal.
*/
public boolean equals(Object otherValue) {
if (!isValid)
throw new IllegalStateException();
if (otherValue instanceof ParameterValue) {
ParameterValue other = (ParameterValue) otherValue;
return value.equals(other.value);
} else {
return false;
}
}
/**
* The hashcode is simply value.hashCode().
*/
public int hashCode() {
if (!isValid)
throw new IllegalStateException();
return value.hashCode();
}
/**
* We override the finalize method to allow this ParameterValue to be
* recycled. It is added to the list of recycled values if the inventory is
* below the given limit.
*/
public void finalize() throws Throwable {
// Recycle this value if we haven't exceeded the limit. A
// normal return will allow this key to be garbage collected
// normally.
synchronized (inventory) {
if (inventory.size() < inventoryLimit) {
recycle();
inventory.add(this);
throw new Throwable();
}
}
}
/**
* Return an unmodifiable list of the current listeners.
*/
public List getPropertyChangeListeners() {
return Collections.unmodifiableList(propertyChangeListeners);
}
/**
* Add a PropertyChangeListener to this ParameterValue.
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
synchronized (propertyChangeListeners) {
if (!propertyChangeListeners.contains(listener)) {
propertyChangeListeners.add(listener);
}
}
}
/**
* Remove a PropertyChangeListener from this ParameterValue.
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
synchronized (propertyChangeListeners) {
propertyChangeListeners.remove(listener);
}
}
}