Source code: com/tripi/asp/AspCollection.java
1 /**
2 * ArrowHead ASP Server
3 * This is a source file for the ArrowHead ASP Server - an 100% Java
4 * VBScript interpreter and ASP server.
5 *
6 * For more information, see http://www.tripi.com/arrowhead
7 *
8 * Copyright (C) 2002 Terence Haddock
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25 package com.tripi.asp;
26
27 import org.apache.log4j.Category;
28
29 import java.io.IOException;
30 import java.io.Serializable;
31 import java.util.Enumeration;
32 import java.util.Hashtable;
33 import java.util.Vector;
34
35 /**
36 * This class implements the ASP version of 'Collections', which is a special
37 * version of a HashTable. It implements common ASP collection routines,
38 * like case insensitive keys and access by key or index.
39 *
40 * @author Terence Haddock
41 */
42 public class AspCollection implements SimpleMap, Serializable
43 {
44 /** Debugging context */
45 static final Category DBG = Category.getInstance(AspCollection.class);
46
47 /**
48 * The items of this collection.
49 */
50 public ItemClass Item = new ItemClass(this);
51
52 /** This boolean value is set to TRUE to make the contents
53 of this collection read-only */
54 boolean readonly = false;
55
56 /** The map vector maps from integer index to key value */
57 Vector map = null;
58
59 /** The contents hashtable maps from key to value */
60 Hashtable contents = null;
61
62 /**
63 * The put method adds an item to this collection
64 * @param key Key under which to store this item
65 * @param obj Object to store
66 * @throws AspException if an error occurs
67 */
68 public synchronized void put(Object key, Object obj) throws AspException
69 {
70 if (readonly) throw new AspReadOnlyException("Item");
71 if (map == null) initialize();
72 key = Types.dereference(key);
73 if (key instanceof Integer)
74 {
75 int iVal = ((Integer)key).intValue() - 1;
76 while (map.size() <= iVal)
77 {
78 map.add(null);
79 }
80 Object realKey = map.get(iVal);
81 if (realKey == null) {
82 realKey = key;
83 map.set(iVal, realKey);
84 } else {
85 if (realKey instanceof String)
86 realKey = ((String)realKey).toLowerCase();
87 }
88 contents.put(realKey, obj);
89 return;
90 }
91 String strKey = Types.coerceToString(key);
92 if (contents.containsKey(strKey.toLowerCase())) {
93 contents.put(strKey.toLowerCase(), obj);
94 return;
95 }
96 map.add(key);
97 contents.put(strKey.toLowerCase(), obj);
98 }
99
100 /**
101 * The get method obtains the value at the specified index or with
102 * the specified key.
103 * @param key Key/Index to obtain
104 * @return the value at the specified index or key
105 * @throws AspException if an error occurs
106 */
107 public synchronized Object get(Object key) throws AspException
108 {
109 if (map == null) initialize();
110 key = Types.dereference(key);
111 Object value;
112 if (key instanceof Integer)
113 {
114 int iVal = ((Integer)key).intValue() - 1;
115
116 Object realKey = map.get(iVal);
117 if (realKey instanceof String)
118 realKey = ((String)realKey).toLowerCase();
119 value=contents.get(realKey);
120 } else {
121 String strKey = Types.coerceToString(key).toLowerCase();
122
123 value=contents.get(strKey);
124 }
125 if (value == null) return Constants.undefinedValueNode;
126 return value;
127 }
128
129 /**
130 * Removes the element from this collection.
131 * @param key Key to remove
132 * @throws AspException on error
133 */
134 public synchronized void remove(Object key) throws AspException
135 {
136 if (readonly) throw new AspReadOnlyException("Item");
137 if (map == null) initialize();
138 key = Types.dereference(key);
139 if (key instanceof Integer)
140 {
141 int iVal = ((Integer)key).intValue() - 1;
142
143 Object realKey = map.get(iVal);
144 if (realKey instanceof String)
145 realKey = ((String)realKey).toLowerCase();
146
147 map.remove(iVal);
148 contents.remove(realKey);
149 } else {
150 String strValue = Types.coerceToString(key);
151
152 map.remove(strValue);
153 contents.remove(strValue.toLowerCase());
154 }
155 }
156
157 /**
158 * Detects if the key is present in this collection.
159 * @param key Key to test
160 * @return <b>true</b> if key is present, <b>false</b> otherwise.
161 * @throws AspException on error
162 */
163 public synchronized boolean containsKey(Object key) throws AspException
164 {
165 if (map == null) initialize();
166 key = Types.dereference(key);
167 if (key instanceof Integer)
168 {
169 int iVal = ((Integer)key).intValue() - 1;
170 if (iVal < map.size()) return true;
171 return false;
172 } else {
173 String value = Types.coerceToString(key).toLowerCase();
174 return contents.containsKey(value);
175 }
176 }
177
178 /**
179 * Obtains an enumeration of the keys in this collection.
180 * @return enumeration of keys in this collection
181 * @throws AspException on error
182 */
183 public synchronized Enumeration keys() throws AspException
184 {
185 if (map == null) initialize();
186 return map.elements();
187 }
188
189 /**
190 * Obtains the elements in this AspCollection.
191 * @return enumeration of elements in this collection
192 * @throws AspException on error
193 */
194 public synchronized Enumeration elements() throws AspException
195 {
196 if (map == null) initialize();
197 return contents.elements();
198 }
199
200 /**
201 * Obtains the size of this collection.
202 * @return size of this collection
203 * @throws AspException on error
204 */
205 public synchronized int size() throws AspException
206 {
207 if (map == null) initialize();
208 return map.size();
209 }
210
211 /**
212 * This ASP-accessible function obtains the number of elements
213 * stored in this collection.
214 * @return number of elements in this collection.
215 * @throws AspException on error
216 */
217 public synchronized int Count() throws AspException
218 {
219 if (map == null) initialize();
220 return map.size();
221 }
222
223 /**
224 * Removes all of the elements from this collection.
225 * @throws AspException on error
226 */
227 public synchronized void removeAll() throws AspException
228 {
229 if (readonly) throw new AspReadOnlyException("Item");
230 if (map == null) initialize();
231 contents = new Hashtable();
232 map = new Vector();
233 }
234
235 /**
236 * Obtains the list of keys stored in this object. Used for
237 * foreach statements.
238 * @return list of keys stores in this application object.
239 * @throws AspException if an error occurs
240 * @see SimpleMap#getKeys()
241 */
242 public synchronized java.util.Enumeration getKeys()
243 throws AspException
244 {
245 if (map == null) initialize();
246 return map.elements();
247 }
248
249 /**
250 * Use this method to set this collection read-only, cannot
251 * be undone.
252 */
253 public void setReadOnly()
254 {
255 readonly = true;
256 }
257
258 /**
259 * Write this object to the output.
260 * First outputs the number of elements in this object, then outputs
261 * each object first key then value. If a value is not Serializable,
262 * the Constants.undefinedValueNode object is outputted.
263 * @param out OutputStream to write object to.
264 * @throws IOException on input/output error
265 */
266 private void writeObject(java.io.ObjectOutputStream out)
267 throws IOException
268 {
269 int size;
270 if (map == null) size = 0;
271 else size = map.size();
272 out.writeInt(size);
273 for (int x = 0; x < size; x++)
274 {
275 Object key = map.get(x);
276 if (DBG.isDebugEnabled())
277 DBG.debug("Key " + x + " = " + key);
278 if (key instanceof String)
279 key = ((String)key).toLowerCase();
280 Object value = contents.get(key);
281 out.writeObject(key);
282 if (value instanceof Serializable) {
283 if (DBG.isDebugEnabled())
284 DBG.debug("Obj(S) " + x + " = " + value);
285 out.writeObject(value);
286 } else {
287 if (DBG.isDebugEnabled())
288 DBG.debug("Obj " + x + " = " + value);
289 out.writeObject(Constants.undefinedValueNode);
290 }
291 }
292 }
293
294 /**
295 * Reads an AspCollection back in from an ObjectInputStream.
296 * @param in InputStream to read object from
297 * @throws IOException on input/output error
298 * @throws ClassNotFoundException when a class cannot be found
299 */
300 private void readObject(java.io.ObjectInputStream in)
301 throws IOException, ClassNotFoundException
302 {
303 try {
304 removeAll();
305 } catch (Exception ex) {
306 }
307 int size = in.readInt();
308 for (int x = 0; x < size; x++)
309 {
310 String strKey = (String)in.readObject();
311 if (DBG.isDebugEnabled())
312 DBG.debug("Key " + x + " = " + strKey);
313 Object objValue = in.readObject();
314 if (DBG.isDebugEnabled())
315 DBG.debug("Obj " + x + " = " + objValue);
316 try {
317 put(strKey, objValue);
318 } catch (Exception ex)
319 {
320 }
321 }
322 }
323
324 /**
325 * This protected function initializes this object.
326 * @throws AspException on error
327 */
328 protected void initialize() throws AspException
329 {
330 map = new Vector();
331 contents = new Hashtable();
332 }
333
334 /**
335 * This class contains an interface back to the contents class
336 */
337 public class ItemClass implements SimpleMap
338 {
339 /** The AspCollection class this class is part of */
340 AspCollection collection;
341
342 /**
343 * Constructor of this sub-class.
344 * @param collection class this item class is contained in
345 */
346 public ItemClass(AspCollection collection)
347 {
348 this.collection = collection;
349 }
350
351 /**
352 * Obtains the value of data contained within the application
353 * object.
354 * @param obj Value to obtain.
355 * @return value of key obtained
356 * @throws AspException if an error occurs, most likely
357 * could not coerce value to string.
358 * @see SimpleMap#get(Object)
359 */
360 public Object get(Object obj)
361 throws AspException
362 {
363 return collection.get(obj);
364 }
365
366 /**
367 * Stores an objects into the application object.
368 * @param key Key to store.
369 * @param value Value to store.
370 * @throws AspException if an error occurs, most likely
371 * could not coerce value to string.
372 * @see SimpleMap#put(Object,Object)
373 */
374 public void put(Object key, Object value)
375 throws AspException
376 {
377 collection.put(key, value);
378 }
379
380 /**
381 * Obtains the list of keys stored in this object. Used for
382 * foreach statements.
383 * @return list of keys stores in this application object.
384 * @throws AspException if an error occurs
385 * @see SimpleMap#getKeys()
386 */
387 public java.util.Enumeration getKeys()
388 throws AspException
389 {
390 return collection.getKeys();
391 }
392
393 /**
394 * This ASP-accessible function removes all of the elements
395 * in the application object.
396 * @throws AspException on error
397 */
398 public void RemoveAll() throws AspException
399 {
400 collection.removeAll();
401 }
402
403 /**
404 * This ASP-accessible function removes the specified element
405 * from this application object.
406 * @param key Key to remove
407 * @throws AspException on error
408 */
409 public void Remove(Object key) throws AspException
410 {
411 collection.remove(key);
412 }
413
414 /**
415 * This ASP-accessible function obtains the number of elements
416 * stored in this application object.
417 * @return number of elements in this array
418 * @throws AspException on error
419 */
420 public int Count() throws AspException
421 {
422 return collection.size();
423 }
424
425 /**
426 * This method returns <b>true</b> if the specified key exists in
427 * this collection, <b>false</b> otherwise.
428 * @param key Key to test
429 * @return true or false
430 * @throws AspException on error
431 */
432 public boolean containsKey(Object key) throws AspException
433 {
434 return collection.containsKey(key);
435 }
436
437 /**
438 * Obtains an enumeration of the keys in this collection.
439 * @return enumeration of keys in this collection
440 * @throws AspException on error
441 */
442 public synchronized Enumeration keys() throws AspException
443 {
444 return collection.keys();
445 }
446
447 /**
448 * Obtains the elements in this AspCollection.
449 * @return enumeration of elements in this collection
450 * @throws AspException on error
451 */
452 public synchronized Enumeration elements() throws AspException
453 {
454 return collection.elements();
455 }
456
457 /**
458 * Obtains the size of this collection.
459 * @return size of this collection
460 * @throws AspException on error
461 */
462 public synchronized int size() throws AspException
463 {
464 return collection.size();
465 }
466 }
467 }