summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
commit40a9d99496e098562f090fb7ffce9e749011b131 (patch)
tree437df24d65470582e943e494a52db8ed65a881ae /projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal
parentff072dfe782f6f22123cd4ba050828d35c0d0fbd (diff)
Formatting pass
Diffstat (limited to 'projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal')
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Duplicator.java439
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Introspector.java1544
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/IntrospectorException.java17
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/MissingPropertyException.java17
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NetworkClassLoader.java574
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NullPrimitiveException.java17
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyComparator.java91
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyListParser.java926
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/QueueMap.java996
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/URLResourceReader.java267
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/ValueConverter.java1215
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/WotonomyException.java135
12 files changed, 2887 insertions, 3351 deletions
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Duplicator.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Duplicator.java
index ddf347d..16ef393 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Duplicator.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Duplicator.java
@@ -26,274 +26,219 @@ import java.io.*;
import java.util.*; //collections
/**
-* Duplicator makes use of Introspector to duplicate objects,
-* either by shallow copy, deep copy, or by copying properties
-* from one object to apply to another object. You may find this
-* class useful because java.lang.Object.clone() only supports
-* shallow copying.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 895 $
-*/
+ * Duplicator makes use of Introspector to duplicate objects, either by shallow
+ * copy, deep copy, or by copying properties from one object to apply to another
+ * object. You may find this class useful because java.lang.Object.clone() only
+ * supports shallow copying.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 895 $
+ */
+
+public class Duplicator {
+ /**
+ * Used to represent null values for properties in the maps returned by
+ * readProperties and cloneProperties and in the parameter to writeProperties.
+ * This actually references the NSNull instance.
+ */
+ public static final Object NULL = NSNull.nullValue();
+ private static NSSelector clone = new NSSelector("clone");
+
+ /**
+ * Returns a list of properties for the specified class that are both readable
+ * and writable.
+ */
+ static public List editablePropertiesForObject(Object anObject) {
+ List readProperties = new ArrayList();
+ String[] read = Introspector.getReadPropertiesForObject(anObject);
+ for (int i = 0; i < read.length; i++) {
+ readProperties.add(read[i]);
+ }
+
+ List properties = new ArrayList();
+ String[] write = Introspector.getWritePropertiesForObject(anObject);
+ for (int i = 0; i < write.length; i++) {
+ properties.add(write[i]);
+ }
+
+ // only use properties on both lists: read/write
+ properties.retainAll(readProperties);
+
+ return properties;
+ }
-public class Duplicator
-{
- /**
- * Used to represent null values for properties in the
- * maps returned by readProperties and cloneProperties
- * and in the parameter to writeProperties.
- * This actually references the NSNull instance.
- */
- public static final Object NULL = NSNull.nullValue();
- private static NSSelector clone = new NSSelector( "clone" );
+ /**
+ * Returns a Map containing only the mutable properties for the specified object
+ * and their values. Any null values for properties will be represented with the
+ * NULL object.
+ */
+ static public Map readPropertiesForObject(Object anObject) {
+ NSMutableDictionary result = new NSMutableDictionary();
- /**
- * Returns a list of properties for the specified class
- * that are both readable and writable.
- */
- static public List editablePropertiesForObject(
- Object anObject )
- {
- List readProperties = new ArrayList();
- String[] read = Introspector.getReadPropertiesForObject( anObject );
- for ( int i = 0; i < read.length; i++ )
- {
- readProperties.add( read[i] );
- }
+ String key;
+ Object value;
+ Iterator it = editablePropertiesForObject(anObject).iterator();
+ while (it.hasNext()) {
+ key = it.next().toString();
+ value = Introspector.get(anObject, key);
+ if (value == null)
+ value = NULL;
+ result.setObjectForKey(value, key);
+ }
+ return result;
+ }
- List properties = new ArrayList();
- String[] write = Introspector.getWritePropertiesForObject( anObject );
- for ( int i = 0; i < write.length; i++ )
- {
- properties.add( write[i] );
- }
-
- // only use properties on both lists: read/write
- properties.retainAll( readProperties );
+ /**
+ * Returns a Map containing only the mutable properties for the specified object
+ * and deep clones of their values. Nulls are represented by the NULL object.
+ */
+ static public Map clonePropertiesForObject(Object anObject) {
+ Object key, value;
+ Map result = readPropertiesForObject(anObject);
+ Iterator it = result.keySet().iterator();
+ while (it.hasNext()) {
+ key = it.next();
+ value = result.get(key);
+ value = deepClone(value);
+ result.put(key, value);
+ }
+ return result;
+ }
- return properties;
- }
-
- /**
- * Returns a Map containing only the mutable properties
- * for the specified object and their values.
- * Any null values for properties will be represented with
- * the NULL object.
- */
- static public Map readPropertiesForObject(
- Object anObject )
- {
- NSMutableDictionary result = new NSMutableDictionary();
-
- String key;
- Object value;
- Iterator it = editablePropertiesForObject( anObject ).iterator();
- while ( it.hasNext() )
- {
- key = it.next().toString();
- value = Introspector.get( anObject, key );
- if ( value == null ) value = NULL;
- result.setObjectForKey( value, key );
- }
- return result;
- }
-
- /**
- * Returns a Map containing only the mutable properties
- * for the specified object and deep clones of their values.
- * Nulls are represented by the NULL object.
- */
- static public Map clonePropertiesForObject(
- Object anObject )
- {
- Object key, value;
- Map result = readPropertiesForObject( anObject );
- Iterator it = result.keySet().iterator();
- while ( it.hasNext() )
- {
- key = it.next();
- value = result.get( key );
- value = deepClone( value );
- result.put( key, value );
- }
- return result;
- }
-
- /**
- * Applies the map of properties and values to the
- * specified object. Null values for properties must
- * be represented by the NULL object.
- */
- static public void writePropertiesForObject(
- Map aMap, Object anObject )
- {
- String key;
- Object value;
- Iterator it = aMap.keySet().iterator();
- while ( it.hasNext() )
- {
- key = it.next().toString();
- value = aMap.get( key );
- if ( NULL.equals( value ) ) value = null;
- Introspector.set( anObject, key, value );
- }
- }
-
- /**
- * Creates a new copy of the specified object.
- * This implementation tries to call clone(),
- * and failing that, calls newInstance
- * and then calls copy() to transfer the values.
- * @throws WotonomyException if any operation fails.
- */
- static public Object clone(
- Object aSource )
- {
- Object result = null;
- if ( clone.implementedByObject( aSource ) )
- {
- try
- {
- result = clone.invoke( aSource );
- return result;
- }
- catch ( Exception exc )
- {
- // fall back on newInstance()
- }
- }
-
- Class c = aSource.getClass();
- try
- {
- result = c.newInstance();
- }
- catch ( Exception exc )
- {
- throw new WotonomyException( exc );
- }
- return copy( aSource, result );
- }
+ /**
+ * Applies the map of properties and values to the specified object. Null values
+ * for properties must be represented by the NULL object.
+ */
+ static public void writePropertiesForObject(Map aMap, Object anObject) {
+ String key;
+ Object value;
+ Iterator it = aMap.keySet().iterator();
+ while (it.hasNext()) {
+ key = it.next().toString();
+ value = aMap.get(key);
+ if (NULL.equals(value))
+ value = null;
+ Introspector.set(anObject, key, value);
+ }
+ }
- /**
- * Creates a deep copy of the specified object.
- * Every object in this objects graph will be
- * duplicated with new instances.
- * @throws WotonomyException if any operation fails.
- */
- static public Object deepClone(
- Object aSource )
- {
- // the only known way to deep copy in
- // java without native code is serialization
-
- try
- {
- ByteArrayOutputStream byteOutput =
- new ByteArrayOutputStream();
- ObjectOutputStream objectOutput =
- new ObjectOutputStream( byteOutput );
-
- objectOutput.writeObject( aSource );
- objectOutput.flush();
- objectOutput.close();
-
- ByteArrayInputStream byteInput =
- new ByteArrayInputStream( byteOutput.toByteArray() );
- ObjectInputStream objectInput =
- new ObjectInputStream( byteInput );
- return objectInput.readObject();
- }
- catch ( Exception exc )
- {
- throw new WotonomyException( "Error cloning object: " + aSource, exc );
- }
- }
+ /**
+ * Creates a new copy of the specified object. This implementation tries to call
+ * clone(), and failing that, calls newInstance and then calls copy() to
+ * transfer the values.
+ *
+ * @throws WotonomyException if any operation fails.
+ */
+ static public Object clone(Object aSource) {
+ Object result = null;
+ if (clone.implementedByObject(aSource)) {
+ try {
+ result = clone.invoke(aSource);
+ return result;
+ } catch (Exception exc) {
+ // fall back on newInstance()
+ }
+ }
- /**
- * Copies values from one object to another.
- * Returns the destination object.
- * @throws WotonomyException if any operation fails.
- */
- static public Object copy(
- Object aSource, Object aDestination )
- {
- try
- {
- writePropertiesForObject(
- readPropertiesForObject( aSource ), aDestination );
- }
- catch ( RuntimeException exc )
- {
- throw new WotonomyException( exc );
- }
- return aDestination;
- }
-
- /**
- * Deeply clones the values from one object and applies them
- * to another object.
- * Returns the destination object.
- * @throws WotonomyException if any operation fails.
- */
- static public Object deepCopy(
- Object aSource, Object aDestination )
- {
- try
- {
- writePropertiesForObject(
- clonePropertiesForObject( aSource ), aDestination );
- }
- catch ( RuntimeException exc )
- {
- throw new WotonomyException( exc );
- }
- return aDestination;
- }
+ Class c = aSource.getClass();
+ try {
+ result = c.newInstance();
+ } catch (Exception exc) {
+ throw new WotonomyException(exc);
+ }
+ return copy(aSource, result);
+ }
+
+ /**
+ * Creates a deep copy of the specified object. Every object in this objects
+ * graph will be duplicated with new instances.
+ *
+ * @throws WotonomyException if any operation fails.
+ */
+ static public Object deepClone(Object aSource) {
+ // the only known way to deep copy in
+ // java without native code is serialization
+
+ try {
+ ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
+ ObjectOutputStream objectOutput = new ObjectOutputStream(byteOutput);
+
+ objectOutput.writeObject(aSource);
+ objectOutput.flush();
+ objectOutput.close();
+
+ ByteArrayInputStream byteInput = new ByteArrayInputStream(byteOutput.toByteArray());
+ ObjectInputStream objectInput = new ObjectInputStream(byteInput);
+ return objectInput.readObject();
+ } catch (Exception exc) {
+ throw new WotonomyException("Error cloning object: " + aSource, exc);
+ }
+ }
+
+ /**
+ * Copies values from one object to another. Returns the destination object.
+ *
+ * @throws WotonomyException if any operation fails.
+ */
+ static public Object copy(Object aSource, Object aDestination) {
+ try {
+ writePropertiesForObject(readPropertiesForObject(aSource), aDestination);
+ } catch (RuntimeException exc) {
+ throw new WotonomyException(exc);
+ }
+ return aDestination;
+ }
+
+ /**
+ * Deeply clones the values from one object and applies them to another object.
+ * Returns the destination object.
+ *
+ * @throws WotonomyException if any operation fails.
+ */
+ static public Object deepCopy(Object aSource, Object aDestination) {
+ try {
+ writePropertiesForObject(clonePropertiesForObject(aSource), aDestination);
+ } catch (RuntimeException exc) {
+ throw new WotonomyException(exc);
+ }
+ return aDestination;
+ }
}
/*
- * $Log$
- * Revision 1.1 2006/02/16 16:52:12 cgruber
- * Add cvsignore crap to find off checking in binary crap.
+ * $Log$ Revision 1.1 2006/02/16 16:52:12 cgruber Add cvsignore crap to find off
+ * checking in binary crap.
*
- * Revision 1.1 2006/02/16 13:22:22 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.11 2001/08/22 19:24:26 mpowers
- * Providing a more helpful error message for cloning exceptions.
+ * Revision 1.11 2001/08/22 19:24:26 mpowers Providing a more helpful error
+ * message for cloning exceptions.
*
- * Revision 1.10 2001/03/29 03:30:36 mpowers
- * Refactored duplicator a bit.
+ * Revision 1.10 2001/03/29 03:30:36 mpowers Refactored duplicator a bit.
* Disabled MissingPropertyExceptions for now.
*
- * Revision 1.9 2001/03/28 14:11:23 mpowers
- * Removed debugging printlns.
+ * Revision 1.9 2001/03/28 14:11:23 mpowers Removed debugging printlns.
*
- * Revision 1.8 2001/03/27 23:25:48 mpowers
- * Basically reverting to the previous version.
+ * Revision 1.8 2001/03/27 23:25:48 mpowers Basically reverting to the previous
+ * version.
*
- * Revision 1.7 2001/03/06 23:18:13 mpowers
- * Clarified some comments.
+ * Revision 1.7 2001/03/06 23:18:13 mpowers Clarified some comments.
*
- * Revision 1.6 2001/03/01 20:36:35 mpowers
- * Better error handling and better handling of nulls.
+ * Revision 1.6 2001/03/01 20:36:35 mpowers Better error handling and better
+ * handling of nulls.
*
- * Revision 1.5 2001/02/27 21:43:40 mpowers
- * Removed NullMarker class in favor of NSNull.
+ * Revision 1.5 2001/02/27 21:43:40 mpowers Removed NullMarker class in favor of
+ * NSNull.
*
- * Revision 1.4 2001/02/26 22:41:51 mpowers
- * Implemented null placeholder classes.
- * Duplicator now uses NSNull.
- * No longer catching base exception class.
+ * Revision 1.4 2001/02/26 22:41:51 mpowers Implemented null placeholder
+ * classes. Duplicator now uses NSNull. No longer catching base exception class.
*
- * Revision 1.3 2001/02/23 21:07:46 mpowers
- * Documented the NULL object.
+ * Revision 1.3 2001/02/23 21:07:46 mpowers Documented the NULL object.
*
- * Revision 1.1 2001/02/16 22:51:29 mpowers
- * Now deep-cloning objects passed between editing contexts.
+ * Revision 1.1 2001/02/16 22:51:29 mpowers Now deep-cloning objects passed
+ * between editing contexts.
*
*
*/
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Introspector.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Introspector.java
index 2b313d0..09687e2 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Introspector.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/Introspector.java
@@ -30,912 +30,750 @@ import java.util.Map;
import java.util.Set;
/**
-* This Introspector is a static utility class written to work
-* around limitations in PropertyDescriptor and Introspector.<br><br>
-*
-* Of particular note are the get() and set() methods, which will attempt
-* to get and set artibrary values on arbitrary objects to the best of its
-* ability, converting values as appropriate. Properties of the form
-* "property.nestedproperty.anotherproperty" are supported to get and set
-* values on property values directly.<br><br>
-*
-* Note that for naming getter methods, this class supports "get", "is",
-* and also the property name itself, which supports NeXT-style properties.
-* Introspector supports Maps by treating the keys a property names,
-* supports Lists by treating the indexes as property names. <br><br>
-*
-* Numeric and boolean types can be inverted by prepending a "!" before
-* the name of the property, like "manager.!active" or "task.!lag".
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
+ * This Introspector is a static utility class written to work around
+ * limitations in PropertyDescriptor and Introspector.<br>
+ * <br>
+ *
+ * Of particular note are the get() and set() methods, which will attempt to get
+ * and set artibrary values on arbitrary objects to the best of its ability,
+ * converting values as appropriate. Properties of the form
+ * "property.nestedproperty.anotherproperty" are supported to get and set values
+ * on property values directly.<br>
+ * <br>
+ *
+ * Note that for naming getter methods, this class supports "get", "is", and
+ * also the property name itself, which supports NeXT-style properties.
+ * Introspector supports Maps by treating the keys a property names, supports
+ * Lists by treating the indexes as property names. <br>
+ * <br>
+ *
+ * Numeric and boolean types can be inverted by prepending a "!" before the name
+ * of the property, like "manager.!active" or "task.!lag".
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
+
+public class Introspector {
+ // allows "hasProperty" or "property" forms
+ public static boolean strict = false;
-public class Introspector
-{
- // allows "hasProperty" or "property" forms
- public static boolean strict = false;
-
// print exception stack traces
private static boolean debug = true;
-
+
// path separator
public static final String SEPARATOR = ".";
- // method cache - use hashtables for thread safety
- private static Map getterMethods = new Hashtable();
- private static Map setterMethods = new Hashtable();
-
- // wildcard value - using this class to represent a "wildcard" generic class.
- // we have to do this when matching methods by parameter types and a
- // null value is passed in - can't tell what class the null should be.
- public static Class WILD = Introspector.class;
-
- // empty class array - prevents having to create one every time
- private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
-
- // use OGNL for property access
- private static boolean useOGNL;
-
- static
- {
- try
- {
- useOGNL = ( Class.forName( "ognl.Ognl" ) != null );
- }
- catch ( ClassNotFoundException t )
- {
- useOGNL = false;
- }
- }
+ // method cache - use hashtables for thread safety
+ private static Map getterMethods = new Hashtable();
+ private static Map setterMethods = new Hashtable();
-/**
-* Utility method to get the read method for a property belonging to a class.
-* Will search for methods in the form of "getProperty" and failing that
-* "isProperty" (to handle booleans).
-* @param objectClass the class whose property methods will be retrieved.
-* @param aProperty The property whose method will be retrieved.
-* @param paramTypes An array of class objects representing the types of parameters.
-* @return The appropriate method for the class, or null if not found.
-*/
- static public Method getPropertyReadMethod(
- Class objectClass, String aProperty, Class[] paramTypes )
- {
- Method result = null;
-
- result = getMethodFromClass( objectClass, aProperty, paramTypes, true );
+ // wildcard value - using this class to represent a "wildcard" generic class.
+ // we have to do this when matching methods by parameter types and a
+ // null value is passed in - can't tell what class the null should be.
+ public static Class WILD = Introspector.class;
- return result;
- }
+ // empty class array - prevents having to create one every time
+ private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
-/**
-* Utility method to get the write method for a property belonging to a class.
-* Will search for methods in the form of "setProperty".
-* @param objectClass the class whose property methods will be retrieved.
-* @param aProperty The property whose method will be retrieved.
-* @param paramTypes An array of class objects representing the types of parameters.
-* @return The appropriate method for the class, or null if not found.
-*/
- static public Method getPropertyWriteMethod(
- Class objectClass, String aProperty, Class[] paramTypes )
- {
- Method result = null;
-
- result = getMethodFromClass( objectClass, aProperty, paramTypes, false );
+ // use OGNL for property access
+ private static boolean useOGNL;
- return result;
- }
+ static {
+ try {
+ useOGNL = (Class.forName("ognl.Ognl") != null);
+ } catch (ClassNotFoundException t) {
+ useOGNL = false;
+ }
+ }
-/**
-* Gets a named method from a class. Using this method is preferred because
-* the results are cached and should be faster than calling Class.getMethod().
-* Note that if an object has a "get" getter method and an "is" getter method
-* with the same signature defined for a given property. The "get" method
-* is called.
-* @param objectClass the Class whose property methods will be retrieved.
-* @param aMethodName A String containing the name of the desired method.
-* @param paramTypes An array of class objects representing the types of parameters.
-* @return The appropriate Method from the Class, or null if not found.
-*/
- static private Method getMethodFromClass(
- Class objectClass, String aProperty, Class[] paramTypes, boolean doGetter)
- { // System.out.print( "Introspector.getMethodFromClass: " + aMethodName + " : " );
-
- Map classesToMethods = (doGetter ?
- getterMethods :
- setterMethods);
-
- Map allMethods = (Map) classesToMethods.get( objectClass );
- if (allMethods == null)
- {
- // need to build maps for this class
- mapPropertiesForClass( objectClass );
- // now the map should exist
- allMethods = (Map) classesToMethods.get( objectClass );
- }
-
- Method[] methods = (Method[]) allMethods.get( aProperty );
- if ( methods == null )
- {
- return null; // property doesn't exist
- }
-
- methods_loop: // walks through all methods for name
- for ( int i = 0; i < methods.length; i++ )
- {
- Class[] types = methods[i].getParameterTypes();
-
- // if parameter lengths don't match
- if ( types.length != paramTypes.length )
- {
- // System.out.println( aMethodName + " : " + types.length + " != " + paramTypes.length );
- continue methods_loop; // continue with outer loop
- }
-
- // match up each parameter
- for ( int j = 0; j < types.length; j++ )
- {
- // convert primitives so they'll match - ugly
- // (would have thought isAssignableFrom() would catch this)
- if ( types[j].isPrimitive() )
- {
- if ( types[j] == Boolean.TYPE )
- {
- types[j] = Boolean.class;
- }
- else
- if ( types[j] == Character.TYPE )
- {
- types[j] = Character.class;
- }
- else
- if ( types[j] == Byte.TYPE )
- {
- types[j] = Byte.class;
- }
- else
- if ( types[j] == Short.TYPE )
- {
- types[j] = Short.class;
- }
- else
- if ( types[j] == Integer.TYPE )
- {
- types[j] = Integer.class;
- }
- else
- if ( types[j] == Long.TYPE )
- {
- types[j] = Long.class;
- }
- else
- if ( types[j] == Float.TYPE )
- {
- types[j] = Float.class;
- }
- else
- if ( types[j] == Double.TYPE )
- {
- types[j] = Double.class;
- }
- }
-
- // if parameters don't match
- if ( ( paramTypes[j] != WILD ) && ( ! types[j].isAssignableFrom( paramTypes[j] ) ) )
- {
+ /**
+ * Utility method to get the read method for a property belonging to a class.
+ * Will search for methods in the form of "getProperty" and failing that
+ * "isProperty" (to handle booleans).
+ *
+ * @param objectClass the class whose property methods will be retrieved.
+ * @param aProperty The property whose method will be retrieved.
+ * @param paramTypes An array of class objects representing the types of
+ * parameters.
+ * @return The appropriate method for the class, or null if not found.
+ */
+ static public Method getPropertyReadMethod(Class objectClass, String aProperty, Class[] paramTypes) {
+ Method result = null;
+
+ result = getMethodFromClass(objectClass, aProperty, paramTypes, true);
+
+ return result;
+ }
+
+ /**
+ * Utility method to get the write method for a property belonging to a class.
+ * Will search for methods in the form of "setProperty".
+ *
+ * @param objectClass the class whose property methods will be retrieved.
+ * @param aProperty The property whose method will be retrieved.
+ * @param paramTypes An array of class objects representing the types of
+ * parameters.
+ * @return The appropriate method for the class, or null if not found.
+ */
+ static public Method getPropertyWriteMethod(Class objectClass, String aProperty, Class[] paramTypes) {
+ Method result = null;
+
+ result = getMethodFromClass(objectClass, aProperty, paramTypes, false);
+
+ return result;
+ }
+
+ /**
+ * Gets a named method from a class. Using this method is preferred because the
+ * results are cached and should be faster than calling Class.getMethod(). Note
+ * that if an object has a "get" getter method and an "is" getter method with
+ * the same signature defined for a given property. The "get" method is called.
+ *
+ * @param objectClass the Class whose property methods will be retrieved.
+ * @param aMethodName A String containing the name of the desired method.
+ * @param paramTypes An array of class objects representing the types of
+ * parameters.
+ * @return The appropriate Method from the Class, or null if not found.
+ */
+ static private Method getMethodFromClass(Class objectClass, String aProperty, Class[] paramTypes,
+ boolean doGetter) { // System.out.print( "Introspector.getMethodFromClass: " + aMethodName + " : "
+ // );
+
+ Map classesToMethods = (doGetter ? getterMethods : setterMethods);
+
+ Map allMethods = (Map) classesToMethods.get(objectClass);
+ if (allMethods == null) {
+ // need to build maps for this class
+ mapPropertiesForClass(objectClass);
+ // now the map should exist
+ allMethods = (Map) classesToMethods.get(objectClass);
+ }
+
+ Method[] methods = (Method[]) allMethods.get(aProperty);
+ if (methods == null) {
+ return null; // property doesn't exist
+ }
+
+ methods_loop: // walks through all methods for name
+ for (int i = 0; i < methods.length; i++) {
+ Class[] types = methods[i].getParameterTypes();
+
+ // if parameter lengths don't match
+ if (types.length != paramTypes.length) {
+ // System.out.println( aMethodName + " : " + types.length + " != " +
+ // paramTypes.length );
+ continue methods_loop; // continue with outer loop
+ }
+
+ // match up each parameter
+ for (int j = 0; j < types.length; j++) {
+ // convert primitives so they'll match - ugly
+ // (would have thought isAssignableFrom() would catch this)
+ if (types[j].isPrimitive()) {
+ if (types[j] == Boolean.TYPE) {
+ types[j] = Boolean.class;
+ } else if (types[j] == Character.TYPE) {
+ types[j] = Character.class;
+ } else if (types[j] == Byte.TYPE) {
+ types[j] = Byte.class;
+ } else if (types[j] == Short.TYPE) {
+ types[j] = Short.class;
+ } else if (types[j] == Integer.TYPE) {
+ types[j] = Integer.class;
+ } else if (types[j] == Long.TYPE) {
+ types[j] = Long.class;
+ } else if (types[j] == Float.TYPE) {
+ types[j] = Float.class;
+ } else if (types[j] == Double.TYPE) {
+ types[j] = Double.class;
+ }
+ }
+
+ // if parameters don't match
+ if ((paramTypes[j] != WILD) && (!types[j].isAssignableFrom(paramTypes[j]))) {
// System.out.println( "Introspector.getMethodFromClass: " +
// aProperty + " : " + types[j] + " != " + paramTypes[j] );
- continue methods_loop; // continue with outer loop
- }
- }
-
- // all params match
- return methods[i];
- }
-
- // no match
- return null;
- }
-
- static private final Method[] getAllMethodsForClass( Class aClass )
- {
- Method[] local = aClass.getDeclaredMethods(); // only local
- Method[] all = aClass.getMethods(); // all public
- Method[] result = new Method[ local.length + all.length ];
- System.arraycopy( local, 0, result, 0, local.length );
- System.arraycopy( all, 0, result, local.length, all.length );
- return result;
- }
-
- /**
- * Generates a map of properties to both getter or setter methods for the given class.
- * Then assigned those maps into the appropriate getterMethods and setterMethods maps
- * keyed by the specified class. Even on error, this method will at least place empty
- * property maps into each of the methods maps.
- */
- static private void mapPropertiesForClass( Class objectClass )
- {
- try
- {
- Map readProperties = new HashMap();
- getterMethods.put( objectClass, readProperties );
- Map writeProperties = new HashMap();
- setterMethods.put( objectClass, writeProperties );
-
- String name, property;
- Method[] methods = getAllMethodsForClass( objectClass ); // throws SecurityException
- for ( int i = 0; i < methods.length; i++ )
- {
- name = methods[i].getName();
- methods[i].setAccessible( true ); // throws SecurityException
- if ( name.startsWith( "set" ) )
- {
- name = name.substring( 3 );
- if ( ! "".equals( name ) ) // excludes "set()"
- {
- putMethodIntoPropertyMap( name, methods[i], writeProperties );
- }
- }
- else
- if ( methods[i].getReturnType() != void.class )
- {
- String fullname = name;
- if ( name.startsWith( "get" ) )
- {
- name = name.substring( 3 );
- }
- else
- if ( name.startsWith( "is" ) )
- {
- name = name.substring( 2 );
- }
- else
- if ( name.startsWith( "has" ) && ( !strict ) ) // what about hashCode()?
- {
- name = name.substring( 3 );
- }
-
- if ( ! "".equals( name ) && ( !strict ) ) // excludes "get()", "has()", and "is()"
- {
- putMethodIntoPropertyMap( name, methods[i], readProperties );
- if ( fullname != name )
- { // allows us to match properties that include the get/set prefix as well
- putMethodIntoPropertyMap( fullname, methods[i], readProperties );
- }
- }
- }
- }
- }
- catch ( SecurityException se )
- {
- System.out.println( "Introspector.getMethodFromClass: " + se );
- // this class will show up with empty getter/setter maps
- }
- }
-
- /**
- * Places a property-method pair into one of the properties maps.
- * This in effect maps a property to an array of methods.
- */
- private static void putMethodIntoPropertyMap( String aProperty, Method aMethod, Map aMap )
- {
- // ensure first character is lower case
- StringBuffer buffer = new StringBuffer( aProperty );
- buffer.setCharAt(0, Character.toLowerCase(buffer.charAt(0)));
- String key = buffer.toString();
-
- // build array of methods for property
- Method[] result = (Method[]) aMap.get( key );
- if ( result == null )
- {
- result = new Method[] { aMethod };
- }
- else
- {
- // create new array that's larger by one and copy
- int i;
- Method[] enlarged = new Method[ result.length + 1 ];
- for ( i = 0; i < result.length; i ++ )
- {
- enlarged[i] = result[i];
- }
- // add the new method to end
- enlarged[i] = aMethod;
- result = enlarged;
- }
- aMap.put( key, result );
- }
+ continue methods_loop; // continue with outer loop
+ }
+ }
-/**
-* Utility method to get a method for a property belonging to a class.
-* Use this if you don't feel like making the Class array from the parameters
-* you will be using - pass in the parameters themselves.
-* @param objectClass the Class whose property methods will be retrieved.
-* @param aProperty The property whose method will be retrieved.
-* @param params An array of parameters to be used.
-* @return The appropriate method for the class, or null if not found.
-*/
- static public Method getPropertyReadMethod(
- Class objectClass, String aProperty, Object[] params )
- {
- // optimization: avoid allocating class array for common case
- if ( params.length == 0 )
- {
- return getPropertyReadMethod(
- objectClass, aProperty, EMPTY_CLASS_ARRAY );
- }
-
- Class[] paramList = new Class[ params.length ];
- for ( int i = 0; i < params.length; i++ )
- {
- if ( params[i] != null )
- {
- paramList[i] = params[i].getClass();
- }
- else
- {
- paramList[i] = WILD;
- }
- }
- return getPropertyReadMethod( objectClass, aProperty, paramList );
- }
+ // all params match
+ return methods[i];
+ }
-/**
-* Utility method to get a method for a property belonging to a class.
-* Use this if you don't feel like making the Class array from the parameters
-* you will be using - pass in the parameters themselves.
-* @param objectClass the Class whose property methods will be retrieved.
-* @param aProperty The property whose method will be retrieved.
-* @param params An array of parameters to be used.
-* @return The appropriate method for the class, or null if not found.
-*/
- static public Method getPropertyWriteMethod(
- Class objectClass, String aProperty, Object[] params )
- {
- Class[] paramList = new Class[ params.length ];
- for ( int i = 0; i < params.length; i++ )
- {
- if ( params[i] != null )
- {
- paramList[i] = params[i].getClass();
- }
- else
- {
- paramList[i] = WILD;
- }
- }
- return getPropertyWriteMethod( objectClass, aProperty, paramList );
- }
-
- /**
- * Gets a list of the readable properties for the given class.
- * Note that readable properties may not be writable - see getWriteProperties().
- * @return An array of property names in no particular order
- * where each name is a string with the first character in lower case.
- */
- public static String[] getReadPropertiesForClass( Class objectClass )
- {
- Map properties = (Map) getterMethods.get( objectClass );
- if ( properties == null )
- {
- // need to build maps for this class
- mapPropertiesForClass( objectClass );
- // now the map should exist
- properties = (Map) getterMethods.get( objectClass );
- }
-
- // put property names into string array
- Set keys = properties.keySet();
- Iterator it = keys.iterator();
- int len = keys.size();
- String[] result = new String[ len ];
- for ( int i = 0; i < len; i++ )
- {
- result[i] = (String) it.next();
- }
- return result;
- }
-
- /**
- * Gets a list of the writable properties for the given class.
- * Note that writable properties may not be writable - see getReadProperties().
- * @return An array of property names in no particular order
- * where each name is a string with the first character in lower case.
- */
- public static String[] getWritePropertiesForClass( Class objectClass )
- {
- Map properties = (Map) setterMethods.get( objectClass );
- if ( properties == null )
- {
- // need to build maps for this class
- mapPropertiesForClass( objectClass );
- // now the map should exist
- properties = (Map) setterMethods.get( objectClass );
- }
-
- // put property names into string array
- Set keys = properties.keySet();
- Iterator it = keys.iterator();
- int len = keys.size();
- String[] result = new String[ len ];
- for ( int i = 0; i < len; i++ )
- {
- result[i] = (String) it.next();
- }
- return result;
- }
-
- /**
- * Gets a list of the readable properties for the given object, which may
- * not be null. This method is more useful than getReadPropertiesForClass
- * in that Maps will return their keys as properties and Lists will return
- * their element indices as properties.
- * Note that readable properties may not be writable - see getWriteProperties().
- * @return An array of property names in no particular order
- * where each name is a string with the first character in lower case.
- */
- public static String[] getReadPropertiesForObject( Object anObject )
- {
- List properties = new ArrayList();
- String[] classProperties =
- getReadPropertiesForClass( anObject.getClass() );
- if ( anObject instanceof List )
- {
- properties.addAll( getPropertiesForList( (List) anObject ) );
- }
- if ( anObject instanceof Map )
- {
- properties.addAll( getPropertiesForMap( (Map) anObject ) );
- }
- int i;
- int len = classProperties.length + properties.size();
- String[] result = new String[ len ];
- for ( i = 0; i < classProperties.length; i++ )
- {
- result[i] = classProperties[i];
- }
- Iterator it = properties.iterator();
- while ( it.hasNext() )
- {
- result[i++] = it.next().toString();
- }
- return result;
- }
-
- /**
- * Gets a list of the writable properties for the given object, which may
- * not be null. This method is more useful than getWritePropertiesForClass
- * in that Maps will return their keys as properties and Lists will return
- * their element indices as properties.
- * Note that writable properties may not be writable - see getReadProperties().
- * @return An array of property names in no particular order
- * where each name is a string with the first character in lower case.
- */
- public static String[] getWritePropertiesForObject( Object anObject )
- {
- List properties = new ArrayList();
- String[] classProperties =
- getWritePropertiesForClass( anObject.getClass() );
- if ( anObject instanceof List )
- {
- properties.addAll( getPropertiesForList( (List) anObject ) );
- }
- if ( anObject instanceof Map )
- {
- properties.addAll( getPropertiesForMap( (Map) anObject ) );
- }
-
- int i;
- int len = classProperties.length + properties.size();
- String[] result = new String[ len ];
- for ( i = 0; i < classProperties.length; i++ )
- {
- result[i] = classProperties[i];
- }
- Iterator it = properties.iterator();
- while ( it.hasNext() )
- {
- result[i++] = it.next().toString();
- }
- return result;
- }
-
- private static List getPropertiesForList( List aList )
- {
- List result = new ArrayList();
- int len = aList.size();
- for ( int i = 0; i < len; i++ )
- {
- result.add( new Integer( i ).toString() );
- }
- return result;
- }
-
- private static List getPropertiesForMap( Map aMap )
- {
- List result = new ArrayList();
- Iterator it = ((Map)aMap).keySet().iterator();
- while ( it.hasNext() )
- {
- result.add( it.next().toString() );
- }
- return result;
- }
-
- private static Object[] EMPTY_ARRAY = new Object[0];
-
- /**
- * Convenience to get a value for a property from an object.
- * An empty property string is considered the identity property
- * and simply returns the object.
- * @throws MissingPropertyException if the property cannot be
- * found on the object.
- */
- public static Object getValueForObject( Object anObject, String aProperty )
- {
- if ( ( aProperty == null ) || ( "".equals( aProperty ) ) )
- {
- return anObject;
- }
-
- if ( useOGNL && aProperty.startsWith( "ognl:" ) )
- {
- try
- {
- return ognl.Ognl.getValue( aProperty, anObject );
- }
- catch ( Throwable t )
- {
- if ( debug )
- {
- System.err.println(
- "Introspector.getValueForObject: "
- + anObject + "' ( " + anObject.getClass() + " )"
- + ", ognl:" + aProperty );
- System.err.println( t );
- }
- return null;
- }
- }
-
- boolean invert = false;
- if ( aProperty.startsWith( "!" ) )
- {
- aProperty = aProperty.substring(1);
- invert = true;
- }
-
- Object result = null;
- try
- {
- Method m = Introspector.getPropertyReadMethod(
- anObject.getClass(), aProperty, EMPTY_ARRAY );
- if ( m != null )
- {
- result = m.invoke( anObject, EMPTY_ARRAY );
+ // no match
+ return null;
+ }
+
+ static private final Method[] getAllMethodsForClass(Class aClass) {
+ Method[] local = aClass.getDeclaredMethods(); // only local
+ Method[] all = aClass.getMethods(); // all public
+ Method[] result = new Method[local.length + all.length];
+ System.arraycopy(local, 0, result, 0, local.length);
+ System.arraycopy(all, 0, result, local.length, all.length);
+ return result;
+ }
+
+ /**
+ * Generates a map of properties to both getter or setter methods for the given
+ * class. Then assigned those maps into the appropriate getterMethods and
+ * setterMethods maps keyed by the specified class. Even on error, this method
+ * will at least place empty property maps into each of the methods maps.
+ */
+ static private void mapPropertiesForClass(Class objectClass) {
+ try {
+ Map readProperties = new HashMap();
+ getterMethods.put(objectClass, readProperties);
+ Map writeProperties = new HashMap();
+ setterMethods.put(objectClass, writeProperties);
+
+ String name, property;
+ Method[] methods = getAllMethodsForClass(objectClass); // throws SecurityException
+ for (int i = 0; i < methods.length; i++) {
+ name = methods[i].getName();
+ methods[i].setAccessible(true); // throws SecurityException
+ if (name.startsWith("set")) {
+ name = name.substring(3);
+ if (!"".equals(name)) // excludes "set()"
+ {
+ putMethodIntoPropertyMap(name, methods[i], writeProperties);
+ }
+ } else if (methods[i].getReturnType() != void.class) {
+ String fullname = name;
+ if (name.startsWith("get")) {
+ name = name.substring(3);
+ } else if (name.startsWith("is")) {
+ name = name.substring(2);
+ } else if (name.startsWith("has") && (!strict)) // what about hashCode()?
+ {
+ name = name.substring(3);
+ }
+
+ if (!"".equals(name) && (!strict)) // excludes "get()", "has()", and "is()"
+ {
+ putMethodIntoPropertyMap(name, methods[i], readProperties);
+ if (fullname != name) { // allows us to match properties that include the get/set prefix as well
+ putMethodIntoPropertyMap(fullname, methods[i], readProperties);
+ }
+ }
+ }
}
- else // no method, try for field
- {
- try
- {
- Field field = anObject.getClass().getDeclaredField( aProperty );
- if ( field != null )
- {
- field.setAccessible( true ); // throws SecurityException
- result = field.get( anObject );
- }
- }
- catch ( Throwable t )
- {
- // ignore for now
- }
- }
-
- if ( result == null )
- {
- if ( anObject instanceof Map )
- {
- result = ((Map)anObject).get( aProperty );
- }
- else
- if ( anObject instanceof List )
- {
- result = ((List)anObject).get( Integer.parseInt( aProperty ) );
- }
- }
-
- if ( invert )
- {
- Object inverted = ValueConverter.invert( result );
- if ( inverted != null ) result = inverted;
- }
- //System.out.println( "getValueForObject: " + anObject + " : " + aProperty + " : " + result );
- return result;
- }
- catch ( Throwable exc )
- {
- if ( exc instanceof InvocationTargetException )
- {
- exc = ((InvocationTargetException)exc).getTargetException();
- }
- if ( exc instanceof RuntimeException )
- {
- throw (RuntimeException)exc;
- }
- if ( debug )
+ } catch (SecurityException se) {
+ System.out.println("Introspector.getMethodFromClass: " + se);
+ // this class will show up with empty getter/setter maps
+ }
+ }
+
+ /**
+ * Places a property-method pair into one of the properties maps. This in effect
+ * maps a property to an array of methods.
+ */
+ private static void putMethodIntoPropertyMap(String aProperty, Method aMethod, Map aMap) {
+ // ensure first character is lower case
+ StringBuffer buffer = new StringBuffer(aProperty);
+ buffer.setCharAt(0, Character.toLowerCase(buffer.charAt(0)));
+ String key = buffer.toString();
+
+ // build array of methods for property
+ Method[] result = (Method[]) aMap.get(key);
+ if (result == null) {
+ result = new Method[] { aMethod };
+ } else {
+ // create new array that's larger by one and copy
+ int i;
+ Method[] enlarged = new Method[result.length + 1];
+ for (i = 0; i < result.length; i++) {
+ enlarged[i] = result[i];
+ }
+ // add the new method to end
+ enlarged[i] = aMethod;
+ result = enlarged;
+ }
+ aMap.put(key, result);
+ }
+
+ /**
+ * Utility method to get a method for a property belonging to a class. Use this
+ * if you don't feel like making the Class array from the parameters you will be
+ * using - pass in the parameters themselves.
+ *
+ * @param objectClass the Class whose property methods will be retrieved.
+ * @param aProperty The property whose method will be retrieved.
+ * @param params An array of parameters to be used.
+ * @return The appropriate method for the class, or null if not found.
+ */
+ static public Method getPropertyReadMethod(Class objectClass, String aProperty, Object[] params) {
+ // optimization: avoid allocating class array for common case
+ if (params.length == 0) {
+ return getPropertyReadMethod(objectClass, aProperty, EMPTY_CLASS_ARRAY);
+ }
+
+ Class[] paramList = new Class[params.length];
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] != null) {
+ paramList[i] = params[i].getClass();
+ } else {
+ paramList[i] = WILD;
+ }
+ }
+ return getPropertyReadMethod(objectClass, aProperty, paramList);
+ }
+
+ /**
+ * Utility method to get a method for a property belonging to a class. Use this
+ * if you don't feel like making the Class array from the parameters you will be
+ * using - pass in the parameters themselves.
+ *
+ * @param objectClass the Class whose property methods will be retrieved.
+ * @param aProperty The property whose method will be retrieved.
+ * @param params An array of parameters to be used.
+ * @return The appropriate method for the class, or null if not found.
+ */
+ static public Method getPropertyWriteMethod(Class objectClass, String aProperty, Object[] params) {
+ Class[] paramList = new Class[params.length];
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] != null) {
+ paramList[i] = params[i].getClass();
+ } else {
+ paramList[i] = WILD;
+ }
+ }
+ return getPropertyWriteMethod(objectClass, aProperty, paramList);
+ }
+
+ /**
+ * Gets a list of the readable properties for the given class. Note that
+ * readable properties may not be writable - see getWriteProperties().
+ *
+ * @return An array of property names in no particular order where each name is
+ * a string with the first character in lower case.
+ */
+ public static String[] getReadPropertiesForClass(Class objectClass) {
+ Map properties = (Map) getterMethods.get(objectClass);
+ if (properties == null) {
+ // need to build maps for this class
+ mapPropertiesForClass(objectClass);
+ // now the map should exist
+ properties = (Map) getterMethods.get(objectClass);
+ }
+
+ // put property names into string array
+ Set keys = properties.keySet();
+ Iterator it = keys.iterator();
+ int len = keys.size();
+ String[] result = new String[len];
+ for (int i = 0; i < len; i++) {
+ result[i] = (String) it.next();
+ }
+ return result;
+ }
+
+ /**
+ * Gets a list of the writable properties for the given class. Note that
+ * writable properties may not be writable - see getReadProperties().
+ *
+ * @return An array of property names in no particular order where each name is
+ * a string with the first character in lower case.
+ */
+ public static String[] getWritePropertiesForClass(Class objectClass) {
+ Map properties = (Map) setterMethods.get(objectClass);
+ if (properties == null) {
+ // need to build maps for this class
+ mapPropertiesForClass(objectClass);
+ // now the map should exist
+ properties = (Map) setterMethods.get(objectClass);
+ }
+
+ // put property names into string array
+ Set keys = properties.keySet();
+ Iterator it = keys.iterator();
+ int len = keys.size();
+ String[] result = new String[len];
+ for (int i = 0; i < len; i++) {
+ result[i] = (String) it.next();
+ }
+ return result;
+ }
+
+ /**
+ * Gets a list of the readable properties for the given object, which may not be
+ * null. This method is more useful than getReadPropertiesForClass in that Maps
+ * will return their keys as properties and Lists will return their element
+ * indices as properties. Note that readable properties may not be writable -
+ * see getWriteProperties().
+ *
+ * @return An array of property names in no particular order where each name is
+ * a string with the first character in lower case.
+ */
+ public static String[] getReadPropertiesForObject(Object anObject) {
+ List properties = new ArrayList();
+ String[] classProperties = getReadPropertiesForClass(anObject.getClass());
+ if (anObject instanceof List) {
+ properties.addAll(getPropertiesForList((List) anObject));
+ }
+ if (anObject instanceof Map) {
+ properties.addAll(getPropertiesForMap((Map) anObject));
+ }
+ int i;
+ int len = classProperties.length + properties.size();
+ String[] result = new String[len];
+ for (i = 0; i < classProperties.length; i++) {
+ result[i] = classProperties[i];
+ }
+ Iterator it = properties.iterator();
+ while (it.hasNext()) {
+ result[i++] = it.next().toString();
+ }
+ return result;
+ }
+
+ /**
+ * Gets a list of the writable properties for the given object, which may not be
+ * null. This method is more useful than getWritePropertiesForClass in that Maps
+ * will return their keys as properties and Lists will return their element
+ * indices as properties. Note that writable properties may not be writable -
+ * see getReadProperties().
+ *
+ * @return An array of property names in no particular order where each name is
+ * a string with the first character in lower case.
+ */
+ public static String[] getWritePropertiesForObject(Object anObject) {
+ List properties = new ArrayList();
+ String[] classProperties = getWritePropertiesForClass(anObject.getClass());
+ if (anObject instanceof List) {
+ properties.addAll(getPropertiesForList((List) anObject));
+ }
+ if (anObject instanceof Map) {
+ properties.addAll(getPropertiesForMap((Map) anObject));
+ }
+
+ int i;
+ int len = classProperties.length + properties.size();
+ String[] result = new String[len];
+ for (i = 0; i < classProperties.length; i++) {
+ result[i] = classProperties[i];
+ }
+ Iterator it = properties.iterator();
+ while (it.hasNext()) {
+ result[i++] = it.next().toString();
+ }
+ return result;
+ }
+
+ private static List getPropertiesForList(List aList) {
+ List result = new ArrayList();
+ int len = aList.size();
+ for (int i = 0; i < len; i++) {
+ result.add(new Integer(i).toString());
+ }
+ return result;
+ }
+
+ private static List getPropertiesForMap(Map aMap) {
+ List result = new ArrayList();
+ Iterator it = ((Map) aMap).keySet().iterator();
+ while (it.hasNext()) {
+ result.add(it.next().toString());
+ }
+ return result;
+ }
+
+ private static Object[] EMPTY_ARRAY = new Object[0];
+
+ /**
+ * Convenience to get a value for a property from an object. An empty property
+ * string is considered the identity property and simply returns the object.
+ *
+ * @throws MissingPropertyException if the property cannot be found on the
+ * object.
+ */
+ public static Object getValueForObject(Object anObject, String aProperty) {
+ if ((aProperty == null) || ("".equals(aProperty))) {
+ return anObject;
+ }
+
+ if (useOGNL && aProperty.startsWith("ognl:")) {
+ try {
+ return ognl.Ognl.getValue(aProperty, anObject);
+ } catch (Throwable t) {
+ if (debug) {
+ System.err.println("Introspector.getValueForObject: " + anObject + "' ( " + anObject.getClass()
+ + " )" + ", ognl:" + aProperty);
+ System.err.println(t);
+ }
+ return null;
+ }
+ }
+
+ boolean invert = false;
+ if (aProperty.startsWith("!")) {
+ aProperty = aProperty.substring(1);
+ invert = true;
+ }
+
+ Object result = null;
+ try {
+ Method m = Introspector.getPropertyReadMethod(anObject.getClass(), aProperty, EMPTY_ARRAY);
+ if (m != null) {
+ result = m.invoke(anObject, EMPTY_ARRAY);
+ } else // no method, try for field
{
- System.out.println(
- "Introspector.getValueForObject: "
- + anObject + "' ( " + anObject.getClass() + " )"
- + ", " + aProperty + ": " );
- }
- throw new WotonomyException( exc );
- }
+ try {
+ Field field = anObject.getClass().getDeclaredField(aProperty);
+ if (field != null) {
+ field.setAccessible(true); // throws SecurityException
+ result = field.get(anObject);
+ }
+ } catch (Throwable t) {
+ // ignore for now
+ }
+ }
+
+ if (result == null) {
+ if (anObject instanceof Map) {
+ result = ((Map) anObject).get(aProperty);
+ } else if (anObject instanceof List) {
+ result = ((List) anObject).get(Integer.parseInt(aProperty));
+ }
+ }
+
+ if (invert) {
+ Object inverted = ValueConverter.invert(result);
+ if (inverted != null)
+ result = inverted;
+ }
+ // System.out.println( "getValueForObject: " + anObject + " : " + aProperty + "
+ // : " + result );
+ return result;
+ } catch (Throwable exc) {
+ if (exc instanceof InvocationTargetException) {
+ exc = ((InvocationTargetException) exc).getTargetException();
+ }
+ if (exc instanceof RuntimeException) {
+ throw (RuntimeException) exc;
+ }
+ if (debug) {
+ System.out.println("Introspector.getValueForObject: " + anObject + "' ( " + anObject.getClass() + " )"
+ + ", " + aProperty + ": ");
+ }
+ throw new WotonomyException(exc);
+ }
//! throw new MissingPropertyException();
- }
-
- /**
- * Convenience to set a value for a property from an object.
- * Returns the return value from executing the specified method,
- * or null if the method returns type void.
- * @throws MissingPropertyException if the property cannot be
- * found on the object.
- * @throws NullPrimitiveException if the property is of primitive
- * type and the value is null.
- */
- public static Object setValueForObject(
- Object anObject, String aProperty, Object aValue )
- {
- if ( useOGNL && aProperty.startsWith( "ognl:" ) )
- {
- try
- {
- ognl.Ognl.setValue( aProperty, anObject, aValue );
- }
- catch ( Throwable t )
- {
- if ( debug )
- {
- System.err.println(
- "Introspector.setValueForObject: "
- + anObject + "' ( " + anObject.getClass() + " )"
- + ", ognl:" + aProperty + " : " + aValue );
- System.err.println( t );
- }
- }
- return null;
- }
-
- try
- {
- if ( aProperty.startsWith( "!" ) )
- {
- aProperty = aProperty.substring(1);
- Object inverted = ValueConverter.invert( aValue );
- if ( inverted != null ) aValue = inverted;
- }
-
- Method m = null;
- if ( aValue != null )
- {
- m = Introspector.getPropertyWriteMethod(
- anObject.getClass(), aProperty, new Class[] { aValue.getClass() } );
- }
- if ( m == null )
- {
- m = Introspector.getPropertyWriteMethod(
- anObject.getClass(), aProperty, new Class[] { WILD } );
- if ( ( m != null ) && ( aValue != null ) )
- {
- // check for null primitive
- if ( ( aValue == null ) &&
- ( m.getParameterTypes()[0].isPrimitive() ) )
- {
- throw new NullPrimitiveException();
- }
-
- // convert if possible
- Object o = ValueConverter.convertObjectToClass(
- aValue, m.getParameterTypes()[0] );
- if ( o != null )
- {
- aValue = o;
- }
- }
- }
- if ( m != null )
- {
- return m.invoke( anObject, new Object[] { aValue } );
+ }
+
+ /**
+ * Convenience to set a value for a property from an object. Returns the return
+ * value from executing the specified method, or null if the method returns type
+ * void.
+ *
+ * @throws MissingPropertyException if the property cannot be found on the
+ * object.
+ * @throws NullPrimitiveException if the property is of primitive type and the
+ * value is null.
+ */
+ public static Object setValueForObject(Object anObject, String aProperty, Object aValue) {
+ if (useOGNL && aProperty.startsWith("ognl:")) {
+ try {
+ ognl.Ognl.setValue(aProperty, anObject, aValue);
+ } catch (Throwable t) {
+ if (debug) {
+ System.err.println("Introspector.setValueForObject: " + anObject + "' ( " + anObject.getClass()
+ + " )" + ", ognl:" + aProperty + " : " + aValue);
+ System.err.println(t);
+ }
}
- else // no method, try for field
- {
- try
- {
- Field field = anObject.getClass().getDeclaredField( aProperty );
- if ( field != null )
- {
- field.setAccessible( true ); // throws SecurityException
- field.set( anObject, aValue );
- return null;
- }
- }
- catch ( Throwable t )
- {
- // ignore for now
- }
- }
-
- if ( anObject instanceof Map )
- {
- return ((Map)anObject).put( aProperty, aValue );
+ return null;
+ }
+
+ try {
+ if (aProperty.startsWith("!")) {
+ aProperty = aProperty.substring(1);
+ Object inverted = ValueConverter.invert(aValue);
+ if (inverted != null)
+ aValue = inverted;
+ }
+
+ Method m = null;
+ if (aValue != null) {
+ m = Introspector.getPropertyWriteMethod(anObject.getClass(), aProperty,
+ new Class[] { aValue.getClass() });
}
- if ( anObject instanceof List )
+ if (m == null) {
+ m = Introspector.getPropertyWriteMethod(anObject.getClass(), aProperty, new Class[] { WILD });
+ if ((m != null) && (aValue != null)) {
+ // check for null primitive
+ if ((aValue == null) && (m.getParameterTypes()[0].isPrimitive())) {
+ throw new NullPrimitiveException();
+ }
+
+ // convert if possible
+ Object o = ValueConverter.convertObjectToClass(aValue, m.getParameterTypes()[0]);
+ if (o != null) {
+ aValue = o;
+ }
+ }
+ }
+ if (m != null) {
+ return m.invoke(anObject, new Object[] { aValue });
+ } else // no method, try for field
{
- List list = (List) anObject;
- int i = Integer.parseInt( aProperty );
- if ( list.size() < i+1 )
- {
- // expand list as necessary
- for ( int j = list.size(); j <= i; j++ )
- {
- list.add( new Object() ); // placeholder
- }
- }
- return list.set( i, aValue );
+ try {
+ Field field = anObject.getClass().getDeclaredField(aProperty);
+ if (field != null) {
+ field.setAccessible(true); // throws SecurityException
+ field.set(anObject, aValue);
+ return null;
+ }
+ } catch (Throwable t) {
+ // ignore for now
+ }
+ }
+
+ if (anObject instanceof Map) {
+ return ((Map) anObject).put(aProperty, aValue);
+ }
+ if (anObject instanceof List) {
+ List list = (List) anObject;
+ int i = Integer.parseInt(aProperty);
+ if (list.size() < i + 1) {
+ // expand list as necessary
+ for (int j = list.size(); j <= i; j++) {
+ list.add(new Object()); // placeholder
+ }
+ }
+ return list.set(i, aValue);
}
- }
- catch ( Throwable exc )
- {
- if ( exc instanceof IllegalArgumentException )
- {
+ } catch (Throwable exc) {
+ if (exc instanceof IllegalArgumentException) {
System.out.println(
- "Introspector.setValueForObject: "
- + anObject + " , " + aProperty + " , '"
- + aValue + "' ):" );
- System.out.println( exc );
- }
- else
- if ( exc instanceof InvocationTargetException )
- {
- exc = ((InvocationTargetException)exc).getTargetException();
- }
- if ( exc instanceof RuntimeException )
- {
- throw (RuntimeException)exc;
- }
- if ( debug )
- {
+ "Introspector.setValueForObject: " + anObject + " , " + aProperty + " , '" + aValue + "' ):");
+ System.out.println(exc);
+ } else if (exc instanceof InvocationTargetException) {
+ exc = ((InvocationTargetException) exc).getTargetException();
+ }
+ if (exc instanceof RuntimeException) {
+ throw (RuntimeException) exc;
+ }
+ if (debug) {
System.out.println(
- "Introspector.setValueForObject: "
- + anObject + " , " + aProperty + " , '"
- + aValue + "' ):" );
+ "Introspector.setValueForObject: " + anObject + " , " + aProperty + " , '" + aValue + "' ):");
}
- throw new WotonomyException( exc );
- }
- return null;
+ throw new WotonomyException(exc);
+ }
+ return null;
//! throw new MissingPropertyException();
- }
-
- /**
- * Gets a value from an object or any of its child objects.
- * This will parse the property string for "."'s and get
- * values for each successive object's property in the path.
- * An empty property string is considered the identity property
- * and simply returns the object.
- */
- public static Object get( Object anObject, String aProperty )
- {
- int i = aProperty.indexOf( SEPARATOR );
- if ( i == -1 ) return getValueForObject( anObject, aProperty );
-
- String pathElement = aProperty.substring( 0, i );
- String remainder = aProperty.substring( i+1 );
-
- Object result = getValueForObject( anObject, pathElement );
- if ( result == null ) return null;
- return get( result, remainder );
- }
-
- /**
- * Sets a value in an object or any of its child objects.
- * This will parse the property string for "."'s and set
- * values for each successive object's property in the path.<br><br>
- *
- * If a property is not found, this method will try to
- * implicitly create hash maps (if possible) to fill out the path.
- * This is useful when dealing with trees of nested maps.
- */
- public static Object set( Object anObject, String aProperty, Object aValue )
- {
- int i = aProperty.indexOf( SEPARATOR );
- if ( i == -1 ) return setValueForObject( anObject, aProperty, aValue );
-
- String pathElement = aProperty.substring( 0, i );
- String remainder = aProperty.substring( i+1 );
-
- Object result = getValueForObject( anObject, pathElement );
- if ( result == null )
- {
+ }
+
+ /**
+ * Gets a value from an object or any of its child objects. This will parse the
+ * property string for "."'s and get values for each successive object's
+ * property in the path. An empty property string is considered the identity
+ * property and simply returns the object.
+ */
+ public static Object get(Object anObject, String aProperty) {
+ int i = aProperty.indexOf(SEPARATOR);
+ if (i == -1)
+ return getValueForObject(anObject, aProperty);
+
+ String pathElement = aProperty.substring(0, i);
+ String remainder = aProperty.substring(i + 1);
+
+ Object result = getValueForObject(anObject, pathElement);
+ if (result == null)
+ return null;
+ return get(result, remainder);
+ }
+
+ /**
+ * Sets a value in an object or any of its child objects. This will parse the
+ * property string for "."'s and set values for each successive object's
+ * property in the path.<br>
+ * <br>
+ *
+ * If a property is not found, this method will try to implicitly create hash
+ * maps (if possible) to fill out the path. This is useful when dealing with
+ * trees of nested maps.
+ */
+ public static Object set(Object anObject, String aProperty, Object aValue) {
+ int i = aProperty.indexOf(SEPARATOR);
+ if (i == -1)
+ return setValueForObject(anObject, aProperty, aValue);
+
+ String pathElement = aProperty.substring(0, i);
+ String remainder = aProperty.substring(i + 1);
+
+ Object result = getValueForObject(anObject, pathElement);
+ if (result == null) {
result = new HashMap(2);
- setValueForObject( anObject, pathElement, result );
+ setValueForObject(anObject, pathElement, result);
}
- return set( result, remainder, aValue );
- }
-
+ return set(result, remainder, aValue);
+ }
+
/**
- * If set to true, exceptions printed to System.out.println.
- * Defaults to true.
- */
- public void setDebug( boolean isDebug )
- {
+ * If set to true, exceptions printed to System.out.println. Defaults to true.
+ */
+ public void setDebug(boolean isDebug) {
debug = isDebug;
- }
+ }
}
/*
- * $Log$
- * Revision 1.2 2006/02/16 13:11:47 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * $Log$ Revision 1.2 2006/02/16 13:11:47 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.19 2004/02/05 02:20:34 mpowers
- * Added experimental ognl support (if ognl is present).
+ * Revision 1.19 2004/02/05 02:20:34 mpowers Added experimental ognl support (if
+ * ognl is present).
*
- * Revision 1.18 2003/03/26 16:44:35 mpowers
- * Now correctly reflecting on all methods, not just locally declared ones.
+ * Revision 1.18 2003/03/26 16:44:35 mpowers Now correctly reflecting on all
+ * methods, not just locally declared ones.
*
- * Revision 1.17 2003/02/21 21:10:51 mpowers
- * Now reaching package, protected, and private methods and fields.
+ * Revision 1.17 2003/02/21 21:10:51 mpowers Now reaching package, protected,
+ * and private methods and fields.
*
- * Revision 1.16 2003/01/28 22:11:59 mpowers
- * Now more lenient in resolving properties starting with "is" "get" or "has".
+ * Revision 1.16 2003/01/28 22:11:59 mpowers Now more lenient in resolving
+ * properties starting with "is" "get" or "has".
*
- * Revision 1.15 2003/01/27 15:10:54 mpowers
- * Better handling for illegal argument exceptions.
+ * Revision 1.15 2003/01/27 15:10:54 mpowers Better handling for illegal
+ * argument exceptions.
*
- * Revision 1.14 2003/01/18 23:30:42 mpowers
- * WODisplayGroup now compiles.
+ * Revision 1.14 2003/01/18 23:30:42 mpowers WODisplayGroup now compiles.
*
- * Revision 1.13 2002/10/11 15:35:12 mpowers
- * Removed printlns.
+ * Revision 1.13 2002/10/11 15:35:12 mpowers Removed printlns.
*
- * Revision 1.11 2001/05/02 17:58:41 mpowers
- * Removed debugging code, added comments.
+ * Revision 1.11 2001/05/02 17:58:41 mpowers Removed debugging code, added
+ * comments.
*
- * Revision 1.10 2001/04/08 21:00:54 mpowers
- * Changes to support new objectsForFetchSpecification scheme.
+ * Revision 1.10 2001/04/08 21:00:54 mpowers Changes to support new
+ * objectsForFetchSpecification scheme.
*
- * Revision 1.9 2001/03/29 03:30:36 mpowers
- * Refactored duplicator a bit.
+ * Revision 1.9 2001/03/29 03:30:36 mpowers Refactored duplicator a bit.
* Disabled MissingPropertyExceptions for now.
*
- * Revision 1.8 2001/03/28 17:52:45 mpowers
- * Corrected the throws in the docs.
+ * Revision 1.8 2001/03/28 17:52:45 mpowers Corrected the throws in the docs.
*
- * Revision 1.7 2001/03/28 17:49:13 mpowers
- * Better exception handling in Introspector.
+ * Revision 1.7 2001/03/28 17:49:13 mpowers Better exception handling in
+ * Introspector.
*
- * Revision 1.6 2001/03/13 21:40:20 mpowers
- * Improved handling of runtime exceptions.
+ * Revision 1.6 2001/03/13 21:40:20 mpowers Improved handling of runtime
+ * exceptions.
*
- * Revision 1.5 2001/03/09 22:06:35 mpowers
- * Now extracting the wrapped exception from InvocationTargetExceptions.
+ * Revision 1.5 2001/03/09 22:06:35 mpowers Now extracting the wrapped exception
+ * from InvocationTargetExceptions.
*
- * Revision 1.4 2001/03/01 20:36:35 mpowers
- * Better error handling and better handling of nulls.
+ * Revision 1.4 2001/03/01 20:36:35 mpowers Better error handling and better
+ * handling of nulls.
*
- * Revision 1.3 2001/01/17 16:20:57 mpowers
- * Introspector now handles the identity property.
+ * Revision 1.3 2001/01/17 16:20:57 mpowers Introspector now handles the
+ * identity property.
*
- * Revision 1.2 2001/01/09 20:08:17 mpowers
- * Slight optimization.
+ * Revision 1.2 2001/01/09 20:08:17 mpowers Slight optimization.
*
- * Revision 1.1.1.1 2000/12/21 15:52:04 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:52:04 mpowers Contributing wotonomy.
*
- * Revision 1.5 2000/12/20 16:25:46 michael
- * Added log to all files.
+ * Revision 1.5 2000/12/20 16:25:46 michael Added log to all files.
*
*
*/
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/IntrospectorException.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/IntrospectorException.java
index b1ad824..45080a2 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/IntrospectorException.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/IntrospectorException.java
@@ -19,14 +19,13 @@ License along with this library; if not, see http://www.gnu.org
package net.wotonomy.foundation.internal;
/**
-* A WotonomyException that is thrown by Introspector.
-* This class serves as a base class for other exceptions.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
+ * A WotonomyException that is thrown by Introspector. This class serves as a
+ * base class for other exceptions.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
-public class IntrospectorException extends WotonomyException
-{
+public class IntrospectorException extends WotonomyException {
}
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/MissingPropertyException.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/MissingPropertyException.java
index c1e30d3..c89742f 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/MissingPropertyException.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/MissingPropertyException.java
@@ -19,14 +19,13 @@ License along with this library; if not, see http://www.gnu.org
package net.wotonomy.foundation.internal;
/**
-* A IntrospectorException that is thrown by Introspector when
-* a property does not exist for an object.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
+ * A IntrospectorException that is thrown by Introspector when a property does
+ * not exist for an object.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
-public class MissingPropertyException extends IntrospectorException
-{
+public class MissingPropertyException extends IntrospectorException {
}
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NetworkClassLoader.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NetworkClassLoader.java
index 43c14a5..7761876 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NetworkClassLoader.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NetworkClassLoader.java
@@ -47,7 +47,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
- */
+ */
package net.wotonomy.foundation.internal;
@@ -59,310 +59,284 @@ import java.util.Enumeration;
import java.util.Hashtable;
/**
- * The correct name for this class should be URLClassLoader.
- * But there is already a class by that name in JDK1.2.
+ * The correct name for this class should be URLClassLoader. But there is
+ * already a class by that name in JDK1.2.
*
- * I have had quite a few problems with URLClassLoader in
- * past, so I ended up writing this ClassLoader. I found that
- * the Java 2's URLClassLoader, does not close the Jar file once
- * opened. It is a pretty good optimization step, but if you
- * modify the class in the jar file, it does not pick it up. Some
- * operating systems may not let you modify the jar file while it is
- * still open. IMHO, it does make sense to close the jar file
- * after you are done reading the class data. But this approach may not
- * get you the performance of the URLClassLoader, but it works in all
- * cases and also runs on JDK1.1. I have enhanced this class loader
- * to read all the zip/jar entries once & cache the data, so that
- * there is no overhead of opening/closing jar file to pick up
+ * I have had quite a few problems with URLClassLoader in past, so I ended up
+ * writing this ClassLoader. I found that the Java 2's URLClassLoader, does not
+ * close the Jar file once opened. It is a pretty good optimization step, but if
+ * you modify the class in the jar file, it does not pick it up. Some operating
+ * systems may not let you modify the jar file while it is still open. IMHO, it
+ * does make sense to close the jar file after you are done reading the class
+ * data. But this approach may not get you the performance of the
+ * URLClassLoader, but it works in all cases and also runs on JDK1.1. I have
+ * enhanced this class loader to read all the zip/jar entries once & cache the
+ * data, so that there is no overhead of opening/closing jar file to pick up
* each entry.
*
*
* @author Harish Prabandham
*/
public class NetworkClassLoader extends ClassLoader {
- private ClassLoader parent = null; // parent classloader
- private Hashtable classCache = new Hashtable();
- private Hashtable urlset = new Hashtable();
-
- /**
- * Creates a new instance of the class loader.
- * @param delegate/parent class loader.
- */
- public NetworkClassLoader(ClassLoader parent) {
- setParent(parent);
- }
-
- /**
- * Sets the parent/delegate class loader.
- * @param delegate/parent class loader.
- */
- protected final void setParent(ClassLoader parent) {
- this.parent = parent;
- }
-
- /**
- * Adds the given URL to this class loader. If the URL
- * ends with "/", then it is assumed to be a directory
- * otherwise, it is assumed to be a zip/jar file. If the
- * same URL is added again, the URL is re-opened and this
- * zip/jar file is used for serving any future class requests.
- * @param URL where to look for the classes.
- */
- public synchronized void addURL(URL url) {
- // System.out.println("Adding url: " + url);
- if(!urlset.containsKey(url)) {
- try {
- urlset.put(url, new URLResourceReader(url));
- }catch(IOException ioe){
- // Probably a bad url...
- }
- } else {
- // remove the old one & add a new one...
- try{
- URLResourceReader newu = new URLResourceReader(url);
- URLResourceReader oldu = (URLResourceReader) urlset.get(url);
- oldu.close();
- urlset.remove(url);
- urlset.put(url, newu);
- } catch (IOException ioe) {
- }
- }
- }
-
- /**
- * @return An enumeration of URLs where this class loader
- * looks for classes.
- */
- public Enumeration getURLs() {
- return urlset.keys();
- }
-
- /**
- * Call this to bypass the implementation of loadClass.
- */
- public Class findClass(String name) {
- byte[] b = loadClassData(name);
- if ( b == null ) return null;
- return defineClass(name, b, 0, b.length);
- }
-
- protected byte[] loadResource(URL url, String resourceName)
- throws IOException {
- URLResourceReader urr = (URLResourceReader) urlset.get(url);
- // System.out.println("Loading from " + urr + " " + resourceName);
- if(urr != null) {
- return urr.getResource(resourceName);
- }
-
- return null;
- }
-
- protected byte[] loadResource(String resource) {
- byte[] barray = null;
- for(Enumeration e = urlset.keys(); e.hasMoreElements();) {
- URL url = (URL) e.nextElement();
-
- try {
- barray = loadResource(url, resource);
- } catch(Exception ex) {
- } finally {
- if(barray != null)
- break;
- }
- }
-
- return barray;
- }
-
- protected byte[] loadClassData(String classname) {
- String resourceName = classname.replace('.', '/') + ".class";
- return loadResource(resourceName);
- }
-
- /**
- * Overridden to search for a resource and return
- * a "jar"-style URL or normal "file" URL as necessary.
- */
- protected URL findResource(String name)
- { //System.out.println( "findResource: " + name );
- URL url;
- byte[] barray = null;
-
- for ( Enumeration e = urlset.keys(); e.hasMoreElements(); )
- {
- url = (URL) e.nextElement();
- try
- {
- barray = loadResource(url, name); // loads fully: wasteful
- }
- catch(Exception ex)
- {
- // do nothing
- }
- if( barray != null )
- {
- try
- {
- String ref = url.toString();
- if ( ref.endsWith( ".jar" ) )
- {
- //System.out.println( "jar:" + ref + "!/" + name );
- return new URL( "jar:" + ref + "!/" + name );
- }
- else
- {
- //System.out.println( new URL( url, name ).toString() );
- return new URL( url, name );
- }
- }
- catch ( Throwable t )
- {
- t.printStackTrace();
- }
- }
- }
-
- return null;
- }
-
- /**
- * @return The resource as the input stream if such a resource
- * exists, otherwise returns null.
- */
- public InputStream getResourceAsStream(String name) {
- //System.out.println( "getResourceAsStream: " + name );
- InputStream istream = null;
-
- // Algorithm:
- //
- // 1. first check the system path for the resource
- // 2. next check the delegate/parent class loader for the resource
- // 3. then attempt to get the resource from the url set.
- //
-
- // Lets check the system path for the resource.
- istream = getSystemResourceAsStream(name);
- if(istream != null)
- return istream;
-
- // Lets check the parent/delegate class loader for the resource.
- if(parent != null) {
- istream = parent.getResourceAsStream(name);
- if(istream != null)
- return istream;
- }
-
- // Lets load it ourselves.
- byte[] data = loadResource(name);
- if(data != null) {
- istream = new ByteArrayInputStream(data);
- }
-
- return istream;
- }
-
- /**
- * java.lang.ClassLoader's defineClass method is final, so the
- * its subclasses cannot override this method. But, this class
- * calls this method in the loadClass() instead.
- * @param The name of the class without ".class" extension.
- * @param The class data bytes.
- * @return The class object.
- */
- protected Class defineClass(String classname, byte[] classdata) {
- return defineClass(classname, classdata, 0, classdata.length);
- }
-
- public synchronized Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- Class c = null;
-
- // Algorithm: (Please do not change the order; unless you
- // have a good reason to do so).
- //
- // 1. first check the system class loader.
- // 2. next check the delegate/parent class loader.
- // 3. next check the class cache
- // 4. then attempt to load classes from the URL set.
- //
-
- // Lets see if the class is in system class loader.
- try {
- c = findSystemClass(name);
- }catch(ClassNotFoundException cnfe) {
- }finally {
- if(c != null)
- return c;
- }
-
- // Lets see if the class is in parent class loader.
- try {
- if(parent != null)
- c = parent.loadClass(name);
- }catch(ClassNotFoundException cnfe) {
- }finally {
- if(c != null)
- return c;
- }
-
- // Lets see if the class is in the cache..
- c = (Class) classCache.get(name);
-
- if(c != null)
- return c;
-
-
- // Lets see if we find the class all by ourselves.
- byte[] data = loadClassData(name);
-
- if(data != null) {
- // we did !!
- c = defineClass(name, data);
- classCache.put(name, c);
- if(resolve)
- resolveClass(c);
- } else {
- // We are out of luck at this point...
- throw new ClassNotFoundException(name);
- }
-
- return c;
- }
-
- /**
- * This method resets this ClassLoader's state. It completely
- * removes all the URLs and classes in this class loader cache.
- */
- public final void clear() {
- urlset.clear();
- classCache.clear();
- }
-
- /**
- * This method resets this ClassLoader's state and resets the
- * references for garbage collection.
- */
- protected void finalize() throws Throwable {
- // Cleanup real well. Otherwise, this can be
- // a major source of memory leaks...
-
- // remove all the urls & class entries.
- clear();
-
- parent = null;
- urlset = null;
- classCache = null;
- }
+ private ClassLoader parent = null; // parent classloader
+ private Hashtable classCache = new Hashtable();
+ private Hashtable urlset = new Hashtable();
+
+ /**
+ * Creates a new instance of the class loader.
+ *
+ * @param delegate/parent class loader.
+ */
+ public NetworkClassLoader(ClassLoader parent) {
+ setParent(parent);
+ }
+
+ /**
+ * Sets the parent/delegate class loader.
+ *
+ * @param delegate/parent class loader.
+ */
+ protected final void setParent(ClassLoader parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Adds the given URL to this class loader. If the URL ends with "/", then it is
+ * assumed to be a directory otherwise, it is assumed to be a zip/jar file. If
+ * the same URL is added again, the URL is re-opened and this zip/jar file is
+ * used for serving any future class requests.
+ *
+ * @param URL where to look for the classes.
+ */
+ public synchronized void addURL(URL url) {
+ // System.out.println("Adding url: " + url);
+ if (!urlset.containsKey(url)) {
+ try {
+ urlset.put(url, new URLResourceReader(url));
+ } catch (IOException ioe) {
+ // Probably a bad url...
+ }
+ } else {
+ // remove the old one & add a new one...
+ try {
+ URLResourceReader newu = new URLResourceReader(url);
+ URLResourceReader oldu = (URLResourceReader) urlset.get(url);
+ oldu.close();
+ urlset.remove(url);
+ urlset.put(url, newu);
+ } catch (IOException ioe) {
+ }
+ }
+ }
+
+ /**
+ * @return An enumeration of URLs where this class loader looks for classes.
+ */
+ public Enumeration getURLs() {
+ return urlset.keys();
+ }
+
+ /**
+ * Call this to bypass the implementation of loadClass.
+ */
+ public Class findClass(String name) {
+ byte[] b = loadClassData(name);
+ if (b == null)
+ return null;
+ return defineClass(name, b, 0, b.length);
+ }
+
+ protected byte[] loadResource(URL url, String resourceName) throws IOException {
+ URLResourceReader urr = (URLResourceReader) urlset.get(url);
+ // System.out.println("Loading from " + urr + " " + resourceName);
+ if (urr != null) {
+ return urr.getResource(resourceName);
+ }
+
+ return null;
+ }
+
+ protected byte[] loadResource(String resource) {
+ byte[] barray = null;
+ for (Enumeration e = urlset.keys(); e.hasMoreElements();) {
+ URL url = (URL) e.nextElement();
+
+ try {
+ barray = loadResource(url, resource);
+ } catch (Exception ex) {
+ } finally {
+ if (barray != null)
+ break;
+ }
+ }
+
+ return barray;
+ }
+
+ protected byte[] loadClassData(String classname) {
+ String resourceName = classname.replace('.', '/') + ".class";
+ return loadResource(resourceName);
+ }
+
+ /**
+ * Overridden to search for a resource and return a "jar"-style URL or normal
+ * "file" URL as necessary.
+ */
+ protected URL findResource(String name) { // System.out.println( "findResource: " + name );
+ URL url;
+ byte[] barray = null;
+
+ for (Enumeration e = urlset.keys(); e.hasMoreElements();) {
+ url = (URL) e.nextElement();
+ try {
+ barray = loadResource(url, name); // loads fully: wasteful
+ } catch (Exception ex) {
+ // do nothing
+ }
+ if (barray != null) {
+ try {
+ String ref = url.toString();
+ if (ref.endsWith(".jar")) {
+ // System.out.println( "jar:" + ref + "!/" + name );
+ return new URL("jar:" + ref + "!/" + name);
+ } else {
+ // System.out.println( new URL( url, name ).toString() );
+ return new URL(url, name);
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return The resource as the input stream if such a resource exists, otherwise
+ * returns null.
+ */
+ public InputStream getResourceAsStream(String name) {
+ // System.out.println( "getResourceAsStream: " + name );
+ InputStream istream = null;
+
+ // Algorithm:
+ //
+ // 1. first check the system path for the resource
+ // 2. next check the delegate/parent class loader for the resource
+ // 3. then attempt to get the resource from the url set.
+ //
+
+ // Lets check the system path for the resource.
+ istream = getSystemResourceAsStream(name);
+ if (istream != null)
+ return istream;
+
+ // Lets check the parent/delegate class loader for the resource.
+ if (parent != null) {
+ istream = parent.getResourceAsStream(name);
+ if (istream != null)
+ return istream;
+ }
+
+ // Lets load it ourselves.
+ byte[] data = loadResource(name);
+ if (data != null) {
+ istream = new ByteArrayInputStream(data);
+ }
+
+ return istream;
+ }
+
+ /**
+ * java.lang.ClassLoader's defineClass method is final, so the its subclasses
+ * cannot override this method. But, this class calls this method in the
+ * loadClass() instead.
+ *
+ * @param The name of the class without ".class" extension.
+ * @param The class data bytes.
+ * @return The class object.
+ */
+ protected Class defineClass(String classname, byte[] classdata) {
+ return defineClass(classname, classdata, 0, classdata.length);
+ }
+
+ public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ Class c = null;
+
+ // Algorithm: (Please do not change the order; unless you
+ // have a good reason to do so).
+ //
+ // 1. first check the system class loader.
+ // 2. next check the delegate/parent class loader.
+ // 3. next check the class cache
+ // 4. then attempt to load classes from the URL set.
+ //
+
+ // Lets see if the class is in system class loader.
+ try {
+ c = findSystemClass(name);
+ } catch (ClassNotFoundException cnfe) {
+ } finally {
+ if (c != null)
+ return c;
+ }
+
+ // Lets see if the class is in parent class loader.
+ try {
+ if (parent != null)
+ c = parent.loadClass(name);
+ } catch (ClassNotFoundException cnfe) {
+ } finally {
+ if (c != null)
+ return c;
+ }
+
+ // Lets see if the class is in the cache..
+ c = (Class) classCache.get(name);
+
+ if (c != null)
+ return c;
+
+ // Lets see if we find the class all by ourselves.
+ byte[] data = loadClassData(name);
+
+ if (data != null) {
+ // we did !!
+ c = defineClass(name, data);
+ classCache.put(name, c);
+ if (resolve)
+ resolveClass(c);
+ } else {
+ // We are out of luck at this point...
+ throw new ClassNotFoundException(name);
+ }
+
+ return c;
+ }
+
+ /**
+ * This method resets this ClassLoader's state. It completely removes all the
+ * URLs and classes in this class loader cache.
+ */
+ public final void clear() {
+ urlset.clear();
+ classCache.clear();
+ }
+
+ /**
+ * This method resets this ClassLoader's state and resets the references for
+ * garbage collection.
+ */
+ protected void finalize() throws Throwable {
+ // Cleanup real well. Otherwise, this can be
+ // a major source of memory leaks...
+
+ // remove all the urls & class entries.
+ clear();
+
+ parent = null;
+ urlset = null;
+ classCache = null;
+ }
}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NullPrimitiveException.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NullPrimitiveException.java
index e367211..bf1dffd 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NullPrimitiveException.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/NullPrimitiveException.java
@@ -19,14 +19,13 @@ License along with this library; if not, see http://www.gnu.org
package net.wotonomy.foundation.internal;
/**
-* A IntrospectorException that is thrown by Introspector when
-* trying to set a primitive type to null.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
+ * A IntrospectorException that is thrown by Introspector when trying to set a
+ * primitive type to null.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
-public class NullPrimitiveException extends IntrospectorException
-{
+public class NullPrimitiveException extends IntrospectorException {
}
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyComparator.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyComparator.java
index abdc82f..c804893 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyComparator.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyComparator.java
@@ -21,80 +21,61 @@ package net.wotonomy.foundation.internal;
import java.io.Serializable;
import java.util.Comparator;
-
/**
-* A Comparator that will sort elements based on the
-* property specified in the constructor.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
-public class PropertyComparator implements Comparator, Serializable
-{
- private String property;
+ * A Comparator that will sort elements based on the property specified in the
+ * constructor.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
+public class PropertyComparator implements Comparator, Serializable {
+ private String property;
-/**
-* Standard constructor to configure the comparator.
-* @param aProperty A property whose value is used to sort elements.
-*/
- public PropertyComparator( String aProperty )
- {
+ /**
+ * Standard constructor to configure the comparator.
+ *
+ * @param aProperty A property whose value is used to sort elements.
+ */
+ public PropertyComparator(String aProperty) {
property = aProperty;
- }
+ }
- // interface Comparator
+ // interface Comparator
- public int compare(Object o1, Object o2)
- {
- Object v1 = Introspector.get( o1, property );
- Object v2 = Introspector.get( o2, property );
- if ( v1 instanceof Comparable )
- {
- return ((Comparable)v1).compareTo( v2 );
- }
- else
- if ( v2 instanceof Comparable )
- {
- return ((Comparable)v2).compareTo( v1 );
- }
- else
- {
- if ( v1 == null )
- {
- if ( v2 == null )
- {
+ public int compare(Object o1, Object o2) {
+ Object v1 = Introspector.get(o1, property);
+ Object v2 = Introspector.get(o2, property);
+ if (v1 instanceof Comparable) {
+ return ((Comparable) v1).compareTo(v2);
+ } else if (v2 instanceof Comparable) {
+ return ((Comparable) v2).compareTo(v1);
+ } else {
+ if (v1 == null) {
+ if (v2 == null) {
return 0; // both nulls are equal
}
return -1; // null is less than any object
- }
- else
- if ( v2 == null )
- {
+ } else if (v2 == null) {
return 1; // any object is greater than null
}
}
// last resort: compare string conversions
- return v1.toString().compareTo( v2.toString() );
+ return v1.toString().compareTo(v2.toString());
}
-
- public boolean equals( Object obj )
- {
- return ( obj instanceof PropertyComparator );
+
+ public boolean equals(Object obj) {
+ return (obj instanceof PropertyComparator);
}
}
/*
- * $Log$
- * Revision 1.2 2006/02/16 13:11:47 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * $Log$ Revision 1.2 2006/02/16 13:11:47 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.1.1.1 2000/12/21 15:52:07 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:52:07 mpowers Contributing wotonomy.
*
- * Revision 1.2 2000/12/20 16:25:46 michael
- * Added log to all files.
+ * Revision 1.2 2000/12/20 16:25:46 michael Added log to all files.
*
*
*/
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyListParser.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyListParser.java
index 03231c7..3698325 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyListParser.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/PropertyListParser.java
@@ -23,23 +23,26 @@ import java.io.*;
/**
* PropertyListParser can parse a property list (plist) file or string, and
- * return the top-level object represented by the plist. <p>
+ * return the top-level object represented by the plist.
+ * <p>
*
- * A property list is a heirarchical data structure containing only Maps,
- * Lists, and Strings -- nothing else. In other words, a property list is
- * either a Map, List, or String instance, with the restrictions that the
- * collections may only contain Map, List, or String instances. <p>
+ * A property list is a heirarchical data structure containing only Maps, Lists,
+ * and Strings -- nothing else. In other words, a property list is either a Map,
+ * List, or String instance, with the restrictions that the collections may only
+ * contain Map, List, or String instances.
+ * <p>
*
- * This class can read a particularly-formatted string or file, and create
- * the property list structure described. It provides a convenient means
- * for having a structured data file, letting programs simply deal with the
- * structure rather than having to do a lot of string parsing work as well.
- * The concept is similar to Properties files, except that the values can
- * be nested Maps or Lists instead of only Strings. <p>
+ * This class can read a particularly-formatted string or file, and create the
+ * property list structure described. It provides a convenient means for having
+ * a structured data file, letting programs simply deal with the structure
+ * rather than having to do a lot of string parsing work as well. The concept is
+ * similar to Properties files, except that the values can be nested Maps or
+ * Lists instead of only Strings.
+ * <p>
*
* A Map is specified in a file by key/value pairs surrounded by brace
- * characters. An equal sign (=) must be between the key and value, and
- * there must be a semicolon (;) following the value.
+ * characters. An equal sign (=) must be between the key and value, and there
+ * must be a semicolon (;) following the value.
*
* <pre>
* {
@@ -49,35 +52,42 @@ import java.io.*;
* }
* </pre>
*
- * A List is specified by a comma-separated list of values surrounded by parentheses, like:
+ * A List is specified by a comma-separated list of values surrounded by
+ * parentheses, like:
+ *
* <pre>
* ( value1, value2, value3, etc... )
* </pre>
*
- * A String can either be quoted in the manner of a constant string in
- * Java, or unquoted. If unquoted, the string can only contain
- * alphanumerics, underscores (_), periods (.), dollar signs ($), colons
- * (:), or forward slashes (/). If any other character appears in the
- * string, it must be quoted (i.e., surrounded by &quot; characters).
- * Quoted strings may also contain \n, \t, \f, \v, \b, and \a escapes,
- * octal escapes of the form \000, and unicode escapes of the form of \U
- * followed by four hexadecimal characters. Any other character escaped
- * by a backslash will be treated as that character, and the escaping
- * backslash character will be omitted. Thus, to represent an actual
- * backslash, it must appear as \\ in the quoted string. <p>
+ * A String can either be quoted in the manner of a constant string in Java, or
+ * unquoted. If unquoted, the string can only contain alphanumerics, underscores
+ * (_), periods (.), dollar signs ($), colons (:), or forward slashes (/). If
+ * any other character appears in the string, it must be quoted (i.e.,
+ * surrounded by &quot; characters). Quoted strings may also contain \n, \t, \f,
+ * \v, \b, and \a escapes, octal escapes of the form \000, and unicode escapes
+ * of the form of \U followed by four hexadecimal characters. Any other
+ * character escaped by a backslash will be treated as that character, and the
+ * escaping backslash character will be omitted. Thus, to represent an actual
+ * backslash, it must appear as \\ in the quoted string.
+ * <p>
+ *
+ * All whitespace between elements is ignored, and both //-style and /*-style
+ * comments are allowed to appear anywhere between elements.
+ * <p>
*
- * All whitespace between elements is ignored, and both //-style and
- * /*-style comments are allowed to appear anywhere between elements. <p>
+ * If there are any syntax errors encountered while parsing, RuntimeExceptions
+ * are thrown with the line number and column of the problem.
+ * <p>
*
- * If there are any syntax errors encountered while parsing,
- * RuntimeExceptions are thrown with the line number and column of the
- * problem. <p>
+ * Currenty, HashMaps and ArrayLists are the actual Map and List classes used
+ * when creating the property list.
+ * <p>
*
- * Currenty, HashMaps and ArrayLists are the actual Map and List classes
- * used when creating the property list. <p>
+ * Examples:
+ * <p>
+ * <blockquote>
*
- * Examples: <p><blockquote>
- <pre>
+ * <pre>
// This plist file represents a Map, since it starts with a '{'.
{
Map1 = { subkey1 = "foo"; };
@@ -104,443 +114,425 @@ import java.io.*;
}
);
}
- </pre>
- </blockquote>
- * For those wondering, this is essentially a re-implementation of
+ * </pre>
+ *
+ * </blockquote> For those wondering, this is essentially a re-implementation of
* NeXT/Apple's property lists, except that data values are not supported.
*
* @author clindberg@blacksmith.com
* @version $Revision: 899 $
*/
-public class PropertyListParser
-{
- private char buffer[];
- private int currIndex;
- private int lineNumber;
- private int currLineStartIndex;
-
- /** Reads an object (String, List, or Map) from plistString and returns it.
- * RuntimeExceptions are raised if there are parse problems.
- */
- public static Object propertyListFromString(String plistString)
- {
- PropertyListParser parser = new PropertyListParser(plistString);
- return parser.readTopLevelObject();
- }
-
- /**
- * Reads all remaining characters from the Reader, and returns the
- * result of propertyListFromString(). RuntimeExceptions are raised if
- * there are parse problems
- */
- public static Object propertyListFromReader(Reader reader) throws IOException
- {
- char charBuffer[] = new char[2048];
- StringBuffer stringBuffer = new StringBuffer();
- int numRead = 0;
-
- while (numRead >= 0)
- {
- numRead = reader.read(charBuffer);
- if (numRead > 0) stringBuffer.append(charBuffer, 0, numRead);
- }
-
- return propertyListFromString(stringBuffer.toString());
- }
-
- /**
- * Reads the contents of the specified file, and parses the contents.
- * If any error occurs, prints out a message using System.out.println()
- * and returns null.
- */
- public static Object propertyListFromFile(String filename)
- {
- try {
- FileInputStream stream = new FileInputStream(filename);
- return propertyListFromReader(new InputStreamReader(stream));
- } catch (Exception exception) {
- String errorMessage = exception.getMessage();
- System.out.println("Error parsing property list from "+filename+": "+errorMessage);
- }
-
- return null;
- }
-
- /**
- * Creates a new PropertyListParser to parse the contents of the
- * specified String.
- */
- public PropertyListParser(String plistString)
- {
- this(plistString.toCharArray());
- }
-
- /**
- * Creates a new PropertyListParser to parse the specified char array.
- */
- public PropertyListParser(char[] charArray)
- {
- buffer = charArray;
- lineNumber = 1;
- currLineStartIndex = 1;
- currIndex = 0;
- }
-
- public Object readTopLevelObject()
- {
- Object plist = readObject();
-
- skipCommentWhitespace();
- if (!isAtEnd())
- {
- throwParseException("Extra characters in plist string after parsing object. A plist should only contain one top-level object.");
- }
-
- return plist;
- }
-
- private void throwParseException(String errorMessage)
- {
- int column = currIndex - currLineStartIndex + 1;
- throw new RuntimeException(errorMessage + " (Line " + lineNumber + ", column " + column + ")");
- }
-
- private void updateLineNumberWithIndex(int lineStartIndex)
- {
- lineNumber++;
- currLineStartIndex = lineStartIndex;
- }
-
- private boolean isAtEnd()
- {
- return currIndex >= buffer.length;
- }
-
- private void skipDoubleslashComment()
- {
- while (!isAtEnd() && buffer[currIndex] != '\n') {
- currIndex++;
- }
- }
-
- private void skipStandardCComment()
- {
- currIndex++; //skip over the starting '/'
-
- while (!isAtEnd())
- {
- if (buffer[currIndex] == '\n')
- updateLineNumberWithIndex(currIndex+1);
-
- currIndex++;
-
- if (buffer[currIndex-2] == '*' && buffer[currIndex-1] == '/')
- {
- return;
- }
- }
-
- throwParseException("Input exhausted while parsing comment");
- }
-
- private void skipWhitespace()
- {
- while (!isAtEnd() && isWhitespace(buffer[currIndex]))
- {
- if (buffer[currIndex] == '\n')
- updateLineNumberWithIndex(currIndex+1);
- currIndex++;
- }
- }
-
- private void skipCommentWhitespace()
- {
- boolean done = false;
-
- while (!done)
- {
- done = true;
-
- skipWhitespace();
- if ((buffer.length - currIndex) > 1 && buffer[currIndex] == '/')
- {
- if (buffer[currIndex+1] == '/') {
- done = false; //iterate again
- skipDoubleslashComment();
- }
- else if (buffer[currIndex+1] == '*') {
- done = false; //iterate again
- skipStandardCComment();
- }
- }
- }
- }
-
- private Object readObject()
- {
- skipCommentWhitespace();
- if (isAtEnd()) return null;
-
- // Data (i.e. byte[]) not supported
- if (buffer[currIndex] == '"')
- return readQuotedString();
- if (buffer[currIndex] == '(')
- return readList();
- if (buffer[currIndex] == '{')
- return readMap();
-
- return readUnquotedString();
- }
-
- private static final byte valueForHexDigit(char c)
- {
- if(c >= '0' && c <= '9') return (byte)(c - '0');
- if(c >= 'a' && c <= 'f') return (byte)((c - 'a') + 10);
- if(c >= 'A' && c <= 'F') return (byte)((c - 'A') + 10);
-
- return 0;
- }
-
- private static final boolean isOctalDigit(char c)
- {
- return c >= '0' && c <= '7';
- }
-
- private static final boolean isHexDigit(char c)
- {
- return (c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F');
- }
-
- private static String unquotedStringChars = "._$:/"; // chars allowed in unquoted strings
- private static String whitespaceChars = " \t\n\r\f";
-
- private static final boolean isWhitespace(char c)
- {
- return whitespaceChars.indexOf(c) >= 0;
- }
-
- private static final boolean isValidUnquotedStringChar(char c)
- {
- return ((c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- unquotedStringChars.indexOf(c) >= 0);
- }
-
- private String readUnquotedString()
- {
- int startIndex = currIndex;
-
- while (!isAtEnd() && isValidUnquotedStringChar(buffer[currIndex]))
- currIndex++;
-
- if (startIndex == currIndex)
- throwParseException("No allowable characters found to parse unquoted string");
-
- return new String(buffer, startIndex, currIndex - startIndex);
- }
-
- private String readQuotedString()
- {
- currIndex++; //skip over '"'
-
- StringBuffer stringBuffer = new StringBuffer();
- int startIndex = currIndex;
-
- while (!isAtEnd() && buffer[currIndex] != '"')
- {
- if (buffer[currIndex] != '\\')
- {
- if (buffer[currIndex] == '\n')
- updateLineNumberWithIndex(currIndex+1);
-
- /*
- * Just increment the index -- all these characters will be
- * appended in chunks, either before an escape sequence or
- * at the end.
- */
- currIndex++;
- }
- else // it's an escape
- {
- /* Append anything scanned past before the '\\' */
- if (startIndex < currIndex)
- stringBuffer.append(buffer, startIndex, currIndex - startIndex);
- currIndex++; // skip over '\\'
-
- if (isAtEnd())
- throwParseException("Input exhausted while parsing escape sequence");
-
- switch (buffer[currIndex])
- {
- case 't': stringBuffer.append('\t'); currIndex++; break; // tab
- case 'n': stringBuffer.append('\n'); currIndex++; break; // newline
- case 'r': stringBuffer.append('\r'); currIndex++; break; // carriage return
- case 'f': stringBuffer.append('\f'); currIndex++; break; // form feed
- case 'b': stringBuffer.append('\b'); currIndex++; break; // backspace
- case 'a': stringBuffer.append('\007'); currIndex++; break; // bell
- case 'v': stringBuffer.append('\013'); currIndex++; break; // vertical tab
- case 'U':
- case 'u':
- {
- /* A Unicode escape. Always followed by 4 hex digits. */
- currIndex++; // skip past the 'U'
- if ((currIndex+4) > buffer.length)
- throwParseException("Not enough chars to parse \\U sequence");
-
- if(!isHexDigit(buffer[currIndex]) || !isHexDigit(buffer[currIndex+1]) ||
- !isHexDigit(buffer[currIndex+2]) || !isHexDigit(buffer[currIndex+3]))
- {
- throwParseException("Four hex digits not found for \\U sequence");
- }
-
- byte byte3 = valueForHexDigit(buffer[currIndex]);
- byte byte2 = valueForHexDigit(buffer[currIndex+1]);
- byte byte1 = valueForHexDigit(buffer[currIndex+2]);
- byte byte0 = valueForHexDigit(buffer[currIndex+3]);
- char theChar = (char)((byte3 << 12) + (byte2 << 8) + (byte1 << 4) + byte0);
- stringBuffer.append(theChar);
- currIndex += 4;
- break;
- }
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- {
- /* An octal escape. Expect 1, 2, or 3 octal digits. */
- int digits = 0;
- int value = 0;
-
- do {
- value *= 8;
- value += (int)(buffer[currIndex] - '0');
- currIndex++;
- digits++;
- } while (digits <= 3 && !isAtEnd() && isOctalDigit(buffer[currIndex]));
-
- if (value > 255)
- throwParseException("Value too large in octal escape sequence (> 0377)");
-
- // This assumes value is in ISO Latin 1 encoding
- stringBuffer.append((char)value);
- break;
- }
- /* I guess plists can't have the \x{HEX}{HEX} escapes */
- default:
- {
- // Unknown escape sequence, just add the character.
- // GCC warns if this isn't a '"', '\'', or '\\'...
- stringBuffer.append(buffer[currIndex]);
- if (buffer[currIndex] == '\n')
- updateLineNumberWithIndex(currIndex+1);
- currIndex++;
- break;
- }
- } // end case
-
- /* Reset startIndex, so a verbatim copy will now start from this index */
- startIndex = currIndex;
-
- } //end '\\' escape
- }
-
- if (isAtEnd())
- throwParseException("Input exhausted while parsing quoted string");
- if (startIndex < currIndex)
- stringBuffer.append(buffer, startIndex, currIndex - startIndex);
- currIndex++; //skip past '"'
-
- return stringBuffer.toString();
- }
-
- private List readList()
- {
- List newList = new ArrayList();
-
- currIndex++; //skip over '('
- skipCommentWhitespace();
- while (!isAtEnd() && buffer[currIndex] != ')')
- {
- /* A comma is required between list elements */
- if (newList.size() > 0)
- {
- if (buffer[currIndex] != ',')
- throwParseException("List parsing failed: expecting ','");
- currIndex++;
- skipCommentWhitespace();
- if (isAtEnd())
- throwParseException("Input exhausted while parsing list");
- }
-
- if (buffer[currIndex] != ')')
- {
- Object plistObject = readObject();
- if (plistObject == null)
- throwParseException("List parsing failed: could not read contained object.");
- newList.add(plistObject);
- skipCommentWhitespace();
- }
- }
-
- if (isAtEnd())
- throwParseException("Input exhausted while parsing list");
- currIndex++; //skip past ')'
-
- return newList;
- }
-
- private Map readMap()
- {
- HashMap newMap = new HashMap();
-
- currIndex++; // skip over open brace
- skipCommentWhitespace();
-
- while (!isAtEnd() && buffer[currIndex] != '}')
- {
- Object key;
- Object value;
-
- key = readObject();
- if (key == null || !(key instanceof String))
- throwParseException("Map parsing failed: could not parse key or key is not a String");
-
- skipCommentWhitespace();
- if (isAtEnd() || buffer[currIndex] != '=')
- throwParseException("Map parsing failed: expecting '='");
- currIndex++; //skip over '='
- skipCommentWhitespace();
- if (isAtEnd())
- throwParseException("Input exhausted while parsing map");
-
- value = readObject();
- if (value == null)
- throwParseException("Map parsing failed: could not parse value object");
-
- skipCommentWhitespace();
- if (isAtEnd() || buffer[currIndex] != ';')
- throwParseException("Map parsing failed: expecting ';'");
- currIndex++; //skip over ';'
- skipCommentWhitespace();
-
- newMap.put(key, value);
- }
-
- if (isAtEnd())
- throwParseException("Input exhausted while parsing map");
- currIndex++; //skip past '}'
-
- return newMap;
- }
-
-
- public static void main(String[] args)
- {
- String filename = args[0];
- Object plist = PropertyListParser.propertyListFromFile(filename);
- System.out.println(plist);
- }
+public class PropertyListParser {
+ private char buffer[];
+ private int currIndex;
+ private int lineNumber;
+ private int currLineStartIndex;
+
+ /**
+ * Reads an object (String, List, or Map) from plistString and returns it.
+ * RuntimeExceptions are raised if there are parse problems.
+ */
+ public static Object propertyListFromString(String plistString) {
+ PropertyListParser parser = new PropertyListParser(plistString);
+ return parser.readTopLevelObject();
+ }
+
+ /**
+ * Reads all remaining characters from the Reader, and returns the result of
+ * propertyListFromString(). RuntimeExceptions are raised if there are parse
+ * problems
+ */
+ public static Object propertyListFromReader(Reader reader) throws IOException {
+ char charBuffer[] = new char[2048];
+ StringBuffer stringBuffer = new StringBuffer();
+ int numRead = 0;
+
+ while (numRead >= 0) {
+ numRead = reader.read(charBuffer);
+ if (numRead > 0)
+ stringBuffer.append(charBuffer, 0, numRead);
+ }
+
+ return propertyListFromString(stringBuffer.toString());
+ }
+
+ /**
+ * Reads the contents of the specified file, and parses the contents. If any
+ * error occurs, prints out a message using System.out.println() and returns
+ * null.
+ */
+ public static Object propertyListFromFile(String filename) {
+ try {
+ FileInputStream stream = new FileInputStream(filename);
+ return propertyListFromReader(new InputStreamReader(stream));
+ } catch (Exception exception) {
+ String errorMessage = exception.getMessage();
+ System.out.println("Error parsing property list from " + filename + ": " + errorMessage);
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new PropertyListParser to parse the contents of the specified
+ * String.
+ */
+ public PropertyListParser(String plistString) {
+ this(plistString.toCharArray());
+ }
+
+ /**
+ * Creates a new PropertyListParser to parse the specified char array.
+ */
+ public PropertyListParser(char[] charArray) {
+ buffer = charArray;
+ lineNumber = 1;
+ currLineStartIndex = 1;
+ currIndex = 0;
+ }
+
+ public Object readTopLevelObject() {
+ Object plist = readObject();
+
+ skipCommentWhitespace();
+ if (!isAtEnd()) {
+ throwParseException(
+ "Extra characters in plist string after parsing object. A plist should only contain one top-level object.");
+ }
+
+ return plist;
+ }
+
+ private void throwParseException(String errorMessage) {
+ int column = currIndex - currLineStartIndex + 1;
+ throw new RuntimeException(errorMessage + " (Line " + lineNumber + ", column " + column + ")");
+ }
+
+ private void updateLineNumberWithIndex(int lineStartIndex) {
+ lineNumber++;
+ currLineStartIndex = lineStartIndex;
+ }
+
+ private boolean isAtEnd() {
+ return currIndex >= buffer.length;
+ }
+
+ private void skipDoubleslashComment() {
+ while (!isAtEnd() && buffer[currIndex] != '\n') {
+ currIndex++;
+ }
+ }
+
+ private void skipStandardCComment() {
+ currIndex++; // skip over the starting '/'
+
+ while (!isAtEnd()) {
+ if (buffer[currIndex] == '\n')
+ updateLineNumberWithIndex(currIndex + 1);
+
+ currIndex++;
+
+ if (buffer[currIndex - 2] == '*' && buffer[currIndex - 1] == '/') {
+ return;
+ }
+ }
+
+ throwParseException("Input exhausted while parsing comment");
+ }
+
+ private void skipWhitespace() {
+ while (!isAtEnd() && isWhitespace(buffer[currIndex])) {
+ if (buffer[currIndex] == '\n')
+ updateLineNumberWithIndex(currIndex + 1);
+ currIndex++;
+ }
+ }
+
+ private void skipCommentWhitespace() {
+ boolean done = false;
+
+ while (!done) {
+ done = true;
+
+ skipWhitespace();
+ if ((buffer.length - currIndex) > 1 && buffer[currIndex] == '/') {
+ if (buffer[currIndex + 1] == '/') {
+ done = false; // iterate again
+ skipDoubleslashComment();
+ } else if (buffer[currIndex + 1] == '*') {
+ done = false; // iterate again
+ skipStandardCComment();
+ }
+ }
+ }
+ }
+
+ private Object readObject() {
+ skipCommentWhitespace();
+ if (isAtEnd())
+ return null;
+
+ // Data (i.e. byte[]) not supported
+ if (buffer[currIndex] == '"')
+ return readQuotedString();
+ if (buffer[currIndex] == '(')
+ return readList();
+ if (buffer[currIndex] == '{')
+ return readMap();
+
+ return readUnquotedString();
+ }
+
+ private static final byte valueForHexDigit(char c) {
+ if (c >= '0' && c <= '9')
+ return (byte) (c - '0');
+ if (c >= 'a' && c <= 'f')
+ return (byte) ((c - 'a') + 10);
+ if (c >= 'A' && c <= 'F')
+ return (byte) ((c - 'A') + 10);
+
+ return 0;
+ }
+
+ private static final boolean isOctalDigit(char c) {
+ return c >= '0' && c <= '7';
+ }
+
+ private static final boolean isHexDigit(char c) {
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+ }
+
+ private static String unquotedStringChars = "._$:/"; // chars allowed in unquoted strings
+ private static String whitespaceChars = " \t\n\r\f";
+
+ private static final boolean isWhitespace(char c) {
+ return whitespaceChars.indexOf(c) >= 0;
+ }
+
+ private static final boolean isValidUnquotedStringChar(char c) {
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
+ || unquotedStringChars.indexOf(c) >= 0);
+ }
+
+ private String readUnquotedString() {
+ int startIndex = currIndex;
+
+ while (!isAtEnd() && isValidUnquotedStringChar(buffer[currIndex]))
+ currIndex++;
+
+ if (startIndex == currIndex)
+ throwParseException("No allowable characters found to parse unquoted string");
+
+ return new String(buffer, startIndex, currIndex - startIndex);
+ }
+
+ private String readQuotedString() {
+ currIndex++; // skip over '"'
+
+ StringBuffer stringBuffer = new StringBuffer();
+ int startIndex = currIndex;
+
+ while (!isAtEnd() && buffer[currIndex] != '"') {
+ if (buffer[currIndex] != '\\') {
+ if (buffer[currIndex] == '\n')
+ updateLineNumberWithIndex(currIndex + 1);
+
+ /*
+ * Just increment the index -- all these characters will be appended in chunks,
+ * either before an escape sequence or at the end.
+ */
+ currIndex++;
+ } else // it's an escape
+ {
+ /* Append anything scanned past before the '\\' */
+ if (startIndex < currIndex)
+ stringBuffer.append(buffer, startIndex, currIndex - startIndex);
+ currIndex++; // skip over '\\'
+
+ if (isAtEnd())
+ throwParseException("Input exhausted while parsing escape sequence");
+
+ switch (buffer[currIndex]) {
+ case 't':
+ stringBuffer.append('\t');
+ currIndex++;
+ break; // tab
+ case 'n':
+ stringBuffer.append('\n');
+ currIndex++;
+ break; // newline
+ case 'r':
+ stringBuffer.append('\r');
+ currIndex++;
+ break; // carriage return
+ case 'f':
+ stringBuffer.append('\f');
+ currIndex++;
+ break; // form feed
+ case 'b':
+ stringBuffer.append('\b');
+ currIndex++;
+ break; // backspace
+ case 'a':
+ stringBuffer.append('\007');
+ currIndex++;
+ break; // bell
+ case 'v':
+ stringBuffer.append('\013');
+ currIndex++;
+ break; // vertical tab
+ case 'U':
+ case 'u': {
+ /* A Unicode escape. Always followed by 4 hex digits. */
+ currIndex++; // skip past the 'U'
+ if ((currIndex + 4) > buffer.length)
+ throwParseException("Not enough chars to parse \\U sequence");
+
+ if (!isHexDigit(buffer[currIndex]) || !isHexDigit(buffer[currIndex + 1])
+ || !isHexDigit(buffer[currIndex + 2]) || !isHexDigit(buffer[currIndex + 3])) {
+ throwParseException("Four hex digits not found for \\U sequence");
+ }
+
+ byte byte3 = valueForHexDigit(buffer[currIndex]);
+ byte byte2 = valueForHexDigit(buffer[currIndex + 1]);
+ byte byte1 = valueForHexDigit(buffer[currIndex + 2]);
+ byte byte0 = valueForHexDigit(buffer[currIndex + 3]);
+ char theChar = (char) ((byte3 << 12) + (byte2 << 8) + (byte1 << 4) + byte0);
+ stringBuffer.append(theChar);
+ currIndex += 4;
+ break;
+ }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': {
+ /* An octal escape. Expect 1, 2, or 3 octal digits. */
+ int digits = 0;
+ int value = 0;
+
+ do {
+ value *= 8;
+ value += (int) (buffer[currIndex] - '0');
+ currIndex++;
+ digits++;
+ } while (digits <= 3 && !isAtEnd() && isOctalDigit(buffer[currIndex]));
+
+ if (value > 255)
+ throwParseException("Value too large in octal escape sequence (> 0377)");
+
+ // This assumes value is in ISO Latin 1 encoding
+ stringBuffer.append((char) value);
+ break;
+ }
+ /* I guess plists can't have the \x{HEX}{HEX} escapes */
+ default: {
+ // Unknown escape sequence, just add the character.
+ // GCC warns if this isn't a '"', '\'', or '\\'...
+ stringBuffer.append(buffer[currIndex]);
+ if (buffer[currIndex] == '\n')
+ updateLineNumberWithIndex(currIndex + 1);
+ currIndex++;
+ break;
+ }
+ } // end case
+
+ /* Reset startIndex, so a verbatim copy will now start from this index */
+ startIndex = currIndex;
+
+ } // end '\\' escape
+ }
+
+ if (isAtEnd())
+ throwParseException("Input exhausted while parsing quoted string");
+ if (startIndex < currIndex)
+ stringBuffer.append(buffer, startIndex, currIndex - startIndex);
+ currIndex++; // skip past '"'
+
+ return stringBuffer.toString();
+ }
+
+ private List readList() {
+ List newList = new ArrayList();
+
+ currIndex++; // skip over '('
+ skipCommentWhitespace();
+ while (!isAtEnd() && buffer[currIndex] != ')') {
+ /* A comma is required between list elements */
+ if (newList.size() > 0) {
+ if (buffer[currIndex] != ',')
+ throwParseException("List parsing failed: expecting ','");
+ currIndex++;
+ skipCommentWhitespace();
+ if (isAtEnd())
+ throwParseException("Input exhausted while parsing list");
+ }
+
+ if (buffer[currIndex] != ')') {
+ Object plistObject = readObject();
+ if (plistObject == null)
+ throwParseException("List parsing failed: could not read contained object.");
+ newList.add(plistObject);
+ skipCommentWhitespace();
+ }
+ }
+
+ if (isAtEnd())
+ throwParseException("Input exhausted while parsing list");
+ currIndex++; // skip past ')'
+
+ return newList;
+ }
+
+ private Map readMap() {
+ HashMap newMap = new HashMap();
+
+ currIndex++; // skip over open brace
+ skipCommentWhitespace();
+
+ while (!isAtEnd() && buffer[currIndex] != '}') {
+ Object key;
+ Object value;
+
+ key = readObject();
+ if (key == null || !(key instanceof String))
+ throwParseException("Map parsing failed: could not parse key or key is not a String");
+
+ skipCommentWhitespace();
+ if (isAtEnd() || buffer[currIndex] != '=')
+ throwParseException("Map parsing failed: expecting '='");
+ currIndex++; // skip over '='
+ skipCommentWhitespace();
+ if (isAtEnd())
+ throwParseException("Input exhausted while parsing map");
+
+ value = readObject();
+ if (value == null)
+ throwParseException("Map parsing failed: could not parse value object");
+
+ skipCommentWhitespace();
+ if (isAtEnd() || buffer[currIndex] != ';')
+ throwParseException("Map parsing failed: expecting ';'");
+ currIndex++; // skip over ';'
+ skipCommentWhitespace();
+
+ newMap.put(key, value);
+ }
+
+ if (isAtEnd())
+ throwParseException("Input exhausted while parsing map");
+ currIndex++; // skip past '}'
+
+ return newMap;
+ }
+
+ public static void main(String[] args) {
+ String filename = args[0];
+ Object plist = PropertyListParser.propertyListFromFile(filename);
+ System.out.println(plist);
+ }
}
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/QueueMap.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/QueueMap.java
index 6d35b7b..59104e5 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/QueueMap.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/QueueMap.java
@@ -21,518 +21,488 @@ package net.wotonomy.foundation.internal;
import java.util.*; //collections
/**
-* A queue based implementation of the Map interface. This class provides for
-* all the opertions of a map, but keeps the entries in the same sequence as
-* originally added. The first entry placed in the map will be the first
-* entry retreived during iteration: first-in, first-out (FIFO). <BR><BR>
-*
-* Keys cannot be duplicated. If an entry is made using a key that already
-* exists, the value for that key will be replaced with that new value. There
-* are no such restrictions on the values. The values may be null. <BR><BR>
-*
-* Some convenience methods are provided for the queue type operations. The
-* first key can be retreived as well as the last key. A key can be used
-* to retreive its corresponding value from the map. A value can also be used
-* to retreive its key from the map, however, since there may be multiple values
-* of the same equality, the first key found will be returned. <BR><BR>
-*
-* @author rglista@blacksmith.com
-* @author mpowers@blacksmith.com
-* @date $Date: 2006-02-18 17:41:36 -0500 (Sat, 18 Feb 2006) $
-* @revision $Revision: 899 $
-*/
-public class QueueMap implements Map
-{
- List values;
- List keys;
- Map keyToValue;
-
-/**
-* Creates an empty QueueMap.
-*/
- public QueueMap()
- {
- values = new LinkedList();
- keys = new LinkedList();
- keyToValue = new HashMap();
- }
-
-/**
-* Creates a QueueMap and places the entries from the passed in map into this map.
-* The order of the entries is based on however the iterator iteratated through
-* the map entries.
-* @param t A map object.
-*/
- public QueueMap( Map t )
- {
- values = new ArrayList();
- keys = new ArrayList();
- keyToValue = new HashMap();
-
- putAll( t );
- }
-
-/**
-* Removes all the entries from this map.
-*/
- public void clear()
- {
- values.clear();
- keys.clear();
- keyToValue.clear();
- }
-
-/**
-* Tests to see if the key is contained in the map. If the key is present in
-* the map, then TRUE is returned, otherwise FALSE is returned. The equals()
-* operation is used to determine equality.
-* @return True if the map contains the given key, false otherwise.
-*/
- public boolean containsKey( Object key )
- {
- return keyToValue.containsKey( key );
- }
-
-/**
-* Tests to see if the value is contained in the map. If the value is present in
-* the map, then TRUE is returned, otherwise FALSE is returned. The equals()
-* operation is used to determine equality. The value can be null and will
-* return TRUE if null is a value in the map. If TRUE is returned, then there
-* may be more than one values in the map.
-* @return True if the map contains the given value, false otherwise.
-*/
- public boolean containsValue( Object value )
- {
- return keyToValue.containsValue( value );
- }
-
-/**
-* Returns a set view of the mappings contained in this map. Each element
-* in the returned set is a <tt>Map.Entry</tt>. The returned set is NOT backed
-* by the map, so changes to the map are NOT reflected in the set, and vice-versa.
-* The returned set is independent of this Map and its underlying structure.
-*
-* @return a set view of the mappings contained in this map.
-*/
- public Set entrySet()
- {
- Set result = new HashSet(keys.size(), 1F);
-
- for ( int i = 0; i < keys.size(); i++ )
- {
- result.add( new KeyValuePair( keys.get(i), values.get(i) ) );
- }
-
- return result;
- }
-
-/**
-* Compares the specified object with this map for equality. Returns
-* <tt>true</tt> if the given object is also a map and the two Maps
-* represent the same mappings. More formally, two maps <tt>t1</tt> and
-* <tt>t2</tt> represent the same mappings if
-* <tt>t1.entrySet().equals(t2.entrySet())</tt>. This ensures that the
-* <tt>equals</tt> method works properly across different implementations
-* of the <tt>Map</tt> interface.
-*
-* @param o object to be compared for equality with this map.
-* @return <tt>true</tt> if the specified object is equal to this map.
-*/
- public boolean equals( Object o )
- {
- return keyToValue.equals( o );
- }
-
-/**
-* Returns the corresponding value for the given key. The returned value may be
-* null as that is a legal value in this map. However, if the key is not
-* contained in this map then null is also returned. Use the containsKey()
-* method to distinguish between the two cases.
-* @param key A key into the map.
-* @return The value corresponding to the key (can be null), or null if the key
-* is not contained in the map.
-*/
- public Object get( Object key )
- {
- return keyToValue.get( key );
- }
-
-/**
-* Returns the hash code value for this map. The hash code of a map
-* is defined to be the sum of the hashCodes of each entry in the map's
-* entrySet view. This ensures that <tt>t1.equals(t2)</tt> implies
-* that <tt>t1.hashCode()==t2.hashCode()</tt> for any two maps
-* <tt>t1</tt> and <tt>t2</tt>, as required by the general
-* contract of Object.hashCode.
-*
-* @return the hash code value for this map.
-*/
- public int hashCode()
- {
- return keyToValue.hashCode();
- }
-
-/**
-* Returns true is this map contains no key-value mappings.
-* @return True is this map contains no entries, false otherwise.
-*/
- public boolean isEmpty()
- {
- return keyToValue.isEmpty();
- }
-
-/**
-* Returns the keys used in the map. There is no order implied in the returned
-* set and may be different than the the order in which they were inserted.
-* @return A Set containing all the keys used in the map.
-*/
- public Set keySet()
- {
- Set result = new HashSet(keys.size(), 1F);
-
- for ( int i = 0; i < keys.size(); i++ )
- {
- result.add( keys.get(i) );
- }
-
- return result;
- }
-
-/**
-* Places the key/value entry into the map at the end position. If the key
-* already exists in the map, then its value is replaced by the new given
-* value. The mapping does not change order in this case. The specified
-* key cannot be null.
-* @param key The key to place into the map, cannot be null.
-* @param value The value to associate with the key, may be null.
-* @return Null if the key is new, the replaced value if the key already
-* existed. (Note: If the key was null, then null is returned.)
-*/
- public Object put( Object key, Object value )
- {
- if ( key == null ) return null;
-
- if ( keys.contains( key ) )
- {
- values.remove( keys.indexOf( key ) );
- values.add( keys.indexOf( key ), value );
- }
- else
- {
- values.add( value );
- keys.add( key );
- }
-
- return keyToValue.put( key, value );
- }
-
-/**
-* Places all the entries from this given map into this map. If the keys
-* already exist, then there values are replaced.
-* @param t A map of key/value entries.
-*/
- public void putAll( Map t )
- {
- if ( t == null )
- {
- // Nothing to do!
- return;
- }
-
- // Place the entries from the passed in map into this map.
- for ( Iterator it = t.keySet().iterator(); it.hasNext(); )
- {
- Object aKey = it.next();
- put( aKey, t.get( aKey ) );
- }
- }
-
-/**
-* Remove the mapping of the key and associated value from this map.
-* Note: null is a valid value in the map.
-* @param key A key to remove from the map, cannot be null.
-* @return The value of the removed mapping, null if the mapping did not exist.
-* Null could also be returned if the associated value of the key was null.
-*/
- public Object remove( Object key )
- {
- if ( key == null ) return null;
-
- Object value = null;
-
- if ( containsKey( key ) )
- {
- value = keyToValue.remove( key );
- int i = values.indexOf( value );
- if ( i != -1 )
- {
- keys.remove( i );
- values.remove( i );
- }
- }
-
- return value;
- }
-
-/**
-* Returns the number of key/value pairs in this map.
-* @return The number of pairs.
-*/
- public int size()
- {
- return values.size();
- }
-
-/**
-* Returns an ordered list of keys from the map. The order is the same
-* as the added order of the mapped items.<br>
-* NOTE: The returned list is the underlying keys list used by this class.
-* If modification are to be made to this list, it should be cloned first.
-* @return An ordered list of keys.
-*/
- public List keys()
- {
- return keys;
- }
-
-/**
-* Returns an ordered list of values from the map. The order is the same
-* as the added order of the mapped items.
-* NOTE: The returned list is the underlying keys list used by this class.
-* If modification are to be made to this list, it should be cloned first.
-* @return An ordered list of values.
-*/
- public Collection values()
- {
- return values;
- }
-
-/**
-* Returns the corresponding value for the given key. The returned value may be
-* null as that is a legal value in this map. However, if the key is not
-* contained in this map then null is also returned. Use the containsKey()
-* method to distinguish between the two cases.
-* @param key A key into the map.
-* @return The value corresponding to the key (can be null), or null if the key
-* is not contained in the map.
-*/
- public Object getValueForKey( Object key )
- {
- return keyToValue.get( key );
- }
-
-/**
-* Returns the associated key for this value. Since there may be more than one
-* of the same value in the map, this returns the first key associated with this
-* value. Null is returned if the value is not in the map.
-* @param value A value that is contained in this map.
-* @return A first key that corresponds to this value.
-*/
- public Object getKeyForValue( Object value )
- {
- int i = values.indexOf( value );
- if ( i != -1 )
- {
- return keys.get( i );
- }
- return null;
- }
-
-/**
-* Returns the first key in the map. If the map is empty, then null is
-* returned.
-* @return The first key in the map, null if there are no mappings.
-*/
- public Object getFirstKey()
- {
- if ( keys.size() < 1 )
- {
- return null;
- }
- return keys.get(0);
- }
-
-/**
-* Returns the last key in the map. If the map is empty, then null is
-* returned.
-* @return The last key in the map, null if there are no mappings.
-*/
- public Object getLastKey()
- {
- if ( keys.size() < 1 )
- {
- return null;
- }
- return keys.get( keys.size() -1 );
- }
-
-/**
-* This class contains a key/value pair. The key must be a valid object,
-* it cannot be null. The value can be a valid object or null.
-*/
- static public class KeyValuePair implements Map.Entry
- {
- Object key;
- Object value;
-
- /**
- * Default constructor. The constructor takes the key and value as parameters.
- * Since the key cannot be null, it must be specified during initialization.
- * The value can be null.
- * @param key The key object of this pair. The key cannot be null.
- * @param value The value object of this pair. The value can be null.
- */
- public KeyValuePair( Object aKey, Object aValue )
- {
- key = aKey;
- value = aValue;
- }
-
- /**
- * Returns the key object of this pair.
- * @return The key object.
- */
- public Object getKey()
- {
- return key;
- }
-
- /**
- * Returns the the value object of this pair. May be null.
- * @return The value object.
- */
- public Object getValue()
- {
- return value;
- }
-
- /**
- * Sets the value object of this pair. May be an object or null.
- * @param aValue The value object to place into this pair.
- */
- public Object setValue( Object aValue )
- {
- Object result = value;
- value = aValue;
- return result;
- }
-
- public boolean equals( Object o )
- {
- if ( o instanceof KeyValuePair )
- {
- KeyValuePair p = (KeyValuePair) o;
- if ( ( key.equals( p.getKey() ) ) && ( value.equals( p.getValue() ) ) )
- {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * Returns a string reprsentation of this class. The contents of the
- * map are placed in the string in its proper order.
- */
- public String toString()
- {
- int max = size() - 1;
- StringBuffer buf = new StringBuffer();
-
- buf.append("{");
- for (int j = 0; j <= max; j++)
- {
- buf.append(keys.get(j) + "=" + values.get(j));
- if (j < max)
- {
- buf.append(", ");
- }
- }
- buf.append("}");
-
- return buf.toString();
- }
-
- // unit test
- public static void main( String[] argv )
- {
- QueueMap qMap;
-
- qMap = new QueueMap();
- for (int i = 0; i < 5; i++)
- {
- qMap.put(Integer.toString(i), Integer.toString(i));
- }
- System.out.println("\nMap = " + qMap);
- System.out.println("Keys = " + qMap.keys());
- System.out.println("Values = " + qMap.values());
-
- qMap = new QueueMap();
- for (int i = 0; i < 5; i++)
- {
- qMap.put(Integer.toString(i), "A");
- }
- System.out.println("\nMap = " + qMap);
- System.out.println("Keys = " + qMap.keys());
- System.out.println("Values = " + qMap.values());
-
- qMap = new QueueMap();
- for (int i = 0; i < 5; i++)
- {
- qMap.put(Integer.toString(i), null);
- }
- System.out.println("\nMap = " + qMap);
- System.out.println("Keys = " + qMap.keys());
- System.out.println("Values = " + qMap.values());
-
- Map aMap = new HashMap();
- for (int i = 0; i < 5; i++)
- {
- aMap.put(Integer.toString(i), Integer.toString(i));
- }
- qMap = new QueueMap( aMap );
- System.out.println("\nHashMap = " + aMap);
- System.out.println("Map = " + qMap);
- System.out.println("Keys = " + qMap.keys());
- System.out.println("Values = " + qMap.values());
-
- qMap = new QueueMap();
- qMap.put( "Test1", "String1" );
- qMap.put( "Test2", "String2" );
- qMap.put( "Test3", "String3" );
- qMap.put( "Test4", "String4" );
- qMap.put( "Test5", "String5" );
- System.out.println("\nStandard Test, Map = " + qMap);
- qMap.put( "Test6", "String6" );
- qMap.put( "Test7", "String7" );
- System.out.println("Put New Test, Map = " + qMap);
- qMap.put( "Test2", "New String2" );
- qMap.put( "Test6", "New String6" );
- System.out.println("Put Existing Test, Map = " + qMap);
- qMap.put( "Test5", null );
- qMap.put( "Test8", null );
- System.out.println("Put Null Test, Map = " + qMap);
- qMap.remove( "Test1" );
- qMap.remove( "Test3" );
- qMap.remove( "Test5" );
- qMap.remove( "Test9" );
- System.out.println("Remove Test, Map = " + qMap);
- System.out.println(" Keys = " + qMap.keys());
- System.out.println(" Values = " + qMap.values());
- qMap.clear();
- qMap.put( "Test10", "String10" );
- qMap.put( "Test11", "String11" );
- qMap.put( "Test12", "String12" );
- System.out.println("Clear Test, Map = " + qMap);
-
- aMap = new HashMap();
- aMap.put( "Test10", "String10" );
- aMap.put( "Test11", "String11" );
- aMap.put( "Test12", "String12" );
- System.out.println("Equality Test, Equal = " + qMap.equals( aMap ));
- }
+ * A queue based implementation of the Map interface. This class provides for
+ * all the opertions of a map, but keeps the entries in the same sequence as
+ * originally added. The first entry placed in the map will be the first entry
+ * retreived during iteration: first-in, first-out (FIFO). <BR>
+ * <BR>
+ *
+ * Keys cannot be duplicated. If an entry is made using a key that already
+ * exists, the value for that key will be replaced with that new value. There
+ * are no such restrictions on the values. The values may be null. <BR>
+ * <BR>
+ *
+ * Some convenience methods are provided for the queue type operations. The
+ * first key can be retreived as well as the last key. A key can be used to
+ * retreive its corresponding value from the map. A value can also be used to
+ * retreive its key from the map, however, since there may be multiple values of
+ * the same equality, the first key found will be returned. <BR>
+ * <BR>
+ *
+ * @author rglista@blacksmith.com
+ * @author mpowers@blacksmith.com
+ * @date $Date: 2006-02-18 17:41:36 -0500 (Sat, 18 Feb 2006) $
+ * @revision $Revision: 899 $
+ */
+public class QueueMap implements Map {
+ List values;
+ List keys;
+ Map keyToValue;
+
+ /**
+ * Creates an empty QueueMap.
+ */
+ public QueueMap() {
+ values = new LinkedList();
+ keys = new LinkedList();
+ keyToValue = new HashMap();
+ }
+
+ /**
+ * Creates a QueueMap and places the entries from the passed in map into this
+ * map. The order of the entries is based on however the iterator iteratated
+ * through the map entries.
+ *
+ * @param t A map object.
+ */
+ public QueueMap(Map t) {
+ values = new ArrayList();
+ keys = new ArrayList();
+ keyToValue = new HashMap();
+
+ putAll(t);
+ }
+
+ /**
+ * Removes all the entries from this map.
+ */
+ public void clear() {
+ values.clear();
+ keys.clear();
+ keyToValue.clear();
+ }
+
+ /**
+ * Tests to see if the key is contained in the map. If the key is present in the
+ * map, then TRUE is returned, otherwise FALSE is returned. The equals()
+ * operation is used to determine equality.
+ *
+ * @return True if the map contains the given key, false otherwise.
+ */
+ public boolean containsKey(Object key) {
+ return keyToValue.containsKey(key);
+ }
+
+ /**
+ * Tests to see if the value is contained in the map. If the value is present in
+ * the map, then TRUE is returned, otherwise FALSE is returned. The equals()
+ * operation is used to determine equality. The value can be null and will
+ * return TRUE if null is a value in the map. If TRUE is returned, then there
+ * may be more than one values in the map.
+ *
+ * @return True if the map contains the given value, false otherwise.
+ */
+ public boolean containsValue(Object value) {
+ return keyToValue.containsValue(value);
+ }
+
+ /**
+ * Returns a set view of the mappings contained in this map. Each element in the
+ * returned set is a <tt>Map.Entry</tt>. The returned set is NOT backed by the
+ * map, so changes to the map are NOT reflected in the set, and vice-versa. The
+ * returned set is independent of this Map and its underlying structure.
+ *
+ * @return a set view of the mappings contained in this map.
+ */
+ public Set entrySet() {
+ Set result = new HashSet(keys.size(), 1F);
+
+ for (int i = 0; i < keys.size(); i++) {
+ result.add(new KeyValuePair(keys.get(i), values.get(i)));
+ }
+
+ return result;
+ }
+
+ /**
+ * Compares the specified object with this map for equality. Returns
+ * <tt>true</tt> if the given object is also a map and the two Maps represent
+ * the same mappings. More formally, two maps <tt>t1</tt> and <tt>t2</tt>
+ * represent the same mappings if <tt>t1.entrySet().equals(t2.entrySet())</tt>.
+ * This ensures that the <tt>equals</tt> method works properly across different
+ * implementations of the <tt>Map</tt> interface.
+ *
+ * @param o object to be compared for equality with this map.
+ * @return <tt>true</tt> if the specified object is equal to this map.
+ */
+ public boolean equals(Object o) {
+ return keyToValue.equals(o);
+ }
+
+ /**
+ * Returns the corresponding value for the given key. The returned value may be
+ * null as that is a legal value in this map. However, if the key is not
+ * contained in this map then null is also returned. Use the containsKey()
+ * method to distinguish between the two cases.
+ *
+ * @param key A key into the map.
+ * @return The value corresponding to the key (can be null), or null if the key
+ * is not contained in the map.
+ */
+ public Object get(Object key) {
+ return keyToValue.get(key);
+ }
+
+ /**
+ * Returns the hash code value for this map. The hash code of a map is defined
+ * to be the sum of the hashCodes of each entry in the map's entrySet view. This
+ * ensures that <tt>t1.equals(t2)</tt> implies that
+ * <tt>t1.hashCode()==t2.hashCode()</tt> for any two maps <tt>t1</tt> and
+ * <tt>t2</tt>, as required by the general contract of Object.hashCode.
+ *
+ * @return the hash code value for this map.
+ */
+ public int hashCode() {
+ return keyToValue.hashCode();
+ }
+
+ /**
+ * Returns true is this map contains no key-value mappings.
+ *
+ * @return True is this map contains no entries, false otherwise.
+ */
+ public boolean isEmpty() {
+ return keyToValue.isEmpty();
+ }
+
+ /**
+ * Returns the keys used in the map. There is no order implied in the returned
+ * set and may be different than the the order in which they were inserted.
+ *
+ * @return A Set containing all the keys used in the map.
+ */
+ public Set keySet() {
+ Set result = new HashSet(keys.size(), 1F);
+
+ for (int i = 0; i < keys.size(); i++) {
+ result.add(keys.get(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * Places the key/value entry into the map at the end position. If the key
+ * already exists in the map, then its value is replaced by the new given value.
+ * The mapping does not change order in this case. The specified key cannot be
+ * null.
+ *
+ * @param key The key to place into the map, cannot be null.
+ * @param value The value to associate with the key, may be null.
+ * @return Null if the key is new, the replaced value if the key already
+ * existed. (Note: If the key was null, then null is returned.)
+ */
+ public Object put(Object key, Object value) {
+ if (key == null)
+ return null;
+
+ if (keys.contains(key)) {
+ values.remove(keys.indexOf(key));
+ values.add(keys.indexOf(key), value);
+ } else {
+ values.add(value);
+ keys.add(key);
+ }
+
+ return keyToValue.put(key, value);
+ }
+
+ /**
+ * Places all the entries from this given map into this map. If the keys already
+ * exist, then there values are replaced.
+ *
+ * @param t A map of key/value entries.
+ */
+ public void putAll(Map t) {
+ if (t == null) {
+ // Nothing to do!
+ return;
+ }
+
+ // Place the entries from the passed in map into this map.
+ for (Iterator it = t.keySet().iterator(); it.hasNext();) {
+ Object aKey = it.next();
+ put(aKey, t.get(aKey));
+ }
+ }
+
+ /**
+ * Remove the mapping of the key and associated value from this map. Note: null
+ * is a valid value in the map.
+ *
+ * @param key A key to remove from the map, cannot be null.
+ * @return The value of the removed mapping, null if the mapping did not exist.
+ * Null could also be returned if the associated value of the key was
+ * null.
+ */
+ public Object remove(Object key) {
+ if (key == null)
+ return null;
+
+ Object value = null;
+
+ if (containsKey(key)) {
+ value = keyToValue.remove(key);
+ int i = values.indexOf(value);
+ if (i != -1) {
+ keys.remove(i);
+ values.remove(i);
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * Returns the number of key/value pairs in this map.
+ *
+ * @return The number of pairs.
+ */
+ public int size() {
+ return values.size();
+ }
+
+ /**
+ * Returns an ordered list of keys from the map. The order is the same as the
+ * added order of the mapped items.<br>
+ * NOTE: The returned list is the underlying keys list used by this class. If
+ * modification are to be made to this list, it should be cloned first.
+ *
+ * @return An ordered list of keys.
+ */
+ public List keys() {
+ return keys;
+ }
+
+ /**
+ * Returns an ordered list of values from the map. The order is the same as the
+ * added order of the mapped items. NOTE: The returned list is the underlying
+ * keys list used by this class. If modification are to be made to this list, it
+ * should be cloned first.
+ *
+ * @return An ordered list of values.
+ */
+ public Collection values() {
+ return values;
+ }
+
+ /**
+ * Returns the corresponding value for the given key. The returned value may be
+ * null as that is a legal value in this map. However, if the key is not
+ * contained in this map then null is also returned. Use the containsKey()
+ * method to distinguish between the two cases.
+ *
+ * @param key A key into the map.
+ * @return The value corresponding to the key (can be null), or null if the key
+ * is not contained in the map.
+ */
+ public Object getValueForKey(Object key) {
+ return keyToValue.get(key);
+ }
+
+ /**
+ * Returns the associated key for this value. Since there may be more than one
+ * of the same value in the map, this returns the first key associated with this
+ * value. Null is returned if the value is not in the map.
+ *
+ * @param value A value that is contained in this map.
+ * @return A first key that corresponds to this value.
+ */
+ public Object getKeyForValue(Object value) {
+ int i = values.indexOf(value);
+ if (i != -1) {
+ return keys.get(i);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first key in the map. If the map is empty, then null is returned.
+ *
+ * @return The first key in the map, null if there are no mappings.
+ */
+ public Object getFirstKey() {
+ if (keys.size() < 1) {
+ return null;
+ }
+ return keys.get(0);
+ }
+
+ /**
+ * Returns the last key in the map. If the map is empty, then null is returned.
+ *
+ * @return The last key in the map, null if there are no mappings.
+ */
+ public Object getLastKey() {
+ if (keys.size() < 1) {
+ return null;
+ }
+ return keys.get(keys.size() - 1);
+ }
+
+ /**
+ * This class contains a key/value pair. The key must be a valid object, it
+ * cannot be null. The value can be a valid object or null.
+ */
+ static public class KeyValuePair implements Map.Entry {
+ Object key;
+ Object value;
+
+ /**
+ * Default constructor. The constructor takes the key and value as parameters.
+ * Since the key cannot be null, it must be specified during initialization. The
+ * value can be null.
+ *
+ * @param key The key object of this pair. The key cannot be null.
+ * @param value The value object of this pair. The value can be null.
+ */
+ public KeyValuePair(Object aKey, Object aValue) {
+ key = aKey;
+ value = aValue;
+ }
+
+ /**
+ * Returns the key object of this pair.
+ *
+ * @return The key object.
+ */
+ public Object getKey() {
+ return key;
+ }
+
+ /**
+ * Returns the the value object of this pair. May be null.
+ *
+ * @return The value object.
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value object of this pair. May be an object or null.
+ *
+ * @param aValue The value object to place into this pair.
+ */
+ public Object setValue(Object aValue) {
+ Object result = value;
+ value = aValue;
+ return result;
+ }
+
+ public boolean equals(Object o) {
+ if (o instanceof KeyValuePair) {
+ KeyValuePair p = (KeyValuePair) o;
+ if ((key.equals(p.getKey())) && (value.equals(p.getValue()))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns a string reprsentation of this class. The contents of the map are
+ * placed in the string in its proper order.
+ */
+ public String toString() {
+ int max = size() - 1;
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("{");
+ for (int j = 0; j <= max; j++) {
+ buf.append(keys.get(j) + "=" + values.get(j));
+ if (j < max) {
+ buf.append(", ");
+ }
+ }
+ buf.append("}");
+
+ return buf.toString();
+ }
+
+ // unit test
+ public static void main(String[] argv) {
+ QueueMap qMap;
+
+ qMap = new QueueMap();
+ for (int i = 0; i < 5; i++) {
+ qMap.put(Integer.toString(i), Integer.toString(i));
+ }
+ System.out.println("\nMap = " + qMap);
+ System.out.println("Keys = " + qMap.keys());
+ System.out.println("Values = " + qMap.values());
+
+ qMap = new QueueMap();
+ for (int i = 0; i < 5; i++) {
+ qMap.put(Integer.toString(i), "A");
+ }
+ System.out.println("\nMap = " + qMap);
+ System.out.println("Keys = " + qMap.keys());
+ System.out.println("Values = " + qMap.values());
+
+ qMap = new QueueMap();
+ for (int i = 0; i < 5; i++) {
+ qMap.put(Integer.toString(i), null);
+ }
+ System.out.println("\nMap = " + qMap);
+ System.out.println("Keys = " + qMap.keys());
+ System.out.println("Values = " + qMap.values());
+
+ Map aMap = new HashMap();
+ for (int i = 0; i < 5; i++) {
+ aMap.put(Integer.toString(i), Integer.toString(i));
+ }
+ qMap = new QueueMap(aMap);
+ System.out.println("\nHashMap = " + aMap);
+ System.out.println("Map = " + qMap);
+ System.out.println("Keys = " + qMap.keys());
+ System.out.println("Values = " + qMap.values());
+
+ qMap = new QueueMap();
+ qMap.put("Test1", "String1");
+ qMap.put("Test2", "String2");
+ qMap.put("Test3", "String3");
+ qMap.put("Test4", "String4");
+ qMap.put("Test5", "String5");
+ System.out.println("\nStandard Test, Map = " + qMap);
+ qMap.put("Test6", "String6");
+ qMap.put("Test7", "String7");
+ System.out.println("Put New Test, Map = " + qMap);
+ qMap.put("Test2", "New String2");
+ qMap.put("Test6", "New String6");
+ System.out.println("Put Existing Test, Map = " + qMap);
+ qMap.put("Test5", null);
+ qMap.put("Test8", null);
+ System.out.println("Put Null Test, Map = " + qMap);
+ qMap.remove("Test1");
+ qMap.remove("Test3");
+ qMap.remove("Test5");
+ qMap.remove("Test9");
+ System.out.println("Remove Test, Map = " + qMap);
+ System.out.println(" Keys = " + qMap.keys());
+ System.out.println(" Values = " + qMap.values());
+ qMap.clear();
+ qMap.put("Test10", "String10");
+ qMap.put("Test11", "String11");
+ qMap.put("Test12", "String12");
+ System.out.println("Clear Test, Map = " + qMap);
+
+ aMap = new HashMap();
+ aMap.put("Test10", "String10");
+ aMap.put("Test11", "String11");
+ aMap.put("Test12", "String12");
+ System.out.println("Equality Test, Equal = " + qMap.equals(aMap));
+ }
}
-
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/URLResourceReader.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/URLResourceReader.java
index 9133a8d..8694564 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/URLResourceReader.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/URLResourceReader.java
@@ -47,7 +47,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
- */
+ */
package net.wotonomy.foundation.internal;
@@ -61,147 +61,134 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
- * This implementation of URL Resource Reader assumes 2 types
- * of base urls. A base url that ends with / is considered a
- * resource folder, whereas a resource that does not end with
- * / is considered a zip/jar resource folder.
+ * This implementation of URL Resource Reader assumes 2 types of base urls. A
+ * base url that ends with / is considered a resource folder, whereas a resource
+ * that does not end with / is considered a zip/jar resource folder.
*
- * If the resource folder happens is a zip/jar archive, the
- * entries are always cached.
- * For non-zip base urls, one could specify whether or not it should
- * be cached.
+ * If the resource folder happens is a zip/jar archive, the entries are always
+ * cached. For non-zip base urls, one could specify whether or not it should be
+ * cached.
*
* @author Harish Prabandham
*/
-public class URLResourceReader {
- private Hashtable resourceCache = new Hashtable();
- private boolean iszip = true;
- private URL url = null;
- private boolean cache = true;
-
- /**
- * Creates a new URLResourceReader object. You can either give
- * the URL of the zip/jar file or a base url where to
- * look for additional resources. If the url ends with
- * "/" then it is assumed to be a Base URL.
- * @param The base url to look for the resources.
- * @param If the base url is not a zip/jar, then true indicates
- * that entries should be cached, false otherwise.
- */
- public URLResourceReader(URL baseurl, boolean cache) throws IOException {
- this.url = baseurl;
- this.cache = cache;
- this.iszip = !url.getFile().endsWith("/");
- if(this.iszip)
- this.cache = true;
- initialize();
- }
-
- /**
- * equivalent to URLResourceReader(baseurl, false)
- */
- public URLResourceReader(URL baseurl) throws IOException {
- this(baseurl, false);
- }
-
- /**
- * Creates a new URLResourceReader object with the given
- * input stream. The stream is assumed to be a zip/jar
- * stream.
- */
- public URLResourceReader(InputStream is) throws IOException {
- init(is);
- }
-
- private void initialize() throws IOException {
- if(iszip) {
- InputStream is = url.openStream();
- init(is);
- is.close();
- }
- }
-
- private byte[] readFully(InputStream is) throws IOException {
- byte[] buf = new byte[1024];
- int num = 0;
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
-
- while( (num = is.read(buf)) != -1) {
- bout.write(buf, 0, num);
- }
-
- return bout.toByteArray();
- }
-
- private void init(InputStream is) throws IOException {
- ZipInputStream zstream = new ZipInputStream(is);
- ZipEntry entry;
-
- while( (entry = zstream.getNextEntry()) != null) {
- byte[] entryData = readFully(zstream);
- if(cache)
- resourceCache.put(entry.getName(), entryData);
- zstream.closeEntry();
- }
-
- zstream.close();
- }
-
- /**
- * Returns an Enumeration of all "known" resource names.
- */
- public Enumeration getResourceNames() {
- return resourceCache.keys();
- }
-
- /**
- * Returns an array of bytes read for this resource if the
- * resource exists. This method blocks until the resource
- * has been fully read. If the resource does not exist,
- * this method returns null.
- */
- public byte[] getResource(String resource) {
- // lookup the data in the cache...
- byte[] data = (byte[]) resourceCache.get(resource);
- if(data != null) {
- return data;
- }
-
- // if the data was to come from a zip file that we
- // already read fully & cached , then it is probably
- // not there.
- if(iszip) {
- return null;
- }
-
- // Now the only choice left is to make a url connection.
- try {
- URL realURL = new URL(url.getProtocol(), url.getHost(),
- url.getFile() + resource);
- data = readFully(realURL.openStream());
- // add it to cache if needed...
- if(cache)
- resourceCache.put(resource, data);
- return data;
- } catch(Exception e) {
- return null;
- }
- }
-
- public void close() {
- resourceCache.clear();
- resourceCache = null;
- }
-
- public String toString() {
- return url.toString();
- }
+public class URLResourceReader {
+ private Hashtable resourceCache = new Hashtable();
+ private boolean iszip = true;
+ private URL url = null;
+ private boolean cache = true;
+
+ /**
+ * Creates a new URLResourceReader object. You can either give the URL of the
+ * zip/jar file or a base url where to look for additional resources. If the url
+ * ends with "/" then it is assumed to be a Base URL.
+ *
+ * @param The base url to look for the resources.
+ * @param If the base url is not a zip/jar, then true indicates that entries
+ * should be cached, false otherwise.
+ */
+ public URLResourceReader(URL baseurl, boolean cache) throws IOException {
+ this.url = baseurl;
+ this.cache = cache;
+ this.iszip = !url.getFile().endsWith("/");
+ if (this.iszip)
+ this.cache = true;
+ initialize();
+ }
+
+ /**
+ * equivalent to URLResourceReader(baseurl, false)
+ */
+ public URLResourceReader(URL baseurl) throws IOException {
+ this(baseurl, false);
+ }
+
+ /**
+ * Creates a new URLResourceReader object with the given input stream. The
+ * stream is assumed to be a zip/jar stream.
+ */
+ public URLResourceReader(InputStream is) throws IOException {
+ init(is);
+ }
+
+ private void initialize() throws IOException {
+ if (iszip) {
+ InputStream is = url.openStream();
+ init(is);
+ is.close();
+ }
+ }
+
+ private byte[] readFully(InputStream is) throws IOException {
+ byte[] buf = new byte[1024];
+ int num = 0;
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+ while ((num = is.read(buf)) != -1) {
+ bout.write(buf, 0, num);
+ }
+
+ return bout.toByteArray();
+ }
+
+ private void init(InputStream is) throws IOException {
+ ZipInputStream zstream = new ZipInputStream(is);
+ ZipEntry entry;
+
+ while ((entry = zstream.getNextEntry()) != null) {
+ byte[] entryData = readFully(zstream);
+ if (cache)
+ resourceCache.put(entry.getName(), entryData);
+ zstream.closeEntry();
+ }
+
+ zstream.close();
+ }
+
+ /**
+ * Returns an Enumeration of all "known" resource names.
+ */
+ public Enumeration getResourceNames() {
+ return resourceCache.keys();
+ }
+
+ /**
+ * Returns an array of bytes read for this resource if the resource exists. This
+ * method blocks until the resource has been fully read. If the resource does
+ * not exist, this method returns null.
+ */
+ public byte[] getResource(String resource) {
+ // lookup the data in the cache...
+ byte[] data = (byte[]) resourceCache.get(resource);
+ if (data != null) {
+ return data;
+ }
+
+ // if the data was to come from a zip file that we
+ // already read fully & cached , then it is probably
+ // not there.
+ if (iszip) {
+ return null;
+ }
+
+ // Now the only choice left is to make a url connection.
+ try {
+ URL realURL = new URL(url.getProtocol(), url.getHost(), url.getFile() + resource);
+ data = readFully(realURL.openStream());
+ // add it to cache if needed...
+ if (cache)
+ resourceCache.put(resource, data);
+ return data;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void close() {
+ resourceCache.clear();
+ resourceCache = null;
+ }
+
+ public String toString() {
+ return url.toString();
+ }
}
-
-
-
-
-
-
-
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/ValueConverter.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/ValueConverter.java
index d6bc797..7f28e06 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/ValueConverter.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/ValueConverter.java
@@ -17,6 +17,7 @@ License along with this library; if not, see http://www.gnu.org
*/
package net.wotonomy.foundation.internal;
+
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.util.Collection;
@@ -25,694 +26,562 @@ import java.util.LinkedList;
import java.util.Map;
/**
-* A utility class to convert objects to a desired class.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
-public class ValueConverter
-{
- /**
- * Returns the specified object as converted to an instance of the
- * specified class, or null if the conversion could not be performed.
- */
- static public Object convertObjectToClass( Object anObject, Class aClass )
- {
- if ( aClass == String.class )
- {
- return getString( anObject );
- }
- if ( aClass == Short.class )
- {
- return getShort( anObject );
- }
- if ( aClass == short.class )
- {
- return getShort( anObject );
- }
- if ( aClass == Integer.class )
- {
- return getInteger( anObject );
- }
- if ( aClass == int.class )
- {
- return getInteger( anObject );
- }
- if ( aClass == Long.class )
- {
- return getLong( anObject );
- }
- if ( aClass == long.class )
- {
- return getLong( anObject );
- }
- if ( aClass == Float.class )
- {
- return getFloat( anObject );
- }
- if ( aClass == float.class )
- {
- return getFloat( anObject );
- }
- if ( aClass == Double.class )
- {
- return getDouble( anObject );
- }
- if ( aClass == double.class )
- {
- return getDouble( anObject );
- }
- if ( aClass == java.util.Date.class )
- {
- return getDate( anObject );
- }
- if ( aClass == Boolean.class )
- {
- return getBoolean( anObject );
- }
- if ( aClass == boolean.class )
- {
- return getBoolean( anObject );
- }
- if ( aClass == Character.class )
- {
- return getCharacter( anObject );
- }
- if ( aClass == char.class )
- {
- return getCharacter( anObject );
- }
- if ( aClass == Byte.class )
- {
- return getByte( anObject );
- }
- if ( aClass == byte.class )
- {
- return getByte( anObject );
- }
- if ( Collection.class.isAssignableFrom( aClass ) )
- {
- return getCollection( anObject, aClass );
- }
- if ( aClass.isArray() )
- {
- return getArray( anObject, aClass );
- }
-
- return convert( anObject, aClass );
- }
-
- /**
- * Called by convertObjectToClass() when we need to
- * convert to an unrecognized type.
- * This implementation scans the constructors of the
- * specified class for the best fit to the object.
- * and returns a new instance with that constructor.
- * Subclasses can override to directly support specific
- * types.
- */
- static protected Object convert( Object anObject, Class aClass )
- {
- Constructor[] ctors = aClass.getConstructors();
-
- Class[] types;
- for ( int i = 0; i < ctors.length; i++ )
- {
- types = ctors[i].getParameterTypes();
- if ( types.length == 1 )
- {
- if ( types[0].equals( anObject.getClass() ) )
- {
- try
- {
- return ctors[i].newInstance( new Object[] { anObject } );
- }
- catch ( Exception exc )
- {
- // fall through
- }
- }
- }
- }
-
- for ( int i = 0; i < ctors.length; i++ )
- {
- types = ctors[i].getParameterTypes();
- if ( types.length == 1 )
- {
- if ( anObject.getClass().isAssignableFrom( types[0] ) )
- {
- try
- {
- return ctors[i].newInstance( new Object[] { anObject } );
- }
- catch ( Exception exc )
- {
- // fall through
- }
- }
- }
- }
-
- return null;
- }
-
- /**
- * Tries to convert all objects to either Numbers or objects
- * that will produce a parsable toString result.
- */
- static protected Object preprocess( Object anObject )
- {
- if ( anObject instanceof Boolean )
- {
- if ( ((Boolean)anObject).booleanValue() )
- {
- return new Double( 1.0 );
- }
- return new Double( 0.0 );
- }
-
- if ( anObject instanceof Character )
- {
- return anObject.toString();
- }
-
- return anObject;
- }
-
- static public short getShortValue( Object anObject )
- {
- Short result = getShort( anObject );
- return ( result == null ) ? (short) 0 : result.shortValue();
- }
- static public Short getShort( Object anObject )
- {
- if ( anObject == null ) return new Short( (short) 0 );
- if ( "".equals( anObject ) ) return new Short( (short) 0 );
- if ( anObject instanceof Short ) return (Short) anObject;
-
- anObject = preprocess( anObject );
-
- if ( anObject instanceof Number )
- {
- return new Short( ((Number)anObject).shortValue() );
- }
-
- try
- {
- return Short.valueOf( anObject.toString() );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
-
- static public int getIntValue( Object anObject )
- {
- Integer result = getInteger( anObject );
- return ( result == null ) ? 0 : result.intValue();
- }
- static public Integer getInteger( Object anObject )
- {
- if ( anObject == null ) return new Integer( 0 );
- if ( "".equals( anObject ) ) return new Integer( 0 );
- if ( anObject instanceof Integer ) return (Integer) anObject;
-
- anObject = preprocess( anObject );
-
- if ( anObject instanceof Number )
- {
- return new Integer( ((Number)anObject).intValue() );
- }
-
- try
- {
- return Integer.valueOf( anObject.toString() );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
-
- static public long getLongValue ( Object anObject )
- {
- Long result = getLong( anObject );
- return ( result == null ) ? (long) 0 : result.longValue();
- }
- static public Long getLong( Object anObject )
- {
- if ( anObject == null ) return new Long( 0 );
- if ( "".equals( anObject ) ) return new Long( 0 );
- if ( anObject instanceof Long ) return (Long) anObject;
-
- anObject = preprocess( anObject );
-
- if ( anObject instanceof Number )
- {
- return new Long( ((Number)anObject).longValue() );
- }
-
- try
- {
- return Long.valueOf( anObject.toString() );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
-
- static public double getDoubleValue ( Object anObject )
- {
- Double result = getDouble( anObject );
- return ( result == null ) ? 0.0f : result.doubleValue();
- }
- static public Double getDouble( Object anObject )
- {
- if ( anObject == null ) return new Double( 0.0 );
- if ( "".equals( anObject ) ) return new Double( 0 );
- if ( anObject instanceof Double ) return (Double) anObject;
-
- anObject = preprocess( anObject );
-
- if ( anObject instanceof Number )
- {
- return new Double( ((Number)anObject).doubleValue() );
- }
-
- try
- {
- return Double.valueOf( anObject.toString() );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
-
- static public float getFloatValue( Object anObject )
- {
- Float result = getFloat( anObject );
- return ( result == null ) ? 0.0f : result.floatValue();
- }
- static public Float getFloat( Object anObject )
- {
- if ( anObject == null ) return new Float( 0.0 );
- if ( "".equals( anObject ) ) return new Float( 0.0 );
- if ( anObject instanceof Float ) return (Float) anObject;
-
- anObject = preprocess( anObject );
-
- if ( anObject instanceof Number )
- {
- return new Float( ((Number)anObject).floatValue() );
- }
-
- try
- {
- return Float.valueOf( anObject.toString() );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
-
- static public char getCharValue( Object anObject )
- {
- Character result = getCharacter( anObject );
- return ( result == null ) ? (char) 0 : result.charValue();
- }
- static public Character getCharacter( Object anObject )
- {
- if ( anObject == null ) return new Character( (char) 0 );
- if ( anObject instanceof Character ) return (Character) anObject;
-
- anObject = preprocess( anObject );
-
- if ( anObject instanceof Number )
- {
- return new Character( (char) ((Number)anObject).byteValue() );
- }
-
- try
- {
- return new Character( anObject.toString().charAt( 0 ) );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
-
- static public byte getByteValue( Object anObject )
- {
- Byte result = getByte ( anObject );
- return ( result == null ) ? (byte) 0 : result.byteValue();
- }
- static public Byte getByte( Object anObject )
- {
- if ( anObject == null ) return new Byte( Byte.MIN_VALUE );
- if ( "".equals( anObject ) ) return new Byte( Byte.MIN_VALUE );
- if ( anObject instanceof Byte ) return (Byte) anObject;
-
- anObject = preprocess( anObject );
-
- if ( anObject instanceof Number )
- {
- return new Byte( ((Number)anObject).byteValue() );
- }
-
- try
- {
- return Byte.decode( anObject.toString() );
- }
- catch ( Exception exc )
- {
- // fall through
- }
-
- try
- {
- return Byte.valueOf( anObject.toString() );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
+ * A utility class to convert objects to a desired class.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
+public class ValueConverter {
+ /**
+ * Returns the specified object as converted to an instance of the specified
+ * class, or null if the conversion could not be performed.
+ */
+ static public Object convertObjectToClass(Object anObject, Class aClass) {
+ if (aClass == String.class) {
+ return getString(anObject);
+ }
+ if (aClass == Short.class) {
+ return getShort(anObject);
+ }
+ if (aClass == short.class) {
+ return getShort(anObject);
+ }
+ if (aClass == Integer.class) {
+ return getInteger(anObject);
+ }
+ if (aClass == int.class) {
+ return getInteger(anObject);
+ }
+ if (aClass == Long.class) {
+ return getLong(anObject);
+ }
+ if (aClass == long.class) {
+ return getLong(anObject);
+ }
+ if (aClass == Float.class) {
+ return getFloat(anObject);
+ }
+ if (aClass == float.class) {
+ return getFloat(anObject);
+ }
+ if (aClass == Double.class) {
+ return getDouble(anObject);
+ }
+ if (aClass == double.class) {
+ return getDouble(anObject);
+ }
+ if (aClass == java.util.Date.class) {
+ return getDate(anObject);
+ }
+ if (aClass == Boolean.class) {
+ return getBoolean(anObject);
+ }
+ if (aClass == boolean.class) {
+ return getBoolean(anObject);
+ }
+ if (aClass == Character.class) {
+ return getCharacter(anObject);
+ }
+ if (aClass == char.class) {
+ return getCharacter(anObject);
+ }
+ if (aClass == Byte.class) {
+ return getByte(anObject);
+ }
+ if (aClass == byte.class) {
+ return getByte(anObject);
+ }
+ if (Collection.class.isAssignableFrom(aClass)) {
+ return getCollection(anObject, aClass);
+ }
+ if (aClass.isArray()) {
+ return getArray(anObject, aClass);
+ }
+
+ return convert(anObject, aClass);
+ }
+
+ /**
+ * Called by convertObjectToClass() when we need to convert to an unrecognized
+ * type. This implementation scans the constructors of the specified class for
+ * the best fit to the object. and returns a new instance with that constructor.
+ * Subclasses can override to directly support specific types.
+ */
+ static protected Object convert(Object anObject, Class aClass) {
+ Constructor[] ctors = aClass.getConstructors();
+
+ Class[] types;
+ for (int i = 0; i < ctors.length; i++) {
+ types = ctors[i].getParameterTypes();
+ if (types.length == 1) {
+ if (types[0].equals(anObject.getClass())) {
+ try {
+ return ctors[i].newInstance(new Object[] { anObject });
+ } catch (Exception exc) {
+ // fall through
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < ctors.length; i++) {
+ types = ctors[i].getParameterTypes();
+ if (types.length == 1) {
+ if (anObject.getClass().isAssignableFrom(types[0])) {
+ try {
+ return ctors[i].newInstance(new Object[] { anObject });
+ } catch (Exception exc) {
+ // fall through
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Tries to convert all objects to either Numbers or objects that will produce a
+ * parsable toString result.
+ */
+ static protected Object preprocess(Object anObject) {
+ if (anObject instanceof Boolean) {
+ if (((Boolean) anObject).booleanValue()) {
+ return new Double(1.0);
+ }
+ return new Double(0.0);
+ }
+
+ if (anObject instanceof Character) {
+ return anObject.toString();
+ }
+
+ return anObject;
+ }
+
+ static public short getShortValue(Object anObject) {
+ Short result = getShort(anObject);
+ return (result == null) ? (short) 0 : result.shortValue();
+ }
+
+ static public Short getShort(Object anObject) {
+ if (anObject == null)
+ return new Short((short) 0);
+ if ("".equals(anObject))
+ return new Short((short) 0);
+ if (anObject instanceof Short)
+ return (Short) anObject;
+
+ anObject = preprocess(anObject);
+
+ if (anObject instanceof Number) {
+ return new Short(((Number) anObject).shortValue());
+ }
+
+ try {
+ return Short.valueOf(anObject.toString());
+ } catch (Exception exc) {
+ return null;
+ }
+ }
+
+ static public int getIntValue(Object anObject) {
+ Integer result = getInteger(anObject);
+ return (result == null) ? 0 : result.intValue();
+ }
+
+ static public Integer getInteger(Object anObject) {
+ if (anObject == null)
+ return new Integer(0);
+ if ("".equals(anObject))
+ return new Integer(0);
+ if (anObject instanceof Integer)
+ return (Integer) anObject;
+
+ anObject = preprocess(anObject);
+
+ if (anObject instanceof Number) {
+ return new Integer(((Number) anObject).intValue());
+ }
+
+ try {
+ return Integer.valueOf(anObject.toString());
+ } catch (Exception exc) {
+ return null;
+ }
+ }
+
+ static public long getLongValue(Object anObject) {
+ Long result = getLong(anObject);
+ return (result == null) ? (long) 0 : result.longValue();
+ }
+
+ static public Long getLong(Object anObject) {
+ if (anObject == null)
+ return new Long(0);
+ if ("".equals(anObject))
+ return new Long(0);
+ if (anObject instanceof Long)
+ return (Long) anObject;
+
+ anObject = preprocess(anObject);
+
+ if (anObject instanceof Number) {
+ return new Long(((Number) anObject).longValue());
+ }
+
+ try {
+ return Long.valueOf(anObject.toString());
+ } catch (Exception exc) {
+ return null;
+ }
+ }
+
+ static public double getDoubleValue(Object anObject) {
+ Double result = getDouble(anObject);
+ return (result == null) ? 0.0f : result.doubleValue();
+ }
+
+ static public Double getDouble(Object anObject) {
+ if (anObject == null)
+ return new Double(0.0);
+ if ("".equals(anObject))
+ return new Double(0);
+ if (anObject instanceof Double)
+ return (Double) anObject;
+
+ anObject = preprocess(anObject);
+
+ if (anObject instanceof Number) {
+ return new Double(((Number) anObject).doubleValue());
+ }
+
+ try {
+ return Double.valueOf(anObject.toString());
+ } catch (Exception exc) {
+ return null;
+ }
+ }
+
+ static public float getFloatValue(Object anObject) {
+ Float result = getFloat(anObject);
+ return (result == null) ? 0.0f : result.floatValue();
+ }
+
+ static public Float getFloat(Object anObject) {
+ if (anObject == null)
+ return new Float(0.0);
+ if ("".equals(anObject))
+ return new Float(0.0);
+ if (anObject instanceof Float)
+ return (Float) anObject;
+
+ anObject = preprocess(anObject);
+
+ if (anObject instanceof Number) {
+ return new Float(((Number) anObject).floatValue());
+ }
+
+ try {
+ return Float.valueOf(anObject.toString());
+ } catch (Exception exc) {
+ return null;
+ }
+ }
+
+ static public char getCharValue(Object anObject) {
+ Character result = getCharacter(anObject);
+ return (result == null) ? (char) 0 : result.charValue();
+ }
+
+ static public Character getCharacter(Object anObject) {
+ if (anObject == null)
+ return new Character((char) 0);
+ if (anObject instanceof Character)
+ return (Character) anObject;
+
+ anObject = preprocess(anObject);
+
+ if (anObject instanceof Number) {
+ return new Character((char) ((Number) anObject).byteValue());
+ }
+
+ try {
+ return new Character(anObject.toString().charAt(0));
+ } catch (Exception exc) {
+ return null;
+ }
+ }
+
+ static public byte getByteValue(Object anObject) {
+ Byte result = getByte(anObject);
+ return (result == null) ? (byte) 0 : result.byteValue();
+ }
+
+ static public Byte getByte(Object anObject) {
+ if (anObject == null)
+ return new Byte(Byte.MIN_VALUE);
+ if ("".equals(anObject))
+ return new Byte(Byte.MIN_VALUE);
+ if (anObject instanceof Byte)
+ return (Byte) anObject;
+
+ anObject = preprocess(anObject);
+
+ if (anObject instanceof Number) {
+ return new Byte(((Number) anObject).byteValue());
+ }
+
+ try {
+ return Byte.decode(anObject.toString());
+ } catch (Exception exc) {
+ // fall through
+ }
+
+ try {
+ return Byte.valueOf(anObject.toString());
+ } catch (Exception exc) {
+ return null;
+ }
+ }
/**
- * Calls getBoolean and converts result to primitive.
- */
- static public boolean getBooleanValue( Object anObject )
- {
- Boolean result = getBoolean( anObject );
- return ( result == null ) ? false : result.booleanValue();
- }
-
+ * Calls getBoolean and converts result to primitive.
+ */
+ static public boolean getBooleanValue(Object anObject) {
+ Boolean result = getBoolean(anObject);
+ return (result == null) ? false : result.booleanValue();
+ }
+
/**
- * Numbers equal to zero are true; Strings equal to "yes" are true;
- * Strings are then passed to the Boolean constructor.
- * Other values return null.
- */
- static public Boolean getBoolean( Object anObject )
- {
- if ( anObject instanceof Boolean )
- {
+ * Numbers equal to zero are true; Strings equal to "yes" are true; Strings are
+ * then passed to the Boolean constructor. Other values return null.
+ */
+ static public Boolean getBoolean(Object anObject) {
+ if (anObject instanceof Boolean) {
return (Boolean) anObject;
}
- if ( anObject instanceof Number )
- {
- return new Boolean( ((Number)anObject).doubleValue() == 0.0 );
- }
-
- if ( anObject instanceof String )
- {
- if ( anObject.toString().toLowerCase().equals( "yes" ) )
- {
+ if (anObject instanceof Number) {
+ return new Boolean(((Number) anObject).doubleValue() == 0.0);
+ }
+
+ if (anObject instanceof String) {
+ if (anObject.toString().toLowerCase().equals("yes")) {
return Boolean.TRUE;
}
- return new Boolean( (String) anObject );
- }
-
- return null;
- }
-
- /**
- * Get an appropriate String representation for the
- * object. Nulls are converted to "null". Date are
- * formatted according to the current date format.
- * All else uses toString.
- */
- static public String getString( Object anObject )
- {
- if ( anObject == null ) return "null";
- if ( anObject instanceof java.util.Date )
- {
- return dateFormat.format( (java.util.Date) anObject );
- }
- return anObject.toString();
- }
-
- /**
- * Converts the object into the specified collection class.
- * If unable to convert in any other way, resorts to creating
- * a new collection of the specified type containing the
- * specified object.
- */
- static public Collection getCollection( Object anObject, Class aCollectionClass )
- {
- if ( anObject == null ) return null;
- if ( aCollectionClass.isAssignableFrom( anObject.getClass() ) )
- {
- return (Collection) anObject;
- }
-
- Collection converted = null;
-
- // convert to collection class
- if ( anObject instanceof Collection )
- {
- converted = (Collection) anObject;
- }
- else
- // try to convert an array
- if ( anObject.getClass().isArray() )
- {
- try
- {
- int length = Array.getLength( anObject );
- converted = new LinkedList();
- for ( int i = 0; i < length; i++ )
- {
- converted.add( Array.get( anObject, i ) );
- }
- }
- catch ( Exception exc )
- {
- // try another approach
- }
- }
- else
- // convert map values to collection and pass through
- if ( anObject instanceof Map )
- {
- converted = ((Map)anObject).values();
- }
-
- // fall back on list containing the object
- if ( converted == null )
- {
- converted = new LinkedList();
- converted.add( anObject );
- }
-
- Collection result = null;
-
- if ( converted != null )
- {
- try
- {
- // collections required to have the copy constructor.
- Constructor ctor = aCollectionClass.getConstructor(
- new Class[] { Collection.class } );
- result = (Collection) ctor.newInstance( new Object[] { converted } );
- }
- catch ( Exception exc )
- {
- try
- {
- result = new LinkedList();
- result.addAll( converted );
- }
- catch ( Exception exc2 )
- {
- // all attempts failed
- result = null;
- }
- }
- }
-
- return result;
- }
-
- /**
- * Convert the object to the specified array type.
- */
- static public Object getArray( Object anObject, Class anArrayClass )
- {
- if ( anObject == null ) return null;
-
- // try to convert an array
- if ( anObject.getClass().isArray() )
- {
- try
- {
- int length = Array.getLength( anObject );
- Object result = Array.newInstance(
- anArrayClass.getComponentType(), length );
- for ( int i = 0; i < length; i++ )
- {
- Array.set( result, i, Array.get( anObject, i ) );
- }
- return result;
- }
- catch ( Exception exc )
- {
- // try another approach
- }
- }
- // convert map values to collection and pass through
- if ( anObject instanceof Map )
- {
- anObject = ((Map)anObject).values();
- }
- // try to convert a collection
- if ( anObject instanceof Collection )
- {
- try
- {
- int length = ((Collection)anObject).size();
- Object result = Array.newInstance(
- anArrayClass.getComponentType(), length );
- Iterator it = ((Collection)anObject).iterator();
- for ( int i = 0; i < length; i++ )
- {
- Array.set( result, i, it.next() );
- }
- return result;
- }
- catch ( Exception exc )
- {
- // try another approach
- }
- }
- // if appropriate type, put the object in a single element array
- if ( anObject.getClass().equals( anArrayClass.getComponentType() ) )
- {
- try
- {
- Object result = Array.newInstance(
- anArrayClass.getComponentType(), 1 );
- Array.set( result, 0, anObject );
- return result;
- }
- catch ( Exception exc )
- {
- // try another approach
- }
- }
- return null;
- }
-
- /**
- * Get an appropriate Date from the given object.
- */
- static public java.util.Date getDate( Object anObject )
- {
- if ( anObject == null ) return new java.util.Date( 0 );
- if ( anObject instanceof java.util.Date )
- return (java.util.Date) anObject;
-
- if ( anObject instanceof Number )
- {
- return new java.util.Date( getLongValue( anObject ) );
- }
-
- try
- {
- return dateFormat.parse( anObject.toString() );
- }
- catch ( Exception exc )
- {
- return null;
- }
- }
-
- static private java.text.DateFormat dateFormat =
- new java.text.SimpleDateFormat();
- static public java.text.DateFormat getDateFormat()
- {
- return dateFormat;
- }
- static public void setDateFormat( java.text.DateFormat aDateFormat )
- {
- if ( aDateFormat != null )
- {
- dateFormat = aDateFormat;
- }
- }
-
- /**
- * Returns the "inverted" value of the specified object.
- * Numbers except for chars and bytes are converted to
- * their negative representation. Chars and bytes are
- * treated as booleans. String are converted to booleans.
- * Booleans are converted to their opposite.
- * All other types return null.
- */
- public static Object invert( Object anObject )
- {
- if ( anObject == null ) return null;
- Class aClass = anObject.getClass();
-
- if ( ( ( anObject instanceof Number )
- &&! ( anObject instanceof Byte )
- &&! ( anObject instanceof Character ) )
- || ( aClass == short.class )
- || ( aClass == int.class )
- || ( aClass == long.class )
- || ( aClass == float.class )
- || ( aClass == double.class ) )
- {
- return convertObjectToClass(
- new Double( getDoubleValue( anObject ) * -1 ), aClass );
- }
-
- Boolean converted = getBoolean( anObject );
- if ( converted != null )
- {
- if ( converted.booleanValue() )
- {
- return convertObjectToClass(
- Boolean.FALSE, anObject.getClass() );
- }
- else
- {
- return convertObjectToClass(
- Boolean.TRUE, anObject.getClass() );
- }
- }
-
- return null;
- }
+ return new Boolean((String) anObject);
+ }
+
+ return null;
+ }
+
+ /**
+ * Get an appropriate String representation for the object. Nulls are converted
+ * to "null". Date are formatted according to the current date format. All else
+ * uses toString.
+ */
+ static public String getString(Object anObject) {
+ if (anObject == null)
+ return "null";
+ if (anObject instanceof java.util.Date) {
+ return dateFormat.format((java.util.Date) anObject);
+ }
+ return anObject.toString();
+ }
+
+ /**
+ * Converts the object into the specified collection class. If unable to convert
+ * in any other way, resorts to creating a new collection of the specified type
+ * containing the specified object.
+ */
+ static public Collection getCollection(Object anObject, Class aCollectionClass) {
+ if (anObject == null)
+ return null;
+ if (aCollectionClass.isAssignableFrom(anObject.getClass())) {
+ return (Collection) anObject;
+ }
+
+ Collection converted = null;
+
+ // convert to collection class
+ if (anObject instanceof Collection) {
+ converted = (Collection) anObject;
+ } else
+ // try to convert an array
+ if (anObject.getClass().isArray()) {
+ try {
+ int length = Array.getLength(anObject);
+ converted = new LinkedList();
+ for (int i = 0; i < length; i++) {
+ converted.add(Array.get(anObject, i));
+ }
+ } catch (Exception exc) {
+ // try another approach
+ }
+ } else
+ // convert map values to collection and pass through
+ if (anObject instanceof Map) {
+ converted = ((Map) anObject).values();
+ }
+
+ // fall back on list containing the object
+ if (converted == null) {
+ converted = new LinkedList();
+ converted.add(anObject);
+ }
+
+ Collection result = null;
+
+ if (converted != null) {
+ try {
+ // collections required to have the copy constructor.
+ Constructor ctor = aCollectionClass.getConstructor(new Class[] { Collection.class });
+ result = (Collection) ctor.newInstance(new Object[] { converted });
+ } catch (Exception exc) {
+ try {
+ result = new LinkedList();
+ result.addAll(converted);
+ } catch (Exception exc2) {
+ // all attempts failed
+ result = null;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Convert the object to the specified array type.
+ */
+ static public Object getArray(Object anObject, Class anArrayClass) {
+ if (anObject == null)
+ return null;
+
+ // try to convert an array
+ if (anObject.getClass().isArray()) {
+ try {
+ int length = Array.getLength(anObject);
+ Object result = Array.newInstance(anArrayClass.getComponentType(), length);
+ for (int i = 0; i < length; i++) {
+ Array.set(result, i, Array.get(anObject, i));
+ }
+ return result;
+ } catch (Exception exc) {
+ // try another approach
+ }
+ }
+ // convert map values to collection and pass through
+ if (anObject instanceof Map) {
+ anObject = ((Map) anObject).values();
+ }
+ // try to convert a collection
+ if (anObject instanceof Collection) {
+ try {
+ int length = ((Collection) anObject).size();
+ Object result = Array.newInstance(anArrayClass.getComponentType(), length);
+ Iterator it = ((Collection) anObject).iterator();
+ for (int i = 0; i < length; i++) {
+ Array.set(result, i, it.next());
+ }
+ return result;
+ } catch (Exception exc) {
+ // try another approach
+ }
+ }
+ // if appropriate type, put the object in a single element array
+ if (anObject.getClass().equals(anArrayClass.getComponentType())) {
+ try {
+ Object result = Array.newInstance(anArrayClass.getComponentType(), 1);
+ Array.set(result, 0, anObject);
+ return result;
+ } catch (Exception exc) {
+ // try another approach
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get an appropriate Date from the given object.
+ */
+ static public java.util.Date getDate(Object anObject) {
+ if (anObject == null)
+ return new java.util.Date(0);
+ if (anObject instanceof java.util.Date)
+ return (java.util.Date) anObject;
+
+ if (anObject instanceof Number) {
+ return new java.util.Date(getLongValue(anObject));
+ }
+
+ try {
+ return dateFormat.parse(anObject.toString());
+ } catch (Exception exc) {
+ return null;
+ }
+ }
+
+ static private java.text.DateFormat dateFormat = new java.text.SimpleDateFormat();
+
+ static public java.text.DateFormat getDateFormat() {
+ return dateFormat;
+ }
+
+ static public void setDateFormat(java.text.DateFormat aDateFormat) {
+ if (aDateFormat != null) {
+ dateFormat = aDateFormat;
+ }
+ }
+
+ /**
+ * Returns the "inverted" value of the specified object. Numbers except for
+ * chars and bytes are converted to their negative representation. Chars and
+ * bytes are treated as booleans. String are converted to booleans. Booleans are
+ * converted to their opposite. All other types return null.
+ */
+ public static Object invert(Object anObject) {
+ if (anObject == null)
+ return null;
+ Class aClass = anObject.getClass();
+
+ if (((anObject instanceof Number) && !(anObject instanceof Byte) && !(anObject instanceof Character))
+ || (aClass == short.class) || (aClass == int.class) || (aClass == long.class) || (aClass == float.class)
+ || (aClass == double.class)) {
+ return convertObjectToClass(new Double(getDoubleValue(anObject) * -1), aClass);
+ }
+
+ Boolean converted = getBoolean(anObject);
+ if (converted != null) {
+ if (converted.booleanValue()) {
+ return convertObjectToClass(Boolean.FALSE, anObject.getClass());
+ } else {
+ return convertObjectToClass(Boolean.TRUE, anObject.getClass());
+ }
+ }
+
+ return null;
+ }
}
/*
- * $Log$
- * Revision 1.2 2006/02/16 13:11:47 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * $Log$ Revision 1.2 2006/02/16 13:11:47 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.4 2002/10/11 15:33:53 mpowers
- * Now supporting "!" to invert the value of a string property.
+ * Revision 1.4 2002/10/11 15:33:53 mpowers Now supporting "!" to invert the
+ * value of a string property.
*
- * Revision 1.3 2001/07/02 16:29:08 mpowers
- * XMLRPC decoder was relying on ValueConverter to convert LinkedLists into
- * the appropriate type. This is now implemented in ValueConverter.
+ * Revision 1.3 2001/07/02 16:29:08 mpowers XMLRPC decoder was relying on
+ * ValueConverter to convert LinkedLists into the appropriate type. This is now
+ * implemented in ValueConverter.
*
- * Revision 1.2 2001/03/01 20:36:35 mpowers
- * Better error handling and better handling of nulls.
+ * Revision 1.2 2001/03/01 20:36:35 mpowers Better error handling and better
+ * handling of nulls.
*
- * Revision 1.1.1.1 2000/12/21 15:52:33 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:52:33 mpowers Contributing wotonomy.
*
- * Revision 1.8 2000/12/20 16:25:48 michael
- * Added log to all files.
+ * Revision 1.8 2000/12/20 16:25:48 michael Added log to all files.
*
*
*/
-
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/WotonomyException.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/WotonomyException.java
index e2210d0..21b47b3 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/WotonomyException.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/internal/WotonomyException.java
@@ -22,113 +22,96 @@ import java.io.PrintStream;
import java.io.PrintWriter;
/**
-* This is a simple RuntimeException that can encapsulate
-* another throwable. Behaves as a normal RuntimeException
-* except that it prints a stack trace of the wrapped
-* throwable if one is specified.
-*
-* Intended to be used anytime you'd
-* report an exception with System.out.println: that is,
-* for debugging and non-user-visible exceptions.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
+ * This is a simple RuntimeException that can encapsulate another throwable.
+ * Behaves as a normal RuntimeException except that it prints a stack trace of
+ * the wrapped throwable if one is specified.
+ *
+ * Intended to be used anytime you'd report an exception with
+ * System.out.println: that is, for debugging and non-user-visible exceptions.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
-public class WotonomyException extends RuntimeException
-{
+public class WotonomyException extends RuntimeException {
protected String message;
protected Throwable wrappedThrowable;
-
+
/**
- * Default constructor.
- */
- public WotonomyException()
- {
+ * Default constructor.
+ */
+ public WotonomyException() {
super();
message = null;
- wrappedThrowable = null;
+ wrappedThrowable = null;
}
-
+
/**
- * Standard constructor with message.
- */
- public WotonomyException( String aMessage )
- {
- super( aMessage );
+ * Standard constructor with message.
+ */
+ public WotonomyException(String aMessage) {
+ super(aMessage);
message = aMessage;
wrappedThrowable = null;
}
-
+
/**
- * Specifies a throwable to wrap.
- */
- public WotonomyException( Throwable aThrowable )
- {
+ * Specifies a throwable to wrap.
+ */
+ public WotonomyException(Throwable aThrowable) {
super();
message = null;
wrappedThrowable = aThrowable;
}
-
+
/**
- * Specifies a message and a throwable to wrap.
- */
- public WotonomyException( String aMessage, Throwable aThrowable )
- {
- super( aMessage );
+ * Specifies a message and a throwable to wrap.
+ */
+ public WotonomyException(String aMessage, Throwable aThrowable) {
+ super(aMessage);
message = aMessage;
wrappedThrowable = aThrowable;
}
-
- /**
- * Returns the wrapped throwable.
- */
- public Throwable getWrappedThrowable()
- {
- return wrappedThrowable;
- }
-
- public void printStackTrace(PrintWriter s)
- {
- if ( message != null )
- {
- s.println( "Exception: " + message );
+
+ /**
+ * Returns the wrapped throwable.
+ */
+ public Throwable getWrappedThrowable() {
+ return wrappedThrowable;
+ }
+
+ public void printStackTrace(PrintWriter s) {
+ if (message != null) {
+ s.println("Exception: " + message);
}
- if ( wrappedThrowable != null )
- {
- wrappedThrowable.printStackTrace( s );
+ if (wrappedThrowable != null) {
+ wrappedThrowable.printStackTrace(s);
return;
}
- super.printStackTrace( s );
+ super.printStackTrace(s);
}
-
- public void printStackTrace(PrintStream s)
- {
- if ( message != null )
- {
- s.println( "Exception: " + message );
+
+ public void printStackTrace(PrintStream s) {
+ if (message != null) {
+ s.println("Exception: " + message);
}
- if ( wrappedThrowable != null )
- {
- wrappedThrowable.printStackTrace( s );
+ if (wrappedThrowable != null) {
+ wrappedThrowable.printStackTrace(s);
return;
}
- super.printStackTrace( s );
+ super.printStackTrace(s);
}
-
- public void printStackTrace()
- {
- if ( message != null )
- {
- System.err.println( "Exception: " + message );
+
+ public void printStackTrace() {
+ if (message != null) {
+ System.err.println("Exception: " + message);
}
- if ( wrappedThrowable != null )
- {
- wrappedThrowable.printStackTrace();
+ if (wrappedThrowable != null) {
+ wrappedThrowable.printStackTrace();
return;
}
super.printStackTrace();
}
-
+
}