/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
package org.apache.beehive.netui.util.iterator;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Collections;
import java.sql.ResultSet;
import javax.sql.RowSet;
import org.apache.beehive.netui.util.config.ConfigUtil;
import org.apache.beehive.netui.util.config.bean.NetUIConfig;
import org.apache.beehive.netui.util.config.bean.IteratorFactoryConfig;
import org.apache.beehive.netui.util.logging.Logger;
/**
* <p>
* This class provides a factory that can create an {@link Iterator} for various types
* of Java objects. Supported types include:
* <ul>
* <li>{@link java.util.Iterator}</li>
* <li>{@link java.util.Collection}</li>
* <li>{@link java.util.Map}</li>
* <li>{@link java.sql.ResultSet}</li>
* <li>{@link javax.sql.RowSet}</li>
* <li>{@link java.util.Enumeration}</li>
* <li>Any Java Object array</li>
* </ul>
* <p/>
* <p>
* If an object type not listed above is supplied the object will be wrapped in
* an iterator that contains only the provided object.
* </p>
*/
public class IteratorFactory {
/**
* Convenience field for accessing an empty {@link Iterator}.
*/
public static final Iterator EMPTY_ITERATOR = Collections.EMPTY_LIST.iterator();
private static final Logger LOGGER = Logger.getInstance(IteratorFactory.class);
private static final LinkedHashMap ITERATOR_FACTORIES;
static {
ITERATOR_FACTORIES = new LinkedHashMap();
initialize();
}
/**
* @exclude
*/
public abstract static class IteratorPlant {
/**
* If it is possible to create an iterator for this type, do so.
* Otherwise return null.
*/
public abstract Iterator createIterator(Object value);
}
/**
* Create a new {@link Iterator} for the supplied object.
*
* @param object the object to build an iterator from
* @return an {@link Iterator} for the <code>object</code> or <code>null</code> if the value is null.
*/
public static final Iterator createIterator(Object object) {
LOGGER.debug("Create an iterator for class: " + (object == null ? "null" : object.getClass().getName()));
if(object == null)
return null;
if(object instanceof Iterator) {
return (Iterator)object;
} else if(object instanceof Collection) {
Collection collection = (Collection)object;
return collection.iterator();
} else if(object instanceof Map) {
return new MapIterator((Map)object);
} else if(object.getClass().isArray()) {
return new ArrayIterator(object);
} else if(object instanceof Enumeration)
return new EnumerationIterator((Enumeration)object);
else if(object instanceof ResultSet && !(object instanceof RowSet))
return new ResultSetIterator((ResultSet)object);
// check to see if there is a registered IteratorPlant that can handle this type
Iterator ret = null;
Iterator factories = ITERATOR_FACTORIES.keySet().iterator();
while(factories.hasNext()) {
IteratorPlant plant = (IteratorPlant)ITERATOR_FACTORIES.get(factories.next());
ret = plant.createIterator(object);
if(ret != null) return ret;
}
return new AtomicObjectIterator(object);
}
/**
* Initialize the configuration parameters used to build Iterator objects
* for custom types.
*/
private static final void initialize() {
Map map = readFromConfig();
if(map != null)
loadFactories(map);
}
private static final Map readFromConfig() {
NetUIConfig config = ConfigUtil.getConfig();
if(config == null)
return null;
IteratorFactoryConfig[] iteratorFactories = config.getIteratorFactories();
if(iteratorFactories != null) {
LinkedHashMap map = new LinkedHashMap();
for(int i = 0; i < iteratorFactories.length; i++) {
map.put(iteratorFactories[i].getName(), iteratorFactories[i].getFactoryClass());
}
return map;
}
else return null;
}
private static final void loadFactories(Map factories) {
Iterator iterator = factories.keySet().iterator();
while(iterator.hasNext()) {
String name = (String)iterator.next();
String className = (String)factories.get(name);
IteratorPlant plant = null;
try {
Class type = Class.forName(className);
plant = (IteratorPlant)type.newInstance();
} catch(ClassNotFoundException cnf) {
LOGGER.warn("Could not create an IteratorPlant for type \"" + className + "\" because the implementation class could not be found.");
continue;
} catch(Exception e) {
assert e instanceof InstantiationException || e instanceof IllegalAccessException;
LOGGER.warn("Could not create an IteratorPlant for type \"" + className + "\" because an error occurred creating the plant. Cause: " + e, e);
continue;
}
if(ITERATOR_FACTORIES.containsKey(name)) {
LOGGER.warn("Overwriting a previously defined IteratorPlant named \"" + name + "\" with a new IteratorPlant of type \"" + className + "\"");
} else LOGGER.info("Adding an IteratorPlant named \"" + name + "\" with implementation \"" + className + "\"");
ITERATOR_FACTORIES.put(name, plant);
}
}
}