KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mapping > PropertyLocation


1 package gnu.mapping;
2 import gnu.lists.*;
3
4 /** Used to implement Lisp-style "property lists".
5  * A <code>PropertyLocation</code> is a location whose value is the
6  * <code>car</code> of a property list.
7  * This class also contains a number of static methods useful for
8  * working with property lists.
9  */

10
11 public class PropertyLocation extends Location
12 {
13   // Location plist;
14

15   Pair pair;
16
17   public final Object JavaDoc get (Object JavaDoc defaultValue)
18   {
19     return pair.car;
20   }
21
22   public boolean isBound ()
23   {
24     return true;
25   }
26
27   public final void set (Object JavaDoc newValue)
28   {
29     pair.car = newValue;
30   }
31
32   /** Get the property list assocated with an object in a given Environment.
33    * @param symbol Usually but not necessarily a Symbol.
34    * (A String is <em>not </em> converted a Symbol by this method.)
35    */

36   public static Object JavaDoc getPropertyList (Object JavaDoc symbol, Environment env)
37   {
38     return env.get(Symbol.PLIST, symbol, LList.Empty);
39   }
40
41   /** Get the property list associated with object in the current Environment.
42    * Corresponds to Common Lisp's <code>symbol-plist</code> function.
43    * @param symbol Usually but not necessarily a Symbol.
44    * (A String is <em>not </em> converted a Symbol by this method.)
45    */

46   public static Object JavaDoc getPropertyList (Object JavaDoc symbol)
47   {
48     return Environment.getCurrent().get(Symbol.PLIST, symbol, LList.Empty);
49   }
50
51   /** Set the property list assocated with an object in a given Environment.
52    * This function should be avoided, since a Symbol's property list may
53    * be used by unknown classes. It also can be slow.
54    * @param symbol Usually but not necessarily a Symbol.
55    * (A String is <em>not </em> converted a Symbol by this method.)
56    */

57   public static void setPropertyList (Object JavaDoc symbol, Object JavaDoc plist,
58                       Environment env)
59   {
60     synchronized (env)
61       {
62     Location lloc = env.lookup(Symbol.PLIST, symbol);
63     if (symbol instanceof Symbol)
64       {
65         Symbol sym = (Symbol) symbol;
66         Object JavaDoc old = lloc.get(LList.Empty);
67         Object JavaDoc p = old;
68         // Remove old PropertyLocation bindings not in plist.
69
for (;;)
70           {
71         if (! (p instanceof Pair))
72           break;
73         Pair pair = (Pair) p;
74         Object JavaDoc property = pair.car;
75         if (plistGet(plist, property, null) != null)
76           env.remove(sym, property);
77         p = ((Pair) pair.cdr).cdr;
78           }
79         // Add/update PropertyLocation bindings from plist.
80
p = plist;
81         for (;;)
82           {
83         if (! (p instanceof Pair))
84           break;
85         Pair pair = (Pair) p;
86         Object JavaDoc property = pair.car;
87         Location loc = env.lookup(sym, property);
88         PropertyLocation ploc;
89         if (loc != null
90             && (loc = loc.getBase()) instanceof PropertyLocation)
91           {
92             ploc = (PropertyLocation) loc;
93           }
94         else
95           {
96             ploc = new PropertyLocation();
97             env.addLocation(sym, property, ploc);
98           }
99         Pair valuePair = (Pair) pair.cdr;
100         ploc.pair = valuePair;
101         //ploc.plist = plist;
102
p = valuePair.cdr;
103           }
104       }
105     lloc.set(plist);
106       }
107   }
108
109   /** Set the property list assocated with an object in a given Environment.
110    * Corresponds to Common Lisp's <code>(setf symbol-plist)</code> function.
111    * @see #setPropertyList(Object, Object, Environment).
112    */

113   public static void setPropertyList (Object JavaDoc symbol, Object JavaDoc plist)
114   {
115     setPropertyList(symbol, plist, Environment.getCurrent());
116
117   }
118
119   /** Gets a property value associated with an object.
120    * @param symbol Usually a <code>Symbol</code>, but can be any
121    * <code>Object>/code>. A <code>String</code> is converted to a
122    * <code>Symbol</code> using <code>env.getSymbol()</code>.
123    * Symbols require a constant-type hash lookup; other object
124    * are serached linearly.
125    */

126   public static Object JavaDoc getProperty (Object JavaDoc symbol, Object JavaDoc property,
127                     Object JavaDoc defaultValue, Environment env)
128   {
129     if (! (symbol instanceof Symbol))
130       {
131     if (symbol instanceof String JavaDoc)
132       symbol = Namespace.getDefaultSymbol((String JavaDoc) symbol);
133     else
134       return plistGet(env.get(Symbol.PLIST, symbol, LList.Empty),
135               property, defaultValue);
136       }
137     return env.get((Symbol) symbol, property, defaultValue);
138   }
139
140   /** Gets a property value associated with an object.
141    * Corresponds to Common Lisp's <code>get</code> function.
142    * @see #getProperty(Object, Object, Object, Environment).
143    */

144   public static Object JavaDoc getProperty (Object JavaDoc symbol, Object JavaDoc property,
145                     Object JavaDoc defaultValue)
146   {
147     return getProperty(symbol, property,
148                defaultValue, Environment.getCurrent());
149   }
150
151   public static void putProperty (Object JavaDoc symbol, Object JavaDoc property,
152                   Object JavaDoc newValue, Environment env)
153   {
154     if (! (symbol instanceof Symbol))
155       {
156     if (symbol instanceof String JavaDoc)
157       symbol = Namespace.getDefaultSymbol((String JavaDoc) symbol);
158     else
159       {
160         Location lloc = env.getLocation(Symbol.PLIST, symbol);
161         lloc.set(plistPut(lloc.get(LList.Empty), property, newValue));
162         return;
163       }
164       }
165     Location loc = env.lookup((Symbol) symbol, property);
166     if (loc != null && (loc = loc.getBase()) instanceof PropertyLocation)
167       ((PropertyLocation) loc).set(newValue);
168     else
169       {
170     Location lloc = env.getLocation(Symbol.PLIST, symbol);
171     Object JavaDoc plist = lloc.get(LList.Empty);
172     Pair pair = null;
173     /*
174     pair = null;
175     if (plist instanceof Pair)
176       {
177         pair = (Pair) plist;
178         for (;;)
179           {
180         if (pair.car == property)
181           break;
182         if (pair.cdr instanceof Pair)
183           pair = (Pair) pair.cdr;
184         else
185           {
186             pair = null;
187             break;
188           }
189           }
190       }
191     if (pair == null)
192       plist = pair = new Pair(property, new Pair(newValue, plist));
193     */

194     pair = new Pair(newValue, plist);
195     plist = new Pair(property, pair);
196     lloc.set(plist);
197     PropertyLocation ploc = new PropertyLocation();
198     //ploc.plist = lloc;
199
ploc.pair = pair;
200     env.addLocation((Symbol) symbol, property, ploc);
201       }
202   }
203
204   /** Sets a property value associated with an object.
205    * Corresponds to Common Lisp's <code>(setf get)</code> function.
206    */

207   public static void putProperty (Object JavaDoc symbol, Object JavaDoc property,
208                   Object JavaDoc newValue)
209   {
210     putProperty(symbol, property, newValue, Environment.getCurrent());
211   }
212
213   /** Remove a properaty assocatied with an object.
214    */

215   public static boolean removeProperty (Object JavaDoc symbol, Object JavaDoc property,
216                     Environment env)
217   {
218     Location ploc = env.lookup(Symbol.PLIST, symbol);
219     if (ploc == null)
220       return false;
221     Object JavaDoc plist = ploc.get(LList.Empty);
222     if (! (plist instanceof Pair))
223       return false;
224     Pair pair = (Pair) plist;
225     Pair prev = null;
226     for (;;)
227       {
228     if (pair.car == property)
229       break;
230     Object JavaDoc next = pair.cdr;
231     if (! (next instanceof Pair))
232       return false;
233     prev = pair;
234     pair = (Pair) next;
235       }
236     Object JavaDoc tail = ((Pair) pair.cdr).cdr;
237     if (prev == null)
238       {
239     plist = tail;
240     ploc.set(plist);
241       }
242     else
243       prev.cdr = tail;
244     if (symbol instanceof Symbol)
245       env.remove((Symbol) symbol, property);
246     return true;
247   }
248
249   /** Remove a properaty assocatied with an object.
250    * Corresponds to Common Lisp's <code>remprop</code> function.
251    */

252   public static boolean removeProperty (Object JavaDoc symbol, Object JavaDoc property)
253   {
254     return removeProperty(symbol, property, Environment.getCurrent());
255   }
256
257   /**
258    * Given a property list and a key, find the corresponding property value.
259    */

260   public static Object JavaDoc plistGet(Object JavaDoc plist, Object JavaDoc prop, Object JavaDoc dfault)
261   {
262     while (plist instanceof Pair)
263       {
264     Pair pair = (Pair) plist;
265     if (pair.car == prop)
266       return ((Pair) pair.cdr).car;
267       }
268     return dfault;
269   }
270
271   /** Modify and add a property binding to a property list.
272    * @return The updated property list.
273    */

274   public static Object JavaDoc plistPut(Object JavaDoc plist, Object JavaDoc prop, Object JavaDoc value)
275   {
276     for (Object JavaDoc p = plist; p instanceof Pair; )
277       {
278     Pair pair = (Pair) p;
279     Pair next = (Pair) pair.cdr;
280     if (pair.car == prop)
281       {
282         next.car = value;
283         return plist;
284       }
285     p = next.cdr;
286       }
287     return new Pair(prop, new Pair(value, plist));
288   }
289
290   /** Remove a property binding from a property list.
291    * @return The updated property list.
292    */

293   public static Object JavaDoc plistRemove(Object JavaDoc plist, Object JavaDoc prop)
294   {
295     Pair prev = null;
296     for (Object JavaDoc p = plist; p instanceof Pair; )
297       {
298     Pair pair = (Pair) p;
299     Pair next = (Pair) pair.cdr;
300     p = next.cdr;
301     if (pair.car == prop)
302       {
303         if (prev == null)
304           return p;
305         prev.cdr = p;
306         return plist;
307       }
308     prev = next;
309       }
310     return plist;
311   }
312 }
313
Popular Tags