001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.util.iterator;
020:
021: import java.util.Collection;
022: import java.util.Enumeration;
023: import java.util.Iterator;
024: import java.util.LinkedHashMap;
025: import java.util.Map;
026: import java.util.Collections;
027: import java.sql.ResultSet;
028: import javax.sql.RowSet;
029:
030: import org.apache.beehive.netui.util.config.ConfigUtil;
031: import org.apache.beehive.netui.util.config.bean.NetUIConfig;
032: import org.apache.beehive.netui.util.config.bean.IteratorFactoryConfig;
033: import org.apache.beehive.netui.util.logging.Logger;
034:
035: /**
036: * <p>
037: * This class provides a factory that can create an {@link Iterator} for various types
038: * of Java objects. Supported types include:
039: * <ul>
040: * <li>{@link java.util.Iterator}</li>
041: * <li>{@link java.util.Collection}</li>
042: * <li>{@link java.util.Map}</li>
043: * <li>{@link java.sql.ResultSet}</li>
044: * <li>{@link javax.sql.RowSet}</li>
045: * <li>{@link java.util.Enumeration}</li>
046: * <li>Any Java Object array</li>
047: * </ul>
048: * <p/>
049: * <p>
050: * If an object type not listed above is supplied the object will be wrapped in
051: * an iterator that contains only the provided object.
052: * </p>
053: */
054: public class IteratorFactory {
055:
056: /**
057: * Convenience field for accessing an empty {@link Iterator}.
058: */
059: public static final Iterator EMPTY_ITERATOR = Collections.EMPTY_LIST
060: .iterator();
061:
062: private static final Logger LOGGER = Logger
063: .getInstance(IteratorFactory.class);
064: private static final LinkedHashMap ITERATOR_FACTORIES;
065:
066: static {
067: ITERATOR_FACTORIES = new LinkedHashMap();
068: initialize();
069: }
070:
071: /**
072: * @exclude
073: */
074: public abstract static class IteratorPlant {
075: /**
076: * If it is possible to create an iterator for this type, do so.
077: * Otherwise return null.
078: */
079: public abstract Iterator createIterator(Object value);
080: }
081:
082: /**
083: * Create a new {@link Iterator} for the supplied object.
084: *
085: * @param object the object to build an iterator from
086: * @return an {@link Iterator} for the <code>object</code> or <code>null</code> if the value is null.
087: */
088: public static final Iterator createIterator(Object object) {
089: LOGGER.debug("Create an iterator for class: "
090: + (object == null ? "null" : object.getClass()
091: .getName()));
092:
093: if (object == null)
094: return null;
095:
096: if (object instanceof Iterator) {
097: return (Iterator) object;
098: } else if (object instanceof Collection) {
099: Collection collection = (Collection) object;
100: return collection.iterator();
101: } else if (object instanceof Map) {
102: return new MapIterator((Map) object);
103: } else if (object.getClass().isArray()) {
104: return new ArrayIterator(object);
105: } else if (object instanceof Enumeration)
106: return new EnumerationIterator((Enumeration) object);
107: else if (object instanceof ResultSet
108: && !(object instanceof RowSet))
109: return new ResultSetIterator((ResultSet) object);
110:
111: // check to see if there is a registered IteratorPlant that can handle this type
112: Iterator ret = null;
113: Iterator factories = ITERATOR_FACTORIES.keySet().iterator();
114: while (factories.hasNext()) {
115: IteratorPlant plant = (IteratorPlant) ITERATOR_FACTORIES
116: .get(factories.next());
117: ret = plant.createIterator(object);
118:
119: if (ret != null)
120: return ret;
121: }
122:
123: return new AtomicObjectIterator(object);
124: }
125:
126: /**
127: * Initialize the configuration parameters used to build Iterator objects
128: * for custom types.
129: */
130: private static final void initialize() {
131: Map map = readFromConfig();
132: if (map != null)
133: loadFactories(map);
134: }
135:
136: private static final Map readFromConfig() {
137: NetUIConfig config = ConfigUtil.getConfig();
138: if (config == null)
139: return null;
140:
141: IteratorFactoryConfig[] iteratorFactories = config
142: .getIteratorFactories();
143:
144: if (iteratorFactories != null) {
145: LinkedHashMap map = new LinkedHashMap();
146: for (int i = 0; i < iteratorFactories.length; i++) {
147: map.put(iteratorFactories[i].getName(),
148: iteratorFactories[i].getFactoryClass());
149: }
150: return map;
151: } else
152: return null;
153: }
154:
155: private static final void loadFactories(Map factories) {
156: Iterator iterator = factories.keySet().iterator();
157: while (iterator.hasNext()) {
158: String name = (String) iterator.next();
159: String className = (String) factories.get(name);
160: IteratorPlant plant = null;
161:
162: try {
163: Class type = Class.forName(className);
164: plant = (IteratorPlant) type.newInstance();
165: } catch (ClassNotFoundException cnf) {
166: LOGGER
167: .warn("Could not create an IteratorPlant for type \""
168: + className
169: + "\" because the implementation class could not be found.");
170: continue;
171: } catch (Exception e) {
172: assert e instanceof InstantiationException
173: || e instanceof IllegalAccessException;
174: LOGGER
175: .warn(
176: "Could not create an IteratorPlant for type \""
177: + className
178: + "\" because an error occurred creating the plant. Cause: "
179: + e, e);
180: continue;
181: }
182:
183: if (ITERATOR_FACTORIES.containsKey(name)) {
184: LOGGER
185: .warn("Overwriting a previously defined IteratorPlant named \""
186: + name
187: + "\" with a new IteratorPlant of type \""
188: + className + "\"");
189: } else
190: LOGGER.info("Adding an IteratorPlant named \"" + name
191: + "\" with implementation \"" + className
192: + "\"");
193:
194: ITERATOR_FACTORIES.put(name, plant);
195: }
196: }
197: }
|