svn commit: r885275 - in /ofbiz/trunk/framework/base/src/org/ofbiz/base/util: cache/ collections/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r885275 - in /ofbiz/trunk/framework/base/src/org/ofbiz/base/util: cache/ collections/

doogie-3
Author: doogie
Date: Sun Nov 29 21:26:37 2009
New Revision: 885275

URL: http://svn.apache.org/viewvc?rev=885275&view=rev
Log:
UtilCache is now a map.  keySet, entrySet, and values iterators won't
reflect items added/removed.  However, most membership tests directly
access the underlying cache anyways, so this isn't a big deal.

Added:
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapCollection.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntry.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntrySet.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapKeySet.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapSet.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapValues.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/IteratorWrapper.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/ReadOnlyMapEntry.java
Modified:
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/CacheLineTable.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/UtilCache.java

Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/CacheLineTable.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/CacheLineTable.java?rev=885275&r1=885274&r2=885275&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/CacheLineTable.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/CacheLineTable.java Sun Nov 29 21:26:37 2009
@@ -23,6 +23,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -34,6 +35,7 @@
 import org.ofbiz.base.util.ObjectType;
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.collections.LRUMap;
+import org.ofbiz.base.util.collections.ReadOnlyMapEntry;
 
 @SuppressWarnings("serial")
 public class CacheLineTable<K, V> implements Serializable {
@@ -212,6 +214,35 @@
         return values;
     }
 
+    public synchronized Iterator<Map.Entry<K, ? extends CacheLine<V>>> iterator() {
+        // this is a list, instead of a set, as the fileTable or
+        // memoryTable has already deduped keys for us, and this ends up
+        // being faster, as the hashCode/equals calls don't need to happen
+        List<Map.Entry<K, ? extends CacheLine<V>>> list = FastList.newInstance();
+        if (fileTable != null) {
+            try {
+                jdbm.helper.FastIterator iter = fileTable.keys();
+                Object key = iter.next();
+                while (key != null) {
+                    CacheLine<V> value = (CacheLine<V>) fileTable.get(key);
+                    if (key instanceof ObjectType.NullObject) {
+                        key = null;
+                    }
+                    list.add(new ReadOnlyMapEntry<K, CacheLine<V>>((K) key, value));
+                    key = iter.next();
+                }
+            } catch (IOException e) {
+                Debug.logError(e, module);
+            }
+        } else {
+            list.addAll(memoryTable.entrySet());
+            if (isNullSet) {
+                list.add(new ReadOnlyMapEntry<K, CacheLine<V>>(null, nullValue));
+            }
+        }
+        return list.iterator();
+    }
+
     /**
      *
      * @return An unmodifiable Set for the keys for this cache; to remove while iterating call the remove method on this class.

Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/UtilCache.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/UtilCache.java?rev=885275&r1=885274&r2=885275&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/UtilCache.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/cache/UtilCache.java Sun Nov 29 21:26:37 2009
@@ -21,8 +21,8 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.MissingResourceException;
@@ -37,6 +37,9 @@
 
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.collections.GenericMap;
+import org.ofbiz.base.util.collections.GenericMapEntry;
+import org.ofbiz.base.util.collections.IteratorWrapper;
 
 /**
  * Generalized caching utility. Provides a number of caching features:
@@ -50,7 +53,7 @@
  *
  */
 @SuppressWarnings("serial")
