KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > context > LocalContext


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 import j2me.lang.UnsupportedOperationException;
11 import javolution.util.FastMap;
12
13 /**
14  * <p> This class represents a local context; it is used to define locally
15  * scoped setting through the use of {@link LocalContext.Reference} typically
16  * wrapped within a static method. For example:[code]
17  * LocalContext.enter();
18  * try {
19  * LargeInteger.setModulus(m); // Performs integer operations modulo m.
20  * Length.showAs(NonSI.INCH); // Shows length in inches.
21  * RelativisticModel.select(); // Uses relativistic physical model.
22  * QuantityFormat.getInstance(); // Returns local format for quantities.
23  * XMLFormat.setFormat(Foo.class, myFormat); // Uses myFormat for instances of Foo.
24  * } finally {
25  * LocalContext.exit(); // Reverts to previous settings.
26  * }[/code]</p>
27  *
28  * <p> Calls to locally scoped methods should be performed either at
29  * start-up (global setting) or within a local context (to avoid
30  * impacting other threads).</p>
31  *
32  * <p> Finally, local settings are inherited by {@link ConcurrentThread
33  * concurrent threads} spawned while in a local context scope.</p>
34  *
35  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
36  * @version 3.6, September 24, 2005
37  * @see javolution.util.LocalMap
38  */

