001: /*
002: * Created on Sep 22, 2004
003: */
004: package uk.org.ponder.util;
005:
006: import java.util.ArrayList;
007: import java.util.Collection;
008: import java.util.Collections;
009: import java.util.Enumeration;
010: import java.util.Iterator;
011: import java.util.List;
012: import java.util.Map;
013:
014: import uk.org.ponder.arrayutil.ArrayEnumeration;
015: import uk.org.ponder.beanutil.BeanLocator;
016: import uk.org.ponder.reflect.ReflectUtils;
017: import uk.org.ponder.reflect.ReflectiveCache;
018:
019: /**
020: * Utilities for converting Java multiple-valued types (arrays, collections,
021: * Maps) into readable (Enumeration) and writeable (Denumeration) iterators over
022: * their contents.
023: *
024: * @author Antranig Basman (antranig@caret.cam.ac.uk)
025: *
026: */
027: public class EnumerationConverter {
028: public static boolean isObjectArray(Class c) {
029: if (!c.isArray())
030: return false;
031: return !c.getComponentType().isPrimitive();
032: }
033:
034: public static boolean isEnumerable(Class c) {
035: return Enumeration.class.isAssignableFrom(c)
036: || Collection.class.isAssignableFrom(c)
037: || Map.class.isAssignableFrom(c)
038: || Iterator.class.isAssignableFrom(c)
039: || isObjectArray(c);
040: }
041:
042: // Maps are not currently denumerable! Pending some scheme for
043: // getting at their keys.
044: public static boolean isDenumerable(Class c) {
045: return /* c != Collection.class && */Collection.class
046: .isAssignableFrom(c)
047: && !isMappable(c) || c.isArray();
048: }
049:
050: public static boolean isMappable(Class c) {
051: return Map.class.isAssignableFrom(c)
052: || BeanLocator.class.isAssignableFrom(c);
053: }
054:
055: public static Map getMap(Object o) {
056: if (o instanceof Map) {
057: return (Map) o;
058: }
059: throw new AssertionException(
060: "getMap called for unmappable type " + o.getClass());
061: }
062:
063: public static int getEnumerableSize(Object o) {
064: if (o instanceof Collection) {
065: return ((Collection) o).size();
066: } else if (o.getClass().isArray()) {
067: return ((Object[]) o).length;
068: }
069: return 1;
070: }
071:
072: /**
073: * Return an enumeration of the contents of the argument o, which may itself
074: * be already either an Enumeration or Iterator, Collection or Array type. If
075: * a Map, return an enumeration of its values, and in the default case, return
076: * an enumeration consisting of just the single argument.
077: */
078: public static Enumeration getEnumeration(final Object o) {
079: if (o instanceof Enumeration) {
080: return (Enumeration) o;
081: } else if (o instanceof Iterator) {
082: return new Enumeration() {
083: public boolean hasMoreElements() {
084: return ((Iterator) o).hasNext();
085: }
086:
087: public Object nextElement() {
088: return ((Iterator) o).next();
089: }
090: };
091: } else if (o instanceof Collection) {
092: return Collections.enumeration((Collection) o);
093: } else if (o instanceof Map) {
094: return Collections.enumeration(((Map) o).values());
095: } else if (o.getClass().isArray()) {
096: return new ArrayEnumeration((Object[]) o);
097: } else
098: return new SingleEnumeration(o);
099: }
100:
101: public static Denumeration getDenumeration(final Object collo,
102: final ReflectiveCache cache) {
103: if (collo instanceof Collection) {
104: return new Denumeration() {
105: public void add(Object o) {
106: ((Collection) collo).add(o);
107: }
108:
109: public boolean remove(Object o) {
110: return ((Collection) collo).remove(o);
111: }
112: };
113: }
114:
115: else if (collo.getClass().isArray()) {
116: final Object[] coll = (Object[]) collo;
117: if (coll.length == 0) {
118: final List buildup = new ArrayList();
119: return new CompletableDenumeration() {
120: public Object complete() {
121: return buildup.toArray((Object[]) ReflectUtils
122: .instantiateContainer(coll.getClass(),
123: buildup.size(), cache));
124: }
125:
126: public void add(Object o) {
127: buildup.add(o);
128: }
129:
130: public boolean remove(Object o) {
131: return buildup.remove(o);
132: }
133:
134: };
135: } else {
136: // TODO: use CompletableDenumeration here to allow "extensible" arrays.
137: return new Denumeration() {
138: int index = 0;
139:
140: public void add(Object o) {
141: coll[index++] = o;
142: }
143:
144: public boolean remove(Object o) {
145: throw new UniversalRuntimeException(
146: "Removal not supported from Array denumerable");
147: }
148:
149: };
150: }
151: }
152: return null;
153: }
154:
155: }
|