KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mapping > Environment


1 // Copyright (c) 2004 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.mapping;
5 import java.util.Hashtable JavaDoc;
6
7 /** A mapping from <code>EnvironmentKey</code> to <code>Location</code>s.
8  * An <code>EnvironmentKey</code> is either a <code>Symbol</code> or
9  * a (<code>Symbol</code>, property)-pair.
10  */

11
12 public abstract class Environment
13   extends PropertySet
14   // implements java.util.map.Map<EnvironmentKey, Object>
15
{
16   static Environment global;
17
18   public static void setGlobal (Environment env)
19   {
20     global = env;
21   }
22
23   public static Environment getGlobal ()
24   {
25     return global;
26   }
27
28   static final int CAN_DEFINE = 1;
29   static final int CAN_REDEFINE = 2;
30
31   /** If 'put' can implicitly define an unbound location. */
32   static final int CAN_IMPLICITLY_DEFINE = 4;
33
34   /** May be shared by multiple threads. */
35   static final int THREAD_SAFE = 8;
36
37   /** If this flag is on, set DIRECT_ON_SET for inherited locations. */
38   static final int DIRECT_INHERITED_ON_SET = 16;
39
40   /** Newly defined locations are created in inherited parent environment. */
41   public static final int INDIRECT_DEFINES = 32;
42
43   int flags = (CAN_DEFINE|CAN_REDEFINE|CAN_IMPLICITLY_DEFINE
44            |DIRECT_INHERITED_ON_SET);
45
46   public int getFlags () { return flags; }
47
48   public void setFlag (boolean setting, int flag)
49   {
50     if (setting) flags |= flag;
51     else flags &= ~flag;
52   }
53
54   /** True if new bindings (non-unbound Locations) can be added. */
55   public boolean getCanDefine() { return ( flags & CAN_DEFINE) != 0; }
56   public void setCanDefine(boolean canDefine)
57   { if (canDefine) flags |= CAN_DEFINE; else flags &= ~CAN_DEFINE; }
58
59   /** True if bindings can be removed or replaced by other kinds of Location.*/
60   public boolean getCanRedefine() { return ( flags & CAN_REDEFINE) != 0; }
61   public void setCanRedefine(boolean canRedefine)
62   { if (canRedefine) flags |= CAN_REDEFINE; else flags &= ~CAN_REDEFINE; }
63
64   /** True if this environment is locked - bindings cannot be added or removed. */
65   public final boolean isLocked()
66   {
67     return (flags & (CAN_DEFINE|CAN_REDEFINE)) == 0;
68   }
69
70   public void setLocked ()
71   {
72     flags &= ~(CAN_DEFINE|CAN_REDEFINE|CAN_IMPLICITLY_DEFINE);
73   }
74
75   public final void setIndirectDefines ()
76   {
77     flags |= Environment.INDIRECT_DEFINES;
78     ((InheritingEnvironment) this).baseTimestamp = 0x7fffffff;
79   }
80
81   /** Return a location bound to (key, property).
82    * Create new unbound Location if no such Location exists. */

83   public final Location getLocation (Symbol key, Object JavaDoc property)
84   {
85     return getLocation(key, property, true);
86   }
87
88   /** Return a location bound to key (and null property).
89    * Create new unbound Location if no such Location exists. */

90   public final Location getLocation (Symbol key)
91   {
92     return getLocation(key, null, true);
93   }
94
95   /** Return a location bound to (key, property).
96    * Return null if no such Location exists. */

97   public final Location lookup (Symbol key, Object JavaDoc property)
98   {
99     return getLocation(key, property, false);
100   }
101
102   public abstract NamedLocation
103   lookup (Symbol name, Object JavaDoc property, int hash);
104
105   public final Location lookup (Symbol key)
106   {
107     return getLocation(key, null, false);
108   }
109
110   public abstract NamedLocation getLocation (Symbol key, Object JavaDoc property,
111                                              int hash, boolean create);
112
113   public final NamedLocation
114   getLocation (Symbol name, Object JavaDoc property, boolean create)
115   {
116     int hash = name.hashCode() ^ System.identityHashCode(property);
117     return getLocation(name, property, hash, create);
118   }
119
120   public final Location getLocation (Object JavaDoc key, boolean create)
121   {
122     Object JavaDoc property = null;
123     if (key instanceof EnvironmentKey)
124       {
125     EnvironmentKey k = (EnvironmentKey) key;
126     key = k.getKeySymbol();
127     property = k.getKeyProperty();
128       }
129     Symbol sym = key instanceof Symbol ? (Symbol) key
130       : getSymbol((String JavaDoc) key);
131     return getLocation(sym, property, create);
132   }
133
134   public boolean isBound(Symbol key, Object JavaDoc property)
135   {
136     Location loc = lookup(key, property);
137     if (loc == null)
138       return false;
139     return loc.isBound();
140   }
141
142   public final boolean isBound(Symbol key)
143   {
144     return isBound(key, null);
145   }
146
147   public final boolean containsKey (Object JavaDoc key)
148   {
149     Object JavaDoc property = null;
150     if (key instanceof EnvironmentKey)
151       {
152     EnvironmentKey k = (EnvironmentKey) key;
153     key = k.getKeySymbol();
154     property = k.getKeyProperty();
155       }
156     Symbol sym = key instanceof Symbol ? (Symbol) key
157       : getSymbol((String JavaDoc) key);
158     return isBound(sym, property);
159   }
160
161   /** Get the value bound to the given name.
162    * @exception gnu.mapping.UnboundLocationException the name has no binding
163    * @see Environment#get(Object)
164    */

165   public final Object JavaDoc getChecked(String JavaDoc name)
166   {
167     Object JavaDoc value = get(name, Location.UNBOUND);
168     if (value == Location.UNBOUND)
169       throw new UnboundLocationException(name+" in "+this);
170     return value;
171   }
172
173   public Object JavaDoc get (Symbol key, Object JavaDoc property, Object JavaDoc defaultValue)
174   {
175     Location loc = lookup(key, property);
176     if (loc == null)
177       return defaultValue;
178     return loc.get(defaultValue);
179   }
180
181   public final Object JavaDoc get (EnvironmentKey key, Object JavaDoc defaultValue)
182   {
183     Symbol symbol = key.getKeySymbol();
184     Object JavaDoc property = key.getKeyProperty();
185     return get(symbol, property, defaultValue);
186   }
187
188   public final Object JavaDoc get(String JavaDoc key, Object JavaDoc defaultValue)
189   {
190     return get(getSymbol(key), null, defaultValue);
191   }
192
193   public Object JavaDoc get (Symbol sym)
194   {
195     Object JavaDoc unb = Location.UNBOUND;
196     Object JavaDoc val = get(sym, null, unb);
197     if (val == unb)
198       throw new UnboundLocationException(sym);
199     return val;
200   }
201
202   public final Object JavaDoc getFunction (Symbol key, Object JavaDoc defaultValue)
203   {
204     return get(key, EnvironmentKey.FUNCTION, defaultValue);
205   }
206
207   public final Object JavaDoc getFunction (Symbol sym)
208   {
209     Object JavaDoc unb = Location.UNBOUND;
210     Object JavaDoc val = get(sym, EnvironmentKey.FUNCTION, unb);
211     if (val == unb)
212       throw new UnboundLocationException(sym);
213     return val;
214   }
215
216   /** Get the value bound to the given name.
217    * Returns null if the name has no binding
218    * (for compatibility with Java2 Collections framework).
219    * @see Environment#getChecked(String)
220    */

221   public final Object JavaDoc get (Object JavaDoc key)
222   {
223     Object JavaDoc property = null;
224     if (key instanceof EnvironmentKey)
225       {
226     EnvironmentKey k = (EnvironmentKey) key;
227     key = k.getKeySymbol();
228     property = k.getKeyProperty();
229       }
230     Symbol sym = key instanceof Symbol ? (Symbol) key
231       : getSymbol((String JavaDoc) key);
232     return get(sym, property, null);
233   }
234
235   public void put(Symbol key, Object JavaDoc property, Object JavaDoc newValue)
236   {
237     Location loc = getLocation(key, property);
238     if (loc.isConstant()) // FIXME - is this helpful?
239
define(key, property, newValue);
240     else
241       loc.set(newValue);
242   }
243
244   public abstract void define (Symbol key, Object JavaDoc property, Object JavaDoc newValue);
245
246   public final void put (Symbol key, Object JavaDoc newValue)
247   {
248     put(key, null, newValue);
249   }
250
251   public final Object JavaDoc put(Object JavaDoc key, Object JavaDoc newValue)
252   {
253     Location loc = getLocation(key, true);
254     Object JavaDoc oldValue = loc.get(null);
255     loc.set(newValue);
256     return oldValue;
257   }
258
259   public final void putFunction(Symbol key, Object JavaDoc newValue)
260   {
261     put(key, EnvironmentKey.FUNCTION, newValue);
262   }
263
264   public final Object JavaDoc put (String JavaDoc key, Object JavaDoc value)
265   {
266     return put((Object JavaDoc) key, value);
267   }
268
269   /** Remove Location from this Environment.
270    * Does not explicitly undefine the location itself.
271    */

272   public Location unlink (Symbol key, Object JavaDoc property, int hash)
273   {
274     throw new RuntimeException JavaDoc("unsupported operation: unlink (aka undefine)");
275   }
276
277   /** Remove Location from this Environment and undefine it. */
278   public Object JavaDoc remove (Symbol key, Object JavaDoc property, int hash)
279   {
280     Location loc = unlink(key, property, hash);
281     if (loc == null)
282       return null;
283     Object JavaDoc value = loc.get(null);
284     loc.undefine();
285     return value;
286  }
287
288   /** Remove and undefine binding.
289    * @return Old value
290    */

291   public final Object JavaDoc remove (EnvironmentKey key)
292   {
293     Symbol symbol = key.getKeySymbol();
294     Object JavaDoc property = key.getKeyProperty();
295     int hash = symbol.hashCode() ^ System.identityHashCode(property);
296     return remove(symbol, property, hash);
297   }
298
299   public final Object JavaDoc remove (Symbol symbol, Object JavaDoc property)
300   {
301     int hash = symbol.hashCode() ^ System.identityHashCode(property);
302     return remove(symbol, property, hash);
303   }
304
305   public final void remove (Symbol sym)
306   {
307     remove(sym, null, sym.hashCode());
308   }
309
310   public final void removeFunction (Symbol sym)
311   {
312     remove(sym, EnvironmentKey.FUNCTION);
313   }
314
315   public final Object JavaDoc remove (Object JavaDoc key)
316   {
317     Object JavaDoc property = null;
318     if (key instanceof EnvironmentKey)
319       {
320     EnvironmentKey k = (EnvironmentKey) key;
321     return remove(k.getKeySymbol(), k.getKeyProperty());
322       }
323     Symbol symbol = key instanceof Symbol ? (Symbol) key
324       : getSymbol((String JavaDoc) key);
325     int hash = symbol.hashCode() ^ System.identityHashCode(property);
326     return remove(symbol, property, hash);
327   }
328
329   public Namespace defaultNamespace()
330   {
331     // FIXME: return get("*package*, Namespace.getDefault())
332
return Namespace.getDefault();
333   }
334
335   public Symbol getSymbol (String JavaDoc name)
336   {
337     return defaultNamespace().getSymbol(name);
338   }
339
340   static final Hashtable JavaDoc envTable = new Hashtable JavaDoc(50);
341
342   public static Environment getInstance(String JavaDoc name)
343   {
344     if (name == null)
345       name = "";
346     synchronized (envTable)
347       {
348     Environment env = (Environment) envTable.get(name);
349     if (env != null)
350       return env;
351     env = new SimpleEnvironment ();
352     env.setName(name);
353     envTable.put(name, env);
354     return env;
355       }
356   }
357
358   /** Does not enumerate inherited Locations. */
359   public abstract LocationEnumeration enumerateLocations();
360
361   /** Does enumerate inherited Locations. */
362   public abstract LocationEnumeration enumerateAllLocations();
363
364   protected abstract boolean hasMoreElements (LocationEnumeration it);
365
366   /**
367     * @deprecated
368     */

369   public static Environment current () { return getCurrent(); }
370   public static Environment getCurrent ()
371   {
372     return CallContext.getInstance().getEnvironment();
373   }
374
375   public static void setCurrent (Environment env)
376   {
377     CallContext.getInstance().curEnvironment = env;
378   }
379
380   public static Environment user () { return getCurrent(); }
381
382   public final void addLocation (NamedLocation loc)
383   {
384     addLocation(loc.getKeySymbol(), loc.getKeyProperty(), loc);
385   }
386
387   public abstract NamedLocation addLocation (Symbol name, Object JavaDoc prop, Location loc);
388
389   public final void addLocation (EnvironmentKey key, Location loc)
390   {
391     addLocation(key.getKeySymbol(), key.getKeyProperty(), loc);
392   }
393
394   public static SimpleEnvironment make ()
395   {
396     return new SimpleEnvironment();
397   }
398
399   public static SimpleEnvironment make (String JavaDoc name)
400   {
401     return new SimpleEnvironment(name);
402   }
403
404   public static InheritingEnvironment make (String JavaDoc name, Environment parent)
405   {
406     return new InheritingEnvironment(name, parent);
407   }
408
409   public String JavaDoc toString ()
410   {
411     return "#<environment "+getName()+'>';
412   }
413
414   /** Overridden in sub-classes - useful for more verbose debug output. */
415   public String JavaDoc toStringVerbose ()
416   {
417     return toString();
418   }
419 }
420
Popular Tags