39 public class LocalContext extends Context {
40
41     /**
42      * Holds the context factory.
43      */

44     private static Factory FACTORY = new Factory() {
45         protected Object JavaDoc create() {
46             return new LocalContext();
47         }
48     };
49
50     /**
51      * Holds any reference associated to this context (reference to
52      * referent mapping).
53      */

54     final FastMap _references = new FastMap();
55
56     /**
57      * Default constructor.
58      */

59     public LocalContext() {
60     }
61
62     /**
63      * Returns the current local context or <code>null<code> if the current
64      * thread does not execute within a local context (global context).
65      *
66      * @return the current local context.
67      */

68     public static/*LocalContext*/Context current() {
69         for (Context ctx = Context.current(); ctx != null; ctx = ctx.getOuter()) {
70             if (ctx instanceof LocalContext)
71                 return (LocalContext) ctx;
72         }
73         return null;
74     }
75
76     /**
77      * Enters a {@link LocalContext} possibly recycled.
78      */

79     public static void enter() {
80         LocalContext ctx = (LocalContext) FACTORY.object();
81         ctx._isInternal = true;
82         Context.enter(ctx);
83     }
84     private transient boolean _isInternal;
85
86     /**
87      * Exits and recycles the current {@link LocalContext}.
88      *
89      * @throws UnsupportedOperationException if the current context
90      * has not been entered using LocalContext.enter() (no parameter).
91      */

92     public static void exit() {
93         LocalContext ctx = (LocalContext) Context.current();
94         if (!ctx._isInternal) throw new UnsupportedOperationException JavaDoc
95            ("The context to exit must be specified");
96         ctx._isInternal = false;
97         Context.exitNoCheck(ctx);
98         FACTORY.recycle(ctx);
99     }
100
101     // Implements Context abstract method.
102
protected void enterAction() {
103         // Do nothing.
104
}
105
106     // Implements Context abstract method.
107
protected void exitAction() {
108         _references.clear();
109     }
110     
111     /**
112      * <p> This class represents a reference whose setting is local to the current
113      * {@link LocalContext}; setting outside of any {@link LocalContext} scope
114      * affects the reference default value (equivalent to {@link #setDefault}).
115      * For example:[code]
116      * public class Foo {
117      * public static final LocalContext.Reference<TextFormat<Foo>> FORMAT
118      * = new LocalContext.Reference<TextFormat<Foo>>(DEFAULT_FORMAT);
119      *
120      * public Text toString() {
121      * return FORMAT.get().format(this).toString();
122      * }
123      * }
124      * ...
125      * LocalContext.enter();
126      * try {
127      * Foo.FORMAT.set(localFormat);
128      * ... // This thread displays Foo instances using localFormat.
129      * } finally {
130      * LocalContext.exit(); // Reverts to previous format.
131      * }[/code]</p>
132      *
133      * <p> Accessing/setting a local reference is fast and does not require
134      * any form of synchronization. Local settings are inherited by
135      * {@link ConcurrentThread concurrent threads} spawned from within the
136      * same {@link LocalContext}.</p>
137      */

138     public static class Reference/*<T>*/implements javolution.lang.Reference/*<T>*/ {
139
140         /**
141          * Holds the default value for this reference.
142          */

143         private Object JavaDoc/*{T}*/_defaultValue;
144
145         /**
146          * Indicates if this reference value has ever been locally overriden
147          * (optimization, most applications use default values).
148          */

149         private boolean _hasBeenLocallyOverriden;
150
151         /**
152          * Default constructor (default referent is <code>null</code>).
153          */

154         public Reference() {
155             this(null);
156         }
157
158         /**
159          * Creates a local reference having the specified default value.
160          *
161          * @param defaultValue the default value or root value of this variable.
162          */

163         public Reference(Object JavaDoc/*{T}*/defaultValue) {
164             _defaultValue = defaultValue;
165         }
166
167         /**
168          * Returns the local value for this reference.
169          * The first outer {@link LocalContext} is searched first, then
170          * all outer {@link LocalContext} are recursively searched up to the
171          * global root context which contains the default value.
172          *
173          * @return the context-local value.
174          */

175         public final Object JavaDoc/*{T}*/get() {
176             return (_hasBeenLocallyOverriden) ? retrieveValue() : _defaultValue;
177         }
178
179         private Object JavaDoc/*{T}*/retrieveValue() {
180             for (Context ctx = Context.current(); ctx != null; ctx = ctx.getOuter()) {
181                 if (ctx instanceof LocalContext) {
182                     LocalContext localContext = (LocalContext) ctx;
183                     Object JavaDoc value = localContext._references.get(this);
184                     if (value != null) {
185                         return (Object JavaDoc/*{T}*/) value;
186                     }
187                 }
188             }
189             // Not found, returns default value.
190
return _defaultValue;
191         }
192
193         /**
194          * Sets the local value (referent) for this reference.
195          *
196          * @param value the new local value or <code>null</code> to inherit
197          * the outer value.
198          */

199         public void set(Object JavaDoc/*{T}*/value) {
200             LocalContext ctx = (LocalContext) LocalContext.current();
201             if (ctx != null) {
202                 FastMap references = ctx._references;
203                 references.put(this, value);
204                 _hasBeenLocallyOverriden = true;
205                 return;
206             }
207             // No local context, sets default value.
208
_defaultValue = value;
209         }
210
211         /**
212          * Returns the default value for this reference.
213          *
214          * @return the defaultValue.
215          */

216         public Object JavaDoc/*{T}*/getDefault() {
217             return _defaultValue;
218         }
219
220         /**
221          * Returns the local (non-inherited) value for this reference.
222          *
223          * @return the local value or <code>null</code> if none (value to be
224          * inherited or not set).
225          */

226         public Object JavaDoc/*{T}*/getLocal() {
227             LocalContext ctx = (LocalContext) LocalContext.current();
228             return (ctx != null) ? (Object JavaDoc/*{T}*/) ctx._references.get(this)
229                     : _defaultValue;
230         }
231
232         /**
233          * Sets the default value for this reference.
234          *
235          * @param defaultValue the root value.
236          */

237         public void setDefault(Object JavaDoc/*{T}*/defaultValue) {
238             _defaultValue = defaultValue;
239         }
240         
241         /**
242          * Returns the string representation of the current value of this
243          * reference.
244          *
245          * @return <code>String.valueOf(this.get())</code>
246          */

247         public String JavaDoc toString() {
248             return String.valueOf(this.get());
249         }
250     }
251 }
Popular Tags