KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > context > PersistentContext


1 /*
2  * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
3  * Copyright (C) 2006 - 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.context;
10
11 import j2me.lang.Comparable;
12 import javolution.util.FastMap;
13 import javolution.xml.XMLFormat;
14 import javolution.xml.stream.XMLStreamException;
15
16 /**
17  * <p> This class represents a context persistent accross multiple program
18  * executions. It is typically used to hold
19  * {@link Reference persistent references}.</p>
20  *
21  * <p> How this context is loaded/saved is application specific.
22  * Although, the simplest way is to use Javolution XML serialization
23  * facility. For example:[code]
24  * import javolution.xml.XMLObjectReader;
25  * import javolution.xml.XMLObjectWriter;
26  * public void main(String[]) {
27  * // Loads persistent context (typically at start-up).
28  * XMLObjectReader reader = XMLObjectReader.newInstance(new FileInputStream("C:/persistent.xml"));
29  * PersistentContext.setCurrent(reader.read(PersistentContext.class));
30  * ...
31  * ...
32  * // Saves persistent context for future execution.
33  * XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream("C:/persistent.xml"));
34  * writer.write(PersistentContext.current(), PersistentContext.class);
35  * }[/code]</p>
36  *
37  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
38  * @version 4.2, December 31, 2006
39  */

