diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..3935ce9
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ================================= WARNING ================================
+ Junit isn't present in your ${ANT_HOME}/lib directory. Tests not executed.
+ ==========================================================================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/maven.xml b/maven.xml
new file mode 100644
index 0000000..90ef3bb
--- /dev/null
+++ b/maven.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..81845fb
--- /dev/null
+++ b/project.properties
@@ -0,0 +1,10 @@
+#repository
+maven.repo.central=
+maven.repo.central.directory=
+maven.repo.remote=http://www.ibiblio.org/maven,http://onemind-commons.sf.net/maven
+maven.license.licenseFile=docs/License.txt
+#maven.repo.remote.enabled=true
+
+#site generation
+maven.docs.src=xdocs
+maven.xdoc.includeProjectDocumentation=yes
diff --git a/project.xml b/project.xml
new file mode 100644
index 0000000..28f1d41
--- /dev/null
+++ b/project.xml
@@ -0,0 +1,85 @@
+
+ 1
+ commons-java
+ onemind-commons
+ commons-java
+ 1.5.5
+ OneMind
+ 2004
+ org.onemind.commons.java
+ /images/logo.gif
+ This is a common java library used to support other developments.
+ commons-java library
+ http://onemind-commons.sourceforge.net/common-java
+
+ http://sourceforge.net/tracker/?group_id=114901
+
+ onemind-commons.sf.net
+
+ /onemind-java
+
+
+ http://onemind-commons.sourceforge.net
+
+
+ maven
+
+
+
+ scm:cvs:pserver:anonymous@cvs.sf.net:/cvsroot/onemind-commons:commons-java
+
+
+ http://cvs.sf.net/viewcvs.py/onemind-commons
+
+
+
+
+
+
+ ${pom.name} Dev List
+
+
+ ${pom.name} User List
+
+
+
+
+ TiongHiang Lee
+ thlee
+ thlee@onemindsoft.org
+
+
+
+
+
+ servletapi
+ servletapi
+ 2.3
+
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.0
+
+
+
+
+ src/java
+ src/test
+
+
+ **/*Test.java
+
+
+
+ ${basedir}/src/test
+
+ **/*.xml
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/BiMap.java b/src/java/org/onemind/commons/java/datastructure/BiMap.java
new file mode 100644
index 0000000..898f54e
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/BiMap.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.HashMap;
+/**
+ * A simple bi-directional map. It uses another map to store the inverse
+ * of this map. The key has to be unique in key space and the value need to
+ * be unique in the value space so that the value can be resolved to the key correctly.
+ * This class is not thread safe.
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: BiMap.java,v 1.1 2004/09/29 02:45:35 thlee Exp $ $Name: $
+ */
+public class BiMap extends HashMap
+{
+
+ /** the inverse **/
+ private final BiMap _inverse;
+
+ /**
+ * Constructor
+ */
+ public BiMap()
+ {
+ _inverse = new BiMap(this);
+ }
+
+ /**
+ * Constructor
+ * @param map the inverse
+ */
+ private BiMap(BiMap inverse)
+ {
+ _inverse = inverse;
+ }
+
+ /**
+ * Get the inverse bimap
+ * @return the bimap
+ */
+ public BiMap getInverse()
+ {
+ return _inverse;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clear()
+ {
+ super.clear();
+ _inverse.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object put(Object key, Object value)
+ {
+ //some critical checks that ensure correctness
+ if (containsKey(key))
+ {
+ if (_inverse.containsKey(value))
+ {//make sure it is true
+ Object v = get(key);
+ boolean sameValue = (v == null) ? v == value : v.equals(value);
+ if (!sameValue)
+ {
+ throw new IllegalArgumentException("Value " + value + " exists in inverse");
+ } //else ok
+ } //else ok
+ } else
+ {
+ if (_inverse.containsKey(value))
+ {//will cause conflict
+ throw new IllegalArgumentException("Value " + value + " exists in inverse");
+ }
+ }
+ //pass the tests, do the things
+ remove(key);
+ _inverse.rawPut(value, key);
+ return rawPut(key, value);
+ }
+
+ /**
+ * Put the key value association with super.put()
+ * @param key the key
+ * @param value the value
+ */
+ private Object rawPut(Object key, Object value)
+ {
+ return super.put(key, value);
+ }
+
+ /**
+ * Remove the key
+ * @param key the key
+ * @return the value by super.remove();
+ */
+ private Object rawRemove(Object key)
+ {
+ return super.remove(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object remove(Object key)
+ {
+ if (containsKey(key))
+ {
+ return _inverse.rawRemove(rawRemove(key));
+ } else
+ {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/ClassSet.java b/src/java/org/onemind/commons/java/datastructure/ClassSet.java
new file mode 100644
index 0000000..2611eeb
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/ClassSet.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+/**
+ * Represents a set of classes. User can use isSubSetOf() to detect whether a given class is subclass of a class in the class set
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ClassSet.java,v 1.3 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public class ClassSet
+{
+
+ /** the classes * */
+ private HashSet _classes = new HashSet();
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClassSet()
+ {
+ super();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClassSet(Collection c)
+ {
+ addAll(c);
+ }
+
+ /**
+ * Add all in the classes to the ClassSet
+ * @param classes the collection containing the classes
+ */
+ public void addAll(Collection classes)
+ {
+ Iterator it = classes.iterator();
+ while (it.hasNext())
+ {
+ Object o = it.next();
+ if (o instanceof Class)
+ {
+ add((Class) o);
+ } else
+ {
+ throw new IllegalArgumentException(o + " is not a subclass of class");
+ }
+ }
+ }
+
+ /**
+ * Add the class
+ * @param c the class
+ */
+ public void add(Class c)
+ {
+ _classes.add(c);
+ }
+
+ /**
+ * Check whether the class is subclass of one of the class in the class set
+ * @param c the class
+ * @return true if is subclass
+ */
+ public boolean isSubclassOfClasses(Class c)
+ {
+ Class current = c;
+ while ((current != null) && (current != Object.class))
+ {
+ if (_classes.contains(c))
+ {
+ return true;
+ } else
+ {
+ current = current.getSuperclass();
+ }
+ }
+ Class[] interfaces = c.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ {
+ if (_classes.contains(interfaces[i]))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the classes
+ * @return the classes
+ */
+ public Set getClasses()
+ {
+ return _classes;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/CounterQueue.java b/src/java/org/onemind/commons/java/datastructure/CounterQueue.java
new file mode 100644
index 0000000..5dc5175
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/CounterQueue.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+/**
+ * Represent a list of counters with a queue per counter objectYou can queue and dequeue to a counter identified by a counter object.
+ * NOTE: This class is not thread-safe
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: CounterQueue.java,v 1.3 2005/04/26 17:41:24 thlee Exp $ $Name: $
+ */
+public class CounterQueue
+{
+
+ /** the counters * */
+ private HashMap _counters = new HashMap();
+
+ /**
+ * {@inheritDoc}
+ */
+ public CounterQueue()
+ {
+ }
+
+ /**
+ * Get the list for the counter object
+ * @param o the counter object
+ * @return the list, or null if there's none
+ */
+ private List _getList(Object o)
+ {
+ if (_counters.containsKey(o))
+ {
+ return (List) _counters.get(o);
+ } else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Get the (unmodifiable) queue of the counter object
+ * @param o the counter object
+ * @return the queue
+ */
+ public List getQueue(Object o)
+ {
+ if (_counters.containsKey(o))
+ {
+ return Collections.unmodifiableList((List) _counters.get(o));
+ } else
+ {
+ return Collections.EMPTY_LIST;
+ }
+ }
+
+ /**
+ * Clear the queue of the counter object
+ * @param o the counter object
+ * @return the queue for the counter object
+ */
+ public List clearQueue(Object o)
+ {
+ Object queue = _counters.remove(o);
+ if (queue != null)
+ {
+ return (List) queue;
+ } else
+ {
+ return Collections.EMPTY_LIST;
+ }
+ }
+
+ /**
+ * Add an queuer to the queue of the counter object. A queue will be created if there's none for the counter object
+ * @param o the counter object
+ * @param queuer the queue
+ * @return true
+ */
+ public boolean addToQueue(Object o, Object queuer)
+ {
+ List l = _getList(o);
+ if (l == null)
+ {
+ l = new ArrayList();
+ _counters.put(o, l);
+ }
+ return l.add(queuer);
+ }
+
+ /**
+ * Remove the next queuer in the queue. Null if queue is empty
+ * @param counter the counter
+ * @return the next queuer in the counter, or null if queue is empty
+ */
+ public Object removeNextFromQueue(Object counter)
+ {
+ List l = _getList(counter);
+ if (l == null || l.size() == 0)
+ {
+ return null;
+ } else
+ {
+ return l.remove(0);
+ }
+ }
+
+ /**
+ * Remove the queuer from the queue of the counter object. If there's no queue for the counter object, it will do nothing and
+ * return false.
+ * @param o the counter object
+ * @param queuer the queuer
+ * @return true if list contains the element
+ */
+ public boolean removeFromQueue(Object o, Object queuer)
+ {
+ List l = _getList(o);
+ if (l != null)
+ {
+ return l.remove(queuer);
+ } else
+ {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/DuoMapKey.java b/src/java/org/onemind/commons/java/datastructure/DuoMapKey.java
new file mode 100644
index 0000000..096949f
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/DuoMapKey.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+/**
+ * Represent a map key that consists of two value
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public class DuoMapKey
+{
+
+ private final int _hashCode;
+
+ /** key1 **/
+ private Object key1;
+
+ /** key2 **/
+ private Object key2;
+
+ /**
+ * Constructor
+ * @param key1
+ * @param key2
+ */
+ public DuoMapKey(Object key1, Object key2)
+ {
+ _hashCode = ((key1 == null) ? 0 : key1.hashCode()) + ((key2 == null) ? 0 : key2.hashCode() >> 4);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode()
+ {
+ return _hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object o)
+ {
+ if (o instanceof DuoMapKey)
+ {
+ DuoMapKey other = (DuoMapKey) o;
+ return _keyEquals(key1, other.key1) && _keyEquals(key2, other.key2);
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Return whether key and other is equals
+ * @param key the key
+ * @param other the other key
+ * @return true if both null or equals
+ */
+ private boolean _keyEquals(Object key, Object other)
+ {
+ if (key == null)
+ {
+ return other == null;
+ } else
+ {
+ return key.equals(other);
+ }
+ }
+}
diff --git a/src/java/org/onemind/commons/java/datastructure/InheritableValueMap.java b/src/java/org/onemind/commons/java/datastructure/InheritableValueMap.java
new file mode 100644
index 0000000..fb92807
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/InheritableValueMap.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+/**
+ * Associate a class and an value object and resolve the mapping through the
+ * class hierachy.
+ *
+ * For example, if a value object A is assosiated with Number class that
+ * means it is associated with the Number class and all the subclasses of
+ * object class. However, if a mapping exists for Integer, the InheritableValueMap
+ * will return the value object associated for the Integer.
+ *
+ * The stopClass controls when the InheritableValueMap stop resolving mapping and
+ * return null (when c==stopClass.getSuperClass()). The stopClass also control
+ * the hierachy of object that can be added the the map - meaning
+ * stopClass.isAssignableFrom(c) must evaluate to true when c is added as mapping key.
+ *
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: InheritableValueMap.java,v 1.3 2005/02/17 19:57:31 thlee Exp $ $Name: $
+ */
+public class InheritableValueMap
+{
+
+ /** the mapping * */
+ private Map _map = new HashMap();
+
+ /** the stop class * */
+ private Class _stopClass;
+
+ /**
+ * Use Object.class as stop class {@inheritDoc}
+ */
+ public InheritableValueMap()
+ {
+ this(Object.class);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param stopClass the stop class
+ */
+ public InheritableValueMap(Class stopClass)
+ {
+ _stopClass = stopClass;
+ }
+
+ /**
+ * Add the mapping between the class c and the object o. The object o must be the stopClass or a subclass of the stopClass
+ * @param c the class
+ * @param o the object
+ */
+ public void put(Class c, Object o)
+ {
+ if (!_stopClass.isAssignableFrom(c))
+ {
+ throw new IllegalArgumentException("Cannot add key class " + c
+ + " that is not a subclass of stopClass " + _stopClass);
+ }
+ _map.put(c, o);
+ }
+
+ /**
+ * Resolve the object associated with class c
+ * @param c the class
+ * @return the object associated with class c, or null
+ */
+ public Object resolve(Class c)
+ {
+ if (c == null)
+ { //add protection
+ return null;
+ } else if (!_stopClass.isAssignableFrom(c))
+ {
+ throw new RuntimeException(
+ "Cannot get entry for key class that is not a subclass of stopClass "
+ + _stopClass);
+ }
+ while (c != _stopClass.getSuperclass())
+ {
+ Object o = _map.get(c);
+ if (o != null)
+ {
+ return o;
+ }
+ c = c.getSuperclass();
+ }
+ return null;
+ }
+
+ /**
+ * Return the key classes
+ * @return the classes
+ */
+ public final Set keySet()
+ {
+ return _map.keySet();
+ }
+
+ /**
+ * Resolve all the mapping that could have apply to c in class c's inheritance hierachy
+ * @param c the class
+ * @return the Collection contains all the mappings
+ */
+ public Collection resolveAll(Class c)
+ {
+ if (!_stopClass.isAssignableFrom(c))
+ {
+ throw new RuntimeException(
+ "Cannot get entry for key class that is not a subclass of stopClass "
+ + _stopClass);
+ }
+ List l = new ArrayList();
+ while (c != _stopClass.getSuperclass())
+ {
+ Object o = _map.get(c);
+ if (o != null)
+ {
+ l.add(o);
+ }
+ c = c.getSuperclass();
+ }
+ return l;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/LongList.java b/src/java/org/onemind/commons/java/datastructure/LongList.java
new file mode 100644
index 0000000..20967f5
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/LongList.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+/**
+ * Represents a list of long
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: LongList.java,v 1.2 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public class LongList
+{
+
+ /** the initial capacity * */
+ private static final int INITIAL_CAPACITY = 10;
+
+ /** the growth rate * */
+ private static final int GROW = 10;
+
+ /** the count of longs in the list * */
+ private int _count;
+
+ /** the list * */
+ private long[] _list = new long[INITIAL_CAPACITY];
+
+ /**
+ * {@inheritDoc}
+ */
+ public LongList()
+ {
+ this(INITIAL_CAPACITY);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param capacity initial capacity
+ */
+ public LongList(int capacity)
+ {
+ _list = new long[INITIAL_CAPACITY];
+ }
+
+ /**
+ * Add a long to the list
+ * @param l the long
+ */
+ public void add(long l)
+ {
+ ensureCapacity(_count + 1);
+ _list[_count] = l;
+ _count++;
+ }
+
+ /**
+ * Get the long on index i in the list
+ * @param i the index
+ * @return the long
+ */
+ public long get(int i)
+ {
+ if ((i < 0) || (i >= _count))
+ {
+ throw new IndexOutOfBoundsException("Invalid index " + i);
+ } else
+ {
+ return _list[i];
+ }
+ }
+
+ /**
+ * Add a long at index i
+ * @param l the long
+ * @param i the index
+ */
+ public void add(long l, int i)
+ {
+ if ((i < 0) || (i > _count))
+ {
+ throw new IndexOutOfBoundsException("Invalid index " + i);
+ } else if (i == _count)
+ {
+ add(l);
+ } else
+ {
+ ensureCapacity(_count + 1);
+ for (int j = _count; j > i; j--)
+ {
+ _list[j] = _list[j - 1];
+ }
+ _count++;
+ _list[i] = l;
+ }
+ }
+
+ /**
+ * ensure the capacity of the long
+ * @param size the size
+ */
+ private void ensureCapacity(int size)
+ {
+ if (_list.length < size)
+ {
+ long[] newlist = new long[_list.length + GROW];
+ for (int i = 0; i < _list.length; i++)
+ {
+ newlist[i] = _list[i];
+ }
+ _list = newlist;
+ }
+ }
+
+ /**
+ * Remove the long at index i
+ * @param i the index
+ * @return the long at index i
+ */
+ public long remove(int i)
+ {
+ if ((i < 0) || (i >= _count))
+ {
+ throw new IndexOutOfBoundsException("Invalid index " + i);
+ } else
+ {
+ long save = _list[i];
+ for (int j = i; j < (_count - 2); j--)
+ {
+ _list[j] = _list[j + 1];
+ }
+ _count--;
+ return save;
+ }
+ }
+
+ /**
+ * Return the first long in the list
+ * @return the first long
+ */
+ public long first()
+ {
+ return _list[0];
+ }
+
+ /**
+ * Return the last long in the list
+ * @return the last long
+ */
+ public long last()
+ {
+ return _list[_count - 1];
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/LookupCache.java b/src/java/org/onemind/commons/java/datastructure/LookupCache.java
new file mode 100644
index 0000000..530a1c6
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/LookupCache.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+/**
+ * A lookup cache implements simple lookup caching algorithm for looking up things. The derived class simply implement the
+ * produce(Object key) method which is assumed an expensive operation and the results will be cached by the lookup cache
+ * implementation. There's no public method on lookup cache, the developer should provide application specific lookup interface.
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: LookupCache.java,v 1.4 2004/09/30 13:26:26 thlee Exp $ $Name: $
+ */
+public abstract class LookupCache
+{
+
+ /** the logger * */
+ private static final Logger _logger = Logger.getLogger(LookupCache.class.getName());
+
+ /** the hit cache * */
+ private Map _cache = new HashMap();
+
+ /** the negative cache * */
+ private Set _negCache;
+
+ /** indicate whether to do negative caching * */
+ private boolean _doNegCache = true;
+
+ /**
+ * {@inheritDoc}
+ */
+ public LookupCache()
+ {
+ this(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param doNegCache whether to do negative caching
+ */
+ public LookupCache(boolean doNegCache)
+ {
+ setDoNegativeCache(doNegCache);
+ }
+
+ /**
+ * The main lookup method. The developer should provide another application specific method that call this method to return what
+ * the application wants
+ * @param key the key
+ * @return the object or null
+ * @todo add synchronization when lookup the same key to avoid double loading
+ */
+ protected final Object lookup(Object key)
+ {
+ if (_doNegCache)
+ {
+ if (_negCache.contains(key))
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Returning negative cache hit");
+ }
+ return null;
+ }
+ }
+ Object o = _cache.get(key);
+ if (o == null)
+ {
+ //TODO: synchronization for looking up same key
+ o = produce(key);
+ if (o != null)
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Put hit of " + key + " to cache");
+ }
+ _cache.put(key, o);
+ } else
+ {
+ if (_doNegCache)
+ {
+ _logger.finest("Put negative hit of " + key + " to cache");
+ _negCache.add(key);
+ }
+ }
+ } else
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Returning positive cache hit of " + key);
+ }
+ }
+ return o;
+ }
+
+ /**
+ * Produce the object given the key. This is assumed to be an expensive operation and it will be called by the lookup method.
+ * The result will be cached by the lookup method and negative result also will be cached to if the doNegCache is turned on.
+ * @param key the key
+ * @return the result or null if no result
+ */
+ protected abstract Object produce(Object key);
+
+ /**
+ * Turn on/off the negative cache
+ * @param b true to turn on the neg cache
+ */
+ protected void setDoNegativeCache(boolean b)
+ {
+ _doNegCache = b;
+ if (b && (_negCache == null))
+ {
+ _negCache = new HashSet();
+ }
+ }
+
+ /**
+ * Get whether the object is in negative cache
+ * @param o the object
+ * @return true if is in negative cache
+ */
+ protected boolean isInNegCache(Object o)
+ {
+ return _negCache.contains(o);
+ }
+
+ /**
+ * Test if the key is in cache
+ * @param o the object
+ * @return true if is in cache
+ */
+ protected boolean isInCache(Object o)
+ {
+ return _cache.containsKey(o);
+ }
+
+ /**
+ * Clear all the negative cache
+ */
+ protected void clearNegCache()
+ {
+ if (_negCache != null)
+ {
+ _negCache.clear();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/MapEntry.java b/src/java/org/onemind/commons/java/datastructure/MapEntry.java
new file mode 100644
index 0000000..3eacd07
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/MapEntry.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.Map;
+/**
+ * A simple Map.Entry implementation that can be used for Map extension
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MapEntry.java,v 1.3 2005/04/26 17:41:48 thlee Exp $ $Name: $
+ */
+public class MapEntry implements Map.Entry
+{
+
+ /** the key * */
+ private Object _key;
+
+ /** the value * */
+ private Object _value;
+
+ /**
+ * {@inheritDoc}
+ */
+ public MapEntry(Object key, Object value)
+ {
+ _key = key;
+ _value = value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getKey()
+ {
+ return _key;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getValue()
+ {
+ return _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object setValue(Object value)
+ {
+ Object o = _value;
+ _value = value;
+ return o;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode()
+ {
+ return _key.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object o)
+ {
+ return _key.equals(((MapEntry) o)._key);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/MruList.java b/src/java/org/onemind/commons/java/datastructure/MruList.java
new file mode 100644
index 0000000..abebd34
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/MruList.java
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+/**
+ * Most recently used list implementation. It support entries expiration
+ * by access time.
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MruList.java,v 1.4 2005/04/26 17:41:59 thlee Exp $ $Name: $
+ */
+public class MruList implements Set
+{
+
+ /**
+ * Represent an entry in the MruList
+ * @author TiongHiang Lee
+ */
+ protected static class MruEntry implements Comparable
+ {
+
+ /** the last access time * */
+ private long _lastAccessTime;
+
+ /** the object * */
+ private Object _obj;
+
+ /**
+ * Constructor
+ * @param obj the object
+ * @param time the time
+ */
+ public MruEntry(Object obj, long time)
+ {
+ _obj = obj;
+ _lastAccessTime = time;
+ }
+
+ /**
+ * Compare by the access time
+ * @param e another entry
+ * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the
+ * specified object.
+ */
+ public int compareTo(MruEntry e)
+ {
+ if (_lastAccessTime > e._lastAccessTime)
+ {
+ return -1;
+ } else if (_lastAccessTime < e._lastAccessTime)
+ {
+ return 1;
+ } else
+ {
+ if (_obj.equals(e._obj))
+ {
+ return 0;
+ } else if (_obj.hashCode() > e._obj.hashCode())
+ {
+ return 1;
+ } else
+ {
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((MruEntry) o);
+ }
+
+ /**
+ * Return the lastAccessTime
+ * @return the lastAccessTime.
+ */
+ public final long getLastAccessTime()
+ {
+ return _lastAccessTime;
+ }
+
+ /**
+ * Set the lastAccessTime
+ * @param lastAccessTime The lastAccessTime to set.
+ */
+ public final void setLastAccessTime(long lastAccessTime)
+ {
+ _lastAccessTime = lastAccessTime;
+ }
+
+ /**
+ * Return the obj
+ * @return the obj.
+ */
+ public final Object getObj()
+ {
+ return _obj;
+ }
+
+ /**
+ * Set the obj
+ * @param obj The obj to set.
+ */
+ public final void setObj(Object obj)
+ {
+ _obj = obj;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return (_obj + ": " + _lastAccessTime);
+ }
+ }
+
+ /**
+ * An iterator to the entries
+ * @author TiongHiang Lee
+ */
+ protected static class MruIterator implements Iterator
+ {
+
+ /** the iterator * */
+ private Iterator _entryIterator;
+
+ /**
+ * Constructor
+ * @param entryIterator the iterator
+ */
+ public MruIterator(Iterator entryIterator)
+ {
+ _entryIterator = entryIterator;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasNext()
+ {
+ return _entryIterator.hasNext();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object next()
+ {
+ MruEntry entry = (MruEntry) _entryIterator.next();
+ return entry._obj;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void remove()
+ {
+ _entryIterator.remove();
+ }
+ }
+
+ /** the entries map * */
+ private HashMap _entryMap = new HashMap();
+
+ /** the last cleanup time * */
+ private long _lastCleanupTime;
+
+ /** the sorted mru list * */
+ private TreeSet _mruList = new TreeSet();
+
+ /** the size * */
+ private long _sizeLimit;
+
+ /** the timeout * */
+ private long _timeout;
+
+ /**
+ * {@inheritDoc}
+ */
+ public MruList()
+ {
+ this(0, 0);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param sizeLimit the size limit of the MruList (0 for no size limit)
+ * @param timeout the timeout (0 for never timeout)
+ */
+ public MruList(long sizeLimit, long timeout)
+ {
+ _sizeLimit = sizeLimit;
+ _timeout = timeout;
+ _lastCleanupTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Record that object o is being accessed. This will put a timestamp to the object
+ * @param o the object
+ * @return true if the object was in the list before
+ */
+ public boolean access(Object o)
+ {
+ long now = System.currentTimeMillis();
+ if ((_timeout > 0) && ((now - _lastCleanupTime) > _timeout))
+ {
+ expireEntries(_timeout);
+ }
+ boolean flag = false;
+ MruEntry entry = (MruEntry) _entryMap.get(o);
+ if (entry != null)
+ { //exist already
+ _mruList.remove(entry);//must remove to add again later
+ entry._lastAccessTime = now;
+ flag = true;
+ } else
+ {
+ entry = new MruEntry(o, now);
+ _entryMap.put(o, entry);
+ }
+ _mruList.add(entry);
+ if ((_sizeLimit > 0) && (size() > _sizeLimit))
+ {
+ truncateEntries(_sizeLimit);
+ }
+ return flag;
+ }
+
+ /**
+ * @see access(Object o)
+ */
+ public boolean add(Object o)
+ {
+ return access(o);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean addAll(Collection c)
+ {
+ Iterator it = c.iterator();
+ while (it.hasNext())
+ {
+ add(it.next());
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clear()
+ {
+ _entryMap.clear();
+ _mruList.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean contains(Object o)
+ {
+ return _entryMap.containsKey(o);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsAll(Collection c)
+ {
+ return _entryMap.keySet().containsAll(c);
+ }
+
+ /**
+ * Expire the entries that was last access longer that time t Document this method.
+ * @param t the elapse time
+ */
+ public void expireEntries(long t)
+ {
+ long now = System.currentTimeMillis();
+ _lastCleanupTime = now;
+ do
+ {
+ MruEntry entry = (MruEntry) _mruList.last();
+ if (entry == null)
+ {
+ break;
+ } else if ((now - entry._lastAccessTime) > t)
+ {
+ expireEntry(entry._obj);
+ } else
+ {
+ break;
+ }
+ } while (true);
+ }
+
+ /**
+ * Get the last access time object obj
+ * @param obj the object
+ * @return the access time, or -1 if the object is not in the cache
+ */
+ public long getLastAccessTime(Object obj)
+ {
+ MruEntry entry = (MruEntry) _entryMap.get(obj);
+ if (entry != null)
+ {
+ return entry._lastAccessTime;
+ } else
+ {
+ return -1;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEmpty()
+ {
+ return _entryMap.size() == 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator iterator()
+ {
+ return new MruIterator(_mruList.iterator());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean remove(Object o)
+ {
+ MruEntry entry = (MruEntry) _entryMap.remove(o);
+ boolean flag = false;
+ if (entry != null)
+ {
+ _mruList.remove(entry);
+ flag = true;
+ }
+ return flag;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean removeAll(Collection c)
+ {
+ boolean flag = false;
+ Iterator it = c.iterator();
+ while (it.hasNext())
+ {
+ if (remove(it.next()))
+ {
+ flag = true;
+ }
+ }
+ return flag;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean retainAll(Collection c)
+ {
+ Iterator it = _entryMap.keySet().iterator();
+ boolean flag = false;
+ while (it.hasNext())
+ {
+ Object obj = it.next();
+ if (!c.contains(obj))
+ {
+ remove(obj);
+ flag = true;
+ }
+ }
+ return flag;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int size()
+ {
+ return _entryMap.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object[] toArray()
+ {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object[] toArray(Object[] a)
+ {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /**
+ * Truncate the entries to specific size
+ * @param size the size
+ */
+ public void truncateEntries(long size)
+ {
+ while (size() > size)
+ {
+ MruEntry entry = (MruEntry) _mruList.last();
+ truncateEntry(entry._obj);
+ }
+ }
+
+ /**
+ * Remove the object from the MruList
+ * @param obj the object
+ */
+ protected void truncateEntry(Object obj)
+ {
+ remove(obj);
+ }
+
+ /**
+ * Remove the entry from the MruList
+ * @param obj expire the entry
+ */
+ protected void expireEntry(Object obj)
+ {
+ remove(obj);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/MruMap.java b/src/java/org/onemind/commons/java/datastructure/MruMap.java
new file mode 100644
index 0000000..f843020
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/MruMap.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+/**
+ * Most recently used map (implementation based on mrulist)
+ *
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MruMap.java,v 1.3 2004/10/31 15:57:55 thlee Exp $ $Name: $
+ */
+public class MruMap extends HashMap implements Map
+{
+
+ /**
+ * For MruMap implementation
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MruMap.java,v 1.3 2004/10/31 15:57:55 thlee Exp $ $Name: $
+ */
+ private class InnerMruList extends MruList
+ {
+ /**
+ * Constructor
+ * @param size the size
+ * @param timeout the timeout
+ */
+ public InnerMruList(long size, long timeout)
+ {
+ super(size, timeout);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void truncateEntry(Object obj)
+ {
+ super.truncateEntry(obj);
+ MruMap.this.remove(obj);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void expireEntry(Object obj)
+ {
+ super.expireEntry(obj);
+ MruMap.this.remove(obj);
+ }
+ }
+
+ /** the list * */
+ private MruList _mruList;
+
+ /**
+ * {@inheritDoc}
+ */
+ public MruMap()
+ {
+ this(0, 0);
+ }
+
+ /**
+ * Constructor
+ * @param size the limit of the map (0 for never timeout)
+ * @param timeout the timeout (0 for never expire)
+ */
+ public MruMap(long size, long timeout)
+ {
+ _mruList = new InnerMruList(size, timeout);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clear()
+ {
+ super.clear();
+ _mruList.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object get(Object key)
+ {
+ _mruList.access(key);
+ return super.get(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object put(Object key, Object value)
+ {
+ Object result = super.put(key, value);
+ _mruList.access(key); //this must be done second
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void putAll(Map t)
+ {
+ super.putAll(t);//this must be done second
+ _mruList.addAll(t.keySet());
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object remove(Object key)
+ {
+ _mruList.remove(key);
+ return super.remove(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void expire(MruList list, Object obj)
+ {
+ super.remove(obj);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void truncate(MruList list, Object obj)
+ {
+ super.remove(obj);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/Nametable.java b/src/java/org/onemind/commons/java/datastructure/Nametable.java
new file mode 100644
index 0000000..507f60f
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/Nametable.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.Map;
+
+/**
+ * A name table interface
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public interface Nametable
+{
+
+ /**
+ * Declare a variable in the name table
+ * @param name the name
+ * @param value the value
+ */
+ void declare(String name, Object value);
+
+ /**
+ * Assign a variable in the name table
+ * @param name the name
+ * @param value the value
+ * @return the old value, or null
+ */
+ Object assign(String name, Object value);
+
+ /**
+ * Whether the nametable contains the name
+ * @param name the name
+ * @return true if contains the name
+ */
+ boolean containsName(String name);
+
+ /**
+ * Access the value associated with name
+ * @param name
+ * @return
+ */
+ Object access(String name);
+
+ /**
+ * Undeclare the name
+ * @param name
+ */
+ void undeclare(String name);
+
+ /**
+ * Return map representation of this nametable
+ * @return unmodifiable map representation of this nametable
+ */
+ Map asMap();
+}
diff --git a/src/java/org/onemind/commons/java/datastructure/NametableStack.java b/src/java/org/onemind/commons/java/datastructure/NametableStack.java
new file mode 100644
index 0000000..6e3e710
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/NametableStack.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+import java.util.logging.Logger;
+/**
+ * A nametable stack contains key-value mapping that has a scope.
+ * A new scope can be opened for putting new mappings and all the
+ * mappings added in this scope can be wiped out easily with a
+ * closeScope command. In effect this is like a stack of Maps,
+ * hence the name NametableStack.
+ *
+ * NOTE: the implementation use a map and list to achieve the behaviour.
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: NametableStack.java,v 1.7 2005/06/22 22:57:37 thlee Exp $ $Name: $
+ */
+public class NametableStack
+{
+
+ /** the logger * */
+ private static final Logger _logger = Logger.getLogger(NametableStack.class.getName());
+
+ /** the map * */
+ private Nametable _nametable;
+
+ /** the list of maps * */
+ private ArrayList _list = new ArrayList();
+
+ /**
+ * The local nametable defines a scope where local variables mask out the global
+ * variables, but the global variable can still be accessed. This is useful for
+ * implementing function context
+ *
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+ private static class LocalNametable implements Nametable
+ {
+
+ /** the local variables **/
+ private final Map _locals = new HashMap();
+
+ /** the global map **/
+ private final Nametable _global;
+
+ /** the scope **/
+ private final int _scope;
+
+ /**
+ * Constructor
+ * @param global the global
+ * @param scope the scope # where this local nametabe is openned
+ */
+ private LocalNametable(Nametable global, int scope)
+ {
+ _global = global;
+ _scope = scope;
+ }
+
+ /**
+ * Get the global
+ * @return the global
+ */
+ private Nametable getGlobal()
+ {
+ return _global;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsName(String key)
+ {
+ return _locals.containsKey(key) || _global.containsName(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void declare(String name, Object value)
+ {
+ _locals.put(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object assign(String name, Object value)
+ {
+ if (_locals.containsKey(name))
+ {
+ return _locals.put(name, value);
+ } else
+ {
+ //TODO: determine whether to allow local scope to reassign global
+ return _global.assign(name, value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object access(String name)
+ {
+ if (_locals.containsKey(name))
+ {
+ return _locals.get(name);
+ } else
+ {
+ return _global.access(name);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void undeclare(String name)
+ {
+ if (_locals.containsKey(name))
+ {
+ _locals.remove(name);
+ } else
+ {
+ //TODO: determine whether to allow local scope to undeclare global
+ _global.undeclare(name);
+ }
+ }
+
+ public String toString(){
+ StringBuffer sb = new StringBuffer();
+ sb.append("Scope=");
+ sb.append(_scope);
+ sb.append("\n");
+ sb.append("Locals=" + _locals + "\n");
+ sb.append("Global=" + _global + "\n");
+ return sb.toString();
+ }
+
+ public Map asMap(){
+ Map m = new HashMap(_global.asMap());
+ m.putAll(_locals);
+ return Collections.unmodifiableMap(m);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NametableStack()
+ {
+ this(new HashMap());
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param m the initial mapping
+ */
+ public NametableStack(Map m)
+ {
+ _nametable = new SimpleNametable(m);
+ }
+
+ /**
+ * Open a new scope for mappings. Return an integer that represents a scope id
+ * @return the new scope
+ */
+ public int newScope()
+ {
+ return _list.size();
+ }
+
+ public int newLocalScope()
+ {
+ _nametable = new LocalNametable(_nametable, _list.size());
+ return _list.size();
+ }
+
+ public void closeLocalScope(int i)
+ {
+ if (_nametable instanceof LocalNametable)
+ {
+ LocalNametable nt = (LocalNametable) _nametable;
+ if (nt._scope != i)
+ {
+ throw new IllegalArgumentException("Local scope " + i + " not matched");
+ } else
+ {
+ for (int k = _list.size(); k > i; k--)
+ {
+ _list.remove(k-1);
+ }
+ _nametable = nt.getGlobal();
+ }
+ } else
+ {
+ throw new IllegalStateException("Cannot find scope " + i);
+ }
+ }
+
+ /**
+ * Close a scope
+ * @param l the scope id
+ */
+ public void closeScope(int l)
+ {
+ if (_nametable instanceof LocalNametable)
+ {
+ if (l < ((LocalNametable) _nametable)._scope)
+ {
+ throw new IllegalStateException("Encounter unclosed local scope");
+ }
+ }
+ int n = _list.size();
+ if (l > n)
+ {
+ throw new IllegalArgumentException("The scope has been closed");
+ } else if (l < n)
+ {
+ int diff = n - l;
+ for (int i = 0; i < diff; i++)
+ {
+ _nametable.undeclare((String)_list.remove(n - i - 1));
+ }
+ }
+ }
+
+ /**
+ * Declare name value pair
+ * @param name
+ * @param value
+ * @return
+ */
+ public void declare(String name, Object value)
+ {
+ _nametable.declare(name, value);
+ _list.add(name);
+ }
+
+ /**
+ * Assign name/value pair
+ * @param name
+ * @param value
+ * @return
+ */
+ public Object assign(String name, Object value)
+ {
+ return _nametable.assign(name, value);
+ }
+
+ /**
+ * Resolve the value associated with key name
+ * @param name the key
+ * @return the value associated with key
+ */
+ public Object access(String name)
+ {
+ return _nametable.access(name);
+ }
+
+ /**
+ * Whether the map contains key name
+ * @param name the key
+ * @return true if map contains key name
+ */
+ public boolean containsName(String name)
+ {
+ return _nametable.containsName(name);
+ }
+
+ /**
+ * Return map representation of the nametable stack
+ * @return the map
+ */
+ public Map asMap()
+ {
+ return _nametable.asMap();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return _nametable.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/Scoreable.java b/src/java/org/onemind/commons/java/datastructure/Scoreable.java
new file mode 100644
index 0000000..aa9f36a
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/Scoreable.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+public class Scoreable implements Comparable
+{
+
+ private int _score;
+
+ private Object _obj;
+
+ public Scoreable(int score, Object obj)
+ {
+ _score = score;
+ _obj = obj;
+ }
+
+ public Object getObject()
+ {
+ return _obj;
+ }
+
+ public int getScore()
+ {
+ return _score;
+ }
+
+ public int compareTo(Object o)
+ {
+ return getScore() - ((Scoreable) o).getScore();
+ }
+}
diff --git a/src/java/org/onemind/commons/java/datastructure/SimpleNametable.java b/src/java/org/onemind/commons/java/datastructure/SimpleNametable.java
new file mode 100644
index 0000000..f4bc7a7
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/SimpleNametable.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.Collections;
+import java.util.Map;
+/**
+ * A simple implementation of nametable
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public class SimpleNametable implements Nametable
+{
+
+ private final Map _table;
+
+ /**
+ * Constructor
+ * @param m the name
+ */
+ public SimpleNametable(Map m)
+ {
+ _table = m;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void declare(String name, Object value)
+ {
+ if (_table.containsKey(name))
+ {
+ throw new IllegalArgumentException("Variable '" + name + "' has been declared.");
+ } else
+ {
+ _table.put(name, value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object assign(String name, Object value)
+ {
+ if (_table.containsKey(name))
+ {
+ return _table.put(name, value);
+ } else
+ {
+ throw new IllegalArgumentException("Variable '" + name + "' has not been declared.");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsName(String name)
+ {
+ return _table.containsKey(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object access(String name)
+ {
+ if (containsName(name))
+ {
+ return _table.get(name);
+ } else
+ {
+ throw new IllegalArgumentException("Varaible '" + name + "' has not been declared.");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void undeclare(String name)
+ {
+ //TODO: need declaration check?
+ _table.remove(name);
+ }
+
+ public String toString()
+ {
+ return _table.toString();
+ }
+
+ /**
+ * Return the name table as a map
+ * @return unmodifiable map representation of the name table
+ */
+ public Map asMap()
+ {
+ return Collections.unmodifiableMap(_table);
+ }
+}
diff --git a/src/java/org/onemind/commons/java/datastructure/Stack.java b/src/java/org/onemind/commons/java/datastructure/Stack.java
new file mode 100644
index 0000000..863bf11
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/Stack.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+/**
+ * An extension of java.util.Stack to have popUntil and pushReturnSize method
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Stack.java,v 1.2 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public class Stack extends java.util.Stack
+{
+
+ /**
+ * {@inheritDoc}
+ */
+ public Stack()
+ {
+ }
+
+ /**
+ * Push the object ot the stack and return the size before pushing the object in
+ * @param o the object
+ * @return the size before the push
+ */
+ public int pushReturnSize(Object o)
+ {
+ int i = size();
+ push(o);
+ return i;
+ }
+
+ /**
+ * Pop until the stack reach size i
+ * @param i the size
+ */
+ public void popUntil(int i)
+ {
+ if (i < 0)
+ {
+ throw new IllegalArgumentException("Invalid size for popUtil");
+ } else if (i > size())
+ {
+ throw new RuntimeException("Stack already less than " + i);
+ }
+ while (size() > i)
+ {
+ pop();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/ThreadLocalStack.java b/src/java/org/onemind/commons/java/datastructure/ThreadLocalStack.java
new file mode 100644
index 0000000..be57b87
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/ThreadLocalStack.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+/**
+ * A stack associated with current thread
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ThreadLocalStack.java,v 1.2 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public class ThreadLocalStack
+{
+
+ /** the thread local * */
+ private ThreadLocal _local = new ThreadLocal();
+
+ /**
+ * Push a local object the the thread local stack
+ * @param localObject the local object
+ * @return the size after the push
+ */
+ public int pushLocal(Object localObject)
+ {
+ return getLocalStack().pushReturnSize(localObject);
+ }
+
+ /**
+ * get the local stack
+ * @return the stack
+ */
+ public Stack getLocalStack()
+ {
+ Stack s = (Stack) _local.get();
+ if (s == null)
+ {
+ s = new Stack();
+ _local.set(s);
+ }
+ return s;
+ }
+
+ /**
+ * Get the top-most local object in local stack
+ * @return the top-most local object in local stack
+ */
+ public Object getLocal()
+ {
+ return getLocalStack().peek();
+ }
+
+ /**
+ * Pop uptil certain size in local stack
+ * @param i the size
+ */
+ public void popLocalUtil(int i)
+ {
+ getLocalStack().popUntil(i);
+ }
+
+ /**
+ * Pop the top-most local object in threadlocal stack
+ * @return the top-most local object
+ */
+ public Object popLocal()
+ {
+ return getLocalStack().pop();
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/TrackedMap.java b/src/java/org/onemind/commons/java/datastructure/TrackedMap.java
new file mode 100644
index 0000000..63af340
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/TrackedMap.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.*;
+/**
+ * A map that has it's map values changes tracked. It uses an inner map to keep the unchanged value and itself to track the changes
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: TrackedMap.java,v 1.2 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public class TrackedMap extends HashMap
+{
+
+ /** the track inner map * */
+ private Map _tracked;
+
+ /**
+ * {@inheritDoc}
+ */
+ public TrackedMap()
+ {
+ this(new HashMap());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TrackedMap(int initialCapacity)
+ {
+ super(initialCapacity);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TrackedMap(int initialCapacity, float loadFactor)
+ {
+ super(initialCapacity, loadFactor);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TrackedMap(Map map)
+ {
+ super();
+ _tracked = map;
+ }
+
+ /**
+ * Return whether this map has been changes
+ * @return true if it has been changed
+ */
+ public boolean hasChanges()
+ {
+ return getChangedKeySet().size() > 0;
+ }
+
+ /**
+ * Return the key set of changed values
+ * @return the key set
+ */
+ public Set getChangedKeySet()
+ {
+ return super.keySet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object get(Object key)
+ {
+ if (containsKey(key))
+ {
+ return super.get(key);
+ } else
+ {
+ return _tracked.get(key);
+ }
+ }
+
+ /**
+ * Make this map as up-to-date.
+ */
+ public void makeUpToDate()
+ {
+ Iterator it = super.keySet().iterator();
+ while (it.hasNext())
+ {
+ Object key = it.next();
+ Object o = super.get(key);
+ _tracked.put(key, o);
+ }
+ super.clear();
+ }
+
+ /**
+ * Clear all the changes
+ */
+ public void clearChanges()
+ {
+ super.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clear()
+ {
+ super.clear();
+ _tracked.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsKey(Object key)
+ {
+ return super.containsKey(key) || _tracked.containsKey(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean containsValue(Object value)
+ {
+ return super.containsValue(value) || _tracked.containsValue(value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set entrySet()
+ {
+ Set s = new HashSet(_tracked.entrySet());
+ s.addAll(super.entrySet());
+ return s;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEmpty()
+ {
+ return super.isEmpty() && _tracked.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set keySet()
+ {
+ Set s = new HashSet(_tracked.keySet());
+ s.addAll(super.keySet());
+ return s;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object remove(Object key)
+ {
+ Object o = get(key);
+ put(key, null);
+ return o;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int size()
+ {
+ return keySet().size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection values()
+ {
+ HashSet set = new HashSet(_tracked.values());
+ set.addAll(super.values());
+ return set;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/XmlProperties.java b/src/java/org/onemind/commons/java/datastructure/XmlProperties.java
new file mode 100644
index 0000000..f374de8
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/XmlProperties.java
@@ -0,0 +1,51 @@
+
+package org.onemind.commons.java.datastructure;
+
+import java.io.*;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.parsers.*;
+import org.onemind.commons.java.lang.reflect.ReflectUtils;
+import org.onemind.commons.java.xml.digest.*;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+/**
+ * An XmlPropertiesReader read a properties out of an xml file. The xml is read
+ * using dom parser. It support all the java primitive types
+ * and in addition creation of instance of ElementDigester
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: XmlProperties.java,v 1.3 2005/06/22 22:57:52 thlee Exp $ $Name: $
+ */
+public class XmlProperties extends HashMap
+{
+ /**
+ * Constructor
+ * @param filename the file name
+ * @throws FileNotFoundException
+ * @throws IOException
+ * @throws SAXException
+ * @throws ParserConfigurationException
+ */
+ public XmlProperties(String filename) throws FileNotFoundException, ParserConfigurationException, SAXException, IOException
+ {
+ this(new FileInputStream(filename));
+ }
+
+ /**
+ * Constructor
+ * @param stream
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws IOException
+ */
+ public XmlProperties(InputStream is) throws ParserConfigurationException, SAXException, IOException
+ {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ // Parse the input
+ SAXParser saxParser = factory.newSAXParser();
+ SaxDigesterHandler handler = new SaxDigesterHandler();
+ handler.addDigester("Properties", new XmlPropertyElementDigester("Property", this));
+ saxParser.parse(is, handler);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/datastructure/XmlPropertyElementDigester.java b/src/java/org/onemind/commons/java/datastructure/XmlPropertyElementDigester.java
new file mode 100644
index 0000000..1228a60
--- /dev/null
+++ b/src/java/org/onemind/commons/java/datastructure/XmlPropertyElementDigester.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+import org.onemind.commons.java.lang.reflect.ReflectUtils;
+import org.onemind.commons.java.xml.digest.*;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+/**
+ * A Sax elemenbt handler that can handle parsing properties specified in an xml file
+ * This syntax of the xml is something like
+ *
+
+
+
+
+
+
+
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public class XmlPropertyElementDigester extends DefaultDigester implements ElementDigester
+{
+
+ private static final Map _typeMap;
+ static
+ {
+ _typeMap = new HashMap();
+ _typeMap.put("short", new Integer(Types.SMALLINT));
+ _typeMap.put("int", new Integer(Types.INTEGER));
+ _typeMap.put("long", new Integer(Types.BIGINT));
+ _typeMap.put("float", new Integer(Types.FLOAT));
+ _typeMap.put("double", new Integer(Types.DOUBLE));
+ _typeMap.put("boolean", new Integer(Types.BOOLEAN));
+ _typeMap.put("char", new Integer(Types.CHAR));
+ _typeMap.put("string", new Integer(Types.VARCHAR));
+ }
+
+ private final Map _prop;
+
+ public XmlPropertyElementDigester(String elementName, Map prop)
+ {
+ super(elementName);
+ _prop = prop;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startDigest(SaxDigesterHandler handler, Attributes attrs) throws SAXException
+ {
+ String name = attrs.getValue("name");
+ String type = attrs.getValue("type");
+ String value = attrs.getValue("value");
+ String clazz = attrs.getValue("class");
+ if (name == null)
+ {
+ throw new SAXException("name attribute must exists on property");
+ }
+ if (type != null && clazz != null)
+ {
+ throw new SAXException("Both type and class cannot be specified on same property");
+ }
+ if (clazz != null)
+ {
+ try
+ {
+ Class c = ReflectUtils.getClass(clazz);
+ Object obj = (Object) ReflectUtils.newInstance(c, null);
+ String digest = attrs.getValue("digest");
+ if (digest != null && digest.equalsIgnoreCase("true"))
+ {
+ if (clazz != null)
+ {
+ if (!ElementDigester.class.isAssignableFrom(obj.getClass()))
+ {
+ throw new SAXException("Class " + clazz + " is not a subclass of ElementDigester");
+ }
+ ElementDigester dig = (ElementDigester) obj;
+ handler.addSubDigester(dig);
+ _prop.put(name, dig);
+ }
+ } else
+ {//just put the object as a property
+ _prop.put(name, obj);
+ }
+ } catch (Exception e)
+ {
+ throw new SAXException(e.getMessage(), e);
+ }
+ } else if (type != null)
+ {
+ Object v = null;
+ Integer typeInt = (Integer) _typeMap.get(type);
+ if (typeInt == null)
+ {
+ throw new SAXException("Unrecognized property type " + type);
+ } else
+ {
+ switch (typeInt.intValue())
+ {
+ case Types.SMALLINT :
+ v = Short.valueOf(value);
+ break;
+ case Types.INTEGER :
+ v = Integer.valueOf(value);
+ break;
+ case Types.BIGINT :
+ v = Long.valueOf(value);
+ break;
+ case Types.FLOAT :
+ v = Float.valueOf(value);
+ break;
+ case Types.DOUBLE :
+ v = Double.valueOf(value);
+ break;
+ case Types.BOOLEAN :
+ v = Boolean.valueOf(value);
+ break;
+ case Types.CHAR :
+ v = new Character(value.charAt(0));
+ break;
+ case Types.VARCHAR :
+ v = value;
+ break;
+ default :
+ throw new IllegalStateException("Unrecognized property type " + type);
+ }
+ }
+ _prop.put(name, v);
+ } else
+ {
+ _prop.put(name, value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endDigest(SaxDigesterHandler handler) throws SAXException
+ {
+ // TODO Auto-generated method stub
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void characters(SaxDigesterHandler handler, char[] chars, int offset, int length) throws SAXException
+ {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/src/java/org/onemind/commons/java/event/EventFirer.java b/src/java/org/onemind/commons/java/event/EventFirer.java
new file mode 100644
index 0000000..abf75d7
--- /dev/null
+++ b/src/java/org/onemind/commons/java/event/EventFirer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.event;
+
+import java.util.EventObject;
+/**
+ * Interface for firing event
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: EventFirer.java,v 1.2 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public interface EventFirer
+{
+
+ /**
+ * Fire an event
+ * @param listener the listener
+ * @param evt the event
+ */
+ public void fireEvent(EventListener listener, EventObject evt);
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/event/EventHandler.java b/src/java/org/onemind/commons/java/event/EventHandler.java
new file mode 100644
index 0000000..bd13745
--- /dev/null
+++ b/src/java/org/onemind/commons/java/event/EventHandler.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.event;
+
+import java.util.EventObject;
+
+public interface EventHandler
+{
+ public void handleEvent(EventObject evt);
+}
diff --git a/src/java/org/onemind/commons/java/event/EventListener.java b/src/java/org/onemind/commons/java/event/EventListener.java
new file mode 100644
index 0000000..d0476b0
--- /dev/null
+++ b/src/java/org/onemind/commons/java/event/EventListener.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.event;
+
+/**
+ * An tagging event listener interface
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: EventListener.java,v 1.2 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public interface EventListener
+{
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/event/EventListenerList.java b/src/java/org/onemind/commons/java/event/EventListenerList.java
new file mode 100644
index 0000000..268e98c
--- /dev/null
+++ b/src/java/org/onemind/commons/java/event/EventListenerList.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.event;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.List;
+/**
+ * A listener list contains listeners and fire events
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: EventListenerList.java,v 1.2 2004/08/26 12:33:16 thlee Exp $ $Name: $
+ */
+public class EventListenerList
+{
+
+ /** the listeners * */
+ private List _eventListeners = new ArrayList();
+
+ /**
+ * {@inheritDoc}
+ */
+ public EventListenerList()
+ {
+ }
+
+ /**
+ * Get the listeners
+ * @return the listeners
+ */
+ public Collection getListeners()
+ {
+ return Collections.unmodifiableCollection(_eventListeners);
+ }
+
+ /**
+ * Fire an event to all listeneres
+ * @param firer the firer
+ * @param obj the event object
+ */
+ public void fireEvent(EventFirer firer, EventObject obj)
+ {
+ Iterator it = _eventListeners.iterator();
+ while (it.hasNext())
+ {
+ EventListener listener = (EventListener) it.next();
+ firer.fireEvent(listener, obj);
+ }
+ }
+
+ /**
+ * Add a listener
+ * @param listener the listener
+ */
+ public void addListener(EventListener listener)
+ {
+ _eventListeners.add(listener);
+ }
+
+ /**
+ * Remove a listener
+ * @param listener the listener
+ */
+ public void removeListener(EventListener listener)
+ {
+ _eventListeners.remove(listener);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/html/css/Css.java b/src/java/org/onemind/commons/java/html/css/Css.java
new file mode 100644
index 0000000..e550e1d
--- /dev/null
+++ b/src/java/org/onemind/commons/java/html/css/Css.java
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.html.css;
+
+import java.util.*;
+import org.onemind.commons.java.lang.Enum;
+/**
+ * Contains css related method and constants
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Css.java,v 1.3 2005/03/07 17:28:17 thlee Exp $ $Name: $
+ */
+public class Css
+{
+
+ /**
+ * Represent the attribute (Currently contains only visual attr)
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Css.java,v 1.3 2005/03/07 17:28:17 thlee Exp $ $Name: $
+ */
+ public static final class Attr extends Enum
+ {
+
+ private static Map _cssAttrs = new HashMap();
+
+ public static final Attr background = new Attr("background");
+
+ public static final Attr background_attachment = new Attr("background-attachment");
+
+ public static final Attr background_color = new Attr("background-color");
+
+ public static final Attr background_image = new Attr("background-image");
+
+ public static final Attr background_position = new Attr("background-position");
+
+ public static final Attr background_repeat = new Attr("background-repeat");
+
+ public static final Attr border = new Attr("border");
+
+ public static final Attr border_bottom = new Attr("border-bottom");
+
+ public static final Attr border_bottom_color = new Attr("border-bottom-color");
+
+ public static final Attr border_bottom_style = new Attr("border-bottom-style");
+
+ public static final Attr border_bottom_width = new Attr("border-bottom-width");
+
+ public static final Attr border_collapse = new Attr("border-collapse");
+
+ public static final Attr border_color = new Attr("border-color");
+
+ public static final Attr border_left = new Attr("border-left");
+
+ public static final Attr border_left_color = new Attr("border-left-color");
+
+ public static final Attr border_left_style = new Attr("border-left-style");
+
+ public static final Attr border_left_width = new Attr("border-left-width");
+
+ public static final Attr border_right = new Attr("border-right");
+
+ public static final Attr border_right_color = new Attr("border-right-color");
+
+ public static final Attr border_right_style = new Attr("border-right-style");
+
+ public static final Attr border_right_width = new Attr("border-right-width");
+
+ public static final Attr border_spacing = new Attr("border-spacing");
+
+ public static final Attr border_style = new Attr("border-style");
+
+ public static final Attr border_top = new Attr("border-top");
+
+ public static final Attr border_top_color = new Attr("border-top-color");
+
+ public static final Attr border_top_style = new Attr("border-top-style");
+
+ public static final Attr border_top_width = new Attr("border-top-width");
+
+ public static final Attr border_width = new Attr("border-width");
+
+ public static final Attr bottom = new Attr("bottom");
+
+ public static final Attr caption_side = new Attr("caption-side");
+
+ public static final Attr clear = new Attr("clear");
+
+ public static final Attr clip = new Attr("clip");
+
+ public static final Attr color = new Attr("color");
+
+ public static final Attr content = new Attr("content");
+
+ public static final Attr counter_increment = new Attr("counter-increment");
+
+ public static final Attr counter_reset = new Attr("counter-reset");
+
+ public static final Attr cursor = new Attr("cursor");
+
+ public static final Attr direction = new Attr("direction");
+
+ public static final Attr display = new Attr("display");
+
+ public static final Attr empty_cells = new Attr("empty-cells");
+
+ public static final Attr float_ = new Attr("float");
+
+ public static final Attr font = new Attr("font");
+
+ public static final Attr font_family = new Attr("font-family");
+
+ public static final Attr font_size = new Attr("font-size");
+
+ public static final Attr font_size_adjust = new Attr("font-size-adjust");
+
+ public static final Attr font_stretch = new Attr("font-stretch");
+
+ public static final Attr font_style = new Attr("font-style");
+
+ public static final Attr font_variant = new Attr("font-variant");
+
+ public static final Attr font_weight = new Attr("font-weight");
+
+ public static final Attr height = new Attr("height");
+
+ public static final Attr left = new Attr("left");
+
+ public static final Attr letter_spacing = new Attr("letter-spacing");
+
+ public static final Attr line_height = new Attr("line-height");
+
+ public static final Attr list_style = new Attr("list-style");
+
+ public static final Attr list_style_image = new Attr("list-style-image");
+
+ public static final Attr list_style_position = new Attr("list-style-position");
+
+ public static final Attr list_style_type = new Attr("list-style-type");
+
+ public static final Attr margin = new Attr("margin");
+
+ public static final Attr margin_bottom = new Attr("margin-bottom");
+
+ public static final Attr margin_left = new Attr("margin-left");
+
+ public static final Attr margin_right = new Attr("margin-right");
+
+ public static final Attr margin_top = new Attr("margin-top");
+
+ public static final Attr marker_offset = new Attr("marker-offset");
+
+ public static final Attr max_height = new Attr("max-height");
+
+ public static final Attr max_width = new Attr("max-width");
+
+ public static final Attr min_height = new Attr("min-height");
+
+ public static final Attr min_width = new Attr("min-width");
+
+ public static final Attr outline = new Attr("outline");
+
+ public static final Attr outline_color = new Attr("outline-color");
+
+ public static final Attr outline_style = new Attr("outline-style");
+
+ public static final Attr outline_width = new Attr("outline-width");
+
+ public static final Attr overflow = new Attr("overflow");
+
+ public static final Attr padding = new Attr("padding");
+
+ public static final Attr padding_bottom = new Attr("padding-bottom");
+
+ public static final Attr padding_left = new Attr("padding-left");
+
+ public static final Attr padding_right = new Attr("padding-right");
+
+ public static final Attr padding_top = new Attr("padding-top");
+
+ public static final Attr position = new Attr("position");
+
+ public static final Attr quotes = new Attr("quotes");
+
+ public static final Attr right = new Attr("right");
+
+ public static final Attr table_layout = new Attr("table-layout");
+
+ public static final Attr text_align = new Attr("text-align");
+
+ public static final Attr text_decoration = new Attr("text-decoration");
+
+ public static final Attr text_indent = new Attr("text-indent");
+
+ public static final Attr text_shadow = new Attr("text-shadow");
+
+ public static final Attr text_transform = new Attr("text-transform");
+
+ public static final Attr top = new Attr("top");
+
+ public static final Attr unicode_bidi = new Attr("unicode-bidi");
+
+ public static final Attr vertical_align = new Attr("vertical-align");
+
+ public static final Attr visibility = new Attr("visibility");
+
+ public static final Attr white_space = new Attr("white-space");
+
+ public static final Attr width = new Attr("width");
+
+ public static final Attr word_spacing = new Attr("word-spacing");
+
+ public static final Attr z_index = new Attr("z-index");
+ static
+ {
+ _cssAttrs.put(background.toString(), background);
+ _cssAttrs.put(background_attachment.toString(), background_attachment);
+ _cssAttrs.put(background_color.toString(), background_color);
+ _cssAttrs.put(background_image.toString(), background_image);
+ _cssAttrs.put(background_position.toString(), background_position);
+ _cssAttrs.put(background_repeat.toString(), background_repeat);
+ _cssAttrs.put(border.toString(), border);
+ _cssAttrs.put(border_bottom.toString(), border_bottom);
+ _cssAttrs.put(border_bottom_color.toString(), border_bottom_color);
+ _cssAttrs.put(border_bottom_style.toString(), border_bottom_style);
+ _cssAttrs.put(border_bottom_width.toString(), border_bottom_width);
+ _cssAttrs.put(border_collapse.toString(), border_collapse);
+ _cssAttrs.put(border_color.toString(), border_color);
+ _cssAttrs.put(border_left.toString(), border_left);
+ _cssAttrs.put(border_left_color.toString(), border_left_color);
+ _cssAttrs.put(border_left_style.toString(), border_left_style);
+ _cssAttrs.put(border_left_width.toString(), border_left_width);
+ _cssAttrs.put(border_right.toString(), border_right);
+ _cssAttrs.put(border_right_color.toString(), border_right_color);
+ _cssAttrs.put(border_right_style.toString(), border_right_style);
+ _cssAttrs.put(border_right_width.toString(), border_right_width);
+ _cssAttrs.put(border_spacing.toString(), border_spacing);
+ _cssAttrs.put(border_style.toString(), border_style);
+ _cssAttrs.put(border_top.toString(), border_top);
+ _cssAttrs.put(border_top_color.toString(), border_top_color);
+ _cssAttrs.put(border_top_style.toString(), border_top_style);
+ _cssAttrs.put(border_top_width.toString(), border_top_width);
+ _cssAttrs.put(border_width.toString(), border_width);
+ _cssAttrs.put(bottom.toString(), bottom);
+ _cssAttrs.put(caption_side.toString(), caption_side);
+ _cssAttrs.put(clear.toString(), clear);
+ _cssAttrs.put(clip.toString(), clip);
+ _cssAttrs.put(color.toString(), color);
+ _cssAttrs.put(content.toString(), content);
+ _cssAttrs.put(counter_increment.toString(), counter_increment);
+ _cssAttrs.put(counter_reset.toString(), counter_reset);
+ _cssAttrs.put(cursor.toString(), cursor);
+ _cssAttrs.put(direction.toString(), direction);
+ _cssAttrs.put(display.toString(), display);
+ _cssAttrs.put(empty_cells.toString(), empty_cells);
+ _cssAttrs.put(float_.toString(), float_);
+ _cssAttrs.put(font.toString(), font);
+ _cssAttrs.put(font_family.toString(), font_family);
+ _cssAttrs.put(font_size.toString(), font_size);
+ _cssAttrs.put(font_size_adjust.toString(), font_size_adjust);
+ _cssAttrs.put(font_stretch.toString(), font_stretch);
+ _cssAttrs.put(font_style.toString(), font_style);
+ _cssAttrs.put(font_variant.toString(), font_variant);
+ _cssAttrs.put(font_weight.toString(), font_weight);
+ _cssAttrs.put(height.toString(), height);
+ _cssAttrs.put(left.toString(), left);
+ _cssAttrs.put(letter_spacing.toString(), letter_spacing);
+ _cssAttrs.put(line_height.toString(), line_height);
+ _cssAttrs.put(list_style.toString(), list_style);
+ _cssAttrs.put(list_style_image.toString(), list_style_image);
+ _cssAttrs.put(list_style_position.toString(), list_style_position);
+ _cssAttrs.put(list_style_type.toString(), list_style_type);
+ _cssAttrs.put(margin.toString(), margin);
+ _cssAttrs.put(margin_bottom.toString(), margin_bottom);
+ _cssAttrs.put(margin_left.toString(), margin_left);
+ _cssAttrs.put(margin_right.toString(), margin_right);
+ _cssAttrs.put(margin_top.toString(), margin_top);
+ _cssAttrs.put(marker_offset.toString(), marker_offset);
+ _cssAttrs.put(max_height.toString(), max_height);
+ _cssAttrs.put(max_width.toString(), max_width);
+ _cssAttrs.put(min_height.toString(), min_height);
+ _cssAttrs.put(min_width.toString(), min_width);
+ _cssAttrs.put(outline.toString(), outline);
+ _cssAttrs.put(outline_color.toString(), outline_color);
+ _cssAttrs.put(outline_style.toString(), outline_style);
+ _cssAttrs.put(outline_width.toString(), outline_width);
+ _cssAttrs.put(overflow.toString(), overflow);
+ _cssAttrs.put(padding.toString(), padding);
+ _cssAttrs.put(padding_bottom.toString(), padding_bottom);
+ _cssAttrs.put(padding_left.toString(), padding_left);
+ _cssAttrs.put(padding_right.toString(), padding_right);
+ _cssAttrs.put(padding_top.toString(), padding_top);
+ _cssAttrs.put(position.toString(), position);
+ _cssAttrs.put(quotes.toString(), quotes);
+ _cssAttrs.put(right.toString(), right);
+ _cssAttrs.put(table_layout.toString(), table_layout);
+ _cssAttrs.put(text_align.toString(), text_align);
+ _cssAttrs.put(text_decoration.toString(), text_decoration);
+ _cssAttrs.put(text_indent.toString(), text_indent);
+ _cssAttrs.put(text_shadow.toString(), text_shadow);
+ _cssAttrs.put(text_transform.toString(), text_transform);
+ _cssAttrs.put(top.toString(), top);
+ _cssAttrs.put(unicode_bidi.toString(), unicode_bidi);
+ _cssAttrs.put(vertical_align.toString(), vertical_align);
+ _cssAttrs.put(visibility.toString(), visibility);
+ _cssAttrs.put(white_space.toString(), white_space);
+ _cssAttrs.put(width.toString(), width);
+ _cssAttrs.put(word_spacing.toString(), word_spacing);
+ _cssAttrs.put(z_index.toString(), z_index);
+ }
+
+ /**
+ * Resolve the str to an attr representation
+ * @param str the str
+ * @return the Attribute
+ */
+ public static Attr resolveAttr(String str)
+ {
+ return (Attr) _cssAttrs.get(str);
+ }
+
+ /**
+ * Return all the defined css attributes
+ * @return all the defined css attribute objects
+ */
+ public static List getAllAttrs()
+ {
+ return new ArrayList(_cssAttrs.values());
+ }
+
+ /**
+ * Constructor
+ * @param name the name of the attribute
+ */
+ private Attr(String name)
+ {
+ super(name);
+ }
+ }
+
+ /**
+ * The css field definitions
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Css.java,v 1.3 2005/03/07 17:28:17 thlee Exp $ $Name: $
+ */
+ public static final class AttrUnit extends Enum
+ {
+
+ public static final AttrUnit deg = new AttrUnit("deg");
+
+ public static final AttrUnit grad = new AttrUnit("grad");
+
+ public static final AttrUnit hz = new AttrUnit("Hz");
+
+ public static final AttrUnit khz = new AttrUnit("kHz");
+
+ public static final AttrUnit ms = new AttrUnit("ms");
+
+ public static final AttrUnit percent = new AttrUnit("%");
+
+ public static final AttrUnit point = new AttrUnit("pt");
+
+ public static final AttrUnit rad = new AttrUnit("rad");
+
+ public static final AttrUnit s = new AttrUnit("s");
+
+ /**
+ * {@inheritDoc}
+ */
+ private AttrUnit(String name)
+ {
+ super(name);
+ }
+ }
+
+ /**
+ * The offset value
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Css.java,v 1.3 2005/03/07 17:28:17 thlee Exp $ $Name: $
+ */
+ public static class AttrValue extends Enum
+ {
+
+ public static final AttrValue absolute = new AttrValue("absolute");
+
+ public static final AttrValue armenian = new AttrValue("armenian");
+
+ public static final AttrValue auto = new AttrValue("auto");
+
+ public static final AttrValue baseline = new AttrValue("baseline");
+
+ public static final AttrValue bidi_override = new AttrValue("bidi-override");
+
+ public static final AttrValue block = new AttrValue("block");
+
+ public static final AttrValue bold = new AttrValue("bold");
+
+ public static final AttrValue bolder = new AttrValue("bolder");
+
+ public static final AttrValue both = new AttrValue("both");
+
+ public static final AttrValue bottom = new AttrValue("bottom");
+
+ public static final AttrValue capitalize = new AttrValue("capitalize");
+
+ public static final AttrValue caption = new AttrValue("caption");
+
+ public static final AttrValue center = new AttrValue("center");
+
+ public static final AttrValue circle = new AttrValue("circle");
+
+ public static final AttrValue cjk_ideographic = new AttrValue("cjk-ideographic");
+
+ public static final AttrValue close_quote = new AttrValue("close-quote");
+
+ public static final AttrValue collapse = new AttrValue("collapse");
+
+ public static final AttrValue compact = new AttrValue("compact");
+
+ public static final AttrValue condensed = new AttrValue("condensed");
+
+ public static final AttrValue crosshair = new AttrValue("crosshair");
+
+ public static final AttrValue decimal = new AttrValue("decimal");
+
+ public static final AttrValue decimal_leading_zero = new AttrValue("decimal-leading-zero");
+
+ public static final AttrValue default_ = new AttrValue("default");
+
+ public static final AttrValue disc = new AttrValue("disc");
+
+ public static final AttrValue e_resize = new AttrValue("e-resize");
+
+ public static final AttrValue embed = new AttrValue("embed");
+
+ public static final AttrValue expanded = new AttrValue("expanded");
+
+ public static final AttrValue extra_condensed = new AttrValue("extra-condensed");
+
+ public static final AttrValue extra_expanded = new AttrValue("extra-expanded");
+
+ public static final AttrValue fixed = new AttrValue("fixed");
+
+ public static final AttrValue georgian = new AttrValue("georgian");
+
+ public static final AttrValue hebrew = new AttrValue("hebrew");
+
+ public static final AttrValue help = new AttrValue("help");
+
+ public static final AttrValue hidden = new AttrValue("hidden");
+
+ public static final AttrValue hide = new AttrValue("hide");
+
+ public static final AttrValue hiragana = new AttrValue("hiragana");
+
+ public static final AttrValue hiragana_iroha = new AttrValue("hiragana-iroha");
+
+ public static final AttrValue icon = new AttrValue("icon");
+
+ public static final AttrValue inherit = new AttrValue("inherit");
+
+ public static final AttrValue inline = new AttrValue("inline");
+
+ public static final AttrValue inline_table = new AttrValue("inline-table");
+
+ public static final AttrValue inside = new AttrValue("inside");
+
+ public static final AttrValue invert = new AttrValue("invert");
+
+ public static final AttrValue italic = new AttrValue("italic");
+
+ public static final AttrValue justify = new AttrValue("justify");
+
+ public static final AttrValue katakana = new AttrValue("katakana");
+
+ public static final AttrValue katakana_iroha = new AttrValue("katakana-iroha");
+
+ public static final AttrValue left = new AttrValue("left");
+
+ public static final AttrValue lighter = new AttrValue("lighter");
+
+ public static final AttrValue list_item = new AttrValue("list-item");
+
+ public static final AttrValue lower_alpha = new AttrValue("lower-alpha");
+
+ public static final AttrValue lower_greek = new AttrValue("lower-greek");
+
+ public static final AttrValue lower_latin = new AttrValue("lower-latin");
+
+ public static final AttrValue lower_roman = new AttrValue("lower-roman");
+
+ public static final AttrValue lowercase = new AttrValue("lowercase");
+
+ public static final AttrValue ltr = new AttrValue("ltr");
+
+ public static final AttrValue marker = new AttrValue("marker");
+
+ public static final AttrValue menu = new AttrValue("menu");
+
+ public static final AttrValue message_box = new AttrValue("message-box");
+
+ public static final AttrValue middle = new AttrValue("middle");
+
+ public static final AttrValue move = new AttrValue("move");
+
+ public static final AttrValue n_resize = new AttrValue("n-resize");
+
+ public static final AttrValue narrower = new AttrValue("narrower");
+
+ public static final AttrValue ne_resize = new AttrValue("ne-resize");
+
+ public static final AttrValue no_open_quote = new AttrValue("no-open-quote");
+
+ public static final AttrValue no_repeat = new AttrValue("no-repeat");
+
+ public static final AttrValue none = new AttrValue("none");
+
+ public static final AttrValue normal = new AttrValue("normal");
+
+ public static final AttrValue nowrap = new AttrValue("nowrap");
+
+ public static final AttrValue nw_resize = new AttrValue("nw-resize");
+
+ public static final AttrValue oblique = new AttrValue("oblique");
+
+ public static final AttrValue open_quote = new AttrValue("open-quote");
+
+ public static final AttrValue outside = new AttrValue("outside");
+
+ public static final AttrValue pointer = new AttrValue("pointer");
+
+ public static final AttrValue pre = new AttrValue("pre");
+
+ public static final AttrValue relative = new AttrValue("relative");
+
+ public static final AttrValue repeat = new AttrValue("repeat");
+
+ public static final AttrValue repeat_x = new AttrValue("repeat-x");
+
+ public static final AttrValue repeat_y = new AttrValue("repeat-y");
+
+ public static final AttrValue right = new AttrValue("right");
+
+ public static final AttrValue rtl = new AttrValue("rtl");
+
+ public static final AttrValue run_in = new AttrValue("rul-in");
+
+ public static final AttrValue s_resize = new AttrValue("s-resize");
+
+ public static final AttrValue scroll = new AttrValue("scroll");
+
+ public static final AttrValue se_resize = new AttrValue("se-resize");
+
+ public static final AttrValue semi_condensed = new AttrValue("semi-condensed");
+
+ public static final AttrValue semi_expanded = new AttrValue("semi-expanded");
+
+ public static final AttrValue separate = new AttrValue("separate");
+
+ public static final AttrValue show = new AttrValue("show");
+
+ public static final AttrValue small_caps = new AttrValue("small-caps");
+
+ public static final AttrValue small_caption = new AttrValue("small-caption");
+
+ public static final AttrValue square = new AttrValue("square");
+
+ public static final AttrValue static_ = new AttrValue("static");
+
+ public static final AttrValue status_bar = new AttrValue("status-bar");
+
+ public static final AttrValue sub = new AttrValue("sub");
+
+ public static final AttrValue super_ = new AttrValue("super");
+
+ public static final AttrValue sw_resize = new AttrValue("sw-resize");
+
+ public static final AttrValue table = new AttrValue("table");
+
+ public static final AttrValue table_caption = new AttrValue("table-caption");
+
+ public static final AttrValue table_cell = new AttrValue("table-cell");
+
+ public static final AttrValue table_column = new AttrValue("table-column");
+
+ public static final AttrValue table_column_group = new AttrValue("table-column-group");
+
+ public static final AttrValue table_footer_group = new AttrValue("table-footer-group");
+
+ public static final AttrValue table_header_group = new AttrValue("table-header-group");
+
+ public static final AttrValue table_row = new AttrValue("table-row");
+
+ public static final AttrValue table_row_group = new AttrValue("table-row-group");
+
+ public static final AttrValue text = new AttrValue("text");
+
+ public static final AttrValue text_bottom = new AttrValue("text-bottom");
+
+ public static final AttrValue text_top = new AttrValue("text-top");
+
+ public static final AttrValue top = new AttrValue("top");
+
+ public static final AttrValue transparent = new AttrValue("transparent");
+
+ public static final AttrValue ultra_condensed = new AttrValue("ultra-condensed");
+
+ public static final AttrValue ultra_expanded = new AttrValue("ultra-expanded");
+
+ public static final AttrValue upper_alpha = new AttrValue("upper-alpha");
+
+ public static final AttrValue upper_latin = new AttrValue("upper-latin");
+
+ public static final AttrValue upper_roman = new AttrValue("upper-roman");
+
+ public static final AttrValue uppercase = new AttrValue("uppercase");
+
+ public static final AttrValue visible = new AttrValue("visible");
+
+ public static final AttrValue w_resize = new AttrValue("w-resize");
+
+ public static final AttrValue wait = new AttrValue("wait");
+
+ public static final AttrValue wider = new AttrValue("wider");
+
+ /**
+ * {@inheritDoc}
+ */
+ private AttrValue(String name)
+ {
+ super(name);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/ConfigurationException.java b/src/java/org/onemind/commons/java/lang/ConfigurationException.java
new file mode 100644
index 0000000..acc3277
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/ConfigurationException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang;
+
+/**
+ * Represent a config exception
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ConfigurationException.java,v 1.2 2004/08/26 12:33:17 thlee Exp $ $Name: $
+ */
+public class ConfigurationException extends RuntimeException
+{
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigurationException()
+ {
+ super();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigurationException(String arg0)
+ {
+ super(arg0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigurationException(String arg0, Throwable arg1)
+ {
+ super(arg0, arg1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigurationException(Throwable arg0)
+ {
+ super(arg0);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/Enum.java b/src/java/org/onemind/commons/java/lang/Enum.java
new file mode 100644
index 0000000..f7e2efd
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/Enum.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang;
+
+/**
+ * Represents an enum
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Enum.java,v 1.2 2004/08/26 12:33:17 thlee Exp $ $Name: $
+ */
+public abstract class Enum
+{
+
+ /** the name * */
+ private String _name;
+
+ /**
+ * Constructor
+ * @param name the name
+ */
+ public Enum(String name)
+ {
+ _name = name;
+ }
+
+ /**
+ * Return the name {@inheritDoc}
+ */
+ public String toString()
+ {
+ return _name;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/MutableDouble.java b/src/java/org/onemind/commons/java/lang/MutableDouble.java
new file mode 100644
index 0000000..01268ba
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/MutableDouble.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang;
+
+/**
+ * A mutable double
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MutableDouble.java,v 1.3 2004/09/03 13:24:14 thlee Exp $ $Name: $
+ */
+public class MutableDouble extends Number
+{
+
+ /** the value * */
+ private double _value;
+
+ /**
+ * {@inheritDoc}
+ * @param l the value
+ */
+ public MutableDouble(double l)
+ {
+ _value = l;
+ }
+
+ /**
+ * Set the double value
+ * @param l the value
+ */
+ public final void set(double l)
+ {
+ _value = l;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final byte byteValue()
+ {
+ return (byte) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final double doubleValue()
+ {
+ return _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final float floatValue()
+ {
+ return (float) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int intValue()
+ {
+ return (int) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long longValue()
+ {
+ return (long) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final short shortValue()
+ {
+ return (short) _value;
+ }
+
+ /**
+ * increase by i
+ * @param i the value to increase
+ */
+ public void inc(double i)
+ {
+ _value += i;
+ }
+
+ /**
+ * decrease by i
+ * @param i the value to decrease
+ */
+ public void dec(double i)
+ {
+ _value -= i;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return String.valueOf(_value);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/MutableFloat.java b/src/java/org/onemind/commons/java/lang/MutableFloat.java
new file mode 100644
index 0000000..8b49c8d
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/MutableFloat.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+package org.onemind.commons.java.lang;
+
+/**
+ * A mutable float
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MutableFloat.java,v 1.3 2004/09/03 13:24:14 thlee Exp $ $Name: $
+ */
+public class MutableFloat extends Number
+{
+
+ /** the float value * */
+ private float _value;
+
+ /**
+ * {@inheritDoc}
+ * @param l the float value
+ */
+ public MutableFloat(float l)
+ {
+ _value = l;
+ }
+
+ /**
+ * Set the float value
+ * @param l the value
+ */
+ public final void set(float l)
+ {
+ _value = l;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final byte byteValue()
+ {
+ return (byte) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final double doubleValue()
+ {
+ return (double) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final float floatValue()
+ {
+ return _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int intValue()
+ {
+ return (int) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long longValue()
+ {
+ return (long) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final short shortValue()
+ {
+ return (short) _value;
+ }
+
+ /**
+ * increase by i
+ * @param i the value to increase
+ */
+ public void inc(float i)
+ {
+ _value += i;
+ }
+
+ /**
+ * decrease by i
+ * @param i the value to decrease
+ */
+ public void dec(float i)
+ {
+ _value -= i;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return String.valueOf(_value);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/MutableInteger.java b/src/java/org/onemind/commons/java/lang/MutableInteger.java
new file mode 100644
index 0000000..4ae5b16
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/MutableInteger.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+package org.onemind.commons.java.lang;
+
+/**
+ * An mutable integer
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MutableInteger.java,v 1.3 2004/09/03 13:24:14 thlee Exp $ $Name: $
+ */
+public class MutableInteger extends Number
+{
+
+ /** the integer value * */
+ private int _value;
+
+ /**
+ * {@inheritDoc}
+ * @param l the int value
+ */
+ public MutableInteger(int l)
+ {
+ _value = l;
+ }
+
+ /**
+ * Set the value
+ * @param l the int value
+ */
+ public final void set(int l)
+ {
+ _value = l;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final byte byteValue()
+ {
+ return (byte) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final double doubleValue()
+ {
+ return (double) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final float floatValue()
+ {
+ return (float) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int intValue()
+ {
+ return _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long longValue()
+ {
+ return (long) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final short shortValue()
+ {
+ return (short) _value;
+ }
+
+ /**
+ * increase by i
+ * @param i the value to increase
+ */
+ public void inc(int i)
+ {
+ _value += i;
+ }
+
+ /**
+ * decrease by i
+ * @param i the value to decrease
+ */
+ public void dec(int i)
+ {
+ _value -= i;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return String.valueOf(_value);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/MutableLong.java b/src/java/org/onemind/commons/java/lang/MutableLong.java
new file mode 100644
index 0000000..334f5c6
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/MutableLong.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang;
+
+/**
+ * An mutable long
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MutableLong.java,v 1.3 2004/09/03 13:24:14 thlee Exp $ $Name: $
+ */
+public class MutableLong extends Number
+{
+
+ /** the long value * */
+ private long _value;
+
+ /**
+ * {@inheritDoc}
+ * @param l the long value
+ */
+ public MutableLong(long l)
+ {
+ _value = l;
+ }
+
+ /**
+ * Set the long value
+ * @param l the long value
+ */
+ public final void set(long l)
+ {
+ _value = l;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final byte byteValue()
+ {
+ return (byte) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final double doubleValue()
+ {
+ return (double) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final float floatValue()
+ {
+ return (float) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int intValue()
+ {
+ return (int) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long longValue()
+ {
+ return _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final short shortValue()
+ {
+ return (short) _value;
+ }
+
+ /**
+ * increase by i
+ * @param i the value to increase
+ */
+ public void inc(long i)
+ {
+ _value += i;
+ }
+
+ /**
+ * decrease by i
+ * @param i the value to decrease
+ */
+ public void dec(long i)
+ {
+ _value -= i;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return String.valueOf(_value);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/MutableShort.java b/src/java/org/onemind/commons/java/lang/MutableShort.java
new file mode 100644
index 0000000..862acc9
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/MutableShort.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang;
+
+/**
+ * An mutable short
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MutableShort.java,v 1.3 2004/09/03 13:24:14 thlee Exp $ $Name: $
+ */
+public class MutableShort extends Number
+{
+
+ /** the long value * */
+ private short _value;
+
+ /**
+ * {@inheritDoc}
+ * @param l the long value
+ */
+ public MutableShort(short l)
+ {
+ _value = l;
+ }
+
+ /**
+ * Set the short value
+ * @param l the short value
+ */
+ public final void set(short l)
+ {
+ _value = l;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final byte byteValue()
+ {
+ return (byte) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final double doubleValue()
+ {
+ return (double) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final float floatValue()
+ {
+ return _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int intValue()
+ {
+ return (int) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long longValue()
+ {
+ return (long) _value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final short shortValue()
+ {
+ return (short) _value;
+ }
+
+ /**
+ * increase by i
+ * @param i the value to increase
+ */
+ public void inc(short i)
+ {
+ _value += i;
+ }
+
+ /**
+ * decrease by i
+ * @param i the value to decrease
+ */
+ public void dec(short i)
+ {
+ _value -= i;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return String.valueOf(_value);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/Null.java b/src/java/org/onemind/commons/java/lang/Null.java
new file mode 100644
index 0000000..c0467f2
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/Null.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang;
+
+/**
+ * Represent a Null object
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Null.java,v 1.2 2004/08/26 12:33:17 thlee Exp $ $Name: $
+ */
+public final class Null
+{
+
+ /**
+ * The instance
+ */
+ public static final Null instance = new Null();
+
+ /**
+ * {@inheritDoc}
+ */
+ private Null()
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/ref/SoftHashMap.java b/src/java/org/onemind/commons/java/lang/ref/SoftHashMap.java
new file mode 100644
index 0000000..aa2c3e5
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/ref/SoftHashMap.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang.ref;
+
+import java.util.*;
+import java.lang.ref.*;
+/**
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: SoftHashMap.java,v 1.1 2004/10/23 15:24:35 thlee Exp $ $Name: $
+ * Credits: Article by Heinz Kabutz at http://archive.devx.com/java/free/articles/Kabutz01/Kabutz01-1.asp
+ */
+public class SoftHashMap extends AbstractMap
+{
+
+ /** We define our own subclass of SoftReference which contains
+ not only the value but also the key to make it easier to find
+ the entry in the HashMap after it's been garbage collected. */
+ private static class SoftValue extends SoftReference
+ {
+ private final Object key; // always make data member final
+
+ /** Did you know that an outer class can access private data
+ members and methods of an inner class? I didn't know that!
+ I thought it was only the inner class who could access the
+ outer class's private information. An outer class can also
+ access private members of an inner class inside its inner
+ class. */
+ private SoftValue(Object k, Object key, ReferenceQueue q)
+ {
+ super(k, q);
+ this.key = key;
+ }
+ }
+
+ /** The internal HashMap that will hold the SoftReference. */
+ private final Map hash = new HashMap();
+
+ /** The number of "hard" references to hold internally. */
+ private final int HARD_REF_SIZE;
+
+ /** The FIFO list of hard references, order of last access. */
+ private final LinkedList hardRefCache;
+
+ /** Reference queue for cleared SoftReference objects. */
+ private final ReferenceQueue queue = new ReferenceQueue();
+
+ /**
+ * Constructor
+ */
+ public SoftHashMap()
+ {
+ this(0);
+ }
+
+ /**
+ * Constructor
+ * @param hardSize the hard reference size to maintain
+ */
+ public SoftHashMap(int hardSize)
+ {
+ HARD_REF_SIZE = hardSize;
+ if (HARD_REF_SIZE>0)
+ {
+ hardRefCache = new LinkedList();
+ } else
+ {
+ hardRefCache = null;
+ }
+ }
+
+ public Object get(Object key)
+ {
+ Object result = null;
+ // get the SoftReference represented by that key
+ SoftReference soft_ref = (SoftReference) hash.get(key);
+ if (soft_ref != null)
+ {
+ // From the SoftReference we get the value, which can be
+ // null if it was not in the map, or it was removed in
+ // the processQueue() method defined below
+ result = soft_ref.get();
+ if (result == null)
+ {
+ // If the value has been garbage collected, remove the
+ // entry from the HashMap.
+ hash.remove(key);
+ } else
+ {
+ if (HARD_REF_SIZE>0)
+ {
+ // We now add this object to the beginning of the hard
+ // reference queue. One reference can occur more than
+ // once, because lookups of the FIFO queue are slow, so
+ // we don't want to search through it each time to remove
+ // duplicates.
+ hardRefCache.addFirst(result);
+ if (hardRefCache.size() > HARD_REF_SIZE)
+ {
+ // Remove the last entry if list longer than HARD_SIZE
+ hardRefCache.removeLast();
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Go through the ReferenceQueue and remove garbage
+ * collected SoftValue objects from the HashMap
+ */
+ private void _cleanCollectedValues()
+ {
+ SoftValue sv;
+ while ((sv = (SoftValue) queue.poll()) != null)
+ {
+ hash.remove(sv.key); // we can access private data!
+ }
+ }
+
+ /**
+ * Here we put the key, value pair into the HashMap using
+ * a SoftValue object.
+ */
+ public Object put(Object key, Object value)
+ {
+ _cleanCollectedValues(); // throw out garbage collected values first
+ return hash.put(key, new SoftValue(value, key, queue));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object remove(Object key)
+ {
+ _cleanCollectedValues(); // throw out garbage collected values first
+ return hash.remove(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clear()
+ {
+ if (HARD_REF_SIZE>0)
+ {
+ hardRefCache.clear();
+ }
+ _cleanCollectedValues(); // throw out garbage collected values
+ hash.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int size()
+ {
+ _cleanCollectedValues(); // throw out garbage collected values first
+ return hash.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set entrySet()
+ {
+ // no, no, you may NOT do that!!! GRRR
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/ref/ValueRef.java b/src/java/org/onemind/commons/java/lang/ref/ValueRef.java
new file mode 100644
index 0000000..c8b4988
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/ref/ValueRef.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang.ref;
+
+/**
+ * ValueRef is a passable reference to a value
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+
+public interface ValueRef
+{
+ public Object getValue();
+
+ public void setValue(Object obj);
+}
diff --git a/src/java/org/onemind/commons/java/lang/reflect/ClassLookupCache.java b/src/java/org/onemind/commons/java/lang/reflect/ClassLookupCache.java
new file mode 100644
index 0000000..3896386
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/reflect/ClassLookupCache.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang.reflect;
+
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.onemind.commons.java.datastructure.LookupCache;
+/**
+ * A class lookup cache can lookup non-fully-qualified name classes for a given set
+ * of packages and will cache the lookup for later use. For example,
+ *
+ *
+ * ClassLookupCache cache = new ClassLookupCache();
+ * cache.addPackage("*"); //default package
+ * cache.addPackage("java.io.*");
+ *
+ * Class c = cache.getClass("File"); //c = java.io.File
+ * c = cache.getClass("File1"); //c = null
+ *
+ *
+ * NOTE:
+ * 1. The cache is static for all instances of the lookup cache.
+ * 2. The packages is instance specific
+ * 3. It will cache only positive and negative response of fully qualified name thus
+ * lookup of non-fully-qualified has some performance hit, but for the sake of correctness
+ *
+ *
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ClassLookupCache.java,v 1.6 2006/10/29 17:02:38 thlee Exp $ $Name: $
+ */
+public class ClassLookupCache extends LookupCache
+{
+
+ /** the packages * */
+ private final HashSet _packages = new LinkedHashSet();
+
+ /** the logger * */
+ private static final Logger _logger = Logger.getLogger(ClassLookupCache.class.getName());
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClassLookupCache()
+ {
+ }
+
+ /**
+ * Add a new package.
+ * @param packageName the package name
+ */
+ public void addImport(String importName)
+ {
+ if (importName==null){
+ throw new IllegalArgumentException("Package name must not be null");
+ }
+ _packages.add(importName);
+ clearNegCache();
+ }
+
+ /**
+ * Get the class given by the fully-qualified or non-fully qualified java class name
+ * @param className the class name
+ * @return the class or null
+ */
+ public Class getClass(String className)
+ {
+ if (className.indexOf('.') == -1)
+ { //not fully qualified name
+ Iterator it = _packages.iterator();
+ Class c = null;
+ while (it.hasNext())
+ {
+ String importName = (String) it.next();
+ String fullName = null;
+ int idx = importName.indexOf("*");
+ if (idx==-1){ //importName is a class name
+ if (importName.endsWith("." + className) || importName.equals(className)){
+ fullName = importName;
+ } else { //don't bother
+ continue;
+ }
+ } else {
+ fullName = importName.substring(0, idx) + className;
+ }
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Looking up class " + fullName);
+ }
+ c = (Class) lookup(fullName);
+ if (c != null)
+ {
+ return c;
+ }
+ }
+ return null;
+ } else
+ {
+ return (Class) lookup(className);
+ }
+ }
+
+ /**
+ * Produce the class given the key {@inheritDoc}
+ */
+ public Object produce(Object key)
+ {
+ String className = (String) key;
+ Class c = null;
+ //first trial
+ try
+ {
+ c = Class.forName(className);
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Lookup class " + key + " successful");
+ //otherwise the ClassNotFoundException must have been throwned
+ }
+ } catch (Exception e)
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Lookup class " + key + " failed");
+ }
+ }
+ return c;
+ }
+
+ /**
+ * Get all the import packages in this lookup cache.
+ * @return the packages
+ */
+ public Set getPackages()
+ {
+ return Collections.unmodifiableSet(_packages);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void clearNegCache()
+ {
+ super.clearNegCache();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected boolean isInCache(Object o)
+ {
+ return super.isInCache(o);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected boolean isInNegCache(Object o)
+ {
+ return super.isInNegCache(o);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void setDoNegativeCache(boolean b)
+ {
+ super.setDoNegativeCache(b);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/lang/reflect/ReflectUtils.java b/src/java/org/onemind/commons/java/lang/reflect/ReflectUtils.java
new file mode 100644
index 0000000..9fdd769
--- /dev/null
+++ b/src/java/org/onemind/commons/java/lang/reflect/ReflectUtils.java
@@ -0,0 +1,646 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang.reflect;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.onemind.commons.java.datastructure.Scoreable;
+import org.onemind.commons.java.util.StringUtils;
+/**
+ * Reflection related utilities
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ReflectUtils.java,v 1.12 2006/08/01 23:57:03 thlee Exp $ $Name: $
+ */
+public final class ReflectUtils
+{
+
+ /** the logger * */
+ private static final Logger _logger = Logger.getLogger(ReflectUtils.class.getName());
+
+ /** the lookup cache * */
+ private static final Map _classCache = new HashMap();
+
+ /** the method cache **/
+ private static final Map _methodCache = new HashMap();
+
+ /** class caching setting **/
+ private static boolean _classCaching = true;
+
+ /** method caching setting **/
+ private static boolean _methodCaching = true;
+
+ /** keep a primitive class and their compatible types **/
+ private static final Map WIDENABLES = new HashMap();
+ static
+ {
+ Object[][] primitiveWideningMap = new Object[][]{
+ {Boolean.TYPE, new Object[]{Boolean.TYPE, Boolean.class}},
+ {Boolean.class, new Object[]{Boolean.TYPE, Boolean.class}},
+ {Byte.TYPE, new Object[]{Byte.TYPE, Byte.class, Short.class, Short.TYPE, Integer.class, Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Byte.class, new Object[]{Byte.TYPE, Byte.class, Short.class, Short.TYPE, Integer.class, Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Short.TYPE, new Object[]{Short.TYPE, Short.class, Integer.class, Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Short.class, new Object[]{Short.TYPE, Short.class, Integer.class, Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Character.TYPE, new Object[]{Character.TYPE, Character.class, Integer.class, Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Character.class, new Object[]{Character.TYPE, Character.class, Integer.class, Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Integer.TYPE, new Object[]{Integer.TYPE, Integer.class, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Integer.class, new Object[]{Integer.TYPE, Integer.class, Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Long.TYPE, new Object[]{Long.TYPE, Long.class, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Long.class, new Object[]{Long.TYPE, Long.class, Float.class, Float.TYPE, Double.class, Double.TYPE}},
+ {Float.TYPE, new Object[]{Float.TYPE, Float.class, Double.class, Double.TYPE}},
+ {Float.class, new Object[]{Float.TYPE, Float.class, Double.class, Double.TYPE}},
+ {Double.TYPE, new Object[]{Double.TYPE, Double.class}},
+ {Double.class, new Object[]{Double.TYPE, Double.class}}};
+
+ for (int i = 0; i < primitiveWideningMap.length; i++)
+ {
+ WIDENABLES.put(primitiveWideningMap[i][0], Arrays.asList((Object[]) primitiveWideningMap[i][1]));
+ }
+ }
+
+ /**
+ * The method key
+ */
+ private static class MethodKey
+ {
+
+ /** the name **/
+ private String _name;
+
+ /** the class **/
+ private Class _clazz;
+
+ /** the arguments **/
+ private Class[] _args;
+
+ /** the hash code **/
+ private int _hashCode;
+
+ /**
+ * Constructor
+ * @param clazz the class
+ * @param name the name
+ * @param args the arguments
+ */
+ public MethodKey(Class clazz, String name, Class[] args)
+ {
+ _clazz = clazz;
+ _name = name;
+ _args = args;
+ _hashCode = _clazz.hashCode() + _name.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode()
+ {
+ return _hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof MethodKey)
+ {
+ MethodKey key = (MethodKey) obj;
+ return _clazz.equals(key._clazz) && _name.equals(key._name) && Arrays.equals(_args, key._args);
+ } else
+ {
+ throw new IllegalArgumentException("Cannot compare " + this + " to " + obj);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ private ReflectUtils()
+ {
+ };
+
+ /**
+ * Construct the argument type class array from a list of arg objects
+ * @param args the arguments
+ * @return the class array
+ * @todo decide what to do with null value arguments and what to do with isCompatibleCheck
+ * TODO decide what to do with null value arguments and what to do with isCompatibleCheck
+ */
+ public static final Class[] toArgTypes(Object[] args)
+ {
+ if (args == null)
+ {
+ args = new Object[0];
+ }
+ Class[] argTypes = new Class[args.length];
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i] != null)
+ {
+ argTypes[i] = args[i].getClass();
+ }
+ }
+ return argTypes;
+ }
+
+ /**
+ * Get the class
+ * @param name the name of the class
+ * @return the class
+ * @throws ClassNotFoundException if the class cannot be found
+ */
+ public static final Class getClass(String name) throws ClassNotFoundException
+ {
+ if (_classCaching && _classCache.containsKey(name))
+ {
+ Class c = (Class) _classCache.get(name);
+ if (c == null)
+ {
+ throw new ClassNotFoundException("Class " + name + " not found");
+ } else
+ {
+ return c;
+ }
+ } else
+ {
+ Class c = null;
+ try
+ {
+ c = Class.forName(name);
+ return c;
+ } finally
+ {
+ if (_classCaching)
+ {
+ _classCache.put(name, c);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the constructor of the type given the arguments to the constructor
+ * @param type the type
+ * @param args the arguments
+ * @return the constructor
+ * @throws NoSuchMethodException if the constructor cannot be found
+ */
+ public static final Constructor getConstructor(Class type, Object[] args) throws NoSuchMethodException
+ {
+ if (args == null)
+ {
+ args = new Object[0];
+ }
+ Class[] argTypes = toArgTypes(args);
+ Constructor c = null;
+ if (_methodCaching) //look in cache
+ {
+ c = (Constructor) _methodCache.get(new MethodKey(type, "$Constructor", argTypes));
+ if (c != null)
+ {
+ return c;
+ }
+ }
+ try
+ {
+ //first trial
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Looking for constructor for " + type.getName() + "(" + StringUtils.concat(argTypes, ",") + ")");
+ }
+ c = type.getConstructor(argTypes);
+ } catch (NoSuchMethodException e)
+ {
+ c = searchConstructor(type, argTypes);
+ }
+ if (c == null)
+ {
+ throw new NoSuchMethodException("Constructor not found for class " + toMethodString(type.getName(), args));
+ } else if (_methodCaching)
+ {
+ _methodCache.put(new MethodKey(type, "$Constructor", argTypes), c);
+ }
+ return c;
+ }
+
+ /**
+ * To the method representation string e.g. toString()
+ * @param methodName the method
+ * @param args the arguments
+ * @return the method representation string
+ */
+ public static final String toMethodString(String methodName, Object[] args)
+ {
+ StringBuffer sb = new StringBuffer(methodName);
+ sb.append("(");
+ if (args != null)
+ {
+ sb.append(StringUtils.concat(args, ","));
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ /**
+ * Search for a particular constructor based on arg types classes
+ * @param type the type
+ * @param argTypes the argument types
+ * @return the constructor
+ */
+ public static final Constructor searchConstructor(Class type, Class[] argTypes)
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Searching for constructor for " + type.getName());
+ }
+ Constructor[] constructors = type.getConstructors();
+ TreeSet scoreboard = new TreeSet();
+ for (int i = 0; i < constructors.length; i++)
+ {
+ Class[] types = constructors[i].getParameterTypes();
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("trying arg types " + StringUtils.concat(types, ","));
+ }
+ int score = computeCompatibalityScore(types, argTypes);
+ if (score > 0)
+ {
+ scoreboard.add(new Scoreable(score, constructors[i]));
+ }
+ }
+ if (scoreboard.size() > 0)
+ {
+ return (Constructor) ((Scoreable) scoreboard.last()).getObject();
+ } else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Return whether the argument objects is compatible with the argument types specification
+ * @param types the argument types
+ * @param args the arguments
+ * @return true if compatible
+ */
+ public static final boolean isCompatible(Class[] types, Object[] args)
+ {
+ return computeCompatibalityScore(types, toArgTypes(args)) > 0;
+ }
+
+ public static final boolean isCompatible(Class[] types, Class[] argTypes)
+ {
+ return computeCompatibalityScore(types, argTypes) > 0;
+ }
+
+ /**
+ * Return whether the types of arguments is compatible with the argument type spec of a method
+ * @param methodTypes the argument type spec of a method
+ * @param argTypes the argument type
+ * @return true if compatible
+ */
+ public static final int computeCompatibalityScore(Class[] methodTypes, Class[] argTypes)
+ {
+ int score = 0;
+ if ((methodTypes == null) || (methodTypes.length == 0))
+ {
+ if ((argTypes == null) || (argTypes.length == 0))
+ {
+ score = 1;
+ }
+ } else if (argTypes != null && methodTypes.length == argTypes.length)
+ {
+ for (int i = 0; i < methodTypes.length; i++)
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Comparing " + methodTypes[i] + " to " + argTypes[i]);
+ }
+ if (methodTypes[i] == argTypes[i])
+ {
+ score += 2;
+ }else if (argTypes[i] == null)
+ {
+ if (methodTypes[i].isPrimitive()){
+ score = 0;
+ break;
+ } else {
+ score += 1; //assume underlying args is null which is allowable
+ }
+ } else if (WIDENABLES.containsKey(argTypes[i]))
+ {//maybe it can be widen
+
+ int thisScore = computeWideningScore(methodTypes[i], argTypes[i]);
+ if (thisScore == 0)
+ {
+ score = 0;
+ break;
+ } else
+ {
+ score += thisScore;
+ }
+ } else if (methodTypes[i].isAssignableFrom(argTypes[i]))
+ {
+ score += 1;
+ } else {
+ score = 0;
+ break;
+ }
+ }
+ }
+ return score;
+ }
+
+ /**
+ * Create a new instance of the class type with the arguments to constructor
+ * @param type the type
+ * @param args the argument
+ * @return the new instance
+ * @throws IllegalAccessException if there's access problem
+ * @throws InstantiationException if there's instantiation problem
+ * @throws InvocationTargetException if there's target exception
+ * @throws NoSuchMethodException if there's no such constructor
+ */
+ public static final Object newInstance(Class type, Object[] args) throws IllegalAccessException, InstantiationException,
+ InvocationTargetException, NoSuchMethodException
+ {
+ if (args == null)
+ {
+ args = new Object[0];
+ }
+ Constructor c = getConstructor(type, args);
+ if (c != null)
+ {
+ return c.newInstance(args);
+ } else
+ {
+ throw new NoSuchMethodException("Constructor not found for " + type);
+ }
+ }
+
+ /**
+ * Invoke a named method on the object using the arguments
+ * @param o the object
+ * @param methodName the name of the method
+ * @param args the arguments
+ * @return the object return by the invocation
+ * @throws NoSuchMethodException if there's no such method
+ * @throws IllegalAccessException if there's access problem
+ * @throws InvocationTargetException if there's target problem
+ * @todo decide if is necessary to check for declaring class before invoke
+ */
+ public static final Object invoke(Object o, String methodName, Object[] args) throws NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException
+ {
+ if (args == null)
+ {
+ args = new Object[0];
+ }
+ Method m = null;
+ if (o instanceof Class)
+ {
+ try
+ {
+ //try to get static method
+ m = getMethod((Class) o, methodName, args);
+ } catch (NoSuchMethodException e)
+ {
+ //when user trying to get the "class instance" method
+ m = getMethod(o.getClass(), methodName, args);
+ }
+ } else
+ {
+ m = getMethod(o.getClass(), methodName, args);
+ }
+ if (m != null)
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Invoking " + m + " on " + o);
+ }
+ return m.invoke(o, args);
+ } else
+ {
+ throw new NoSuchMethodException("There's no method " + toMethodString(methodName, args) + " for " + m);
+ }
+ }
+
+ /**
+ * Resolve the method from the interfaces
+ * @param c the class
+ * @param methodName the method
+ * @param argTypes the arg types
+ * @return the method or null
+ * @todo decide if this method is needed
+ */
+ public static final Method getInterfaceMethod(Class[] c, String methodName, Class[] argTypes)
+ {
+ //TODO: decide if needed
+ return null;
+ }
+
+ /**
+ * Get a named method of class type with the argument type compatible with the argument passed in.
+ *
+ * @param type the class
+ * @param methodName the method name
+ * @param args the arguments
+ * @return the method
+ * @throws NoSuchMethodException if the method cannot be found
+ */
+ public static final Method getMethod(Class type, String methodName, Object[] args) throws NoSuchMethodException
+ {
+ Method m = null;
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Finding method " + toMethodString(methodName, args) + " of " + type);
+ }
+ if (args == null)
+ {
+ args = new Object[0];
+ }
+ Class[] argTypes = toArgTypes(args);
+ return getMethod(type, methodName, argTypes);
+ }
+
+ /**
+ * Get a named method of class type with the argument type compatible with the argument passed in.
+ *
+ * @param type the class
+ * @param methodName the method name
+ * @param args the arguments
+ * @return the method
+ * @throws NoSuchMethodException if the method cannot be found
+ */
+ public static final Method getMethod(Class type, String methodName, Class[] argTypes) throws NoSuchMethodException
+ {
+ Method m;
+ if (_methodCaching) //look in cache
+ {
+ m = (Method) _methodCache.get(new MethodKey(type, methodName, argTypes));
+ if (m != null)
+ {
+ return m;
+ }
+ }
+ try
+ {
+ //first trial
+ m = type.getMethod(methodName, argTypes);
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Found using reflection");
+ }
+ } catch (NoSuchMethodException nme)
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Failed using reflection: " + nme.getMessage() + ". Search for method.");
+ }
+ m = searchMethod(type, methodName, argTypes);
+ }
+ if (m != null)
+ {
+ if (_methodCaching)
+ {
+ _methodCache.put(new MethodKey(type, methodName, argTypes), m);
+ }
+ if (!m.isAccessible())
+ {
+ m.setAccessible(true);
+ }
+ } else
+ {
+ throw new NoSuchMethodException("Method " + type.getName() + "." + toMethodString(methodName, argTypes) + " not found.");
+ }
+ return m;
+ }
+
+ /**
+ * Search a named method of class type through the class's hierachy
+ * @param type the class
+ * @param methodName the method name
+ * @param argTypes the argument types
+ * @return the method
+ */
+ private static final Method searchMethod(Class type, String methodName, Class[] argTypes)
+ {
+ TreeSet scoreboard = new TreeSet();
+ Method[] methods = type.getMethods();
+ for (int i = 0; i < methods.length; i++)
+ {
+ Method m = methods[i];
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Checking compatibility with " + m);
+ }
+ if (m.getName().equals(methodName))
+ {
+ int score = computeCompatibalityScore(m.getParameterTypes(), argTypes);
+ if (score > 0)
+ {
+ scoreboard.add(new Scoreable(score, methods[i]));
+ }
+ }
+ }
+ if (scoreboard.size() > 0)
+ {
+ return (Method) ((Scoreable) scoreboard.last()).getObject();
+ }
+ return null;
+ }
+
+ /**
+ * Set the classCaching
+ * @param caching true to turn on class caching
+ */
+ protected static final void setClassCaching(boolean caching)
+ {
+ _classCaching = caching;
+ }
+
+ /**
+ * Set the _methodCaching
+ * @param caching true to turn on method caching
+ */
+ protected static final void setMethodCaching(boolean caching)
+ {
+ _methodCaching = caching;
+ }
+
+ /**
+ * Return whether a given object is a primitive or compatible (through unwrapping and widening) instance of primitiveClass
+ * @param primitiveClass the primitive class
+ * @param obj the object
+ * @return true if is instance
+ */
+ public static final boolean isPrimitiveInstance(Class primitiveClass, Object obj)
+ {
+ if (!primitiveClass.isPrimitive())
+ {
+ throw new IllegalArgumentException(primitiveClass + " is not primitive type ");
+ }
+ if (obj == null)
+ {
+ return false;
+ } else
+ {
+ return isPrimitiveCompatible(primitiveClass, obj.getClass());
+ }
+ }
+
+ /**
+ * Check if class c can be widen to targetClass and return the score.
+ * Return 2 if c==primitiveClass, 1 if c can be widened, or 0 if c cannot be widened.
+ * @param primitiveClass
+ * @param c
+ * @return
+ */
+
+ private static final int computeWideningScore(Class primitiveClass, Class c)
+ {
+ //check if c can be widen to primitiveClass
+ List set = (List) WIDENABLES.get(c);
+ int i = set.indexOf(primitiveClass);
+ if (i==-1){
+ return 0;
+ } else if (i<2){
+ return 2; //exact match
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Return true if primitiveClass and clazz is both primitive and clazz is primitive compatible with primitiveClass
+ * using java rules (unwrapping or widening)
+ * @param primitiveClass
+ * @param clazz
+ * @return
+ */
+ public static final boolean isPrimitiveCompatible(Class primitiveClass, Class clazz)
+ {
+ return computeWideningScore(primitiveClass, clazz) > 0;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/pattern/DynamicVisitor.java b/src/java/org/onemind/commons/java/pattern/DynamicVisitor.java
new file mode 100644
index 0000000..fccad5f
--- /dev/null
+++ b/src/java/org/onemind/commons/java/pattern/DynamicVisitor.java
@@ -0,0 +1,126 @@
+
+package org.onemind.commons.java.pattern;
+
+import java.lang.reflect.Method;
+import org.onemind.commons.java.datastructure.InheritableValueMap;
+import org.onemind.commons.java.lang.reflect.ReflectUtils;
+/**
+ * An abstract implementation of visitor that is extensible for handling
+ * different kind of object nodes by simple adding more methods. The subclass need to
+ * set up for handlers of node type in the constructor.
+ *
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: DynamicVisitor.java,v 1.2 2004/10/31 16:02:08 thlee Exp $ $Name: $
+ */
+public abstract class DynamicVisitor
+{
+
+ /** the object array class **/
+ private static Class OBJECT_ARRAY_CLASS = new Object[0].getClass();
+
+ /**
+ * The handler
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: DynamicVisitor.java,v 1.2 2004/10/31 16:02:08 thlee Exp $ $Name: $
+ */
+ public static interface NodeHandler
+ {
+
+ /**
+ * Handle node
+ * @param node
+ * @param data
+ */
+ public Object handleNode(Object node, Object[] data) throws Exception;
+ }
+
+ /**
+ * A handler use reflection to invoke given method for visiting
+ */
+ protected class MethodNodeHandler implements NodeHandler
+ {
+
+ /** the method **/
+ private Method _method;
+
+ /**
+ * Constructor
+ * @param methodName the method name
+ */
+ public MethodNodeHandler(Method method)
+ {
+ _method = method;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object handleNode(Object node, Object[] data) throws Exception
+ {
+ Object[] args = {node, data};
+ return _method.invoke(DynamicVisitor.this, args);
+ }
+ }
+
+ /** contains the handlers for different kind of nodese **/
+ private final InheritableValueMap _handlers = new InheritableValueMap();
+
+ /**
+ * Constructor
+ */
+ public DynamicVisitor()
+ {
+ initNodeHandlers();
+ }
+
+ /**
+ * Initialize the node handlers
+ */
+ protected abstract void initNodeHandlers();
+
+ /**
+ * Add node handler
+ * @param type the type
+ * @param handler the handler
+ */
+ protected void addNodeHandler(Class type, NodeHandler handler)
+ {
+ _handlers.put(type, handler);
+ }
+
+ /**
+ * Add MethodNodeHandler using the given method name
+ * throws RuntimeException if the method cannot be found.
+ * @param type the type
+ * @param methodName the method name
+ */
+ protected void addMethodNodeHandler(Class type, String methodName)
+ {
+ try
+ {
+ Class args[] = {type, new Object[0].getClass()};
+ Method m = ReflectUtils.getMethod(getClass(), methodName, args);
+ _handlers.put(type, new MethodNodeHandler(m));
+ } catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The object
+ * @param obj the object
+ * @param args the arguments
+ */
+ public Object visit(Object obj, Object[] args) throws Exception
+ {
+ NodeHandler handler = (NodeHandler) _handlers.resolve(obj.getClass());
+ if (handler != null)
+ {
+ return handler.handleNode(obj, args);
+ } else
+ {
+ throw new IllegalArgumentException("Cannot find handler method for object " + obj);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/sql/Field.java b/src/java/org/onemind/commons/java/sql/Field.java
new file mode 100644
index 0000000..112787a
--- /dev/null
+++ b/src/java/org/onemind/commons/java/sql/Field.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.sql;
+
+/**
+ * A Field contains meta infomration of a field in the database table
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Field.java,v 1.2 2004/08/26 12:33:18 thlee Exp $ $Name: $
+ */
+public class Field
+{
+
+ /** the name * */
+ private String _name;
+
+ /** the sql type * */
+ private int _type;
+
+ /**
+ * create a new field with name name and type type
+ * @param name the name
+ * @param type the type
+ */
+ public Field(String name, int type)
+ {
+ _name = name;
+ _type = type;
+ }
+
+ /**
+ * return the name of the field
+ * @return the name
+ */
+ public String getName()
+ {
+ return _name;
+ }
+
+ /**
+ * get the type of the field
+ * @return the type
+ */
+ public int getType()
+ {
+ return _type;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return "Field:" + _name + ":" + _type;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/sql/JdbcUtils.java b/src/java/org/onemind/commons/java/sql/JdbcUtils.java
new file mode 100644
index 0000000..d7f5d2f
--- /dev/null
+++ b/src/java/org/onemind/commons/java/sql/JdbcUtils.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.sql;
+
+import java.math.BigDecimal;
+import java.sql.*;
+import java.util.*;
+import java.util.Date;
+/**
+ * JDBC utilities
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: JdbcUtils.java,v 1.3 2004/10/23 15:25:44 thlee Exp $ $Name: $
+ */
+public final class JdbcUtils
+{
+
+ /** map the java classes to jdbc type int * */
+ public static final Map CLASS_TO_TYPE_MAP;
+ static
+ {
+ Map m = new HashMap();
+ m.put(String.class, new Integer(Types.CHAR));
+ m.put(String.class, new Integer(Types.VARCHAR));
+ m.put(String.class, new Integer(Types.LONGVARCHAR));
+ m.put(BigDecimal.class, new Integer(Types.NUMERIC));
+ m.put(Boolean.class, new Integer(Types.BIT));
+ m.put(Boolean.TYPE, new Integer(Types.BIT));
+ m.put(Integer.class, new Integer(Types.INTEGER));
+ m.put(Integer.TYPE, new Integer(Types.INTEGER));
+ m.put(Long.class, new Integer(Types.BIGINT));
+ m.put(Long.TYPE, new Integer(Types.BIGINT));
+ m.put(Float.class, new Integer(Types.REAL));
+ m.put(Float.TYPE, new Integer(Types.REAL));
+ m.put(Double.class, new Integer(Types.DOUBLE));
+ m.put(Double.TYPE, new Integer(Types.DOUBLE));
+ m.put(byte[].class, new Integer(Types.BINARY));
+ m.put(byte[].class, new Integer(Types.VARBINARY));
+ m.put(byte[].class, new Integer(Types.LONGVARBINARY));
+ m.put(Date.class, new Integer(Types.DATE));
+ m.put(Time.class, new Integer(Types.TIME));
+ m.put(Timestamp.class, new Integer(Types.TIMESTAMP));
+ m.put(Clob.class, new Integer(Types.CLOB));
+ m.put(Blob.class, new Integer(Types.BLOB));
+ m.put(Array.class, new Integer(Types.ARRAY));
+ m.put(Struct.class, new Integer(Types.STRUCT));
+ m.put(Ref.class, new Integer(Types.REF));
+ m.put(Class.class, new Integer(Types.JAVA_OBJECT));
+ CLASS_TO_TYPE_MAP = Collections.unmodifiableMap(m);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ private JdbcUtils()
+ {
+ }
+
+ /**
+ * Get the MetaData from the resultset
+ * @param rst the result set
+ * @param name the name of metadata to create
+ * @return the metadata
+ * @throws SQLException if there's database problem
+ */
+ public static MetaData getMetaData(ResultSet rst, String name) throws SQLException
+ {
+ return getMetaData(rst.getMetaData(), name);
+ }
+
+ /**
+ * return the MetaData
+ * @param meta the resultset metadata
+ * @param name the name
+ * @return the meta data
+ * @throws SQLException if there's database problem
+ */
+ public static MetaData getMetaData(ResultSetMetaData meta, String name) throws SQLException
+ {
+ MetaData metaData = new MetaData(name);
+ int n = meta.getColumnCount();
+ for (int i = 1; i <= n; i++)
+ {
+ String cname = meta.getColumnName(i);
+ int ctype = meta.getColumnType(i);
+ metaData.addField(new Field(cname, ctype));
+ }
+ return metaData;
+ }
+
+ /**
+ * Return the jdbc type given the java type (based on JDBC spec)
+ * @param c the java class
+ * @return the jdbc type
+ */
+ public static int toJdbcType(Class c)
+ {
+ Integer i = (Integer) CLASS_TO_TYPE_MAP.get(c);
+ if (i != null)
+ {
+ return i.intValue();
+ } else
+ {
+ throw new IllegalArgumentException("Unknown class type" + c);
+ }
+ }
+
+ /**
+ * Return whether a java type is a jdbc type
+ * @param c the class
+ * @return true if it's jdbc type
+ */
+ public static boolean isJdbcType(Class c)
+ {
+ return CLASS_TO_TYPE_MAP.containsKey(c);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/sql/MetaData.java b/src/java/org/onemind/commons/java/sql/MetaData.java
new file mode 100644
index 0000000..a7976f2
--- /dev/null
+++ b/src/java/org/onemind/commons/java/sql/MetaData.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+package org.onemind.commons.java.sql;
+
+import java.util.*;
+/**
+ * A MetaData contains metadata about a database table
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MetaData.java,v 1.2 2004/08/26 12:33:18 thlee Exp $ $Name: $
+ */
+public class MetaData
+{
+
+ /** the fields * */
+ private Map _fields = new LinkedHashMap();
+
+ /** the name * */
+ private String _name;
+
+ /** the primary key field name * */
+ private String _idFieldName;
+
+ /**
+ * create a MetaData with id id
+ * @param name the name
+ */
+ public MetaData(String name)
+ {
+ this._name = name;
+ }
+
+ /**
+ * create a MetaData with id id and primaryke pj
+ * @param name the name
+ * @param idFieldName the unique identifier field name
+ */
+ public MetaData(String name, String idFieldName)
+ {
+ this(name);
+ _idFieldName = idFieldName;
+ }
+
+ /**
+ * add a new field
+ * @param field the field
+ */
+ public void addField(Field field)
+ {
+ _fields.put(field.getName(), field);
+ }
+
+ /**
+ * get the field with id name
+ * @param name the name
+ * @return the field, or null
+ */
+ public Field getField(String name)
+ {
+ return (Field) _fields.get(name);
+ }
+
+ /**
+ * get the fields in this MetaData
+ * @return Map the map
+ */
+ public Map getFields()
+ {
+ return Collections.unmodifiableMap(_fields);
+ }
+
+ /**
+ * return the id of the MetaData
+ * @return the id
+ */
+ public String getId()
+ {
+ return _name;
+ }
+
+ /**
+ * return the primary key field
+ * @return the id field
+ */
+ public Field getIdField()
+ {
+ return (Field) _fields.get(getIdField());
+ }
+
+ /**
+ * Return the id field name
+ * @return the id field name
+ */
+ public String getIdFieldName()
+ {
+ return _idFieldName;
+ }
+
+ /**
+ * return whether there's a field with id name
+ * @param name the field name
+ * @return true if has the field
+ */
+ public boolean hasField(String name)
+ {
+ return _fields.containsKey(name);
+ }
+
+ /**
+ * set the fields of the MetaData
+ * @param fields the fields
+ */
+ public void setFields(Map fields)
+ {
+ _fields.clear();
+ _fields.putAll(fields);
+ }
+
+ /**
+ * Set the id field name
+ * @param string the id field name
+ */
+ public void setIdFieldName(String string)
+ {
+ _idFieldName = string;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/sql/TypeMapper.java b/src/java/org/onemind/commons/java/sql/TypeMapper.java
new file mode 100644
index 0000000..090df4a
--- /dev/null
+++ b/src/java/org/onemind/commons/java/sql/TypeMapper.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.sql;
+
+import java.math.BigDecimal;
+import java.sql.*;
+import java.util.*;
+import java.util.Date;
+/**
+ * May jdbc type to java type
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: TypeMapper.java,v 1.2 2004/08/26 12:33:18 thlee Exp $ $Name: $
+ */
+public final class TypeMapper
+{
+
+ /** map the java classes to jdbc type int * */
+ public static final Map CLASS_TO_TYPE_MAP;
+ static
+ {
+ Map m = new HashMap();
+ m.put(String.class, new Integer(Types.CHAR));
+ m.put(String.class, new Integer(Types.VARCHAR));
+ m.put(String.class, new Integer(Types.LONGVARCHAR));
+ m.put(BigDecimal.class, new Integer(Types.NUMERIC));
+ m.put(Boolean.class, new Integer(Types.BIT));
+ m.put(Boolean.TYPE, new Integer(Types.BIT));
+ m.put(Integer.class, new Integer(Types.INTEGER));
+ m.put(Integer.TYPE, new Integer(Types.INTEGER));
+ m.put(Long.class, new Integer(Types.BIGINT));
+ m.put(Long.TYPE, new Integer(Types.BIGINT));
+ m.put(Float.class, new Integer(Types.REAL));
+ m.put(Float.TYPE, new Integer(Types.REAL));
+ m.put(Double.class, new Integer(Types.DOUBLE));
+ m.put(Double.TYPE, new Integer(Types.DOUBLE));
+ m.put(byte[].class, new Integer(Types.BINARY));
+ m.put(byte[].class, new Integer(Types.VARBINARY));
+ m.put(byte[].class, new Integer(Types.LONGVARBINARY));
+ m.put(Date.class, new Integer(Types.DATE));
+ m.put(Time.class, new Integer(Types.TIME));
+ m.put(Timestamp.class, new Integer(Types.TIMESTAMP));
+ m.put(Clob.class, new Integer(Types.CLOB));
+ m.put(Blob.class, new Integer(Types.BLOB));
+ m.put(Array.class, new Integer(Types.ARRAY));
+ m.put(Struct.class, new Integer(Types.STRUCT));
+ m.put(Ref.class, new Integer(Types.REF));
+ m.put(Class.class, new Integer(Types.JAVA_OBJECT));
+ CLASS_TO_TYPE_MAP = Collections.unmodifiableMap(m);
+ }
+
+ /**
+ * Return the jdbc type given the java type (based on JDBC spec)
+ * @param c the java class
+ * @return the jdbc type
+ */
+ public static int toJdbcType(Class c)
+ {
+ Integer i = (Integer) CLASS_TO_TYPE_MAP.get(c);
+ if (i != null)
+ {
+ return i.intValue();
+ } else
+ {
+ throw new IllegalArgumentException("Unknown class type" + c);
+ }
+ }
+
+ /**
+ * Return whether a java type is a jdbc type
+ * @param c the class
+ * @return true if it's jdbc type
+ */
+ public static boolean isJdbcType(Class c)
+ {
+ return CLASS_TO_TYPE_MAP.containsKey(c);
+ }
+
+ /**
+ * Constructor
+ */
+ private TypeMapper()
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/text/SimpleTextGenerator.java b/src/java/org/onemind/commons/java/text/SimpleTextGenerator.java
new file mode 100644
index 0000000..85e77cd
--- /dev/null
+++ b/src/java/org/onemind/commons/java/text/SimpleTextGenerator.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.text;
+
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * A simple implementation of generator
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public class SimpleTextGenerator implements TextGenerator
+{
+
+ /** the delimiter **/
+ private String _delimiter;
+
+ /** sub delimiter **/
+ private String _subDelimiter;
+
+ /** attr generators * */
+ private Map _generators = new HashMap();
+
+ /**
+ * Constructor
+ */
+ public SimpleTextGenerator(String delimiter, String subDelimiter)
+ {
+ _delimiter = delimiter;
+ _subDelimiter = subDelimiter;
+ }
+
+ /**
+ * add text generator to the sub specification
+ * @param subSpec the sub spec
+ * @param gen the sub generator
+ */
+ public void addGenerator(String subSpec, TextGenerator gen)
+ {
+ _generators.put(subSpec, gen);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuffer generateText(String spec, Object obj)
+ {
+ StringBuffer sb = new StringBuffer();
+ generateText(spec, obj, sb);
+ return sb;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void generateText(String spec, Object obj, StringBuffer sb)
+ {
+ String[] fields = spec.split(_delimiter);
+ for (int i = 0; i < fields.length; i++)
+ {
+ if (_subDelimiter != null)
+ {
+ TextGenerator gen = getGenerator(fields[i]);
+ if (gen == null)
+ {
+ throw new IllegalArgumentException("No sub generator for " + fields[i]);
+ } else
+ {
+ gen.generateText(null, obj, sb);
+ }
+ } else
+ {
+ String specs[] = fields[i].split(_subDelimiter);
+ TextGenerator subGen = getGenerator(specs[0]);
+ if (subGen == null)
+ {
+ throw new IllegalArgumentException("No sub generator for " + specs[0]);
+ }
+ if (specs.length > 1)
+ {
+ subGen.generateText(specs[1], obj, sb);
+ } else
+ {
+ subGen.generateText(null, obj, sb);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the generator for subSpec
+ * @param subSpec the sub spec
+ * @return the generator for the sub spec
+ */
+ public TextGenerator getGenerator(String subSpec)
+ {
+ return (TextGenerator) _generators.get(subSpec);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/text/TextGenerator.java b/src/java/org/onemind/commons/java/text/TextGenerator.java
new file mode 100644
index 0000000..873bee4
--- /dev/null
+++ b/src/java/org/onemind/commons/java/text/TextGenerator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.text;
+
+/**
+ * A simple interface for text generation.
+ * The generator generates some text on a passed in regarding a target object.
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public interface TextGenerator
+{
+ /**
+ * Generate some text through the spec passed in
+ * @param spec the specification
+ * @param obj the target object where the text should be generate towards
+ * @return the text
+ */
+ public void generateText(String spec, Object obj, StringBuffer sb);
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/util/Counter.java b/src/java/org/onemind/commons/java/util/Counter.java
new file mode 100644
index 0000000..0f260a2
--- /dev/null
+++ b/src/java/org/onemind/commons/java/util/Counter.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
+import org.onemind.commons.java.lang.MutableLong;
+/**
+ * For counting things
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: Counter.java,v 1.2 2005/06/22 22:58:25 thlee Exp $ $Name: $
+ */
+public class Counter
+{
+
+ /** the counts **/
+ private final Map counts = new HashMap();
+
+ /**
+ * Constructor
+ */
+ public Counter()
+ {
+ }
+
+ /**
+ * Add count. Count as 1 if it is not counted before
+ * @param counted
+ */
+ public void count(Object counted)
+ {
+ count(counted, 1);
+ }
+
+ /**
+ * Adjust count by value
+ * @param counted the counted
+ * @param countValue the count value
+ */
+ public void count(Object counted, long countValue)
+ {
+ MutableLong count = (MutableLong) counts.get(counted);
+ if (count == null)
+ {
+ counts.put(counted, new MutableLong(countValue));
+ } else
+ {
+ count.inc(countValue);
+ }
+ }
+
+ /**
+ * Remove the count. Count as -1 if it is not counted before
+ * @param counted the counted
+ */
+ public void removeCount(Object counted)
+ {
+ MutableLong count = (MutableLong) counts.get(counted);
+ if (count == null)
+ {
+ counts.put(counted, new MutableLong(-1));
+ } else
+ {
+ count.dec(1);
+ }
+ }
+
+ /**
+ * Get the count
+ * @param counted the counted
+ * @return the count
+ */
+ public long getCount(Object counted)
+ {
+ MutableLong count = (MutableLong) counts.get(counted);
+ if (count == null)
+ {
+ return 0;
+ } else
+ {
+ return count.longValue();
+ }
+ }
+
+ /**
+ * Dump to output
+ * @param writer the writer
+ */
+ public void dump(Writer writer) throws IOException
+ {
+ MapUtils.dump(counts, writer);
+ }
+
+ /**
+ * Reset the count for counted
+ * @param counted the counted
+ */
+ public void resetCount(Object counted)
+ {
+ counts.remove(counted);
+ }
+
+ /**
+ * Reset all the counters
+ */
+ public void resetAll()
+ {
+ counts.clear();
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer(super.toString());
+ sb.append(" - [");
+ Iterator it = counts.keySet().iterator();
+ while (it.hasNext())
+ {
+ Object obj = it.next();
+ sb.append(obj);
+ sb.append("=");
+ sb.append(counts.get(obj));
+ if (it.hasNext())
+ {
+ sb.append(", ");
+ }
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/util/FileUtils.java b/src/java/org/onemind/commons/java/util/FileUtils.java
new file mode 100644
index 0000000..279b51b
--- /dev/null
+++ b/src/java/org/onemind/commons/java/util/FileUtils.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import java.io.*;
+/**
+ * File related utilities methods
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: FileUtils.java,v 1.3 2004/09/19 20:07:04 thlee Exp $ $Name: $
+ */
+public final class FileUtils
+{
+
+ /**
+ * {@inheritDoc}
+ */
+ private FileUtils()
+ {
+ };
+
+ /** the forward slash * */
+ private static final String FSLASH = "/";
+
+ /** the back slash * */
+ private static final String BSLASH = "\\";
+
+ /** the separator * */
+ private static final String SEPARATOR = FSLASH; //use forward slash since
+
+ // both unix and windows jdk
+ // support it
+ /**
+ * Concat the strings to be a valid file path
+ * @param args the string
+ * @return the file path
+ * @todo add doc to describe the behavior
+ */
+ public static String concatFilePath(String[] args)
+ {
+ StringBuffer sb = new StringBuffer(args[0]);
+ for (int i = 1; i < args.length; i++)
+ {
+ concatFilePath(sb, args[i]);
+ }
+ return sb.toString();
+ }
+
+ //TODO: Describe behaviors
+ /**
+ * Concat filepath with the prefix and suffix
+ * @param prefix the prefix
+ * @param suffix the suffix
+ * @return the file path
+ * @todo add doc to describe the behavior
+ */
+ public static String concatFilePath(String prefix, String suffix)
+ {
+ return concatFilePath(new StringBuffer(prefix), suffix);
+ }
+
+ /**
+ * concat a meaning file path
+ * @param prefix the prefix
+ * @param suffix the suffix
+ * @return the concat'ed file path
+ */
+ private static String concatFilePath(StringBuffer prefix, String suffix)
+ {
+ String pf = prefix.toString();
+ if (pf.endsWith(FSLASH) || pf.endsWith(BSLASH))
+ {
+ if (suffix.startsWith(FSLASH) || suffix.startsWith(BSLASH))
+ {
+ if (suffix.length() > 1)
+ {
+ prefix.append(suffix.substring(1));
+ }
+ //else do nothing
+ } else
+ {
+ prefix.append(suffix);
+ }
+ } else
+ {
+ if (suffix.startsWith(FSLASH) || suffix.startsWith(BSLASH))
+ {
+ prefix.append(suffix);
+ } else
+ {
+ prefix.append(FSLASH);
+ prefix.append(suffix);
+ }
+ }
+ return prefix.toString();
+ }
+
+ /**
+ * Copy the input to the output. Will not close the output after copying
+ * @param input the input stream
+ * @param output the output
+ * @param chunkSize the chunk size
+ *
+ */
+ public static void copyStream(InputStream input, OutputStream output, int chunkSize) throws IOException
+ {
+ byte[] buffer = new byte[chunkSize];
+ int n = input.read(buffer, 0, chunkSize);
+ while (n != -1)
+ {
+ output.write(buffer, 0, n);
+ n = input.read(buffer, 0, chunkSize);
+ }
+ output.flush();
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/util/LogUtils.java b/src/java/org/onemind/commons/java/util/LogUtils.java
new file mode 100644
index 0000000..fcd6030
--- /dev/null
+++ b/src/java/org/onemind/commons/java/util/LogUtils.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import java.io.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.logging.LogManager;
+/**
+ * Utility methods for loggin
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: LogUtils.java,v 1.4 2005/08/08 05:21:51 thlee Exp $ $Name: $
+ */
+public final class LogUtils
+{
+
+ /**
+ * {@inheritDoc}
+ */
+ private LogUtils()
+ {
+ }
+
+ /**
+ * Init java logging by looking for logging.properties in the class paths
+ */
+ public static void initLoggingFromClassPath()
+ {
+ String classPath = (String) System.getProperties().get("java.class.path");
+ String[] paths = null;
+ if (classPath.indexOf(";") != -1)
+ { //must be windows
+ paths = classPath.split(";");
+ } else
+ {
+ paths = classPath.split(":");
+ }
+ for (int i = 0; i < paths.length; i++)
+ {
+ if (!paths[i].endsWith(".jar"))
+ {
+ String config = FileUtils.concatFilePath(paths[i], "logging.properties");
+ if (new File(config).exists())
+ {
+ //System.out.println("Use logging configuration " + config);
+ try
+ {
+ LogManager.getLogManager().readConfiguration(new FileInputStream(config));
+ } catch (Exception e)
+ {
+ //nothing it can do
+ //System.out.println("- init logging problem: " + e.getMessage());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the stack trace in a string
+ * @param e the exception
+ * @return the stack trace string
+ */
+ public static String getTrace(Throwable e)
+ {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(buffer);
+ e.printStackTrace(ps);
+ ps.flush();
+ return new String(buffer.toByteArray());
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/util/MapUtils.java b/src/java/org/onemind/commons/java/util/MapUtils.java
new file mode 100644
index 0000000..10ce72e
--- /dev/null
+++ b/src/java/org/onemind/commons/java/util/MapUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import java.io.*;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.Map;
+/**
+ * A map utility class
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MapUtils.java,v 1.3 2004/10/31 16:02:21 thlee Exp $ $Name: $
+ */
+public final class MapUtils
+{
+
+ /**
+ * {@inheritDoc}
+ */
+ private MapUtils()
+ {
+ };
+
+ /**
+ * Dump the map in name=value lines
+ * @param m the map
+ * @param writer the writer
+ * @throws IOException if there's IO problem
+ */
+ public static void dump(Map m, Writer writer) throws IOException
+ {
+ Iterator it = m.keySet().iterator();
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ writer.write(key + " = " + m.get(key) + "\n");
+ }
+ }
+
+ /**
+ * Get a string representation of the content in the map
+ * @param m the map
+ * @return a string with the format of a=b separated by line break
+ * @throws IOException
+ */
+ public static String toString(Map m) throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(bout);
+ dump(m, writer);
+ writer.flush();
+ bout.close();
+ return new String(bout.toByteArray());
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/util/ObjectUtils.java b/src/java/org/onemind/commons/java/util/ObjectUtils.java
new file mode 100644
index 0000000..becc948
--- /dev/null
+++ b/src/java/org/onemind/commons/java/util/ObjectUtils.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+package org.onemind.commons.java.util;
+
+/**
+ * Property utilities
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ObjectUtils.java,v 1.2 2004/08/26 12:33:17 thlee Exp $ $Name: $
+ */
+public final class ObjectUtils
+{
+
+ /**
+ * Constructor
+ */
+ private ObjectUtils()
+ {
+ super();
+ }
+
+ /**
+ * Convert the object the boolean, return the default if it cannot be converted
+ * @param value the value
+ * @param def the default
+ * @return the converted value, or def if value is null
+ */
+ public static final boolean toBool(Object value, boolean def)
+ {
+ if (value instanceof Boolean)
+ {
+ return ((Boolean) value).booleanValue();
+ } else if (value instanceof String)
+ {
+ if ("TRUE".equalsIgnoreCase((String) value))
+ {
+ return true;
+ } else if ("FALSE".equalsIgnoreCase((String) value))
+ {
+ return false;
+ } else
+ {
+ return def;
+ }
+ } else
+ {
+ return def;
+ }
+ }
+
+ /**
+ * Convert the object to int, or return the default if it cannot be converted
+ * @param value the value
+ * @param def the default
+ * @return the converted int, or default if it cannot be converted
+ */
+ public static int toInt(Object value, int def)
+ {
+ if (value instanceof Integer)
+ {
+ return ((Integer) value).intValue();
+ } else if (value instanceof String)
+ {
+ try
+ {
+ return Integer.parseInt((String) value);
+ } catch (NumberFormatException e)
+ {
+ return def;
+ }
+ } else
+ {
+ return def;
+ }
+ }
+
+ /**
+ * Convert the object to long, or return the default if it cannot be converted
+ * @param value the value
+ * @param def the default
+ * @return the converted int, or default if it cannot be converted
+ */
+ public static long toLong(Object value, long def)
+ {
+ if (value instanceof Long)
+ {
+ return ((Long) value).longValue();
+ } else if (value instanceof String)
+ {
+ try
+ {
+ return Long.parseLong((String) value);
+ } catch (NumberFormatException e)
+ {
+ return def;
+ }
+ } else
+ {
+ return def;
+ }
+ }
+
+ /**
+ * Convert the object to float, or return the default if it cannot be converted
+ * @param value the value
+ * @param def the default
+ * @return the converted int, or default if it cannot be converted
+ */
+ public static float toFloat(Object value, float def)
+ {
+ if (value instanceof Float)
+ {
+ return ((Float) value).floatValue();
+ } else if (value instanceof String)
+ {
+ try
+ {
+ return Float.parseFloat((String) value);
+ } catch (NumberFormatException e)
+ {
+ return def;
+ }
+ } else
+ {
+ return def;
+ }
+ }
+
+ /**
+ * Convert the object to double, or return the default if it cannot be converted
+ * @param value the value
+ * @param def the default
+ * @return the converted int, or default if it cannot be converted
+ */
+ public static double toDouble(Object value, double def)
+ {
+ if (value instanceof Double)
+ {
+ return ((Double) value).doubleValue();
+ } else if (value instanceof String)
+ {
+ try
+ {
+ return Double.parseDouble((String) value);
+ } catch (NumberFormatException e)
+ {
+ return def;
+ }
+ } else
+ {
+ return def;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/util/ServletUtils.java b/src/java/org/onemind/commons/java/util/ServletUtils.java
new file mode 100644
index 0000000..62df0ff
--- /dev/null
+++ b/src/java/org/onemind/commons/java/util/ServletUtils.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import java.io.File;
+import java.util.*;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import org.apache.commons.fileupload.*;
+import org.apache.commons.fileupload.DiskFileUpload;
+import org.apache.commons.fileupload.FileUpload;
+/**
+ * The servlet utiltity
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ServletUtils.java,v 1.3 2004/10/23 15:27:01 thlee Exp $ $Name: $
+ */
+public final class ServletUtils
+{
+
+ /**
+ * Constructor
+ */
+ private ServletUtils()
+ {
+ };
+
+ /**
+ * Get the request environment
+ * @param req the request
+ * @return the environment in a map
+ */
+ public static Map getRequestEnvironment(HttpServletRequest req)
+ {
+ Map m = new HashMap();
+ m.put("REQUEST", req);
+ m.put("REQUEST_AUTH_TYPE", req.getAuthType());
+ //m.put("REQUEST_CONTEXT_PATH", req.getContextPath());
+ m.put("REQUEST_COOKIES", req.getCookies());
+ Enumeration enum = req.getHeaderNames();
+ while (enum.hasMoreElements())
+ {
+ String header = (String) enum.nextElement();
+ String value = req.getHeader(header);
+ m.put(header, value);
+ }
+ m.put("REQUEST_METHOD", req.getMethod());
+ m.put("PATH_INFO", req.getPathInfo());
+ m.put("PATH_TRANSLATED", req.getPathTranslated());
+ m.put("QUERY_STRING", req.getQueryString());
+ m.put("REMOTE_ADDR", req.getRemoteAddr());
+ m.put("REMOTE_HOST", req.getRemoteHost());
+ m.put("REMOTE_USER", req.getRemoteUser());
+ m.put("REQUESTED_SESSION_ID", req.getRequestedSessionId());
+ m.put("REQUEST_URI", req.getRequestURI());
+ //m.put("REQUEST_URL", req.getRequestURL());
+ m.put("SERVLET_PATH", req.getServletPath());
+ m.put("SESSION", req.getSession(true));
+ //env
+ return m;
+ }
+
+ /**
+ * Get request attributes (Only for jsdk 2.3)
+ * @param req the request
+ * @return the servlet attributes
+ */
+ public static Map getExtraRequestEnvironment(HttpServletRequest req)
+ {
+ Map m = new HashMap();
+ Enumeration enum = req.getAttributeNames();
+ while (enum.hasMoreElements())
+ {
+ String attr = (String) enum.nextElement();
+ m.put(attr, req.getAttribute(attr));
+ }
+ m.put("CHARACTER_ENCODING", req.getCharacterEncoding());
+ m.put("CONTENT_LENGTH", new Integer(req.getContentLength()));
+ m.put("CONTENT_TYPE", req.getContentType());
+ m.put("REQUEST_PROTOCOL", req.getProtocol());
+ m.put("REQUEST_SCHEME", req.getScheme());
+ m.put("SERVER_NAME", req.getServerName());
+ m.put("SERVER_PORT", new Integer(req.getServerPort()));
+ return m;
+ }
+
+ /**
+ * Get the servlet environment from the config
+ * @param config the config
+ * @return the environment in a map
+ */
+ public static Map getServletEnvironment(ServletConfig config)
+ {
+ Map m = new HashMap();
+ m.put("SERVLET_CONTEXT", config.getServletContext());
+ return m;
+ }
+
+ /**
+ * Get the request parameters in a mp
+ * @param req the request
+ * @return the environment in the map
+ */
+ public static Map getRequestParameters(HttpServletRequest req, DiskFileUpload upload) throws FileUploadException
+ {
+ Map m = new HashMap();
+ if (FileUpload.isMultipartContent(req))
+ {
+ // Parse the request
+ List items = upload.parseRequest(req);
+ Iterator iter = items.iterator();
+ while (iter.hasNext())
+ {
+ FileItem item = (FileItem) iter.next();
+ if (item.isFormField())
+ {
+ m.put(item.getFieldName(), item.getString());
+ } else
+ {
+ String fieldName = item.getFieldName();
+ m.put(fieldName + ".FILENAME", item.getName()); //file name
+ m.put(fieldName + ".CONTENT_TYPE", item.getContentType());
+ m.put(fieldName + ".ITEM", item);
+ }
+ }
+ } else
+ {
+ Enumeration enum = req.getParameterNames();
+ while (enum.hasMoreElements())
+ {
+ String key = (String) enum.nextElement();
+ String[] value = req.getParameterValues(key);
+ if (value.length == 0)
+ {
+ m.put(key, null);
+ } else if (value.length == 1)
+ {
+ m.put(key, value[0]);
+ } else
+ {
+ m.put(key, value);
+ }
+ }
+ }
+ return m;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/util/StringUtils.java b/src/java/org/onemind/commons/java/util/StringUtils.java
new file mode 100644
index 0000000..d9e5a0d
--- /dev/null
+++ b/src/java/org/onemind/commons/java/util/StringUtils.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import java.util.Collection;
+/**
+ * String utilities method
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: StringUtils.java,v 1.3 2004/09/19 20:07:32 thlee Exp $ $Name: $
+ */
+public final class StringUtils
+{
+
+ /**
+ * Constructor
+ */
+ private StringUtils()
+ {
+ super();
+ }
+
+ /**
+ * Concat the collection l to string with delimenter
+ * @param l the collection
+ * @param delimiter the delimiter
+ * @return the result string
+ */
+ public static String concat(Collection l, String delimiter)
+ {
+ return concat(l.toArray(), delimiter);
+ }
+
+ /**
+ * Concant the object in the array (using objects.toString()), delimited by delimiter
+ * @param objects the objects
+ * @param delimiter the delimiter
+ * @return a string
+ */
+ public static String concat(Object[] objects, String delimiter)
+ {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < objects.length; i++)
+ {
+ sb.append(objects[i]);
+ if (i < (objects.length - 1))
+ {
+ sb.append(delimiter);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Return the substring after the first occurrance of pattern
+ * @param str the str
+ * @param pattern the pattern
+ * @return the substring of pattern can be matched in str, or null
+ */
+ public static String substringAfter(String str, String pattern)
+ {
+ int i = str.indexOf(pattern);
+ if (i == -1)
+ {
+ return null;
+ }
+ return str.substring(i + pattern.length());
+ }
+
+ /**
+ * Return substring of str after the the last occurrance of pattern
+ * @param str the str
+ * @param pattern the pattern
+ * @return the substring if pattern can be matched in the str, or null
+ */
+ public static String substringAfterLast(String str, String pattern)
+ {
+ int i = str.lastIndexOf(pattern);
+ if (i == -1)
+ {
+ return null;
+ }
+ return str.substring(i + pattern.length());
+ }
+
+ /**
+ * Return substring of str before the last occurrance of str
+ * @param str the str
+ * @param pattern the pattern
+ * @return the substring if pattern can be matched, or null
+ */
+ public static String substringBeforeLast(String str, String pattern)
+ {
+ int i = str.lastIndexOf(pattern);
+ if (i == -1)
+ {
+ return null;
+ }
+ return str.substring(0, i);
+ }
+
+ /**
+ * Whether the string is empty
+ * @param str whether is null or zero length (after trim)
+ * @return true if null of zero length after trim
+ */
+ public static boolean isNullOrEmpty(String str)
+ {
+ return (str == null || str.trim().length() == 0);
+ }
+
+ /**
+ * Whether the string is empty
+ * @param str whether is null or zero length (after trim)
+ * @return true if null of zero length after trim
+ */
+ public static boolean isNullOrEmpty(Object strObject)
+ {
+ if (strObject == null)
+ {
+ return true;
+ } else if (strObject instanceof String)
+ {
+ return isNullOrEmpty((String) strObject);
+ } else
+ {
+ return isNullOrEmpty(strObject.toString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/AbstractElementCreatorDigester.java b/src/java/org/onemind/commons/java/xml/digest/AbstractElementCreatorDigester.java
new file mode 100644
index 0000000..86a03d7
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/AbstractElementCreatorDigester.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import java.util.EventObject;
+import org.onemind.commons.java.event.*;
+import org.onemind.commons.java.event.EventFirer;
+import org.onemind.commons.java.event.EventListenerList;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+/**
+ * The abstract implementation of ElementCreatorDigester. The element creator will fire an event
+ * at the end of digestion
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public abstract class AbstractElementCreatorDigester extends DefaultDigester implements ElementCreatorDigester
+{
+ /** the listener list **/
+ private final EventListenerList _listeners = new EventListenerList();
+
+ /** the created object **/
+ private Object _created;
+
+ /** event firer for element event **/
+ private static final EventFirer _FIRER = new EventFirer()
+ {
+
+ /**
+ * {@inheritDoc}
+ */
+ public void fireEvent(EventListener listener, EventObject evt)
+ {
+ ((ElementListener) listener).objectCreated(((ElementEvent) evt).getElement());
+ }
+ };
+
+ /**
+ * Constructor
+ * @param name the element name
+ */
+ public AbstractElementCreatorDigester(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addListener(ElementListener l)
+ {
+ _listeners.addListener(l);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void removeListener(ElementListener l)
+ {
+ _listeners.removeListener(l);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endDigest(SaxDigesterHandler handler) throws SAXException
+ {
+ _listeners.fireEvent(_FIRER, new ElementEvent(this, getCreatedElement()));
+ }
+
+ /**
+ * Set the created element
+ * @param obj the object
+ */
+ protected final void setCreatedElement(Object obj)
+ {
+ _created = obj;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Object getCreatedElement()
+ {
+ return _created;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/ChainedDigester.java b/src/java/org/onemind/commons/java/xml/digest/ChainedDigester.java
new file mode 100644
index 0000000..c86c230
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/ChainedDigester.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import org.onemind.commons.java.lang.reflect.ReflectUtils;
+import org.onemind.commons.java.util.StringUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+/**
+ * A ChainedDigester is a helper digester that chains the digestion
+ * of xml dynamically based on a dynamic digester configured as a
+ * attribute name.
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ */
+public class ChainedDigester extends AbstractElementCreatorDigester
+{
+ /** the attribute name that specify the digester class **/
+ private String _attrName;
+
+ /** the argument to pass the constructor of the dynamic digester **/
+ private Object[] _args;
+
+ /**
+ * Constructor
+ * @param name the name of element
+ */
+ public ChainedDigester(String name)
+ {
+ this(name, "className", null);
+ }
+
+ /**
+ * Constructor
+ * @param name the element name
+ * @param attrName the attr
+ */
+ public ChainedDigester(String name, String attrName)
+ {
+ this(name, attrName, null);
+ }
+
+ /**
+ * Constructor
+ * @param name the element name
+ * @param attrName the attribute the specifies the dynamic digester
+ * @param args arguments to pass to constructor of the dynamic digester
+ */
+ public ChainedDigester(String name, String attrName, Object[] args)
+ {
+ super(name);
+ _attrName = attrName;
+ _args = args;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startDigest(SaxDigesterHandler handler, Attributes attrs) throws SAXException
+ {
+ String className = attrs.getValue(_attrName);
+ if (StringUtils.isNullOrEmpty(className))
+ {
+ throw new SAXException("className attribute need to be present at " + handler.getCurrentPath());
+ } else
+ {
+ try
+ {
+ ElementDigester dig = (ElementDigester) ReflectUtils.newInstance(ReflectUtils.getClass(className), _args);
+ setCreatedElement(dig);
+ handler.addSubDigester(dig);
+ } catch (Exception e)
+ {
+ throw new SAXException("Cannot instantiate render context " + className, e);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/DefaultDigester.java b/src/java/org/onemind/commons/java/xml/digest/DefaultDigester.java
new file mode 100644
index 0000000..5296403
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/DefaultDigester.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@thinklient.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+/**
+ * A default digesters that does nothing
+ * @author TiongHiang Lee (thlee@thinklient.org)
+ */
+public class DefaultDigester implements ElementDigester
+{
+
+ /** the element name **/
+ private final String _elementName;
+
+ /**
+ * Constructor
+ * @param name the name
+ */
+ public DefaultDigester(String name)
+ {
+ _elementName = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startDigest(SaxDigesterHandler handler, Attributes attrs) throws SAXException
+ {
+ //do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endDigest(SaxDigesterHandler handler) throws SAXException
+ {
+ //do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void characters(SaxDigesterHandler handler, char[] chars, int offset, int length) throws SAXException
+ {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String getElementName()
+ {
+ return _elementName;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/ElementCreatorDigester.java b/src/java/org/onemind/commons/java/xml/digest/ElementCreatorDigester.java
new file mode 100644
index 0000000..c603449
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/ElementCreatorDigester.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+/**
+ * An creator digester is a digester that digests an element in xml and
+ * creates an element object as represented by xml. It provides a mechanism
+ * for xml element digestion implementation outside of the element object itself.
+ *
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ElementCreatorDigester.java,v 1.1 2005/01/30 06:30:53 thlee Exp $ $Name: $
+ */
+public interface ElementCreatorDigester extends ElementDigester
+{
+
+ /**
+ * Add listener
+ * @param l the listener
+ */
+ public abstract void addListener(ElementListener l);
+
+ /**
+ * Remove listener
+ * @param l the listener
+ */
+ public abstract void removeListener(ElementListener l);
+
+ /**
+ * Get the created object
+ * @return the created object
+ */
+ public abstract Object getCreatedElement();
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/ElementDigester.java b/src/java/org/onemind/commons/java/xml/digest/ElementDigester.java
new file mode 100644
index 0000000..aaddc71
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/ElementDigester.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@thinklient.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+/**
+ * An element digester digest a particular element inside an xml file in common-digest framework
+ * @author TiongHiang Lee (thlee@thinklient.org)
+ * @version $Id: ElementDigester.java,v 1.3 2005/06/22 22:58:58 thlee Exp $ $Name: $
+ */
+public interface ElementDigester
+{
+ /**
+ * Get the element name
+ * @return the element name
+ */
+ public String getElementName();
+
+ /**
+ * Start an element with the given attributes
+ * @param handler the handler
+ * @param attr the attributes
+ * @throws SAXException if there's handling exception
+ */
+ public void startDigest(SaxDigesterHandler handler, Attributes attr) throws SAXException;
+
+ /**
+ * End the element
+ * @param handler the handler
+ * @throws SAXException if there's handling exception
+ */
+ public void endDigest(SaxDigesterHandler handler) throws SAXException;
+
+ /**
+ * Handle the characters
+ * @param handler the handler
+ * @param chars the characters
+ * @param offset the offset
+ * @param length the length
+ * @throws SAXException if there's parse problem
+ */
+ public void characters(SaxDigesterHandler handler, char[] chars, int offset, int length) throws SAXException;
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/ElementEvent.java b/src/java/org/onemind/commons/java/xml/digest/ElementEvent.java
new file mode 100644
index 0000000..86f4dec
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/ElementEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import java.util.EventObject;
+/**
+ * The element event
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ElementEvent.java,v 1.1 2005/01/30 06:30:53 thlee Exp $ $Name: $
+ */
+public class ElementEvent extends EventObject
+{
+
+ /** the element **/
+ private Object _element;
+
+ /**
+ * Constructor
+ * @param dig the digester the fires the event
+ * @param element the element created
+ */
+ public ElementEvent(ElementDigester dig, Object element)
+ {
+ super(dig);
+ _element = element;
+ }
+
+ /**
+ * the element
+ * @return the element
+ */
+ public Object getElement()
+ {
+ return _element;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/ElementListener.java b/src/java/org/onemind/commons/java/xml/digest/ElementListener.java
new file mode 100644
index 0000000..5093922
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/ElementListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import org.onemind.commons.java.event.EventListener;
+
+/**
+ * The object creation listener
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ElementListener.java,v 1.1 2005/01/30 06:30:53 thlee Exp $ $Name: $
+ */
+public interface ElementListener extends EventListener
+{
+ /**
+ * Called by an ElementCreatorDigester when an element is created
+ * @param obj the object created
+ */
+ public void objectCreated(Object obj);
+}
\ No newline at end of file
diff --git a/src/java/org/onemind/commons/java/xml/digest/SaxDigesterHandler.java b/src/java/org/onemind/commons/java/xml/digest/SaxDigesterHandler.java
new file mode 100644
index 0000000..8f0d1ce
--- /dev/null
+++ b/src/java/org/onemind/commons/java/xml/digest/SaxDigesterHandler.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@thinklient.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.*;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+/**
+ * The SaxDigesterHandler use digesters to digest the elements in the xml. The digesters can be added using the addDigester(). By
+ * default the sequential digester list is used.
+ * @author TiongHiang Lee (thlee@thinklient.org)
+ * @version $Id: SaxDigesterHandler.java,v 1.3 2005/01/30 06:31:37 thlee Exp $ $Name: $
+ */
+public class SaxDigesterHandler extends DefaultHandler
+{
+
+ /** the logger * */
+ private static final Logger _logger = Logger.getLogger(SaxDigesterHandler.class.getName());
+
+ /** the map contains subdigesters **/
+ private Map _digesters = new HashMap();
+
+ /** keep track of the path for current element **/
+ private List _elementPath = new ArrayList();
+
+ /**
+ * Constructor
+ */
+ public SaxDigesterHandler()
+ {
+ }
+
+ /**
+ * Adding a digester to the root path
+ * @param dig the digester
+ */
+ public void addDigester(ElementDigester dig)
+ {
+ addDigester(null, dig);
+ }
+
+ /**
+ * Add a digester for the path
+ * @param path the path
+ * @param dig the digester
+ */
+ public void addDigester(String path, ElementDigester dig)
+ {
+ if (path == null)
+ {
+ _digesters.put(dig.getElementName(), dig);
+ } else
+ {
+ _digesters.put(path + "/" + dig.getElementName(), dig);
+ }
+ }
+
+ /**
+ * Add a subdigester to current element path
+ * @param dig the digester
+ */
+ public void addSubDigester(ElementDigester dig)
+ {
+ String path = getCurrentPath();
+ addDigester(path, dig);
+ }
+
+ /**
+ * Add a sub digester at a path of current path + prefixPath
+ * @param prefixPath the prefix path
+ * @param dig the digester
+ */
+ public void addSubDigester(String prefixPath, ElementDigester dig)
+ {
+ String path = getCurrentPath();
+ if (path == null)
+ {
+ addDigester(prefixPath, dig);
+ } else if (prefixPath == null)
+ {
+ addDigester(path, dig);
+ } else
+ {
+ addDigester(path + "/" + prefixPath, dig);
+ }
+ }
+
+ /**
+ * Append the name to the element path and return the new path string
+ * @param name the name of new element
+ * @return the new path string
+ */
+ private String appendElementPath(String name)
+ {
+ int i = _elementPath.size();
+ if (i > 0)
+ {
+ String str = (String) _elementPath.get(i - 1);
+ String newStr = str + "/" + name;
+ _elementPath.add(newStr);
+ return newStr;
+ } else
+ {
+ _elementPath.add(name);
+ return name;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void characters(char[] ch, int start, int length) throws SAXException
+ {
+ ElementDigester dig = getDigester(getCurrentPath());
+ if (dig != null)
+ {
+ dig.characters(this, ch, start, length);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endDocument() throws SAXException
+ {
+ //do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endElement(String uri, String localName, String qName) throws SAXException
+ {
+ String str = removeElementPath(qName);
+ ElementDigester dig = (ElementDigester) getDigester(str);
+ if (dig != null)
+ {
+ dig.endDigest(this);
+ }
+ }
+
+ /**
+ * Get the current element path
+ * @return the path, or null if at start of document
+ */
+ public String getCurrentPath()
+ {
+ int i = _elementPath.size();
+ if (i > 0)
+ {
+ return (String) _elementPath.get(i - 1);
+ } else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Get the digester for particular path
+ * @param path the path
+ * @return the digester, or null if there's none found
+ */
+ private ElementDigester getDigester(String path)
+ {
+ return (ElementDigester) _digesters.get(path);
+ }
+
+ /**
+ * Remove the element path
+ * @param qname the element name is being removed
+ * @return the path string before the path is removed
+ */
+ private String removeElementPath(String qname)
+ {
+ int i = _elementPath.size();
+ if (i > 0)
+ {
+ String str = (String) _elementPath.remove(i - 1);
+ return str;
+ } else
+ {
+ throw new IllegalStateException("Cannot remove element path " + qname);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startDocument() throws SAXException
+ {
+ //do nothing
+ }
+
+ /**
+ * Call start of particular element digester, if there's any
+ * @param attr the attribute
+ * @param path the path
+ * @throws SAXException
+ */
+ private void startDigest(String path, Attributes attr) throws SAXException
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("Digesting " + path);
+ }
+ ElementDigester dig = (ElementDigester) getDigester(path);
+ if (dig != null)
+ {
+ if (_logger.isLoggable(Level.FINEST))
+ {
+ _logger.finest("with " + dig);
+ }
+ dig.startDigest(this, attr);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startElement(String namespaceURI, String lName, // local name
+ String qName, // qualified name
+ Attributes attrs) throws SAXException
+ {
+ String newPath = appendElementPath(qName);
+ startDigest(newPath, attrs);
+ }
+
+ /**
+ * Parse an input
+ * @param stream the stream
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws IOException
+ */
+ public synchronized void parse(InputStream stream) throws ParserConfigurationException, SAXException, IOException
+ {
+ SAXParserFactory fac = SAXParserFactory.newInstance();
+ SAXParser parser = fac.newSAXParser();
+ parser.parse(stream, this);
+ }
+}
\ No newline at end of file
diff --git a/src/test/Dummy.java b/src/test/Dummy.java
new file mode 100644
index 0000000..d565656
--- /dev/null
+++ b/src/test/Dummy.java
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+public class Dummy
+{
+}
diff --git a/src/test/log4j.xml b/src/test/log4j.xml
new file mode 100644
index 0000000..cfe4abb
--- /dev/null
+++ b/src/test/log4j.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/org/onemind/commons/java/datastructure/BiMapTest.java b/src/test/org/onemind/commons/java/datastructure/BiMapTest.java
new file mode 100644
index 0000000..7862619
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/BiMapTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import junit.framework.TestCase;
+/**
+ * Unit test for BiMap
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: BiMapTest.java,v 1.1 2004/09/29 02:45:36 thlee Exp $ $Name: $
+ */
+public class BiMapTest extends TestCase
+{
+
+ /**
+ * Test bimap functionality
+ * @throws Exception
+ */
+ public void testBiMap() throws Exception
+ {
+ BiMap biMap = new BiMap();
+ biMap.put("1", "one");
+ //assert values is correct
+ BiMap inverse = biMap.getInverse();
+ assertEquals("one", biMap.get("1"));
+ assertEquals("1", inverse.get("one"));
+ try
+ {
+ //test conflicts
+ biMap.put("2", "one");
+ throw new Exception("BiMap should not accept non-unique value");
+ } catch (IllegalArgumentException e)
+ {
+ //expected
+ }
+ //test insert different value
+ biMap.put("1", "two");
+ assertEquals("two", biMap.get("1"));
+ assertEquals("1", inverse.get("two"));
+ //test remove
+ biMap.remove("1");
+ assertEquals(biMap.get("1"), null);
+ assertEquals(inverse.get("one"), null);
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/ClassSetTest.java b/src/test/org/onemind/commons/java/datastructure/ClassSetTest.java
new file mode 100644
index 0000000..37e199c
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/ClassSetTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.onemind.commons.java.datastructure.ClassSet;
+import junit.framework.TestCase;
+/**
+ * Testing for ClassSet
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ClassSetTest.java,v 1.2 2004/08/26 12:33:09 thlee Exp $ $Name: $
+ */
+public class ClassSetTest extends TestCase
+{
+
+ public void testIsSubClasses()
+ {
+ ClassSet set = new ClassSet();
+ set.add(Number.class);
+ assertTrue(!set.isSubclassOfClasses(Object.class));
+ assertTrue(set.isSubclassOfClasses(Number.class));
+ }
+
+ public void testAddAll()
+ {
+ List l = new ArrayList();
+ l.add(Object.class);
+ l.add(Number.class);
+ ClassSet set = new ClassSet();
+ set.addAll(l);
+ l.add(new Object());
+ try
+ {
+ set.addAll(l);
+ throw new Exception("Object should have be accepted by addAll()");
+ } catch (Exception e)
+ {
+ //pass
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/CounterQueueTest.java b/src/test/org/onemind/commons/java/datastructure/CounterQueueTest.java
new file mode 100644
index 0000000..b3169c2
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/CounterQueueTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.List;
+import junit.framework.TestCase;
+import org.onemind.commons.java.datastructure.CounterQueue;
+/**
+ * The test for counter queue
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: CounterQueueTest.java,v 1.2 2004/08/26 12:33:09 thlee Exp $ $Name: $
+ */
+public class CounterQueueTest extends TestCase
+{
+
+ public void testCounterQueue()
+ {
+ CounterQueue cq = new CounterQueue();
+ Object counter = new Object();
+ Object queuer1 = new Object();
+ Object queuer2 = new Object();
+ //just check for random counter object
+ assertEquals(cq.getQueue(new Object()).size(), 0);
+ //adding
+ cq.addToQueue(counter, queuer1);
+ cq.addToQueue(counter, queuer2);
+ //just check for random counter object
+ assertEquals(cq.getQueue(new Object()).size(), 0);
+ //test added result
+ List l = cq.getQueue(counter);
+ assertEquals(l.size(), 2);
+ assertEquals(l.get(0), queuer1);
+ assertEquals(l.get(1), queuer2);
+ //test remove next from queue
+ assertEquals(cq.removeNextFromQueue(counter), queuer1);
+ assertEquals(l.size(), 1);
+ //test remove from queuer
+ cq.removeFromQueue(counter, queuer2);
+ assertEquals(l.size(), 0);
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/DuoMapKeyTest.java b/src/test/org/onemind/commons/java/datastructure/DuoMapKeyTest.java
new file mode 100644
index 0000000..3388ac5
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/DuoMapKeyTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.HashMap;
+import java.util.Map;
+import junit.framework.TestCase;
+public class DuoMapKeyTest extends TestCase
+{
+
+ public void testKey()
+ {
+ Map m = new HashMap();
+ Object o1 = new Object();
+ Object o2 = new Object();
+ m.put(new DuoMapKey(null, null), o1);
+ assertEquals(m.get(new DuoMapKey(null, null)), o1);
+ m.put(new DuoMapKey("test1", "test2"), o2);
+ assertEquals(m.get(new DuoMapKey("test1", "test2")), o2);
+ assertEquals(m.get(new DuoMapKey("test2", "test2")), null);
+ }
+}
diff --git a/src/test/org/onemind/commons/java/datastructure/InheritableValueMapTest.java b/src/test/org/onemind/commons/java/datastructure/InheritableValueMapTest.java
new file mode 100644
index 0000000..fd361f8
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/InheritableValueMapTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import org.onemind.commons.java.datastructure.InheritableValueMap;
+import junit.framework.TestCase;
+/**
+ * Test inherited value map
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: InheritableValueMapTest.java,v 1.2 2004/08/26 12:33:08 thlee Exp $ $Name: $
+ */
+public class InheritableValueMapTest extends TestCase
+{
+
+ public void testInheritedValueMap()
+ {
+ InheritableValueMap map = new InheritableValueMap();
+ Object numberValue = new Object();
+ // add in number mapping
+ map.put(Number.class, numberValue);
+ // test result
+ assertEquals(map.resolve(Number.class), numberValue);
+ assertEquals(map.resolve(Integer.class), numberValue);
+ // add in integer mapping
+ Object intValue = new Object();
+ map.put(Integer.class, intValue);
+ //test result
+ assertEquals(map.resolve(Number.class), numberValue);
+ assertEquals(map.resolve(Integer.class), intValue);
+ //test wrong argument
+ try
+ {
+ map.resolve(Object.class);
+ throw new Exception("Should not pass this");
+ } catch (Exception e)
+ {
+ //pass
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/LookupCacheTest.java b/src/test/org/onemind/commons/java/datastructure/LookupCacheTest.java
new file mode 100644
index 0000000..f7bf363
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/LookupCacheTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import org.onemind.commons.java.datastructure.LookupCache;
+import junit.framework.TestCase;
+/**
+ * Test for lookup cache
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: LookupCacheTest.java,v 1.2 2004/08/26 12:33:09 thlee Exp $ $Name: $
+ */
+public class LookupCacheTest extends TestCase
+{
+
+ /**
+ * A test implemement for the lookup cache
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: LookupCacheTest.java,v 1.2 2004/08/26 12:33:09 thlee Exp $ $Name: $
+ */
+ private class TestCacheImpl extends LookupCache
+ {
+
+ /**
+ * Only produce value if key is "One" {@inheritDoc}
+ */
+ protected Object produce(Object key)
+ {
+ if (key.equals("One"))
+ {
+ return new Integer("1");
+ } else
+ {
+ return null;
+ }
+ }
+ }
+
+ public void testLookupCache()
+ {
+ TestCacheImpl cache = new TestCacheImpl();
+ String one = "One";
+ String two = "Two";
+ assertFalse(cache.isInCache(one));
+ assertFalse(cache.isInCache(two));
+ assertFalse(cache.isInNegCache(one));
+ assertFalse(cache.isInNegCache(two));
+ cache.lookup("One");
+ cache.lookup("Two");
+ assertTrue(cache.isInCache(one));
+ assertTrue(cache.isInNegCache(two));
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/MruListTest.java b/src/test/org/onemind/commons/java/datastructure/MruListTest.java
new file mode 100644
index 0000000..07426b8
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/MruListTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.TreeSet;
+import org.onemind.commons.java.datastructure.MruList;
+import junit.framework.TestCase;
+/**
+ * Test for MruList
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MruListTest.java,v 1.2 2004/08/26 12:33:09 thlee Exp $ $Name: $
+ */
+public class MruListTest extends TestCase
+{
+
+ /**
+ * Test the MruEntry implementation
+ * @throws Exception if there's problem
+ */
+ public void testMruEntry() throws Exception
+ {
+ TreeSet set = new TreeSet();
+ Object first = new String("first");
+ Object second = new String("second");
+ MruList.MruEntry entry1 = new MruList.MruEntry(first, System.currentTimeMillis());
+ Thread.currentThread().sleep(20);
+ MruList.MruEntry entry2 = new MruList.MruEntry(second, System.currentTimeMillis());
+ set.add(entry1);
+ set.add(entry2);
+ assertEquals(set.iterator().next(), entry2);
+ System.out.println(set);
+ Thread.currentThread().sleep(20);
+ entry1.setLastAccessTime(System.currentTimeMillis());
+ set.remove(entry1);
+ set.add(entry1);
+ System.out.println(set);
+ assertEquals(set.iterator().next(), entry1);
+ }
+
+ /**
+ * Test the MruList
+ * @throws Exception if there's problem
+ */
+ public void testMruList() throws Exception
+ {
+ MruList list = new MruList();
+ Object first = new String("first");
+ Object second = new String("second");
+ list.add(first);
+ Thread.currentThread().sleep(20);
+ list.add(second);
+ System.out.println(list.iterator().next());
+ assertEquals(list.iterator().next(), second);
+ Thread.currentThread().sleep(20);
+ list.add(first);
+ assertEquals(list.iterator().next(), first);
+ }
+
+ /**
+ * Test truncation
+ */
+ public void testTruncate()
+ {
+ MruList list = new MruList(3, 0);
+ for (int i = 0; i < 10; i++)
+ {
+ Integer obj = new Integer(i);
+ list.add(obj);
+ }
+ assertEquals(list.size(), 3);
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/MruMapTest.java b/src/test/org/onemind/commons/java/datastructure/MruMapTest.java
new file mode 100644
index 0000000..bd38a9e
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/MruMapTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import org.onemind.commons.java.datastructure.MruMap;
+import junit.framework.TestCase;
+/**
+ * Test for MruMap
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: MruMapTest.java,v 1.2 2004/08/26 12:33:08 thlee Exp $ $Name: $
+ */
+public class MruMapTest extends TestCase
+{
+ public void testMruMap() throws Exception
+ {
+ MruMap map = new MruMap(3, 0);
+ for (int i = 0; i < 10; i++)
+ {
+ Integer obj = new Integer(i);
+ Thread.sleep(200);
+ map.put(obj, obj);
+ }
+ assertEquals(map.size(), 3);
+ assertTrue(map.containsKey(new Integer(9)));
+ assertTrue(map.containsKey(new Integer(8)));
+ assertTrue(map.containsKey(new Integer(7)));
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/NametableStackTest.java b/src/test/org/onemind/commons/java/datastructure/NametableStackTest.java
new file mode 100644
index 0000000..5be2b03
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/NametableStackTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import org.onemind.commons.java.datastructure.NametableStack;
+import junit.framework.TestCase;
+/**
+ * Test for nametable stack
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: NametableStackTest.java,v 1.3 2005/04/06 15:40:43 thlee Exp $ $Name: $
+ */
+public class NametableStackTest extends TestCase
+{
+
+ public void testCloseScope()
+ {
+ NametableStack stack = new NametableStack();
+ //add 0-4
+ for (int i = 0; i < 5; i++)
+ {
+ String name = String.valueOf(i);
+ stack.declare(name, name);
+ }
+ //open new scope
+ int scope = stack.newScope();
+ //add 5-9
+ for (int i = 5; i < 10; i++)
+ {
+ String name = String.valueOf(i);
+ stack.declare(name, name);
+ }
+ // check all values valid
+ for (int i = 0; i < 10; i++)
+ {
+ String name = String.valueOf(i);
+ assertEquals(stack.access(name), name);
+ }
+ //close scope
+ stack.closeScope(scope);
+ //check only 0-4 valid
+ for (int i = 5; i < 10; i++)
+ {
+ String name = String.valueOf(i);
+ assertFalse(stack.containsName(name));
+ }
+ for (int i = 0; i < 5; i++)
+ {
+ String name = String.valueOf(i);
+ assertEquals(stack.access(name), name);
+ }
+ }
+
+ public void testLocalScope()
+ {
+ NametableStack stack = new NametableStack();
+ //add 0-4
+ for (int i = 0; i < 5; i++)
+ {
+ String name = String.valueOf(i);
+ stack.declare(name, name);
+ }
+ //open new local scope
+ int scope = stack.newLocalScope();
+ //add 5-9
+ for (int i = 2; i < 7; i++)
+ {
+ String name = String.valueOf(i);
+ stack.declare(name, name);
+ }
+ // check all values valid
+ for (int i = 0; i < 7; i++)
+ {
+ String name = String.valueOf(i);
+ assertEquals(stack.access(name), name);
+ }
+ //close scope
+ stack.closeLocalScope(scope);
+ //check only 0-4 valid
+ for (int i = 5; i < 7; i++)
+ {
+ String name = String.valueOf(i);
+ assertFalse(stack.containsName(name));
+ }
+ for (int i = 0; i < 5; i++)
+ {
+ String name = String.valueOf(i);
+ assertEquals(stack.access(name), name);
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/StackTest.java b/src/test/org/onemind/commons/java/datastructure/StackTest.java
new file mode 100644
index 0000000..e5c9714
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/StackTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import org.onemind.commons.java.datastructure.Stack;
+import junit.framework.TestCase;
+
+/**
+ * Test for stack
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: StackTest.java,v 1.2 2004/08/26 12:33:08 thlee Exp $ $Name: $
+ */
+public class StackTest extends TestCase
+{
+
+ public void testStack()
+ {
+ Stack st = new Stack();
+ assertEquals(st.pushReturnSize(new Integer(1)), 0);
+ assertEquals(st.pushReturnSize(new Integer(2)), 1);
+ st.popUntil(1);
+ assertEquals(st.size(), 1);
+ assertTrue(st.contains(new Integer(1)));
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/TrackedMapTest.java b/src/test/org/onemind/commons/java/datastructure/TrackedMapTest.java
new file mode 100644
index 0000000..f40f144
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/TrackedMapTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.onemind.commons.java.datastructure.TrackedMap;
+import junit.framework.TestCase;
+/**
+ * Test for TrackedMap
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: TrackedMapTest.java,v 1.2 2004/08/26 12:33:09 thlee Exp $ $Name: $
+ */
+public class TrackedMapTest extends TestCase
+{
+
+ public void testTrackedMap()
+ {
+ Object first = new String("first");
+ Object second = new String("second");
+ Object third = new String("third");
+ Map m = new HashMap();
+ m.put(first, first);
+
+ //start with first
+ TrackedMap map = new TrackedMap(m);
+ assertEquals(map.size(), 1);
+ assertEquals(map.keySet().size(), 1);
+ assertEquals(map.values().size(), 1);
+ //replace first
+ map.put(first, first);
+ assertTrue(map.hasChanges());
+ assertEquals(map.size(), 1);
+ assertEquals(map.keySet().size(), 1);
+ assertEquals(map.values().size(), 1);
+
+ //add second
+ map.put(second, second);
+ //assert that it's changed
+ assertTrue(map.hasChanges());
+ assertEquals(map.size(), 2);
+ assertEquals(map.keySet().size(), 2);
+ assertEquals(map.values().size(), 2);
+
+ //make up-to-date
+ map.makeUpToDate();
+ assertTrue(!map.hasChanges());
+ assertEquals(map.size(), 2);
+ assertEquals(map.keySet().size(), 2);
+ assertEquals(map.values().size(), 2);
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/XmlProperties.xml b/src/test/org/onemind/commons/java/datastructure/XmlProperties.xml
new file mode 100644
index 0000000..a9d2281
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/XmlProperties.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/datastructure/XmlPropertiesTest.java b/src/test/org/onemind/commons/java/datastructure/XmlPropertiesTest.java
new file mode 100644
index 0000000..7917762
--- /dev/null
+++ b/src/test/org/onemind/commons/java/datastructure/XmlPropertiesTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.datastructure;
+
+import org.onemind.commons.java.xml.digest.DefaultDigester;
+import org.onemind.commons.java.xml.digest.SaxDigesterHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import junit.framework.TestCase;
+/**
+ * Xml properties
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: XmlPropertiesTest.java,v 1.3 2005/06/22 22:59:13 thlee Exp $ $Name: $
+ */
+public class XmlPropertiesTest extends TestCase
+{
+
+ public static class TestElement extends DefaultDigester
+ {
+
+ public boolean processed = false;
+
+ /**
+ * Constructor
+ */
+ public TestElement()
+ {
+ super("TestElement");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startDigest(SaxDigesterHandler handler, Attributes attrs) throws SAXException
+ {
+ processed = true;
+ }
+ }
+
+ public void testXmlProperties() throws Exception
+ {
+ XmlProperties prop = new XmlProperties(getClass().getResourceAsStream("XmlProperties.xml"));
+ assertEquals("default", prop.get("defaultvalue"));
+ assertEquals(new Short((short) 1), prop.get("shortvalue"));
+ assertEquals(new Integer(1), prop.get("intvalue"));
+ assertEquals(new Long(1), prop.get("longvalue"));
+ assertEquals(new Float(1), prop.get("floatvalue"));
+ assertEquals(new Double(1), prop.get("doublevalue"));
+ assertEquals(new Character('c'), prop.get("charvalue"));
+ assertEquals("string", prop.get("stringvalue"));
+ TestElement e = (TestElement) prop.get("element");
+ assertEquals(e.processed, true);
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/lang/ref/SoftHashMapTest.java b/src/test/org/onemind/commons/java/lang/ref/SoftHashMapTest.java
new file mode 100644
index 0000000..e062e79
--- /dev/null
+++ b/src/test/org/onemind/commons/java/lang/ref/SoftHashMapTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang.ref;
+
+import junit.framework.TestCase;
+/**
+ * Testing SoftHashMap
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: SoftHashMapTest.java,v 1.2 2004/10/31 16:03:13 thlee Exp $ $Name: $
+ */
+public class SoftHashMapTest extends TestCase
+{
+
+ /** the map **/
+ private SoftHashMap _map;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setUp()
+ {
+ _map = new SoftHashMap();
+ }
+
+ /**
+ * Test the map
+ * @throws Exception
+ */
+ public void testMap() throws Exception
+ {
+ boolean collected = false;
+ for (int i = 1; i < 1000; i++)
+ {
+ _map.put(new Integer(i), new Integer(i));
+ if (_map.size() < i)
+ {
+ collected = true;
+ break;
+ }
+ System.gc();
+ }
+ if (!collected)
+ {
+ throw new Exception("SoftHashMap entries are not garbage collected");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/lang/reflect/ClassLooupCacheTest.java b/src/test/org/onemind/commons/java/lang/reflect/ClassLooupCacheTest.java
new file mode 100644
index 0000000..5fb1d5f
--- /dev/null
+++ b/src/test/org/onemind/commons/java/lang/reflect/ClassLooupCacheTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+package org.onemind.commons.java.lang.reflect;
+
+import org.onemind.commons.java.lang.reflect.ClassLookupCache;
+import junit.framework.TestCase;
+
+
+/**
+ * Unit test the class lookup cache
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ClassLooupCacheTest.java,v 1.4 2006/10/29 17:02:38 thlee Exp $ $Name: $
+ */
+public class ClassLooupCacheTest extends TestCase
+{
+ /** the cache **/
+ private ClassLookupCache _cache;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setUp()
+ {
+ _cache = new ClassLookupCache();
+ _cache.addImport("java.io.*");
+ }
+
+ /**
+ * Test lookup
+ */
+ public void testClassLookup() throws Exception
+ {
+ Class c = _cache.getClass("File");
+ assertEquals(c, java.io.File.class);
+ c = _cache.getClass("File1");
+ assertEquals(c, null);
+
+ //do it again to test the cache behavior.
+ //result verified through log4j output
+ assertTrue(_cache.isInCache("java.io.File"));
+ c = _cache.getClass("File1");
+ assertEquals(c, null);
+
+ c = _cache.getClass("Dummy");
+ assertEquals(c, null);
+
+ _cache.addImport("*");
+ c = _cache.getClass("Dummy");
+ assertEquals(Class.forName("Dummy"), c);
+ }
+}
diff --git a/src/test/org/onemind/commons/java/lang/reflect/ReflectUtilsTest.java b/src/test/org/onemind/commons/java/lang/reflect/ReflectUtilsTest.java
new file mode 100644
index 0000000..9289d85
--- /dev/null
+++ b/src/test/org/onemind/commons/java/lang/reflect/ReflectUtilsTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.lang.reflect;
+
+import java.lang.reflect.Method;
+import junit.framework.TestCase;
+/**
+ * Unit test for reflection utilities
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: ReflectUtilsTest.java,v 1.7 2006/08/02 00:07:24 thlee Exp $ $Name: $
+ */
+public class ReflectUtilsTest extends TestCase
+{
+
+ private Class[] _classNames = {java.lang.Object.class, java.lang.Integer.class, java.lang.Float.class, java.lang.Double.class,
+ java.lang.Long.class, java.lang.Boolean.class, java.lang.String.class, java.lang.Double.class, java.lang.Byte.class,
+ java.lang.Character.class, java.lang.Exception.class, java.lang.Class.class};
+
+ /** a test class * */
+ public static class TestClass
+ {
+
+ /**
+ * Static method
+ */
+ public static void staticMethod()
+ {
+ }
+
+ public String normalMethod(Object obj)
+ {
+ return "A";
+ //do nothing
+ }
+
+ public String normalMethod(Integer obj)
+ {
+ return "B";
+ //do nothing
+ }
+
+ public String normalMethod(String obj)
+ {
+ return "C";
+ //do nothing
+ }
+
+ public String similarMethod(short a)
+ {
+ return "short";
+ }
+
+ public String similarMethod(int a)
+ {
+ return "int";
+ }
+
+ public String similarMethod(long a)
+ {
+ return "long";
+ }
+ }
+
+ public static class TestSubClass extends TestClass
+ {
+ }
+
+ /** test the util * */
+ public void testStaticMethodInvocation() throws Exception
+ {
+ ReflectUtils.invoke(TestClass.class, "staticMethod", null);
+ ReflectUtils.invoke(TestSubClass.class, "staticMethod", null);
+ }
+
+ public void testClassMethodInvocation() throws Exception
+ {
+ ReflectUtils.invoke(new TestSubClass().getClass(), "getName", null);
+ ReflectUtils.invoke(new TestSubClass().getClass(), "getName", null);
+ }
+
+ public void testObjectMethodInvcation() throws Exception
+ {
+ ReflectUtils.invoke(new TestClass(), "normalMethod", new Object[]{null});
+ }
+
+ public void testMethodSearch() throws Exception
+ {
+ Object result = ReflectUtils.invoke(new TestSubClass(), "similarMethod", new Object[]{new Long(1)});
+ assertTrue(result.equals("long"));
+ result = ReflectUtils.invoke(new TestSubClass(), "similarMethod", new Object[]{new Integer(1)});
+ assertTrue(result.equals("int"));
+ result = ReflectUtils.invoke(new TestSubClass(), "similarMethod", new Object[]{new Short((short) 1)});
+ assertTrue(result.equals("short"));
+ Object args[] = new Object[] { new Integer(1), new Integer(1) } ;
+ ReflectUtils.invoke(Math.class, "pow", args);
+ }
+
+ public void testClassCache() throws Exception
+ {
+ long start = System.currentTimeMillis();
+ ReflectUtils.setClassCaching(false);
+ for (int i = 0; i < 10000; i++)
+ {
+ lookForClasses();
+ }
+ long end = System.currentTimeMillis();
+ System.out.println("Time used for class lookup without caching = " + (end - start));
+ start = System.currentTimeMillis();
+ ReflectUtils.setClassCaching(true);
+ start = System.currentTimeMillis();
+ for (int i = 0; i < 10000; i++)
+ {
+ lookForClasses();
+ }
+ end = System.currentTimeMillis();
+ System.out.println("Time used for class lookup with caching = " + (end - start));
+ }
+
+ public void testMethodCache() throws Exception
+ {
+ long start = System.currentTimeMillis();
+ ReflectUtils.setMethodCaching(false);
+ for (int i = 0; i < 10000; i++)
+ {
+ lookForMethods();
+ }
+ long end = System.currentTimeMillis();
+ System.out.println("Time used for method lookup without caching = " + (end - start));
+ start = System.currentTimeMillis();
+ ReflectUtils.setMethodCaching(true);
+ start = System.currentTimeMillis();
+ for (int i = 0; i < 10000; i++)
+ {
+ lookForMethods();
+ }
+ end = System.currentTimeMillis();
+ System.out.println("Time used for method lookup with caching = " + (end - start));
+ }
+
+ private void lookForClasses() throws Exception
+ {
+ for (int i = 0; i < _classNames.length; i++)
+ {
+ ReflectUtils.getClass(_classNames[i].getName());
+ }
+ }
+
+ private void lookForMethods() throws Exception
+ {
+ for (int i = 0; i < _classNames.length; i++)
+ {
+ ReflectUtils.getMethod(_classNames[i], "equals", new Class[]{Object.class});
+ }
+ }
+
+ public void testPrimitiveArgumentCheck() throws Exception
+ {
+ assertTrue(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Object[]{new Long(1)}));
+ assertTrue(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Object[]{new Integer(1)}));
+ assertFalse(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Object[]{new Float(1.5)}));
+ assertFalse(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Object[]{new Double(1.5)}));
+ assertTrue(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Class[]{Long.class}));
+ assertTrue(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Class[]{Integer.class}));
+ assertFalse(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Class[]{Float.class}));
+ assertFalse(ReflectUtils.isCompatible(new Class[]{Long.TYPE}, new Class[]{Double.class}));
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ ReflectUtilsTest test = new ReflectUtilsTest();
+ test.testClassCache();
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/pattern/DynamicVisitorTest.java b/src/test/org/onemind/commons/java/pattern/DynamicVisitorTest.java
new file mode 100644
index 0000000..166f752
--- /dev/null
+++ b/src/test/org/onemind/commons/java/pattern/DynamicVisitorTest.java
@@ -0,0 +1,60 @@
+
+package org.onemind.commons.java.pattern;
+
+import junit.framework.TestCase;
+/**
+ * @author TiongHiang Lee (tlee@i2rd.com)
+ * @version $Id: DynamicVisitorTest.java,v 1.1 2004/10/31 16:03:44 thlee Exp $ $Name: $
+ */
+public class DynamicVisitorTest extends TestCase
+{
+
+ private class TestBaseClass
+ {
+ }
+
+ public class TestClass extends TestBaseClass
+ {
+ }
+
+ public class TestSubClass extends TestClass
+ {
+ }
+
+ public class TestVisitor extends DynamicVisitor
+ {
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void initNodeHandlers()
+ {
+ addMethodNodeHandler(TestBaseClass.class, "visit");
+ addMethodNodeHandler(TestClass.class, "visit");
+ addMethodNodeHandler(TestSubClass.class, "visit");
+ }
+
+ public Object visit(TestBaseClass obj, Object[] data)
+ {
+ assertTrue(obj.getClass()==TestBaseClass.class);
+ return null;
+ }
+
+ public Object visit(TestClass obj, Object[] data)
+ {
+ assertTrue(obj.getClass()==TestClass.class);
+ return null;
+ }
+
+ public Object visit(TestSubClass obj, Object[] data)
+ {
+ assertTrue(obj.getClass()==TestSubClass.class);
+ return null;
+ }
+ };
+
+ public void testVisitor()
+ {
+ TestVisitor visitor = new TestVisitor();
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/util/FileUtilsTest.java b/src/test/org/onemind/commons/java/util/FileUtilsTest.java
new file mode 100644
index 0000000..6cb504e
--- /dev/null
+++ b/src/test/org/onemind/commons/java/util/FileUtilsTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import org.onemind.commons.java.util.FileUtils;
+import junit.framework.TestCase;
+
+/**
+ * Test for utils test
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: FileUtilsTest.java,v 1.2 2004/08/26 12:33:17 thlee Exp $ $Name: $
+ */
+public class FileUtilsTest extends TestCase
+{
+
+ public void testFileUtils()
+ {
+ assertEquals(FileUtils.concatFilePath("/test", "test1"), "/test/test1");
+ assertEquals(FileUtils.concatFilePath("/test", "/test1"), "/test/test1");
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/util/StringUtilsTest.java b/src/test/org/onemind/commons/java/util/StringUtilsTest.java
new file mode 100644
index 0000000..b03034a
--- /dev/null
+++ b/src/test/org/onemind/commons/java/util/StringUtilsTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@onemindsoft.org
+ */
+
+package org.onemind.commons.java.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.onemind.commons.java.util.StringUtils;
+import junit.framework.TestCase;
+/**
+ * Test for string utilities
+ * @author TiongHiang Lee (thlee@onemindsoft.org)
+ * @version $Id: StringUtilsTest.java,v 1.2 2004/08/26 12:33:17 thlee Exp $ $Name: $
+ */
+public class StringUtilsTest extends TestCase
+{
+
+ public void testConcatCollection()
+ {
+ List l = new ArrayList();
+ l.add(new String("first"));
+ l.add(new String("second"));
+ l.add(new String("third"));
+ String result = StringUtils.concat(l, ",");
+ assertEquals(result, "first,second,third");
+ }
+
+ public void testSubStringAfterLast()
+ {
+ String result = StringUtils.substringAfter("abcdefg", "cd");
+ assertEquals(result, "efg");
+ }
+
+ public void testSubStringBeforeLast()
+ {
+ String result = StringUtils.substringBeforeLast("abcdefg", "cd");
+ assertEquals(result, "ab");
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/xml/digest/SaxDigesterTest.java b/src/test/org/onemind/commons/java/xml/digest/SaxDigesterTest.java
new file mode 100644
index 0000000..e030591
--- /dev/null
+++ b/src/test/org/onemind/commons/java/xml/digest/SaxDigesterTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2004 TiongHiang Lee
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Email: thlee@thinklient.org
+ */
+
+package org.onemind.commons.java.xml.digest;
+
+import java.io.InputStream;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import junit.framework.TestCase;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+/**
+ * SaxDigester test. The model is with exactly one "RootElement" which can have 0-1 "Element" that can any random "SubElement1" and
+ * "SubElement2"
+ * @author TiongHiang Lee (thlee@thinklient.org)
+ * @version $Id: SaxDigesterTest.java,v 1.4 2005/04/26 17:46:39 thlee Exp $ $Name: $
+ */
+public class SaxDigesterTest extends TestCase
+{
+
+ /**
+ * Root element digester
+ */
+ public class TestElementDigester extends DefaultDigester
+ {
+
+ /** the count start is called**/
+ int startCount;
+
+ /** the count end is called **/
+ int endCount;
+
+ /** the count characters is called **/
+ int charCount;
+
+ /**
+ * {@inheritDoc}
+ */
+ public TestElementDigester(String str)
+ {
+ super(str);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void startDigest(SaxDigesterHandler handler, Attributes attrs) throws SAXException
+ {
+ startCount++;
+ //System.out.println("Starting " + handler.getCurrentPath());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endDigest(SaxDigesterHandler handler) throws SAXException
+ {
+ endCount++;
+ //System.out.println("Ending " + handler.getCurrentPath());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void characters(SaxDigesterHandler handler, char[] chars, int offset, int length) throws SAXException
+ {
+ charCount++;
+ //System.out.println("Character " + handler.getCurrentPath());
+ }
+ }
+
+ /**
+ * parse the file with the handler
+ * @throws Exception
+ */
+ private void _testHandler(InputStream in, SaxDigesterHandler handler) throws Exception
+ {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ // Parse the input
+ SAXParser saxParser = factory.newSAXParser();
+ saxParser.parse(in, handler);
+ }
+
+ /**
+ * Test when there's one element
+ * @throws Exception if there's exception
+ */
+ public void testOneElement() throws Exception
+ {
+ SaxDigesterHandler handler = new SaxDigesterHandler();
+ TestElementDigester rootElement = new TestElementDigester("RootElement");
+ TestElementDigester rootElement1 = new TestElementDigester("RootElment1");
+ TestElementDigester subElement1 = new TestElementDigester("SubElement1");
+ handler.addDigester(rootElement);
+ handler.addDigester(rootElement1);
+ handler.addDigester("RootElement/Element1", subElement1);
+ _testHandler(getClass().getResourceAsStream("SaxDigesterTest.xml"), handler);
+ assertTrue(rootElement.startCount == 1);
+ assertTrue(rootElement.endCount == 1);
+ assertTrue(rootElement1.startCount == 0);
+ assertTrue(rootElement1.endCount == 0);
+ assertTrue(subElement1.startCount == 2);
+ assertTrue(subElement1.endCount == 2);
+ }
+}
\ No newline at end of file
diff --git a/src/test/org/onemind/commons/java/xml/digest/SaxDigesterTest.xml b/src/test/org/onemind/commons/java/xml/digest/SaxDigesterTest.xml
new file mode 100644
index 0000000..64be325
--- /dev/null
+++ b/src/test/org/onemind/commons/java/xml/digest/SaxDigesterTest.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ asdfdsf
+
+
+
+
+