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 + + + + +