[Schmitzm-commits] r941 - in trunk: . src/schmitzm/lang src_junit/schmitzm/lang
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Jul 22 12:20:11 CEST 2010
Author: mojays
Date: 2010-07-22 12:20:09 +0200 (Thu, 22 Jul 2010)
New Revision: 941
Added:
trunk/src/schmitzm/lang/LimitedHashMap.java
trunk/src_junit/schmitzm/lang/LimitedHashMapTest.java
Modified:
trunk/build.xml
trunk/src/schmitzm/lang/LangUtil.java
trunk/src/schmitzm/lang/LimitedVector.java
Log:
build.xml: updated on new target folder
LangUtil: new helper methods for string/object connect
LimitedVector: java doc updated
LimitedHashMap: new class analogous to LimitedVector
LimitedHashMapTest: new junit test for LimitedHashMap
Modified: trunk/build.xml
===================================================================
--- trunk/build.xml 2010-07-21 18:07:39 UTC (rev 940)
+++ trunk/build.xml 2010-07-22 10:20:09 UTC (rev 941)
@@ -3,7 +3,7 @@
dependencies)!!
Option "jar" -> a JAR from the existing binaries expected in folder
- "classes" plus a ZIP of the JAR
+ "targes/classes" plus a ZIP of the JAR
Option "src" -> a ZIP of the source code in folder "src"
Option "javadoc" -> a JavaDoc in folder "javadoc" plus a ZIP of
this folder
@@ -40,7 +40,7 @@
<property name="FILE.SRC.ZIP" value="${DEST.DIR}/${PROJECT.PREFIX}-src.zip"/>
<!-- Source and Destination for JAR file -->
- <property name="DIR.CLASSES" value="classes"/>
+ <property name="DIR.CLASSES" value="target/classes"/>
<property name="FILE.JAR" value="${DEST.DIR}/${PROJECT.PREFIX}.jar"/>
<property name="FILE.JAR.ZIP" value="${FILE.JAR}.zip"/>
Modified: trunk/src/schmitzm/lang/LangUtil.java
===================================================================
--- trunk/src/schmitzm/lang/LangUtil.java 2010-07-21 18:07:39 UTC (rev 940)
+++ trunk/src/schmitzm/lang/LangUtil.java 2010-07-22 10:20:09 UTC (rev 941)
@@ -90,21 +90,59 @@
* @return
*/
public static String listString(String delim, String... strList) {
- StringBuffer resultStr = new StringBuffer();
- for (int i=0; i<strList.length; i++) {
- // ignore item if it it null or empty
- if ( strList[i] == null || "".equals(strList[i].trim()) )
- continue;
- // append delimiter (if necessary)
- if ( resultStr.length() > 0 && delim != null )
- resultStr.append(delim);
- // append string
- resultStr.append(strList[i].trim());
- }
- return resultStr.toString();
+// StringBuffer resultStr = new StringBuffer();
+// for (int i=0; i<strList.length; i++) {
+// // ignore item if it it null or empty
+// if ( strList[i] == null || "".equals(strList[i].trim()) )
+// continue;
+// // append delimiter (if necessary)
+// if ( resultStr.length() > 0 && delim != null )
+// resultStr.append(delim);
+// // append string
+// resultStr.append(strList[i].trim());
+// }
+// return resultStr.toString();
+ return listObjects(delim, true, (Object[])strList);
}
- /**
+ /**
+ * Haengt Objekte (als String) aneinander, getrennt durch Trennzeichen.
+ * @param delim Trennzeichen (kann {@code null} sein)
+ * @param ignoreNulls bestimmt, ob {@code null}-Elemente (und leere Strings)
+ * ignoriert werden
+ * @param objList Liste von Objekten
+ * @return
+ */
+ public static String listObjects(String delim, boolean ignoreNulls, Object... objList) {
+ StringBuffer resultStr = new StringBuffer();
+ for (int i=0; i<objList.length; i++) {
+ // ignore item if it is null or empty
+ if ( ignoreNulls && (objList[i] == null || objList[i] instanceof String && "".equals(((String)objList[i]).trim()) ) )
+ continue;
+ // append delimiter (if necessary)
+ if ( resultStr.length() > 0 && delim != null )
+ resultStr.append(delim);
+ // append string
+ String str = (objList[i] == null) ? "null" : objList[i].toString();
+ resultStr.append(str.trim());
+ }
+ return resultStr.toString();
+ }
+
+ /**
+ * Haengt Objekte (als String) aneinander, getrennt durch Trennzeichen.
+ * @param delim Trennzeichen (kann {@code null} sein)
+ * @param ignoreNulls bestimmt, ob {@code null}-Elemente (und leere Strings)
+ * ignoriert werden
+ * @param objList Liste von Objekten
+ * @return
+ */
+ public static String listObjects(String delim, boolean ignoreNulls, Collection<?> values) {
+ Object[] objArray = values.toArray();
+ return listObjects(delim,ignoreNulls,objArray);
+ }
+
+ /**
* Prueft, ob ein {@link Enum} ein spezielles Feld besitzt.
*
* @param enumClass
Added: trunk/src/schmitzm/lang/LimitedHashMap.java
===================================================================
--- trunk/src/schmitzm/lang/LimitedHashMap.java 2010-07-21 18:07:39 UTC (rev 940)
+++ trunk/src/schmitzm/lang/LimitedHashMap.java 2010-07-22 10:20:09 UTC (rev 941)
@@ -0,0 +1,268 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ *
+ * This file is part of the SCHMITZM library - a collection of utility
+ * classes based on Java 1.6, focusing (not only) on Java Swing
+ * and the Geotools library.
+ *
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ *
+ * This program 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 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ *
+ * Contributors:
+ * Martin O. J. Schmitz - initial API and implementation
+ * Stefan A. Tzeggai - additional utility classes
+ ******************************************************************************/
+package schmitzm.lang;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Vector;
+
+import schmitzm.data.event.AbstractObjectTraceable;
+import schmitzm.data.event.GeneralObjectChangeEvent;
+import schmitzm.data.event.Invoker;
+import schmitzm.data.event.ObjectChangeEvent;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectTraceable;
+
+/**
+ * This class represents a {@link HashMap} which is limited to a number
+ * of elements. When the maximum number of elements is exceeded, the
+ * "oldest" element is removed.<br>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class LimitedHashMap<K,V> extends HashMap<K,V> implements ObjectTraceable {
+
+ /**
+ * Defines which element is removed when the maximum number of elements
+ * is exceeded.
+ */
+ public enum TRUNC_METHOD {
+ /** The oldest element in the map (with the oldest {@code put(.)}-call)
+ * is removed. */
+ OLDEST_PUT,
+ /** The element with the oldest accessed (oldest {@code get(.)}-call)
+ * is removed. */
+ OLDEST_GET
+ }
+
+ /** Defines the behavior to truncate the map when the maximum number
+ * of elements is exceeded. */
+ protected TRUNC_METHOD truncMethod = null;
+ /** Holds the maximum count of elements, the map can hold. */
+ protected int maxLoad = 0;
+ /** Holds the keys of the map in the order of age. */
+ protected Vector<K> oldestKeys = new Vector<K>();
+
+ // Einfache Implementierung von ObjectTraceable, um die Methoden der
+ // Listener-Verwaltung nicht doppelt implementieren zu muessen
+ private AbstractObjectTraceable objectTraceableProxy = new AbstractObjectTraceable() {
+ };
+
+ /**
+ * Creates an empty map.
+ * @param maxLoad max. number of elements the map can hold
+ * @param truncMethod method applied if the maximum map load is exeeced
+ */
+ public LimitedHashMap(int maxLoad, TRUNC_METHOD truncMethod) {
+ super(maxLoad);
+ this.truncMethod = truncMethod;
+ setMaxLoad(maxLoad);
+ }
+
+ /**
+ * Returns the maximum number of elements, the map can hold.
+ */
+ public int getMaxLoad() {
+ return maxLoad;
+ }
+
+ /**
+ * Sets the maximum number of elements, the map can hold. If this number
+ * is exceeded, the oldest element is removed.
+ * @param maxLoad maximum number of elements, the map can hold
+ * @see TRUNC_METHOD
+ */
+ public void setMaxLoad(int maxLoad) {
+ this.maxLoad = maxLoad;
+ truncate();
+ }
+
+ /**
+ * Returns the behavior when truncating surplus elements.
+ */
+ public TRUNC_METHOD getTruncMethod() {
+ return this.truncMethod;
+ }
+
+ /**
+ * Removes the oldest element from the map until the maximum element
+ * count is reached.
+ */
+ protected void truncate() {
+ while( size() > maxLoad ) {
+ // determine the oldest element key (and remove it)
+ K oldestKey = oldestKeys.remove(0);
+ // remove element from map
+ remove( oldestKey );
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////// Ueberschreiben von Vector ///////////////////
+ ///////////////////////////////////////////////////////////////////
+ /**
+ * Adds an element to the map and removes all surplus elements.
+ * An {@link ObjectChangeEvent} is initiated if the map changes.
+ * @param key element key
+ * @param value element value
+ * @return the former value mapped to {@code key} ({@code null} if there
+ * was no such element)
+ */
+ @Override
+ public V put(K key, V value) {
+ int oldSize = size();
+ V oldValue = super.put(key,value);
+
+ // truncate the map before updating the oldest list, so that
+ // the new element is ignored in this truncate
+ truncate();
+
+ // update the "oldest" list
+ switch ( truncMethod ) {
+ // OLDEST_PUT: the new element is the youngest, so add the key of the
+ // new element at the end of the oldest list
+ case OLDEST_PUT: oldestKeys.add(key);
+ break;
+ // OLDEST_GET: the new element is not yet accessed by get, so add the key
+ // at the front of the oldest list
+ case OLDEST_GET: oldestKeys.add(0,key);
+ break;
+ }
+
+ // fire an event if the map has changed
+ if ( oldValue != value )
+ fireEvent( new ObjectChangeEvent(new Invoker(this),oldValue,value) );
+
+ return oldValue;
+ }
+
+ /**
+ * Returns an element of the map.
+ * @param key element key
+ */
+ @Override
+ public V get(Object key) {
+ V value = super.get(key);
+
+ // update the oldest list if the truncate method is OLDEST_GET
+ if ( oldestKeys.contains(key) && TRUNC_METHOD.OLDEST_GET.equals(truncMethod) ) {
+ oldestKeys.remove(key); // remove from current position
+ oldestKeys.add((K)key); // add to the end
+ }
+
+ return value;
+ }
+
+ /**
+ * Removes an element from the map and fires an {@link ObjectChangeEvent},
+ * if the map has changed.
+ * @param key element key
+ * @return the former value mapped to {@code key} ({@code null} if there
+ * was no such element)
+ */
+ @Override
+ public V remove(Object key) {
+ // remove element from map
+ V oldValue = super.remove(key);
+ // remove key from oldest list
+ oldestKeys.remove(key);
+
+ // fire change event if the list has changed
+ if ( oldValue != null )
+ fireEvent( new ObjectChangeEvent(new Invoker(this),oldValue,null) );
+
+ return oldValue;
+ }
+
+ /**
+ * Clears the map and fires an {@link GeneralObjectChangeEvent} if the list
+ * changes.
+ */
+ @Override
+ public void clear() {
+ if ( isEmpty() )
+ return;
+ // clear the map
+ super.clear();
+ // clear the oldest list
+ oldestKeys.clear();
+
+ fireEvent(new GeneralObjectChangeEvent(this));
+ }
+
+
+ ///////////////////////////////////////////////////////////////////
+ //////////// Implementierung von ObjectTraceable //////////////
+ ///////////////////////////////////////////////////////////////////
+ /**
+ * Adds a listener to the map, which is informed on map changes.
+ */
+ public void addObjectListener(ObjectListener listener) {
+ this.objectTraceableProxy.addObjectListener(listener);
+ }
+
+ /**
+ * Removes a listener from the map.
+ */
+ public void removeObjectListener(ObjectListener listener) {
+ this.objectTraceableProxy.removeObjectListener(listener);
+ }
+
+ /**
+ * Checks, whether a listener is already connected to the map.
+ */
+ public boolean containsObjectListener(ObjectListener l) {
+ return this.objectTraceableProxy.containsObjectListener(l);
+ }
+
+ /**
+ * Returns all listener of a special type.
+ * @param type kind of listener (filter)
+ */
+ public ObjectListener[] getObjectListener(Class type) {
+ return this.objectTraceableProxy.getObjectListener(type);
+ }
+
+ /**
+ * Fires an event to all connected listeners.
+ */
+ public void fireEvent(ObjectEvent e) {
+ this.objectTraceableProxy.fireEvent(e);
+ }
+
+ /**
+ * Fires an event to all listeners of a special type.
+ */
+ public void fireEvent(ObjectEvent e, Class c) {
+ this.objectTraceableProxy.fireEvent(e, c);
+ }
+
+}
Modified: trunk/src/schmitzm/lang/LimitedVector.java
===================================================================
--- trunk/src/schmitzm/lang/LimitedVector.java 2010-07-21 18:07:39 UTC (rev 940)
+++ trunk/src/schmitzm/lang/LimitedVector.java 2010-07-22 10:20:09 UTC (rev 941)
@@ -90,7 +90,7 @@
}
/**
- * Loescht solange das letzte Element der Liste, bis die maximale Anzahl
+ * Loescht solange das erste Element der Liste, bis die maximale Anzahl
* an Elementen erreicht ist.
*/
protected void truncate() {
Added: trunk/src_junit/schmitzm/lang/LimitedHashMapTest.java
===================================================================
--- trunk/src_junit/schmitzm/lang/LimitedHashMapTest.java 2010-07-21 18:07:39 UTC (rev 940)
+++ trunk/src_junit/schmitzm/lang/LimitedHashMapTest.java 2010-07-22 10:20:09 UTC (rev 941)
@@ -0,0 +1,107 @@
+package schmitzm.lang;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.geotools.feature.FeatureCollection;
+import org.geotools.filter.text.cql2.CQLException;
+import org.jfree.chart.ChartFrame;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.AxisState;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.NumberTick;
+import org.jfree.chart.axis.NumberTickUnit;
+import org.jfree.chart.axis.TickUnits;
+import org.jfree.chart.axis.ValueTick;
+import org.jfree.ui.RectangleEdge;
+import org.jfree.ui.TextAnchor;
+import org.junit.Test;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.io.IOUtil;
+import schmitzm.jfree.chart.style.ChartAxisStyle;
+import schmitzm.jfree.chart.style.ChartLabelStyle;
+import schmitzm.jfree.chart.style.ChartRendererStyle;
+import schmitzm.jfree.chart.style.ChartType;
+import schmitzm.jfree.table.AggregationFunction;
+
+public class LimitedHashMapTest {
+ private static Logger log = Logger.getLogger(LimitedHashMapTest.class);
+ /** If tests are run on a system with head, we may theoretically open dialgs, frames etc. **/
+ boolean INTERACTIVE = !GraphicsEnvironment.isHeadless();
+
+
+ @Test
+ public void testLimitedHashMap() throws IOException, InterruptedException {
+ LimitedHashMap<Integer, String> lhm = new LimitedHashMap<Integer, String>(5, LimitedHashMap.TRUNC_METHOD.OLDEST_GET);
+
+ // Initialisierung pruefen
+ assertEquals("Map muss leer sein.", 0, lhm.size());
+ assertEquals("Oldest list muss leer sein.", 0, lhm.oldestKeys.size());
+
+ // Elemente einfuegen bis Map voll ist
+ for (int i=1; i<=lhm.getMaxLoad(); i++) {
+ lhm.put(i, "Element "+i);
+ assertEquals("Map muss "+i+" Elemente haben.", i, lhm.size());
+ assertEquals("Oldest list "+i+" Elemente haben.", i, lhm.oldestKeys.size());
+ }
+ debugLimitedHashMap(lhm);
+
+ // Weiteres Element hinzufuegen
+ lhm.put(6, "Element "+6);
+ debugLimitedHashMap(lhm);
+ // Map muss weiterhin 5 Elemente haben
+ assertEquals("Map muss 5 Elemente haben.", 5, lhm.size());
+ assertEquals("Oldest list 5 Elemente haben.", 5, lhm.oldestKeys.size());
+ switch ( lhm.getTruncMethod() ) {
+ case OLDEST_PUT:
+ // 1 muesste geloescht worden sein
+ assertEquals("Erstes Element in Oldest-List muss 2 sein.", 2, (int)lhm.oldestKeys.firstElement());
+ // 6 muesste letztes Element sein
+ assertEquals("Letztes Element in Oldest-List muss 6 sein.", 6, (int)lhm.oldestKeys.lastElement());
+ // 5 muesste vorletztes Element sein
+ assertEquals("Vorletztes Element in Oldest-List muss 5 sein.", 5, (int)lhm.oldestKeys.elementAt(lhm.size()-2));
+ break;
+ case OLDEST_GET:
+ // 5 muesste geloescht worden sein
+ assertEquals("Erstes Element in Oldest-List muss 6 sein.", 6, (int)lhm.oldestKeys.firstElement());
+ // 6 muesste letztes Element sein
+ assertEquals("Letztes Element in Oldest-List muss 1 sein.", 1, (int)lhm.oldestKeys.lastElement());
+ // 4 muesste vorletztes Element sein
+ assertEquals("Vorletztes Element in Oldest-List muss 2 sein.", 2, (int)lhm.oldestKeys.elementAt(lhm.size()-2));
+ break;
+ }
+
+ lhm.get(7); // noch nicht drin, nichts darf sich aendern
+ debugLimitedHashMap(lhm);
+ lhm.get(6); // 6 muss ans Ende der Oldest-List rutschen
+ debugLimitedHashMap(lhm);
+
+
+ lhm.put(7, "Element "+7);
+ debugLimitedHashMap(lhm);
+ }
+
+ private void debugLimitedHashMap(LimitedHashMap<?, ?> lhm) {
+ System.out.println("Elemente: "+LangUtil.listObjects(", ", false, lhm.values()));
+ System.out.println("OldestList: "+LangUtil.listObjects(", ", false, lhm.oldestKeys));
+ }
+
+}
More information about the Schmitzm-commits
mailing list