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); } } }