KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > lang > PersistentReference


1 /*
2  * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
3  * Copyright (C) 2005 - Javolution (http://javolution.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package javolution.lang;
10
11 import j2me.io.Serializable;
12 import j2me.util.Iterator;
13 import j2me.util.Map;
14 import javolution.util.FastMap;
15
16 /**
17  * <p> This class represents a reference whose value can be kept persistent
18  * accross multiple program executions. Instances of this class can be
19  * used to retrieve/set profiling configuration parameters, such as the
20  * appropriate array size to avoid resizing. For example:<pre>
21  * public class Foo {
22  * // Holds the configurable nominal size to avoid resizing.
23  * private static final PersistentReference&lt;Integer> SIZE
24  * = new PersistentReference&lt;Integer>("Foo#SIZE", new Integer(100));
25  * private Entry[] _entries = new Entry[SIZE.get().intValue()];
26  * private int _count;
27  *
28  * public void addEntry(Entry entry) {
29  * if (_count >= _entries.length) { // Ooops, resizes.
30  * Entry[] tmp = new Entry[_entries.length * 2];
31  * System.arraycopy(_entries, 0, tmp, 0, _entries.length);
32  * _entries = tmp;
33  * SIZE.set(new Integer(_entries.length)); // Saves.
34  * }
35  * _entries[_count++] = entry;
36  * }
37  * }</pre></p>
38  *
39  * <p> Real-time application may use persistent references for pre-built data
40  * structure to avoid delaying time critical code. For example:<pre>
41  * public class Unit {
42  * // Holds the unit multiplication table. Allows for persistency.
43  * private static final PersistentReference&lt;FastMap&lt;Unit, FastMap&lt;Unit, Unit>>>
44  * MULT_TABLE = new PersistentReference&lt;FastMap&lt;Unit, FastMap&lt;Unit, Unit>>>(
45  * "org.jscience.physics.units.Unit#MULT_TABLE",
46  * new FastMap&lt;Unit, FastMap&lt;Unit, Unit>>());
47  *
48  * public final Unit times(Unit that) {
49  * // Checks the multiplication table first,
50  * // if not present calculates (slow).
51  * FastMap&lt;Unit, Unit> thisMult = MULT_TABLE.get().get(this);
52  * ...
53  * }
54  * }</pre></p>
55  *
56  * <p> How persistent references are loaded/saved is application specific.
57  * Although, the simplest way is to use Javolution xml serialization
58  * facility. For example:<pre>
59  * import javolution.xml.ObjectReader;
60  * import javolution.xml.ObjectWriter;
61  * public void main(String[]) {
62  * Map values = (Map) new ObjectReader().read(new FileInputStream("C:/persistent.xml"));
63  * PersistentReference.putAll(values)
64  * ...
65  * new ObjectWriter().write(PersistentReference.values(), new FileOutputStream("C:/persistent.xml"));
66  * }</pre></p>
67  *
68  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
69  * @version 3.3, May 10, 2005
70  */

71 public final class PersistentReference /*<T>*/implements Reference/*<T>*/, Serializable {
72
73     /**
74      * Holds the reference collection (id to reference).
75      */

76     private static final FastMap COLLECTION = new FastMap();
77
78     /**
79      * Holds reference current values (id to value mapping).
80      */

81     private static final FastMap VALUES = new FastMap();
82
83     /**
84      * Holds the collection update lock.
85      */

86     private static final Object LOCK = new Object();
87
88     /**
89      * Holds the unique identifier.
90      */

91     private final String _id;
92
93     /**
94      * Holds the reference value.
95      */

96     private volatile Object/*T*/_value;
97
98     /**
99      * Creates a persistent reference having the specified identifier
100      * and default value.
101      *
102      * @param id the unique identifier.
103      * @param defaultValue the associated default value.
104      * @throws IllegalArgumentException if the id is in use.
105      */

106     public PersistentReference(String id, Object/*T*/defaultValue) {
107         synchronized (LOCK) {
108             if (COLLECTION.containsKey(id))
109                 throw new IllegalArgumentException("id: " + id + " in use");
110             _id = id;
111             if (VALUES.containsKey(id)) { // Mapping already set.
112
_value = (Object/*T*/) VALUES.get(id);
113                 ;
114             } else {
115                 _value = defaultValue;
116             }
117             COLLECTION.put(id, this);
118             VALUES.put(id, _value);
119         }
120     }
121
122     /**
123      * Returns the unique identifier for this persistent reference.
124      *
125      * @return this reference identifier.
126      */

127     public String id() {
128         return _id;
129     }
130
131     // Implements Reference interface.
132
public Object/*T*/get() {
133         return _value;
134     }
135
136     // Implements Reference interface.
137
public void set(Object/*T*/value) {
138         synchronized (LOCK) {
139             _value = value;
140             VALUES.put(_id, _value);
141         }
142     }
143
144     /**
145      * Returns a thread-safe, unmodifiable view over the persistent references
146      * values (id to value mapping).
147      *
148      * @return a view over the references mapping.
149      */

150     public static Map values() {
151         return VALUES.unmodifiable(); // Thread-safe, ids cannot be removed.
152
}
153
154     /**
155      * Sets the value of the reference identified by the specified id.
156      *
157      * @param id the persistent reference identifier.
158      * @param value the value to use instead of the current value; or if the
159      * reference does not exist, in place of the default value when
160      * reference is created.
161      */

162     public static void put(String id, Object value) {
163         synchronized (LOCK) {
164             if (COLLECTION.containsKey(id)) {
165                 PersistentReference ref = (PersistentReference) COLLECTION
166                         .get(id);
167                 ref._value = value;
168             }
169             VALUES.put(id, value);
170         }
171     }
172
173     /**
174      * Overwrites the current values with the ones specified (equivalent to
175      * {@link #put put(id, value)} for each entry of the specified map).
176      *
177      * @param values the new values (id to value mapping).
178      */

179     public static void putAll(Map values) {
180         for (Iterator i = values.entrySet().iterator(); i.hasNext();) {
181             Map.Entry e = (Map.Entry) i.next();
182             put((String) e.getKey(), e.getValue());
183         }
184     }
185 }
Popular Tags