40 public class PersistentContext extends Context {
41
42     /**
43      * Holds the class object (cannot use .class with j2me).
44      */

45     private static final Class JavaDoc CLASS = new PersistentContext().getClass();;
46
47     /**
48      * Holds the single instance.
49      */

50     private static PersistentContext _PersistentContext = new PersistentContext();
51
52     /**
53      * Holds current id to value mapping.
54      */

55     private final FastMap _idToValue = new FastMap();
56
57     /**
58      * Holds the XML representation for persistent contexts
59      * (holds persistent reference mapping).
60      */

61     protected static final XMLFormat/*<PersistentContext>*/XML = new XMLFormat(
62             CLASS) {
63         public void read(InputElement xml, Object JavaDoc obj)
64                 throws XMLStreamException {
65             final PersistentContext ctx = (PersistentContext) obj;
66             ctx._idToValue.putAll((FastMap) xml.get("References"));
67         }
68
69         public void write(Object JavaDoc obj, OutputElement xml)
70                 throws XMLStreamException {
71             final PersistentContext ctx = (PersistentContext) obj;
72             xml.add(ctx._idToValue, "References");
73         }
74     };
75
76     /**
77      * Default constructor.
78      */

79     public PersistentContext() {
80     }
81
82     /**
83      * Sets the persistent instance.
84      *
85      * @param ctx the persistent instance.
86      */

87     public static void setCurrent(PersistentContext ctx) {
88         _PersistentContext = ctx;
89         synchronized (Reference.INSTANCES) {
90              for (FastMap.Entry e = Reference.INSTANCES.head(), end = Reference.INSTANCES.tail();
91                    (e = (FastMap.Entry) e.getNext())!= end;) {
92                  Reference reference = (Reference) e.getValue();
93                  if (ctx._idToValue.containsKey(reference._id)) {
94                      reference.set(ctx._idToValue.get(reference._id));
95                  }
96              }
97         }
98     }
99
100     /**
101      * Returns the persistent context instance (singleton).
102      *
103      * @return the persistent context instance.
104      */

105     public static/*PersistentContext*/Context current() {
106         return _PersistentContext;
107     }
108
109     /**
110      * Throws <code>UnsupportedOperationException</code> persistent context
111      * are global to all threads (singleton).
112      */

113     protected void enterAction() {
114         throw new j2me.lang.UnsupportedOperationException(
115                 "Cannot enter persistent context (already in)");
116     }
117
118     /**
119      * Throws <code>UnsupportedOperationException</code> persistent context
120      * are global to all threads (singleton).
121      */

122     protected void exitAction() {
123         throw new j2me.lang.UnsupportedOperationException(
124                 "Cannot exit persistent context (always in)");
125     }
126
127     /**
128      * <p> This class represents a reference over an object which can be kept
129      * persistent accross multiple program executions. Instances of this class
130      * are typically used to hold global data time consuming to regenerate.
131      * For example:[code]
132      * public class FastMap<K,V> implements Map<K, V> {
133      * // Provides a constructor for persistent maps.
134      * public FastMap(String id) {
135      * new PersistentContext<Map<K, V>.Reference(id, this) {
136      * protected void notifyChange() {
137      * FastMap.this.clear();
138      * FastMap.this.putAll(this.get());
139      * }
140      * };
141      * }
142      * }
143      * ...
144      * // Persistent lookup table for units multiplications.
145      * static FastMap<Unit, FastMap<Unit, Unit>> UNITS_MULT_LOOKUP
146      * = new FastMap<Unit, FastMap<Unit, Unit>>("UNITS_MULT_LOOKUP").setShared(true);
147      * [/code]</p>
148      *
149      * <p> Persistent references may also be used to hold optimum configuration
150      * values set from previous executions. For example:[code]
151      * public Targets {
152      * private static PersistentContext.Reference<Integer> CAPACITY
153      * = new PersistentContext.Reference<Integer>("Targets#CAPACITY", 256);
154      * private Target[] _targets = new Target[CAPACITY.get()];
155      * private int _count;
156      * public void add(Target target) {
157      * if (_count == _targets.length) { // Ooops, resizes.
158      * Target[] tmp = new Target[_count * 2];
159      * System.arraycopy(_targets, 0, tmp, 0, _count);
160      * _targets = tmp;
161      * CAPACITY.setMinimum(_targets.length); // Persists.
162      * }
163      * _targets[_count++] target;
164      * }
165      * }[/code]
166      *
167      * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
168      * @version 4.0, September 4, 2006
169      */

170     public static class Reference /*<T>*/implements
171             javolution.lang.Reference/*<T>*/ {
172
173         /**
174          * Holds the instances.
175          */

176         private final static FastMap INSTANCES = new FastMap();
177
178         /**
179          * Holds the unique identifier.
180          */

181         private final String JavaDoc _id;
182
183         /**
184          * Holds the current value.
185          */

186         private Object JavaDoc/*{T}*/ _value;
187
188         /**
189          * Creates a persistent reference identified by the specified name and
190          * having the specified default value.
191          *
192          * @param id the unique identifier.
193          * @param defaultValue the default value.
194          * @throws IllegalArgumentException if the name is not unique.
195          */

196         public Reference(String JavaDoc id, Object JavaDoc/*{T}*/defaultValue) {
197             _id = id;
198             _value = defaultValue;
199             synchronized (INSTANCES) {
200                 if (INSTANCES.containsKey(id))
201                     throw new IllegalArgumentException JavaDoc("Identifier " + id
202                             + " already in use");
203                 INSTANCES.put(id, this);
204             }
205             if (_PersistentContext._idToValue.containsKey(id)) {
206                 set((Object JavaDoc/*{T}*/) _PersistentContext._idToValue.get(id));
207             }
208         }
209
210         // Implements Reference interface.
211
public Object JavaDoc/*{T}*/get() {
212             return _value;
213         }
214
215         // Implements Reference interface.
216
public void set(Object JavaDoc/*{T}*/value) {
217             _value = value;
218             notifyChange();
219         }
220
221         /**
222          * Sets this reference to the specified value only if
223          * <code>(value.compareTo(this.get()) &gt; 0)</code>.
224          *
225          * @param value the minimum value for this reference.
226          * @throws IllegalArgumentException if the specified value is not
227          * {@link Comparable} or an {@link Integer} instance (J2ME).
228          */

229         public void setMinimum(Object JavaDoc/*{T}*/value) {
230             synchronized (this) {
231                 if (value instanceof Comparable JavaDoc) {
232                     Object JavaDoc prevValue = get();
233                     if (((Comparable JavaDoc) value).compareTo(prevValue) > 0) {
234                         set(value);
235                     }
236                 } else if (value instanceof Integer JavaDoc) {
237                     Object JavaDoc prevValue = get();
238                     if (((Integer JavaDoc) value).intValue() > ((Integer JavaDoc) prevValue)
239                             .intValue()) {
240                         set(value);
241                     }
242                 } else {
243                     throw new IllegalArgumentException JavaDoc();
244                 }
245             }
246         }
247
248         /**
249          * Sets this reference to the specified value only if
250          * <code>(value.compareTo(this.get()) &lt; 0)</code>.
251          *
252          * @param value the maximum value for this reference.
253          * @throws IllegalArgumentException if the specified value is not
254          * {@link Comparable} or an {@link Integer} instance (J2ME).
255          */

256         public void setMaximum(Object JavaDoc/*{T}*/value) {
257             synchronized (this) {
258                 if (value instanceof Comparable JavaDoc) {
259                     Object JavaDoc prevValue = get();
260                     if (((Comparable JavaDoc) value).compareTo(prevValue) < 0) {
261                         set(value);
262                     }
263                 } else if (value instanceof Integer JavaDoc) {
264                     Object JavaDoc prevValue = get();
265                     if (((Integer JavaDoc) value).intValue() < ((Integer JavaDoc) prevValue)
266                             .intValue()) {
267                         set(value);
268                     }
269                 } else {
270                     throw new IllegalArgumentException JavaDoc();
271                 }
272             }
273         }
274
275         /**
276          * Returns the string representation of the current value of this
277          * reference.
278          *
279          * @return <code>String.valueOf(this.get())</code>
280          */

281         public String JavaDoc toString() {
282             return String.valueOf(get());
283         }
284
285         /**
286          * Notifies this reference that its value has changed (for example
287          * a new persistent context has been loaded).
288          * The default implementation does nothing.
289          */

290         protected void notifyChange() {
291         }
292     }
293 }
Popular Tags