001: /*****************************************************************************
002: * *
003: * This file is part of the BeanShell Java Scripting distribution. *
004: * Documentation and updates may be found at http://www.beanshell.org/ *
005: * *
006: * Sun Public License Notice: *
007: * *
008: * The contents of this file are subject to the Sun Public License Version *
009: * 1.0 (the "License"); you may not use this file except in compliance with *
010: * the License. A copy of the License is available at http://www.sun.com *
011: * *
012: * The Original Code is BeanShell. The Initial Developer of the Original *
013: * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
014: * (C) 2000. All Rights Reserved. *
015: * *
016: * GNU Public License Notice: *
017: * *
018: * Alternatively, the contents of this file may be used under the terms of *
019: * the GNU Lesser General Public License (the "LGPL"), in which case the *
020: * provisions of LGPL are applicable instead of those above. If you wish to *
021: * allow use of your version of this file only under the terms of the LGPL *
022: * and not to allow others to use your version of this file under the SPL, *
023: * indicate your decision by deleting the provisions above and replace *
024: * them with the notice and other provisions required by the LGPL. If you *
025: * do not delete the provisions above, a recipient may use your version of *
026: * this file under either the SPL or the LGPL. *
027: * *
028: * Patrick Niemeyer (pat@pat.net) *
029: * Author of Learning Java, O'Reilly & Associates *
030: * http://www.pat.net/~pat/ *
031: * *
032: *****************************************************************************/package bsh;
033:
034: import java.util.Enumeration;
035: import java.util.Vector;
036: import java.util.Hashtable;
037: import java.lang.reflect.Array;
038:
039: /**
040: The default CollectionManager (which remains Java 1.1 compatible)
041: supports iteration over objects of type:
042: Enumeration, Vector, String, StringBuffer and array.
043: The dynamically loaded CollectionManagerImpl supports additional types when
044: it is present.
045:
046: @see BshIterable.java
047: */
048: public class CollectionManager {
049: private static CollectionManager manager;
050:
051: public synchronized static CollectionManager getCollectionManager() {
052: if (manager == null
053: && Capabilities.classExists("java.util.Collection")) {
054: Class clas;
055: try {
056: clas = Class
057: .forName("bsh.collection.CollectionManagerImpl");
058: manager = (CollectionManager) clas.newInstance();
059: } catch (Exception e) {
060: Interpreter
061: .debug("unable to load CollectionManagerImpl: "
062: + e);
063: }
064: }
065:
066: if (manager == null)
067: manager = new CollectionManager(); // default impl
068:
069: return manager;
070: }
071:
072: /**
073: */
074: public boolean isBshIterable(Object obj) {
075: // This could be smarter...
076: try {
077: getBshIterator(obj);
078: return true;
079: } catch (IllegalArgumentException e) {
080: return false;
081: }
082: }
083:
084: public BshIterator getBshIterator(Object obj)
085: throws IllegalArgumentException {
086: return new BasicBshIterator(obj);
087: }
088:
089: public boolean isMap(Object obj) {
090: return obj instanceof Hashtable;
091: }
092:
093: public Object getFromMap(Object map, Object key) {
094: return ((Hashtable) map).get(key);
095: }
096:
097: public Object putInMap(Object map, Object key, Object value) {
098: return ((Hashtable) map).put(key, value);
099: }
100:
101: /**
102: Determine dynamically if the target is an iterator by the presence of a
103: pair of next() and hasNext() methods.
104: public static boolean isIterator() { }
105: */
106:
107: /**
108: * An implementation that works with JDK 1.1
109: */
110: public static class BasicBshIterator implements BshIterator {
111: Enumeration enumeration;
112:
113: /**
114: * Construct a basic BasicBshIterator
115: *
116: * @param The object over which we are iterating
117: *
118: * @throws java.lang.IllegalArgumentException If the argument is not a
119: * supported (i.e. iterable) type.
120: *
121: * @throws java.lang.NullPointerException If the argument is null
122: */
123: public BasicBshIterator(Object iterateOverMe) {
124: enumeration = createEnumeration(iterateOverMe);
125: }
126:
127: /**
128: * Create an enumeration over the given object
129: *
130: * @param iterateOverMe Object of type Enumeration, Vector, String,
131: * StringBuffer or an array
132: *
133: * @return an enumeration
134: *
135: * @throws java.lang.IllegalArgumentException If the argument is not a
136: * supported (i.e. iterable) type.
137: *
138: * @throws java.lang.NullPointerException If the argument is null
139: */
140: protected Enumeration createEnumeration(Object iterateOverMe) {
141: if (iterateOverMe == null)
142: throw new NullPointerException(
143: "Object arguments passed to "
144: + "the BasicBshIterator constructor cannot be null.");
145:
146: if (iterateOverMe instanceof Enumeration)
147: return (Enumeration) iterateOverMe;
148:
149: if (iterateOverMe instanceof Vector)
150: return ((Vector) iterateOverMe).elements();
151:
152: if (iterateOverMe.getClass().isArray()) {
153: final Object array = iterateOverMe;
154: return new Enumeration() {
155: int index = 0, length = Array.getLength(array);
156:
157: public Object nextElement() {
158: return Array.get(array, index++);
159: }
160:
161: public boolean hasMoreElements() {
162: return index < length;
163: }
164: };
165: }
166:
167: if (iterateOverMe instanceof String)
168: return createEnumeration(((String) iterateOverMe)
169: .toCharArray());
170:
171: if (iterateOverMe instanceof StringBuffer)
172: return createEnumeration(iterateOverMe.toString()
173: .toCharArray());
174:
175: throw new IllegalArgumentException(
176: "Cannot enumerate object of type "
177: + iterateOverMe.getClass());
178: }
179:
180: /**
181: * Fetch the next object in the iteration
182: *
183: * @return The next object
184: */
185: public Object next() {
186: return enumeration.nextElement();
187: }
188:
189: /**
190: * Returns true if and only if there are more objects available
191: * via the <code>next()</code> method
192: *
193: * @return The next object
194: */
195: public boolean hasNext() {
196: return enumeration.hasMoreElements();
197: }
198: }
199: }
|