/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2005 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution37.javolution.lang;
import java.io.Serializable;
import java.lang.Comparable;
import java.util.Map;
import javolution37.javolution.util.FastMap;
import javolution37.javolution.util.FastSet;
/**
* This class represents a reference over an object which can be kept
* persistent accross multiple program executions. Instances of this class
* are typically used to hold global data time consuming to regenerate.
* For example:[code]
* public class FastMap implements Map {
* // Provides constructor for persistent maps.
* public FastMap(String id) {
* PersistentReference> ref = new PersistentReference>(id);
* FastMap persistentMap = ref.get();
* if (persistentMap != null) this.putAll(persistentMap);
* ref.set(this); // Sets this map as the persistent map.
* }
* }
* ...
* // Persistent lookup table for units multiplications.
* static FastMap> UNITS_MULT_LOOKUP
* = new FastMap>("UNITS_MULT_LOOKUP").setShared(true);
* [/code]
*
* Persistent references may also be used to hold optimum configuration
* values set from previous executions. For example:[code]
* public Targets {
* private static PersistentReference CAPACITY
* = new PersistentReference(Targets#CAPACITY, 256);
* private Target[] _targets = new Target[CAPACITY.get()];
* private int _count;
* public void add(Target target) {
* if (_count == _targets.length) { // Ooops, resizes.
* Target[] tmp = new Target[_count * 2];
* System.arraycopy(_targets, 0, tmp, 0, _count);
* _targets = tmp;
* CAPACITY.setMinimum(_targets.length); // Persists.
* }
* _targets[_count++] target;
* }
* }[/code]
*
* How persistent references are loaded/saved is application specific.
* Although, the simplest way is to use Javolution xml serialization
* facility. For example:[code]
* import javolution.xml.ObjectReader;
* import javolution.xml.ObjectWriter;
* public void main(String[]) {
* // Loads persistent reference values at start-up.
* Map values = new ObjectReader
*
* @author Jean-Marie Dautelle
* @version 3.7, February 24, 2006
*/
public class PersistentReference implements Reference ,
Serializable {
/**
* Holds the identifiers collection (for unicity).
*/
private static final FastSet IDENTIFIERS = new FastSet();
/**
* Holds current id to value mapping).
*/
private static final FastMap ID_TO_VALUE = new FastMap();
/**
* Holds the unique identifier.
*/
private final String _id;
/**
* Creates a persistent reference having the specified unique identifier.
*
* @param id the unique identifier.
* @throws IllegalArgumentException if the identifier is not unique.
*/
public PersistentReference(String id) {
synchronized (IDENTIFIERS) {
if (IDENTIFIERS.contains(id))
throw new IllegalArgumentException("id: " + id
+ " already in use");
IDENTIFIERS.add(id);
}
_id = id;
}
/**
* Creates a persistent reference having the specified unique identifier
* and default value if not set.
*
* @param id the unique identifier.
* @param defaultValue the default value if not set.
* @throws IllegalArgumentException if the identifier is not unique.
*/
public PersistentReference(String id, T defaultValue) {
this(id);
synchronized (ID_TO_VALUE) {
if (!ID_TO_VALUE.containsKey(_id)) {
ID_TO_VALUE.put(id, defaultValue);
}
}
}
/**
* Returns the unique identifier for this persistent reference.
*
* @return this reference identifier.
*/
public final String id() {
return _id;
}
// Implements Reference interface.
public T get() {
synchronized (ID_TO_VALUE) {
return ( T ) ID_TO_VALUE.get(_id);
}
}
// Implements Reference interface.
public void set( T value) {
synchronized (ID_TO_VALUE) {
ID_TO_VALUE.put(_id, value);
}
}
/**
* Sets this reference to the specified value only if
* (value.compareTo(this.get()) > 0).
*
* @param value the minimum value for this reference.
* @throws IllegalArgumentException if the specified value is not
* {@link Comparable} or an {@link Integer} instance (J2ME).
*/
public void setMinimum( T value) {
synchronized (ID_TO_VALUE) {
if (value instanceof Comparable) {
Object prevValue = get();
if (((Comparable) value).compareTo(prevValue) > 0) {
ID_TO_VALUE.put(_id, value);
}
} else if (value instanceof Integer) {
Object prevValue = get();
if (((Integer) value).intValue() > ((Integer) prevValue)
.intValue()) {
ID_TO_VALUE.put(_id, value);
}
} else {
throw new IllegalArgumentException();
}
}
}
/**
* Sets this reference to the specified value only if
* (value.compareTo(this.get()) < 0).
*
* @param value the maximum value for this reference.
* @throws IllegalArgumentException if the specified value is not
* {@link Comparable} or an {@link Integer} instance (J2ME).
*/
public void setMaximum( T value) {
synchronized (ID_TO_VALUE) {
if (value instanceof Comparable) {
Object prevValue = get();
if (((Comparable) value).compareTo(prevValue) < 0) {
ID_TO_VALUE.put(_id, value);
}
} else if (value instanceof Integer) {
Object prevValue = get();
if (((Integer) value).intValue() < ((Integer) prevValue)
.intValue()) {
ID_TO_VALUE.put(_id, value);
}
} else {
throw new IllegalArgumentException();
}
}
}
/**
* Returns a thread-safe, unmodifiable view over the persistent references
* values (id to value mapping).
*
* @return a view over the references mapping.
*/
public static Map values() {
return ID_TO_VALUE.unmodifiable(); // Thread-safe, ids cannot be removed.
}
/**
* Sets the value of the referenced object associated to the specified id.
*
* @param id the object identifier.
* @param value the value to use instead of the current value.
*/
public static void put(String id, Object value) {
ID_TO_VALUE.put(id, value);
}
/**
* Overwrites the current values with the ones specified (equivalent to
* {@link #put put(id, value)} for each entry of the specified map).
*
* @param values the new values (id to value mapping).
*/
public static void putAll(Map values) {
ID_TO_VALUE.putAll(values);
}
/**
* Returns the string representation of the current value of this
* reference.
*
* @return String.valueOf(this.get())
*/
public String toString() {
return String.valueOf(this.get());
}
}
Ads help maintain this website.