-public class UtilCache<K, V> implements Serializable {
+public class UtilCache<K, V> extends GenericMap<K, V> implements Serializable {
 
     public static final String module = UtilCache.class.getName();
 
@@ -222,6 +225,41 @@
         return cacheLineTable.isEmpty();
     }
 
+    protected Iterator<Map.Entry<K, V>> iterator(final boolean noteAccess) {
+        return new IteratorWrapper<Map.Entry<K, V>, Map.Entry<K, ? extends CacheLine<V>>>(cacheLineTable.iterator()) {
+            protected Map.Entry<K, V> convert(Map.Entry<K, ? extends CacheLine<V>> src) {
+                return new GenericMapEntry<K, V>(UtilCache.this, src.getKey(), noteAccess);
+            }
+
+            protected void noteRemoval(Map.Entry<K, V> dest, Map.Entry<K, ? extends CacheLine<V>> src) {
+                UtilCache.this.remove(dest.getKey());
+            }
+        };
+    }
+
+    protected <KE extends K, VE extends V> void putAll(Iterator<Map.Entry<KE, VE>> it) {
+        long accessTime = System.currentTimeMillis();
+        while (it.hasNext()) {
+            Map.Entry<KE, VE> entry = it.next();
+            K key = entry.getKey();
+            V value = entry.getValue();
+            CacheLine<V> oldCacheLine;
+            CacheLine<V> newCacheLine;
+            if (expireTime > 0) {
+                newCacheLine = useSoftReference ? new SoftRefCacheLine<V>(value, accessTime, expireTime) : new HardRefCacheLine<V>(value, accessTime, expireTime);
+            } else {
+                newCacheLine = useSoftReference ? new SoftRefCacheLine<V>(value, expireTime) : new HardRefCacheLine<V>(value, expireTime);
+            }
+            oldCacheLine = cacheLineTable.put(key, newCacheLine);
+
+            if (oldCacheLine == null) {
+                noteAddition(key, value);
+            } else {
+                noteUpdate(key, value, oldCacheLine.getValue());
+            }
+        }
+    }
+
     /** Puts or loads the passed element into the cache
      * @param key The key for the element, used to reference it in the hastables and LRU linked list
      * @param value The value of the element
@@ -260,8 +298,8 @@
      * @param key The key for the element, used to reference it in the hastables and LRU linked list
      * @return The value of the element specified by the key
      */
-    public V get(Object key) {
-        CacheLine<V> line = getInternal(key, true);
+    protected V get(Object key, boolean noteAccess) {
+        CacheLine<V> line = getInternal(key, noteAccess);
         if (line == null) {
             return null;
         } else {
@@ -294,19 +332,6 @@
         return line;
     }
 
-    public Collection<V> values() {
-        if (cacheLineTable.isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        List<V> valuesList = FastList.newInstance();
-        for (K key: cacheLineTable.keySet()) {
-            valuesList.add(this.get(key));
-        }
-
-        return valuesList;
-    }
-
     public long getSizeInBytes() {
         long totalSize = 0;
         for (CacheLine<V> line: cacheLineTable.values()) {
@@ -535,7 +560,7 @@
      * This behavior is necessary for now for the persisted cache feature.
      */
     public Set<? extends K> getCacheLineKeys() {
-        return cacheLineTable.keySet();
+        return keySet();
     }
 
     public Collection<? extends CacheLine<V>> getCacheLineValues() {

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMap.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,190 @@
+/*******n***********************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+import org.ofbiz.base.util.Appender;
+import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.base.util.UtilObject;
+
+public abstract class GenericMap<K, V> implements Appender<StringBuilder>, Map<K, V>, Serializable {
+    private static final AtomicReferenceFieldUpdater<GenericMap, Set> keySetUpdater = AtomicReferenceFieldUpdater.newUpdater(GenericMap.class, Set.class, "keySet");
+    private static final AtomicReferenceFieldUpdater<GenericMap, Set> entrySetUpdater = AtomicReferenceFieldUpdater.newUpdater(GenericMap.class, Set.class, "entrySet");
+    private static final AtomicReferenceFieldUpdater<GenericMap, Collection> valuesUpdater = AtomicReferenceFieldUpdater.newUpdater(GenericMap.class, Collection.class, "values");
+
+    private volatile Set<K> keySet;
+    private volatile Set<Map.Entry<K, V>> entrySet;
+    private volatile Collection<V> values;
+
+    public boolean containsValue(Object value) {
+        return values().contains(value);
+    }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof Map)) return false;
+        if (this == o) return true;
+        Map map = (Map) o;
+        if (size() != map.size()) return false;
+        if (o instanceof GenericMap) return equalsGenericMap((GenericMap) o);
+        return equalsMap(map);
+    }
+
+    protected boolean equalsGenericMap(GenericMap map) {
+        Iterator<Map.Entry<K, V>> it = iterator(false);
+        while (it.hasNext()) {
+            Map.Entry<K, V> entry = it.next();
+            K key = entry.getKey();
+            V value = entry.getValue();
+            if (value != null) {
+                if (!value.equals(map.get(key, false))) return false;
+            } else {
+                Object otherValue = map.get(key, false);
+                if (otherValue != null) return false;
+                if (!map.containsKey(key)) return false;
+            }
+        }
+        return true;
+    }
+
+    protected boolean equalsMap(Map map) {
+        Iterator<Map.Entry<K, V>> it = iterator(false);
+        while (it.hasNext()) {
+            Map.Entry<K, V> entry = it.next();
+            K key = entry.getKey();
+            V value = entry.getValue();
+            if (value != null) {
+                if (!value.equals(map.get(key))) return false;
+            } else {
+                Object otherValue = map.get(key);
+                if (otherValue != null) return false;
+                if (!map.containsKey(key)) return false;
+            }
+        }
+        return true;
+    }
+
+    public final V get(Object key) {
+        return get(key, true);
+    }
+
+    protected abstract V get(Object key, boolean noteAccess);
+
+    public final Set<Map.Entry<K, V>> entrySet() {
+        if (entrySet == null) {
+            entrySetUpdater.compareAndSet(this, null, new GenericMapEntrySet<K, V, GenericMap<K, V>>(this) {
+                protected boolean contains(Object key, Object value) {
+                    return UtilObject.equalsHelper(get(key, false), value);
+                }
+
+                public Iterator<Map.Entry<K, V>> iterator(boolean noteAccess) {
+                    return GenericMap.this.iterator(noteAccess);
+                }
+            });
+        }
+        return entrySet;
+    }
+
+    protected abstract Iterator<Map.Entry<K, V>> iterator(boolean noteAccess);
+
+    public final Set<K> keySet() {
+        if (keySet == null) {
+            keySetUpdater.compareAndSet(this, null, new GenericMapKeySet<K, V, GenericMap<K, V>>(this) {
+                public boolean contains(Object key) {
+                    return containsKey(key);
+                }
+
+                public Iterator<K> iterator(boolean noteAccess) {
+                    return new IteratorWrapper<K, Map.Entry<K, V>>(GenericMap.this.iterator(noteAccess)) {
+                        protected void noteRemoval(K dest, Map.Entry<K, V> src) {
+                            // No need to note the remove, the wrapped iterator does that for us
+                            // evictionPolicy.remove(evictionDeque, dest);
+                            // if (diskStore != null) diskStore.remove(dest);
+                        }
+
+                        protected K convert(Map.Entry<K, V> src) {
+                            return src.getKey();
+                        }
+                    };
+                }
+            });
+        }
+        return keySet;
+    }
+
+    public final Collection<V> values() {
+        if (values == null) {
+            valuesUpdater.compareAndSet(this, null, new GenericMapValues<K, V, GenericMap<K, V>>(this) {
+                public Iterator<V> iterator(boolean noteAccess) {
+                    return new IteratorWrapper<V, Map.Entry<K, V>>(GenericMap.this.iterator(noteAccess)) {
+                        protected void noteRemoval(V dest, Map.Entry<K, V> src) {
+                            // No need to note the remove, the wrapped iterator does that for us
+                            // evictionPolicy.remove(evictionDeque, src.getKey());
+                            // if (diskStore != null) diskStore.remove(src.getKey());
+                        }
+
+                        protected V convert(Map.Entry<K, V> src) {
+                            return src.getValue();
+                        }
+                    };
+                }
+            });
+        }
+        return values;
+    }
+
+    public void putAll(Map<? extends K, ? extends V> map) {
+        putAllInternal(map);
+    }
+
+    private <KE extends K, VE extends V> void putAllInternal(Map<KE, VE> map) {
+        Iterator<Map.Entry<KE, VE>> it;
+        if (map instanceof GenericMap) {
+            GenericMap<KE, VE> otherMap = UtilGenerics.cast(map);
+            it = otherMap.iterator(false);
+        } else {
+            it = map.entrySet().iterator();
+        }
+        putAll(it);
+    }
+
+    protected abstract <KE extends K, VE extends V> void putAll(Iterator<Map.Entry<KE, VE>> it);
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        return appendTo(new StringBuilder()).toString();
+    }
+
+    public StringBuilder appendTo(StringBuilder sb) {
+        sb.append("{");
+        Iterator<Map.Entry<K, V>> it = iterator(false);
+        while (it.hasNext()) {
+            Map.Entry<K, V> entry = it.next();
+            sb.append(entry.getKey()).append("=").append(entry.getValue());
+            if (it.hasNext()) sb.append(",");
+        }
+        return sb.append("}");
+    }
+}
+

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapCollection.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapCollection.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapCollection.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapCollection.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javolution.util.FastList;
+
+import org.ofbiz.base.util.Appender;
+
+public abstract class GenericMapCollection<K, V, M extends Map<K, V>, I> implements Collection<I> {
+    protected final M source;
+
+    public GenericMapCollection(M source) {
+        this.source = source;
+    }
+
+    public boolean add(I item) {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean addAll(Collection<? extends I> collection) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void clear() {
+        source.clear();
+    }
+
+    public boolean containsAll(Collection<?> collection) {
+        int count = 0;
+        for (Object item: collection) {
+            if (!contains(item)) return false;
+        }
+        return true;
+    }
+
+    public boolean isEmpty() {
+        return source.isEmpty();
+    }
+
+    public final Iterator<I> iterator() {
+        return iterator(true);
+    }
+
+    protected abstract Iterator<I> iterator(boolean noteAccess);
+
+    public boolean removeAll(Collection<?> collection) {
+        int count = 0;
+        for (Object item: collection) {
+            if (remove(item)) count++;
+        }
+        return count > 0;
+    }
+
+    public boolean retainAll(Collection<?> collection) {
+        int count = 0;
+        Iterator<I> it = iterator(false);
+        while (it.hasNext()) {
+            I item = it.next();
+            if (!collection.contains(item)) {
+                it.remove();
+                count++;
+            }
+        }
+        return count > 0;
+    }
+
+    public int size() {
+        return source.size();
+    }
+
+    public Object[] toArray() {
+        List<I> list = FastList.newInstance();
+        Iterator<I> it = iterator(false);
+        while (it.hasNext()) {
+            list.add(it.next());
+        }
+        return list.toArray();
+    }
+
+    public <T> T[] toArray(T[] array) {
+        List<Object> list = FastList.newInstance();
+        Iterator<I> it = iterator(false);
+        while (it.hasNext()) {
+            list.add(it.next());
+        }
+        return list.toArray(array);
+    }
+
+    public String toString() {
+        return appendTo(new StringBuilder()).toString();
+    }
+
+    public StringBuilder appendTo(StringBuilder sb) {
+        sb.append("[");
+        Iterator<I> it = iterator(false);
+        while (it.hasNext()) {
+            sb.append(it.next());
+            if (it.hasNext()) sb.append(", ");
+        }
+        return sb.append("]");
+    }
+}
+

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntry.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntry.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntry.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntry.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Map;
+
+import org.ofbiz.base.util.UtilObject;
+
+public class GenericMapEntry<K, V> implements Map.Entry<K, V> {
+    protected final GenericMap<K, V> map;
+    protected final K key;
+    protected final boolean noteAccess;
+
+    public GenericMapEntry(GenericMap<K, V> map, K key, boolean noteAccess) {
+        this.map = map;
+        this.key = key;
+        this.noteAccess = noteAccess;
+    }
+
+    public K getKey() {
+        return key;
+    }
+
+    public V getValue() {
+        return map.get(key, noteAccess);
+    }
+
+    public V setValue(V value) {
+        return map.put(key, value);
+    }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof Map.Entry)) return false;
+        if (this == o) return true;
+        Map.Entry other = (Map.Entry) o;
+        return UtilObject.equalsHelper(getKey(), other.getKey()) && UtilObject.equalsHelper(getValue(), other.getValue());
+    }
+
+    public int hashCode() {
+        return UtilObject.doHashCode(getKey()) ^ UtilObject.doHashCode(getValue());
+    }
+}

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntrySet.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntrySet.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntrySet.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapEntrySet.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Map;
+import java.util.Set;
+
+public abstract class GenericMapEntrySet<K, V, M extends GenericMap<K, V>> extends GenericMapSet<K, V, M, Map.Entry<K, V>> {
+    public GenericMapEntrySet(M source) {
+        super(source);
+    }
+
+    public boolean contains(Object item) {
+        if (item == null) return false;
+        if (!(item instanceof Map.Entry)) return false;
+        Map.Entry other = (Map.Entry) item;
+        return contains(other.getKey(), other.getValue());
+    }
+
+    protected abstract boolean contains(Object key, Object value);
+
+    public boolean remove(Object item) {
+        if (item == null) return false;
+        if (!(item instanceof Map.Entry)) return false;
+        Map.Entry other = (Map.Entry) item;
+        Object key = other.getKey();
+        if (!source.containsKey(key)) return false;
+        source.remove(key);
+        return true;
+    }
+}
+

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapKeySet.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapKeySet.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapKeySet.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapKeySet.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Map;
+import java.util.Set;
+
+public abstract class GenericMapKeySet<K, V, M extends Map<K, V>> extends GenericMapSet<K, V, M, K> {
+    public GenericMapKeySet(M source) {
+        super(source);
+    }
+
+    public boolean remove(Object item) {
+        return source.remove(item) != null;
+    }
+}
+

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapSet.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapSet.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapSet.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapSet.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Map;
+import java.util.Set;
+
+public abstract class GenericMapSet<K, V, M extends Map<K, V>, I> extends GenericMapCollection<K, V, M, I> implements Set<I> {
+    public GenericMapSet(M source) {
+        super(source);
+    }
+
+    public final boolean equals(Object o) {
+        if (!(o instanceof Set)) return false;
+        Set other = (Set) o;
+        if (source.size() != other.size()) return false;
+        for (I item: this) {
+            if (!other.contains(item)) return false;
+        }
+        return true;
+    }
+
+    public final int hashCode() {
+        int h = 0;
+        for (I item: this) {
+            if (item == null) continue;
+            h += item.hashCode();
+        }
+        return h;
+    }
+}
+

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapValues.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapValues.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapValues.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/GenericMapValues.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.ofbiz.base.util.UtilObject;
+
+public abstract class GenericMapValues<K, V, M extends Map<K, V>> extends GenericMapCollection<K, V, M, V> {
+    public GenericMapValues(M source) {
+        super(source);
+    }
+
+    public boolean contains(Object item) {
+        Iterator<V> it = iterator(false);
+        while (it.hasNext()) {
+            if (UtilObject.equalsHelper(item, it.next())) return true;
+        }
+        return false;
+    }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof Collection)) return false;
+        if (o instanceof List || o instanceof Set) return false;
+        Collection other = (Collection) o;
+        if (source.size() != other.size()) return false;
+        Iterator<V> it = iterator(false);
+        while (it.hasNext()) {
+            V item = it.next();
+            if (!other.contains(item)) return false;
+        }
+        return true;
+    }
+
+    public int hashCode() {
+        int h = 0;
+        Iterator<V> it = iterator(false);
+        while (it.hasNext()) {
+            V item = it.next();
+            if (item == null) continue;
+            h += item.hashCode();
+        }
+        return h;
+    }
+
+    public boolean remove(Object item) {
+        Iterator<V> it = iterator(false);
+        while (it.hasNext()) {
+            if (UtilObject.equalsHelper(item, it.next())) {
+                it.remove();
+                return true;
+            }
+        }
+        return false;
+    }
+}
+

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/IteratorWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/IteratorWrapper.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/IteratorWrapper.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/IteratorWrapper.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public abstract class IteratorWrapper<DEST, SRC> implements Iterator<DEST> {
+    private final Iterator<? extends SRC> it;
+    private DEST lastDest;
+    private SRC lastSrc;
+
+    protected IteratorWrapper(Iterator<? extends SRC> it) {
+        this.it = it;
+    }
+
+    public boolean hasNext() {
+        return it.hasNext();
+    }
+
+    public DEST next() {
+        try {
+            lastSrc = it.next();
+            return lastDest = convert(lastSrc);
+        } catch (NoSuchElementException e) {
+            lastDest = null;
+            lastSrc = null;
+            throw e;
+        }
+    }
+
+    public void remove() {
+        if (lastSrc != null) {
+            it.remove();
+            noteRemoval(lastDest, lastSrc);
+            lastDest = null;
+            lastSrc = null;
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+
+    protected abstract void noteRemoval(DEST dest, SRC src);
+    protected abstract DEST convert(SRC src);
+}
+

Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/ReadOnlyMapEntry.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/ReadOnlyMapEntry.java?rev=885275&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/ReadOnlyMapEntry.java (added)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/collections/ReadOnlyMapEntry.java Sun Nov 29 21:26:37 2009
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.base.util.collections;
+
+import java.util.Map;
+
+import org.ofbiz.base.util.UtilObject;
+
+/** this class can go away when ofbiz switches to java 1.6, replaced by
+ *  AbstractMap.SimpleImmutableEntry
+ */
+public class ReadOnlyMapEntry<K, V> implements Map.Entry<K, V> {
+    protected final K key;
+    protected final V value;
+
+    public ReadOnlyMapEntry(K key, V value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    public K getKey() {
+        return key;
+    }
+
+    public V getValue() {
+        return value;
+    }
+
+    public V setValue(V value) {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof Map.Entry)) return false;
+        if (this == o) return true;
+        Map.Entry other = (Map.Entry) o;
+        return UtilObject.equalsHelper(getKey(), other.getKey()) && UtilObject.equalsHelper(getValue(), other.getValue());
+    }
+
+    public int hashCode() {
+        return UtilObject.doHashCode(getKey()) ^ UtilObject.doHashCode(getValue());
+    }
+}