[jboss-cvs] JBossCache/src/org/jboss/cache/util ...
Elias Ross
genman at noderunner.net
Wed Feb 7 17:06:42 EST 2007
User: genman
Date: 07/02/07 17:06:42
Modified: src/org/jboss/cache/util MapCopy.java
Added: src/org/jboss/cache/util Caches.java SimpleEntry.java
Log:
JBCACHE-969 - Move transaction classes to org.jboss.cache.transaction
Revision Changes Path
1.8 +4 -54 JBossCache/src/org/jboss/cache/util/MapCopy.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: MapCopy.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/util/MapCopy.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- MapCopy.java 3 Jan 2007 16:42:34 -0000 1.7
+++ MapCopy.java 7 Feb 2007 22:06:42 -0000 1.8
@@ -40,6 +40,10 @@
init();
}
+ public MapCopy() {
+ this(new java.util.HashMap());
+ }
+
private void init()
{
this.entrySet = new AbstractSet<Map.Entry<K, V>>()
@@ -76,60 +80,6 @@
}
}
- /**
- * Where is Java 1.6?
- */
- private static class SimpleEntry<K, V> implements Map.Entry<K, V>, Serializable
- {
- private static final long serialVersionUID = -6092752114794052323L;
-
- private K key;
-
- private V value;
-
- public SimpleEntry(Entry<K, V> me)
- {
- key = me.getKey();
- value = me.getValue();
- }
-
- public K getKey()
- {
- return key;
- }
-
- public V getValue()
- {
- return value;
- }
-
- public V setValue(V arg0)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean equals(Object o)
- {
- Map.Entry e2 = (Map.Entry) o;
- return (getKey() == null ? e2.getKey() == null : getKey().equals(e2.getKey()))
- && (getValue() == null ? e2.getValue() == null : getValue().equals(e2.getValue()));
- }
-
- @Override
- public int hashCode()
- {
- return (getKey() == null ? 0 : getKey().hashCode()) ^
- (getValue() == null ? 0 : getValue().hashCode());
- }
-
- @Override
- public String toString()
- {
- return key + "=" + value;
- }
- }
-
@Override
public Set entrySet()
{
1.1 date: 2007/02/07 22:06:42; author: genman; state: Exp;JBossCache/src/org/jboss/cache/util/Caches.java
Index: Caches.java
===================================================================
package org.jboss.cache.util;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.loader.CacheLoader;
import org.jboss.cache.pojo.collection.IntegerCache;
/**
* Adaptors for {@link Cache} classes, such as {@link Node}.
* This is useful for integration of JBoss Cache into existing applications.
*
* Example use:
* <pre>
* Cache c = ...;
* Map m = Caches.asMap(c);
* m.put("a", "b"); // null
* m.containsKey("a"); // true
* m.remove("a"); // "b"
* </pre>
*/
public class Caches
{
private Caches()
{
}
/**
* Returns a {@link Map} from the root node.
* @see #asMap(Node)
*/
public static Map asMap(Cache cache)
{
if (cache == null)
throw new NullPointerException("cache");
return asMap(cache.getRoot());
}
/**
* Returns a {@link Map}, where map keys are named children of the given Node,
* and values are kept under a single key for this node.
* The map may be safely concurrently modified through this Map or externally,
* and its contents reflect the cache state and
* existing data of the Node.
* This means that {@link ConcurrentModificationException} is never thrown
* and all methods are thread safe.
* <p/>
* The map is not serializable.
* <p/>
* Usage note: As a single node is used for every key, it is most efficient to store
* data for a single entity (e.g. Person) in a single object.
* <p/>
* Also, when using a {@link CacheLoader} for storage, keys used must be valid as
* part of the {@link Fqn} used in calls. Generally speaking, simple string values are
* preferred.
*/
public static Map asMap(Node node)
{
return new MapNode(node);
}
/**
* Returns a {@link Map}, where map data is put and returned directly from a single Node.
* This method is "simple" as data is kept under a single node.
* Note that storing all data in a single Node can be inefficient when using persistence,
* replication, or transactions.
* The map may be safely concurrently modified through this Map or externally.
* This means that {@link ConcurrentModificationException} is never thrown
* and all methods are thread safe.
* <p/>
* The methods {@link Map#entrySet} and {@link Map#values} and {@link Map#keySet}
* do not allow for modification of the Node.
* Further all these methods return a collection which is a snapshot (copy)
* of the data at time of calling. This may be very inefficient.
* <p/>
* The map is not serializable.
*/
public static Map asSimpleMap(Node node)
{
return new SimpleMapNode(node);
}
/**
* Returns a {@link Set}, where set entries are data entries of the given Node.
* This method is "simple" as data is kept under a single node.
* <p/>
* Note that storing all data in a single Node can be inefficient when using persistence,
* replication, or transactions.
* The set may be safely concurrently modified through this Map or externally.
* This means that {@link ConcurrentModificationException} is never thrown
* and all methods are thread safe.
* <p/>
* The set is not serializable.
*/
public static Set asSimpleSet(Node node)
{
return new SimpleSetNode(node);
}
/**
* Returns a {@link Map}, where map entries are partitioned into
* children nodes, within a cache node.
* The default child selector divides the data into 16 child nodes based on hash code.
* Note that for large data sets, the number of child nodes should be increased.
*
* @param node node to cache under
*/
public static Map asPartitionedMap(Node node)
{
return new PartitionedMapNode(node, HashKeySelector.DEFAULT);
}
/**
* Returns a {@link Map}, where map entries are partitioned
* into children, within a cache node, by key hash code.
* <p/>
* The map is not serializable.
* <p/>
* Usage note: This is a performance (and size) compromise between {@link #asMap(Node)}
* and {@link #asSimpleMap(Node)}. For applications using a {@link org.jboss.cache.CacheLoader},
* {@link #asMap(Node)} is a better choice.
* <p/>
*
* @param node node to cache under
* @param selector selector strategy that chooses a segment based on key
*/
public static Map asPartitionedMap(Node node, ChildSelector selector)
{
return new PartitionedMapNode(node, selector);
}
/**
* Returns a {@link Map}, where map entries are partitioned into child nodes,
* within the cache root, by key hash code.
*
* @param cache cache to use
* @return
*/
public static Map asPartitionedMap(Cache cache)
{
return asPartitionedMap(cache.getRoot());
}
/**
* Returns a segment ({@link Node#getChild(Object) child node name})
* to use based on the characteristics of a key.
* <p/>
* Here is an example class which selects a child based on a person's department:
<pre>
public static class DepartmentSelector implements ChildSelector<Person>
{
public Object childName(Person key)
{
return key.getDepartment();
}
}
</pre>
* @
*/
public interface ChildSelector<T>
{
/**
* Returns a child node name for a key.
* @param key for calls to {@link Map#put}, {@link Map#get} etc.
* @return node name
*/
Object childName(T key);
}
/**
* Class that returns a child name to use based on the hash code of a key.
*/
public static class HashKeySelector implements ChildSelector
{
static ChildSelector DEFAULT = new HashKeySelector(16);
protected int segments;
/**
* Constructs with N segments, where N must be a power of 2.
*/
public HashKeySelector(int segments)
{
this.segments = segments;
if (Integer.bitCount(segments) != 1)
throw new IllegalArgumentException();
if (segments <= 0)
throw new IllegalArgumentException();
}
/**
* Computes an improved hash code from an object's hash code.
*/
protected int hashCode(int i)
{
i ^= i >>> 20 ^ i >>> 12;
return i ^ i >>> 7 ^ i >>> 4;
}
/**
* Returns the segment for this key, in the inclusive range 0 to {@link #segments} - 1.
*/
protected int segmentFor(Object key)
{
if (key == null)
return 0;
int hc = key.hashCode();
return hashCode(hc) & (segments - 1);
}
/**
* Returns the node name for this segment.
*/
protected Object childName(int segment)
{
return IntegerCache.toString(segment);
}
/**
* Returns the node name for this key.
* By default, returns a String containing the segment.
*/
public Object childName(Object key)
{
return childName(segmentFor(key));
}
public String toString()
{
return super.toString() + " segments=" + segments;
}
}
static class MapNode extends AbstractMap
{
public static final String KEY = "K";
private Node node;
public MapNode(Node node)
{
if (node == null)
throw new NullPointerException("node");
this.node = node;
}
@Override
public Set entrySet()
{
return new AbstractSet()
{
@Override
public Iterator iterator()
{
final Iterator<Node> i = set().iterator();
return new Iterator()
{
Object name;
boolean next = false;
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
Node n = i.next();
this.name = n.getFqn().getLastElement();
this.next = true;
Object key = n.get(KEY);
return new SimpleEntry(name, key);
}
public void remove()
{
if (!next)
throw new IllegalStateException();
node.removeChild(name);
}
public String toString()
{
return "Itr name=" + name;
}
};
}
private Set<Node> set()
{
return node.getChildren();
}
@Override
public int size()
{
return set().size();
}
};
}
@Override
public void clear()
{
for (Object o : node.getChildrenNames())
node.removeChild(o);
}
@Override
public boolean containsKey(Object arg0)
{
return node.getChild(arg0) != null;
}
@Override
public Object get(Object arg0)
{
Node child = node.getChild(arg0);
if (child == null)
return null;
return child.get(KEY);
}
@Override
public boolean isEmpty()
{
return node.getChildrenNames().isEmpty();
}
@Override
public Set keySet()
{
return new AbstractSet()
{
private Set set()
{
return node.getChildrenNames();
}
@Override
public Iterator iterator()
{
final Iterator i = set().iterator();
return new Iterator()
{
Object child;
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
child = i.next();
return child;
}
public void remove()
{
if (child == null)
throw new IllegalStateException();
node.removeChild(child);
// since set is read-only, invalidate
}
};
}
@Override
public boolean remove(Object key)
{
return node.removeChild(key);
}
@Override
public int size()
{
return set().size();
}
};
}
@Override
public Object put(Object arg0, Object arg1)
{
return node.addChild(new Fqn(arg0)).put(KEY, arg1);
}
@Override
public Object remove(Object arg0)
{
Node child = node.getChild(arg0);
if (child == null)
return null;
Object o = child.remove(KEY);
node.removeChild(arg0);
return o;
}
@Override
public int size()
{
return node.getChildrenNames().size();
}
}
static class SimpleMapNode extends AbstractMap implements java.util.Map
{
private Node node;
public SimpleMapNode(Node node)
{
if (node == null)
throw new NullPointerException("node");
this.node = node;
}
@Override
public void clear()
{
node.clearData();
}
@Override
public boolean containsKey(Object key)
{
return node.getKeys().contains(key);
}
@Override
public boolean containsValue(Object value)
{
return node.getData().containsValue(value);
}
/**
* getData returns a snapshot of the data.
*/
public Set entrySet()
{
return node.getData().entrySet();
}
@Override
public Object get(Object key)
{
return node.get(key);
}
@Override
public Set keySet()
{
return node.getKeys();
}
@Override
public Object put(Object key, Object value)
{
return node.put(key, value);
}
@Override
public void putAll(Map map)
{
node.putAll(map);
}
@Override
public Object remove(Object key)
{
return node.remove(key);
}
@Override
public int size()
{
return node.dataSize();
}
}
static class SimpleSetNode extends AbstractSet implements java.util.Set
{
private Node node;
private static final Boolean VALUE = Boolean.TRUE;
public SimpleSetNode(Node node)
{
if (node == null)
throw new NullPointerException("node");
this.node = node;
}
@Override
public void clear()
{
node.clearData();
}
@Override
public boolean contains(Object key)
{
return node.getKeys().contains(key);
}
@Override
public boolean remove(Object key)
{
return node.remove(key) != null;
}
@Override
public int size()
{
return node.dataSize();
}
@Override
public boolean add(Object arg0)
{
return node.put(arg0, VALUE) == null;
}
@Override
public Iterator iterator()
{
final Iterator i = node.getKeys().iterator();
return new Iterator()
{
Object key;
boolean next = false;
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
key = i.next();
next = true;
return key;
}
public void remove()
{
if (!next)
throw new IllegalStateException();
node.remove(key);
}
};
}
}
static class PartitionedMapNode extends AbstractMap
{
private Node node;
private ChildSelector selector;
public PartitionedMapNode(Node node, ChildSelector selector)
{
if (node == null)
throw new IllegalArgumentException("node");
if (selector == null)
throw new IllegalArgumentException("selector");
this.node = node;
this.selector = selector;
}
@Override
public Set entrySet()
{
return new AbstractSet<Map.Entry>()
{
Iterator<Node> ci = node.getChildren().iterator();
@Override
public Iterator<Entry> iterator()
{
return new Iterator<Entry>()
{
Iterator ni;
{
nextChild();
findNext();
}
private void nextChild()
{
ni = new SimpleMapNode(ci.next()).entrySet().iterator();
}
private void findNext()
{
while (!ni.hasNext())
{
if (!ci.hasNext())
return;
nextChild();
}
}
public boolean hasNext()
{
return ni.hasNext();
}
public Entry next()
{
Entry n = (Entry) ni.next();
findNext();
return n;
}
public void remove()
{
ni.remove();
}
};
}
@Override
public int size()
{
return PartitionedMapNode.this.size();
}
};
}
@Override
public Set keySet()
{
return new AbstractSet<Map.Entry>()
{
@Override
public Iterator<Entry> iterator()
{
return PartitionedMapNode.super.keySet().iterator();
}
@Override
public boolean remove(Object o)
{
boolean key = PartitionedMapNode.this.containsKey(o);
PartitionedMapNode.this.remove(o);
return key;
}
@Override
public boolean contains(Object o)
{
return PartitionedMapNode.this.containsKey(o);
}
@Override
public int size()
{
return PartitionedMapNode.this.size();
}
};
}
@Override
public void clear()
{
for (Object childName : node.getChildrenNames())
node.removeChild(childName);
}
private Node nodeFor(Object o)
{
return node.getChild(selector.childName(o));
}
@Override
public boolean containsKey(Object o)
{
Node n = nodeFor(o);
if (n == null) return false;
return n.getKeys().contains(o);
}
@Override
public Object get(Object o)
{
Node n = nodeFor(o);
if (n == null) return null;
return n.get(o);
}
@Override
public Object put(Object key, Object value)
{
Object name = selector.childName(key);
Node n = node.getChild(name);
if (n == null)
n = node.addChild(new Fqn(name));
return n.put(key, value);
}
@Override
public Object remove(Object o)
{
Node n = nodeFor(o);
if (n == null)
return null;
return n.remove(o);
}
/**
* Removes nodes without any data.
*/
public void clean()
{
for (Node n : node.getChildren())
{
if (n.dataSize() == 0)
node.removeChild(n.getFqn().getLastElement());
}
}
@Override
public int size()
{
int size = 0;
for (Object o : node.getChildrenNames())
{
Node child = node.getChild(o);
size += child.dataSize();
}
return size;
}
}
}
1.1 date: 2007/02/07 22:06:42; author: genman; state: Exp;JBossCache/src/org/jboss/cache/util/SimpleEntry.java
Index: SimpleEntry.java
===================================================================
package org.jboss.cache.util;
import java.io.Serializable;
import java.util.Map;
import java.util.Map.Entry;
/**
* Where is Java 1.6?
*/
class SimpleEntry<K, V> implements Map.Entry<K, V>, Serializable
{
private static final long serialVersionUID = -6092752114794052323L;
private K key;
private V value;
public SimpleEntry(Entry<K, V> me)
{
key = me.getKey();
value = me.getValue();
}
public SimpleEntry(K key, V value)
{
this.key = key;
this.value = value;
}
public K getKey()
{
return key;
}
public V getValue()
{
return value;
}
public V setValue(V arg0)
{
throw new UnsupportedOperationException();
}
@Override
public boolean equals(Object o)
{
Map.Entry e2 = (Map.Entry) o;
return (getKey() == null ? e2.getKey() == null : getKey().equals(e2.getKey()))
&& (getValue() == null ? e2.getValue() == null : getValue().equals(e2.getValue()));
}
@Override
public int hashCode()
{
return (getKey() == null ? 0 : getKey().hashCode()) ^
(getValue() == null ? 0 : getValue().hashCode());
}
@Override
public String toString()
{
return key + "=" + value;
}
}
More information about the jboss-cvs-commits
mailing list