mirror of https://github.com/apache/openjpa.git
Move to dynamically-created bytecode proxies for second class objects, rather
than checked-in proxy classes. This allows us to proxy custom collection, map, and bean types. git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@484693 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
db25f08565
commit
e54b0c1908
|
@ -19,7 +19,6 @@ import java.sql.SQLException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCStore;
|
import org.apache.openjpa.jdbc.kernel.JDBCStore;
|
||||||
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
||||||
|
@ -50,10 +49,9 @@ public class LRSProxyCollection
|
||||||
|
|
||||||
private final LRSCollectionFieldStrategy _strat;
|
private final LRSCollectionFieldStrategy _strat;
|
||||||
|
|
||||||
public LRSProxyCollection(LRSCollectionFieldStrategy strat,
|
public LRSProxyCollection(LRSCollectionFieldStrategy strat) {
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
super(strat.getFieldMapping().getElement().getDeclaredType(),
|
super(strat.getFieldMapping().getElement().getDeclaredType(),
|
||||||
strat.getFieldMapping().getOrderColumn() != null, conf);
|
strat.getFieldMapping().getOrderColumn() != null);
|
||||||
_strat = strat;
|
_strat = strat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCStore;
|
import org.apache.openjpa.jdbc.kernel.JDBCStore;
|
||||||
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
||||||
|
@ -53,9 +52,9 @@ class LRSProxyMap
|
||||||
|
|
||||||
private final LRSMapFieldStrategy _strat;
|
private final LRSMapFieldStrategy _strat;
|
||||||
|
|
||||||
public LRSProxyMap(LRSMapFieldStrategy strat, OpenJPAConfiguration conf) {
|
public LRSProxyMap(LRSMapFieldStrategy strat) {
|
||||||
super(strat.getFieldMapping().getKey().getDeclaredType(),
|
super(strat.getFieldMapping().getKey().getDeclaredType(),
|
||||||
strat.getFieldMapping().getElement().getDeclaredType(), conf);
|
strat.getFieldMapping().getElement().getDeclaredType());
|
||||||
_strat = strat;
|
_strat = strat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,7 @@ public abstract class MapTableFieldStrategy
|
||||||
JDBCFetchConfiguration fetch)
|
JDBCFetchConfiguration fetch)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
if (field.isLRS()) {
|
if (field.isLRS()) {
|
||||||
sm.storeObjectField(field.getIndex(), new LRSProxyMap(this,
|
sm.storeObjectField(field.getIndex(), new LRSProxyMap(this));
|
||||||
store.getConfiguration()));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,8 @@ public class RelationCollectionInverseKeyFieldStrategy
|
||||||
return super.joinElementRelation(joins, elem);
|
return super.joinElementRelation(joins, elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
|
protected Proxy newLRSProxy() {
|
||||||
return new LRSProxyCollection(this, conf);
|
return new LRSProxyCollection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void map(boolean adapt) {
|
public void map(boolean adapt) {
|
||||||
|
|
|
@ -80,8 +80,8 @@ public class RelationCollectionTableFieldStrategy
|
||||||
return super.joinElementRelation(joins, elem);
|
return super.joinElementRelation(joins, elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
|
protected Proxy newLRSProxy() {
|
||||||
return new LRSProxyCollection(this, conf);
|
return new LRSProxyCollection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void map(boolean adapt) {
|
public void map(boolean adapt) {
|
||||||
|
|
|
@ -140,8 +140,8 @@ public class RelationMapInverseKeyFieldStrategy
|
||||||
return joinElementRelation(joins, val);
|
return joinElementRelation(joins, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
|
protected Proxy newLRSProxy() {
|
||||||
return new LRSProxyMap(this, conf);
|
return new LRSProxyMap(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void add(JDBCStore store, Object coll, Object obj) {
|
protected void add(JDBCStore store, Object coll, Object obj) {
|
||||||
|
|
|
@ -140,8 +140,8 @@ public class RelationMapTableFieldStrategy
|
||||||
return joinElementRelation(joins, val);
|
return joinElementRelation(joins, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Proxy newLRSProxy(OpenJPAConfiguration conf) {
|
protected Proxy newLRSProxy() {
|
||||||
return new LRSProxyMap(this, conf);
|
return new LRSProxyMap(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void add(JDBCStore store, Object coll, Object obj) {
|
protected void add(JDBCStore store, Object coll, Object obj) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
/**
|
/**
|
||||||
* Return a large result set proxy for this field.
|
* Return a large result set proxy for this field.
|
||||||
*/
|
*/
|
||||||
protected abstract Proxy newLRSProxy(OpenJPAConfiguration conf);
|
protected abstract Proxy newLRSProxy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the field value to a collection. Handles collections and
|
* Convert the field value to a collection. Handles collections and
|
||||||
|
@ -409,7 +409,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
final JDBCFetchConfiguration fetch)
|
final JDBCFetchConfiguration fetch)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
if (field.isLRS()) {
|
if (field.isLRS()) {
|
||||||
Proxy coll = newLRSProxy(store.getConfiguration());
|
Proxy coll = newLRSProxy();
|
||||||
|
|
||||||
// if this is ordered we need to know the next seq to use in case
|
// if this is ordered we need to know the next seq to use in case
|
||||||
// objects are added to the collection
|
// objects are added to the collection
|
||||||
|
|
|
@ -123,6 +123,7 @@ class SingleFieldManager
|
||||||
proxy = getProxyManager().newCustomProxy(objval);
|
proxy = getProxyManager().newCustomProxy(objval);
|
||||||
ret = proxy != null;
|
ret = proxy != null;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy != null) {
|
if (proxy != null) {
|
||||||
|
|
|
@ -18,9 +18,9 @@ package org.apache.openjpa.util;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections.map.IdentityMap;
|
|
||||||
import org.apache.commons.collections.set.MapBackedSet;
|
import org.apache.commons.collections.set.MapBackedSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,7 +184,7 @@ public abstract class AbstractChangeTracker
|
||||||
*/
|
*/
|
||||||
protected Set newSet() {
|
protected Set newSet() {
|
||||||
if (_identity == Boolean.TRUE)
|
if (_identity == Boolean.TRUE)
|
||||||
return MapBackedSet.decorate(new IdentityMap());
|
return MapBackedSet.decorate(new IdentityHashMap());
|
||||||
return new HashSet();
|
return new HashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ public abstract class AbstractChangeTracker
|
||||||
if (identity && cur instanceof HashSet) {
|
if (identity && cur instanceof HashSet) {
|
||||||
if (cur.isEmpty())
|
if (cur.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
Set replace = MapBackedSet.decorate(new IdentityMap());
|
Set replace = MapBackedSet.decorate(new IdentityHashMap());
|
||||||
replace.addAll(cur);
|
replace.addAll(cur);
|
||||||
return replace;
|
return replace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.util.Set;
|
||||||
import org.apache.commons.collections.Predicate;
|
import org.apache.commons.collections.Predicate;
|
||||||
import org.apache.commons.collections.iterators.FilterIterator;
|
import org.apache.commons.collections.iterators.FilterIterator;
|
||||||
import org.apache.commons.collections.iterators.IteratorChain;
|
import org.apache.commons.collections.iterators.IteratorChain;
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||||
import org.apache.openjpa.lib.util.Closeable;
|
import org.apache.openjpa.lib.util.Closeable;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
@ -65,10 +64,9 @@ public abstract class AbstractLRSProxyCollection
|
||||||
* restrictions
|
* restrictions
|
||||||
* @param ordered true if this collection is ordered
|
* @param ordered true if this collection is ordered
|
||||||
*/
|
*/
|
||||||
public AbstractLRSProxyCollection(Class elementType, boolean ordered,
|
public AbstractLRSProxyCollection(Class elementType, boolean ordered) {
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_elementType = elementType;
|
_elementType = elementType;
|
||||||
_ct = new CollectionChangeTrackerImpl(this, false, ordered, conf);
|
_ct = new CollectionChangeTrackerImpl(this, false, ordered);
|
||||||
_ct.setAutoOff(false);
|
_ct.setAutoOff(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +107,13 @@ public abstract class AbstractLRSProxyCollection
|
||||||
|
|
||||||
public boolean add(Object o) {
|
public boolean add(Object o) {
|
||||||
Proxies.assertAllowedType(o, _elementType);
|
Proxies.assertAllowedType(o, _elementType);
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
_ct.added(o);
|
_ct.added(o);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addAll(Collection all) {
|
public boolean addAll(Collection all) {
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
Object add;
|
Object add;
|
||||||
for (Iterator itr = all.iterator(); itr.hasNext();) {
|
for (Iterator itr = all.iterator(); itr.hasNext();) {
|
||||||
|
@ -130,14 +128,14 @@ public abstract class AbstractLRSProxyCollection
|
||||||
public boolean remove(Object o) {
|
public boolean remove(Object o) {
|
||||||
if (!contains(o))
|
if (!contains(o))
|
||||||
return false;
|
return false;
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
Proxies.removed(this, o, false);
|
Proxies.removed(this, o, false);
|
||||||
_ct.removed(o);
|
_ct.removed(o);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeAll(Collection all) {
|
public boolean removeAll(Collection all) {
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
Object rem;
|
Object rem;
|
||||||
for (Iterator itr = all.iterator(); itr.hasNext();) {
|
for (Iterator itr = all.iterator(); itr.hasNext();) {
|
||||||
|
@ -157,7 +155,7 @@ public abstract class AbstractLRSProxyCollection
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
Itr itr = (Itr) iterator();
|
Itr itr = (Itr) iterator();
|
||||||
try {
|
try {
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
|
@ -177,7 +175,7 @@ public abstract class AbstractLRSProxyCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
Itr itr = (Itr) iterator();
|
Itr itr = (Itr) iterator();
|
||||||
try {
|
try {
|
||||||
Object rem;
|
Object rem;
|
||||||
|
@ -394,7 +392,7 @@ public abstract class AbstractLRSProxyCollection
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (_state == CLOSED || _last == null)
|
if (_state == CLOSED || _last == null)
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
Proxies.dirty(AbstractLRSProxyCollection.this);
|
Proxies.dirty(AbstractLRSProxyCollection.this, false);
|
||||||
_ct.removed(_last);
|
_ct.removed(_last);
|
||||||
Proxies.removed(AbstractLRSProxyCollection.this, _last, false);
|
Proxies.removed(AbstractLRSProxyCollection.this, _last, false);
|
||||||
_last = null;
|
_last = null;
|
||||||
|
|
|
@ -68,11 +68,10 @@ public abstract class AbstractLRSProxyMap
|
||||||
private int _count = -1;
|
private int _count = -1;
|
||||||
private boolean _iterated = false;
|
private boolean _iterated = false;
|
||||||
|
|
||||||
public AbstractLRSProxyMap(Class keyType, Class valueType,
|
public AbstractLRSProxyMap(Class keyType, Class valueType) {
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_keyType = keyType;
|
_keyType = keyType;
|
||||||
_valueType = valueType;
|
_valueType = valueType;
|
||||||
_ct = new MapChangeTrackerImpl(this, conf);
|
_ct = new MapChangeTrackerImpl(this);
|
||||||
_ct.setAutoOff(false);
|
_ct.setAutoOff(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +195,7 @@ public abstract class AbstractLRSProxyMap
|
||||||
public Object put(Object key, Object value) {
|
public Object put(Object key, Object value) {
|
||||||
Proxies.assertAllowedType(key, _keyType);
|
Proxies.assertAllowedType(key, _keyType);
|
||||||
Proxies.assertAllowedType(value, _valueType);
|
Proxies.assertAllowedType(value, _valueType);
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
if (_map == null)
|
if (_map == null)
|
||||||
_map = new HashMap();
|
_map = new HashMap();
|
||||||
Object old = _map.put(key, value);
|
Object old = _map.put(key, value);
|
||||||
|
@ -220,7 +219,7 @@ public abstract class AbstractLRSProxyMap
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object remove(Object key) {
|
public Object remove(Object key) {
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
Object old = (_map == null) ? null : _map.remove(key);
|
Object old = (_map == null) ? null : _map.remove(key);
|
||||||
if (old == null && (!_ct.getTrackKeys()
|
if (old == null && (!_ct.getTrackKeys()
|
||||||
|| !_ct.getRemoved().contains(key)))
|
|| !_ct.getRemoved().contains(key)))
|
||||||
|
@ -234,7 +233,7 @@ public abstract class AbstractLRSProxyMap
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
Proxies.dirty(this);
|
Proxies.dirty(this, false);
|
||||||
Itr itr = iterator(MODE_ENTRY);
|
Itr itr = iterator(MODE_ENTRY);
|
||||||
try {
|
try {
|
||||||
Map.Entry entry;
|
Map.Entry entry;
|
||||||
|
@ -482,7 +481,7 @@ public abstract class AbstractLRSProxyMap
|
||||||
if (_state == CLOSED || _last == null)
|
if (_state == CLOSED || _last == null)
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
|
|
||||||
Proxies.dirty(AbstractLRSProxyMap.this);
|
Proxies.dirty(AbstractLRSProxyMap.this, false);
|
||||||
Proxies.removed(AbstractLRSProxyMap.this, _last.getKey(), true);
|
Proxies.removed(AbstractLRSProxyMap.this, _last.getKey(), true);
|
||||||
Proxies.removed(AbstractLRSProxyMap.this, _last.getValue(), false);
|
Proxies.removed(AbstractLRSProxyMap.this, _last.getValue(), false);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@ package org.apache.openjpa.util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default {@link CollectionChangeTracker}.
|
* Default {@link CollectionChangeTracker}.
|
||||||
*
|
*
|
||||||
|
@ -42,12 +40,26 @@ public class CollectionChangeTrackerImpl
|
||||||
* @param order true if the collection is ordered, false otherwise
|
* @param order true if the collection is ordered, false otherwise
|
||||||
*/
|
*/
|
||||||
public CollectionChangeTrackerImpl(Collection coll, boolean dups,
|
public CollectionChangeTrackerImpl(Collection coll, boolean dups,
|
||||||
boolean order, OpenJPAConfiguration conf) {
|
boolean order) {
|
||||||
_coll = coll;
|
_coll = coll;
|
||||||
_dups = dups;
|
_dups = dups;
|
||||||
_order = order;
|
_order = order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the underlying collection allows duplicates.
|
||||||
|
*/
|
||||||
|
public boolean allowsDuplicates() {
|
||||||
|
return _dups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the underlying collection is ordered.
|
||||||
|
*/
|
||||||
|
public boolean isOrdered() {
|
||||||
|
return _order;
|
||||||
|
}
|
||||||
|
|
||||||
public void added(Object elem) {
|
public void added(Object elem) {
|
||||||
super.added(elem);
|
super.added(elem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,6 @@ package org.apache.openjpa.util;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default {@link MapChangeTracker}.
|
* Default {@link MapChangeTracker}.
|
||||||
*
|
*
|
||||||
|
@ -35,7 +33,7 @@ public class MapChangeTrackerImpl
|
||||||
/**
|
/**
|
||||||
* Constructor; supply delegate map.
|
* Constructor; supply delegate map.
|
||||||
*/
|
*/
|
||||||
public MapChangeTrackerImpl(Map map, OpenJPAConfiguration conf) {
|
public MapChangeTrackerImpl(Map map) {
|
||||||
_map = map;
|
_map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,6 @@ import org.apache.openjpa.lib.util.Localizer;
|
||||||
*/
|
*/
|
||||||
public class Proxies {
|
public class Proxies {
|
||||||
|
|
||||||
public static final int MODE_ENTRY = 0;
|
|
||||||
public static final int MODE_KEY = 1;
|
|
||||||
public static final int MODE_VALUE = 2;
|
|
||||||
|
|
||||||
private static final Localizer _loc = Localizer.forPackage(Proxies.class);
|
private static final Localizer _loc = Localizer.forPackage(Proxies.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,14 +60,15 @@ public class Proxies {
|
||||||
/**
|
/**
|
||||||
* Used by proxy types to dirty their owner.
|
* Used by proxy types to dirty their owner.
|
||||||
*/
|
*/
|
||||||
public static void dirty(Proxy proxy) {
|
public static void dirty(Proxy proxy, boolean stopTracking) {
|
||||||
if (proxy.getOwner() != null)
|
if (proxy.getOwner() != null)
|
||||||
proxy.getOwner().dirty(proxy.getOwnerField());
|
proxy.getOwner().dirty(proxy.getOwnerField());
|
||||||
|
if (stopTracking && proxy.getChangeTracker() != null)
|
||||||
|
proxy.getChangeTracker().stopTracking();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by proxy types to notify their owner that an element has been
|
* Used by proxy types to notify collection owner on element removal.
|
||||||
* removed.
|
|
||||||
*/
|
*/
|
||||||
public static void removed(Proxy proxy, Object removed, boolean key) {
|
public static void removed(Proxy proxy, Object removed, boolean key) {
|
||||||
if (proxy.getOwner() != null && removed != null)
|
if (proxy.getOwner() != null && removed != null)
|
||||||
|
@ -79,172 +76,13 @@ public class Proxies {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an iterator that dirties its owner on calls to remove. This
|
* Used by proxy types to serialize non-proxy versions.
|
||||||
* iterator assumes that the given proxy collection uses a
|
|
||||||
* {@link CollectionChangeTracker}.
|
|
||||||
*/
|
*/
|
||||||
public static Iterator iterator(final ProxyCollection proxy,
|
public static Object writeReplace(Proxy proxy) {
|
||||||
final Iterator itr) {
|
if (proxy == null || proxy.getOwner() == null
|
||||||
return new Iterator() {
|
|| proxy.getOwner().isDetached())
|
||||||
private Object _last = null;
|
return proxy;
|
||||||
|
return proxy.copy(proxy);
|
||||||
public boolean hasNext() {
|
|
||||||
return itr.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object next() {
|
|
||||||
_last = itr.next();
|
|
||||||
return _last;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
dirty(proxy);
|
|
||||||
itr.remove();
|
|
||||||
if (proxy.getChangeTracker() != null)
|
|
||||||
((CollectionChangeTracker) proxy.getChangeTracker()).
|
|
||||||
removed(_last);
|
|
||||||
removed(proxy, _last, false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a proxy iterator that dirties its owner on remove, set, and
|
|
||||||
* add. This iterator assumes that the given proxy collection uses a
|
|
||||||
* {@link CollectionChangeTracker}.
|
|
||||||
*/
|
|
||||||
public static ListIterator listIterator(final ProxyCollection proxy,
|
|
||||||
final ListIterator itr, final Class allowed) {
|
|
||||||
return new ListIterator() {
|
|
||||||
private Object _last = null;
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return itr.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int nextIndex() {
|
|
||||||
return itr.nextIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object next() {
|
|
||||||
_last = itr.next();
|
|
||||||
return _last;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasPrevious() {
|
|
||||||
return itr.hasPrevious();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int previousIndex() {
|
|
||||||
return itr.previousIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object previous() {
|
|
||||||
_last = itr.previous();
|
|
||||||
return _last;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(Object o) {
|
|
||||||
assertAllowedType(o, allowed);
|
|
||||||
dirty(proxy);
|
|
||||||
itr.set(o);
|
|
||||||
if (proxy.getChangeTracker() != null)
|
|
||||||
proxy.getChangeTracker().stopTracking();
|
|
||||||
removed(proxy, _last, false);
|
|
||||||
_last = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(Object o) {
|
|
||||||
assertAllowedType(o, allowed);
|
|
||||||
dirty(proxy);
|
|
||||||
itr.add(o);
|
|
||||||
if (proxy.getChangeTracker() != null) {
|
|
||||||
if (hasNext())
|
|
||||||
proxy.getChangeTracker().stopTracking();
|
|
||||||
else
|
|
||||||
((CollectionChangeTracker) proxy.getChangeTracker()).
|
|
||||||
added(o);
|
|
||||||
}
|
|
||||||
_last = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
dirty(proxy);
|
|
||||||
itr.remove();
|
|
||||||
if (proxy.getChangeTracker() != null)
|
|
||||||
((CollectionChangeTracker) proxy.getChangeTracker()).
|
|
||||||
removed(_last);
|
|
||||||
removed(proxy, _last, false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a proxy for the given map key or entry set.
|
|
||||||
*/
|
|
||||||
public static Set entrySet(final ProxyMap proxy, final Set set,
|
|
||||||
final int mode) {
|
|
||||||
return new AbstractSet() {
|
|
||||||
public int size() {
|
|
||||||
return set.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
if (mode != MODE_KEY)
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
|
|
||||||
Map map = (Map) proxy;
|
|
||||||
if (!map.containsKey(o))
|
|
||||||
return false;
|
|
||||||
map.remove(o);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator iterator() {
|
|
||||||
final Iterator itr = set.iterator();
|
|
||||||
return new Iterator() {
|
|
||||||
private Map.Entry _last = null;
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return itr.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object next() {
|
|
||||||
_last = (Map.Entry) itr.next();
|
|
||||||
switch (mode) {
|
|
||||||
case MODE_KEY:
|
|
||||||
return _last.getKey();
|
|
||||||
case MODE_VALUE:
|
|
||||||
return _last.getValue();
|
|
||||||
default:
|
|
||||||
return _last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
dirty(proxy);
|
|
||||||
itr.remove();
|
|
||||||
if (proxy.getChangeTracker() != null)
|
|
||||||
((MapChangeTracker) proxy.getChangeTracker()).
|
|
||||||
removed(_last.getKey(), _last.getValue());
|
|
||||||
removed(proxy, _last.getKey(), true);
|
|
||||||
removed(proxy, _last.getValue(), false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
switch (mode) {
|
|
||||||
case MODE_KEY:
|
|
||||||
return ((Map) proxy).keySet();
|
|
||||||
case MODE_VALUE:
|
|
||||||
return ((Map) proxy).values();
|
|
||||||
default:
|
|
||||||
return ((Map) proxy).entrySet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link ArrayList} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyArrayList
|
|
||||||
extends ArrayList
|
|
||||||
implements ProxyCollection {
|
|
||||||
|
|
||||||
private transient Class _elementType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient CollectionChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyArrayList() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyArrayList(Class elementType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_elementType = elementType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new CollectionChangeTrackerImpl(this, true, true, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new ArrayList((Collection) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyCollection newInstance(Class elementType, Comparator compare,
|
|
||||||
boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
return new ProxyArrayList(elementType, trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(int index, Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
super.add(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean add(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.add(value)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.added(value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(int index, Collection values) {
|
|
||||||
ensureCapacity(size() + values.size());
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
|
|
||||||
add(index, itr.next());
|
|
||||||
return values.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(Collection values) {
|
|
||||||
ensureCapacity(size() + values.size());
|
|
||||||
boolean added = false;
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext();)
|
|
||||||
added = add(itr.next()) || added;
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
for (int i = 0; i < size(); i++)
|
|
||||||
Proxies.removed(this, get(i), false);
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator iterator() {
|
|
||||||
return Proxies.iterator(this, super.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListIterator listIterator() {
|
|
||||||
return Proxies.listIterator(this, super.listIterator(), _elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListIterator listIterator(int index) {
|
|
||||||
return Proxies.listIterator(this, super.listIterator(index),
|
|
||||||
_elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object remove(int index) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
Object rem = super.remove(index);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(rem);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.remove(o)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(o);
|
|
||||||
Proxies.removed(this, o, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean removeAll(Collection c) {
|
|
||||||
boolean removed = false;
|
|
||||||
for (Iterator itr = c.iterator(); itr.hasNext();)
|
|
||||||
removed = remove(itr.next()) || removed;
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean retainAll(Collection c) {
|
|
||||||
int size = size();
|
|
||||||
for (Iterator itr = iterator(); itr.hasNext();)
|
|
||||||
if (!c.contains(itr.next()))
|
|
||||||
itr.remove();
|
|
||||||
return size() < size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object set(int index, Object element) {
|
|
||||||
Proxies.assertAllowedType(element, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Object rem = super.set(index, element);
|
|
||||||
if (rem != element)
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.apache.openjpa.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface implemented by all generated custom types, which use JavaBean
|
||||||
|
* conventions for copying state.
|
||||||
|
*
|
||||||
|
* @author Abe White
|
||||||
|
*/
|
||||||
|
public interface ProxyBean
|
||||||
|
extends Proxy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of this proxy type with the same state as the
|
||||||
|
* given instance.
|
||||||
|
*/
|
||||||
|
public ProxyBean newInstance(Object orig);
|
||||||
|
}
|
|
@ -18,8 +18,8 @@ package org.apache.openjpa.util;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by all built-in proxies on
|
* Interface implemented by all generated proxies on {@link java.util.Calendar}
|
||||||
* {@link java.util.Calendar} types.
|
* types.
|
||||||
*
|
*
|
||||||
* @author Marc Prud'hommeaux
|
* @author Marc Prud'hommeaux
|
||||||
*/
|
*/
|
||||||
|
@ -29,6 +29,5 @@ public interface ProxyCalendar
|
||||||
/**
|
/**
|
||||||
* Return a new instance of this calendar type.
|
* Return a new instance of this calendar type.
|
||||||
*/
|
*/
|
||||||
public ProxyCalendar newInstance(TimeZone timeZone);
|
public ProxyCalendar newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,23 +18,22 @@ package org.apache.openjpa.util;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by all built-in proxies on {@link Collection} types.
|
* Interface implemented by all proxy collection types.
|
||||||
*
|
*
|
||||||
* @author Abe White
|
* @author Abe White
|
||||||
*/
|
*/
|
||||||
public interface ProxyCollection
|
public interface ProxyCollection
|
||||||
extends Proxy {
|
extends Proxy, Collection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method should return a new proxy of the same concrete type as the
|
* The collection element type.
|
||||||
* implementing class. Used by the {@link ProxyManager} factories: one
|
|
||||||
* template instance of each type is created for the purpose of producing
|
|
||||||
* new instances via this method. Overcomes the performance penalties of
|
|
||||||
* reflection.
|
|
||||||
*/
|
*/
|
||||||
public ProxyCollection newInstance(Class elementType, Comparator compare,
|
public Class getElementType();
|
||||||
boolean trackChanges, OpenJPAConfiguration conf);
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of this proxy type.
|
||||||
|
*/
|
||||||
|
public ProxyCollection newInstance(Class elementType, Comparator comp,
|
||||||
|
boolean trackChanges);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,468 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.apache.openjpa.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods used by collection proxies.
|
||||||
|
*
|
||||||
|
* @author Abe White
|
||||||
|
* @nojavadoc
|
||||||
|
*/
|
||||||
|
public class ProxyCollections
|
||||||
|
extends Proxies {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link List#add(int,Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeAdd(ProxyCollection coll, int index, Object value){
|
||||||
|
assertAllowedType(value, coll.getElementType());
|
||||||
|
dirty(coll, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Vector#insertElementAt(Object,int)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeInsertElementAt(ProxyCollection coll, Object value,
|
||||||
|
int index) {
|
||||||
|
beforeAdd(coll, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Collection#add(Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeAdd(ProxyCollection coll, Object value) {
|
||||||
|
assertAllowedType(value, coll.getElementType());
|
||||||
|
dirty(coll, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Collection#add(Object)} on super.
|
||||||
|
*
|
||||||
|
* @param added whether the object was added
|
||||||
|
* @return <code>added</code>, for convenience
|
||||||
|
*/
|
||||||
|
public static boolean afterAdd(ProxyCollection coll, Object value,
|
||||||
|
boolean added) {
|
||||||
|
if (added && coll.getChangeTracker() != null)
|
||||||
|
((CollectionChangeTracker) coll.getChangeTracker()).added(value);
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Vector#addElement(Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeAddElement(ProxyCollection coll, Object value) {
|
||||||
|
beforeAdd(coll, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Vector#addElement(Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void afterAddElement(ProxyCollection coll, Object value) {
|
||||||
|
afterAdd(coll, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link LinkedList#addFirst(Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeAddFirst(ProxyCollection coll, Object value) {
|
||||||
|
beforeAdd(coll, 0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link LinkedList#addLast(Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeAddLast(ProxyCollection coll, Object value) {
|
||||||
|
beforeAdd(coll, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link LinkedList#addLast(Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void afterAddLast(ProxyCollection coll, Object value) {
|
||||||
|
afterAdd(coll, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Queue#offer(Object)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeOffer(ProxyCollection coll, Object value) {
|
||||||
|
beforeAdd(coll, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Queue#offer(Object)} on super.
|
||||||
|
*
|
||||||
|
* @param added whether the object was added
|
||||||
|
* @return <code>added</code>, for convenience
|
||||||
|
*/
|
||||||
|
public static boolean afterOffer(ProxyCollection coll, Object value,
|
||||||
|
boolean added) {
|
||||||
|
return afterAdd(coll, value, added);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for {@link List#addAll(int, Collection)}.
|
||||||
|
*/
|
||||||
|
public static boolean addAll(ProxyCollection coll, int index,
|
||||||
|
Collection values) {
|
||||||
|
List list = (List) coll;
|
||||||
|
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
|
||||||
|
list.add(index, itr.next());
|
||||||
|
return values.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for {@link Collection#addAll}.
|
||||||
|
*/
|
||||||
|
public static boolean addAll(ProxyCollection coll, Collection values) {
|
||||||
|
boolean added = false;
|
||||||
|
for (Iterator itr = values.iterator(); itr.hasNext();)
|
||||||
|
added |= coll.add(itr.next());
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before clearing collection.
|
||||||
|
*/
|
||||||
|
public static void beforeClear(ProxyCollection coll) {
|
||||||
|
dirty(coll, true);
|
||||||
|
for (Iterator itr = coll.iterator(); itr.hasNext();)
|
||||||
|
removed(coll, itr.next(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before clearing vector.
|
||||||
|
*/
|
||||||
|
public static void beforeRemoveAllElements(ProxyCollection coll) {
|
||||||
|
beforeClear(coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap given iterator in a proxy.
|
||||||
|
*/
|
||||||
|
public static Iterator afterIterator(final ProxyCollection coll,
|
||||||
|
final Iterator itr) {
|
||||||
|
// check for proxied; some coll impls delegate iterator methods
|
||||||
|
if (itr instanceof ProxyIterator)
|
||||||
|
return itr;
|
||||||
|
return new ProxyIterator() {
|
||||||
|
private Object _last = null;
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return itr.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object next() {
|
||||||
|
_last = itr.next();
|
||||||
|
return _last;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
dirty(coll, false);
|
||||||
|
itr.remove();
|
||||||
|
if (coll.getChangeTracker() != null)
|
||||||
|
((CollectionChangeTracker) coll.getChangeTracker()).
|
||||||
|
removed(_last);
|
||||||
|
Proxies.removed(coll, _last, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap given iterator in a proxy.
|
||||||
|
*/
|
||||||
|
public static ListIterator afterListIterator(final ProxyCollection coll,
|
||||||
|
int idx, final ListIterator itr) {
|
||||||
|
return afterListIterator(coll, itr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap given iterator in a proxy.
|
||||||
|
*/
|
||||||
|
public static ListIterator afterListIterator(final ProxyCollection coll,
|
||||||
|
final ListIterator itr) {
|
||||||
|
// check for proxied; some coll impls delegate iterator methods
|
||||||
|
if (itr instanceof ProxyListIterator)
|
||||||
|
return itr;
|
||||||
|
return new ProxyListIterator() {
|
||||||
|
private Object _last = null;
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return itr.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int nextIndex() {
|
||||||
|
return itr.nextIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object next() {
|
||||||
|
_last = itr.next();
|
||||||
|
return _last;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPrevious() {
|
||||||
|
return itr.hasPrevious();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int previousIndex() {
|
||||||
|
return itr.previousIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object previous() {
|
||||||
|
_last = itr.previous();
|
||||||
|
return _last;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Object o) {
|
||||||
|
assertAllowedType(o, coll.getElementType());
|
||||||
|
dirty(coll, false);
|
||||||
|
itr.set(o);
|
||||||
|
if (coll.getChangeTracker() != null)
|
||||||
|
coll.getChangeTracker().stopTracking();
|
||||||
|
Proxies.removed(coll, _last, false);
|
||||||
|
_last = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Object o) {
|
||||||
|
assertAllowedType(o, coll.getElementType());
|
||||||
|
dirty(coll, false);
|
||||||
|
itr.add(o);
|
||||||
|
if (coll.getChangeTracker() != null) {
|
||||||
|
if (hasNext())
|
||||||
|
coll.getChangeTracker().stopTracking();
|
||||||
|
else
|
||||||
|
((CollectionChangeTracker) coll.getChangeTracker()).
|
||||||
|
added(o);
|
||||||
|
}
|
||||||
|
_last = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
dirty(coll, false);
|
||||||
|
itr.remove();
|
||||||
|
if (coll.getChangeTracker() != null)
|
||||||
|
((CollectionChangeTracker) coll.getChangeTracker()).
|
||||||
|
removed(_last);
|
||||||
|
Proxies.removed(coll, _last, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link List#remove(int)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeRemove(ProxyCollection coll, int index) {
|
||||||
|
dirty(coll, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link List#remove(int)} on super.
|
||||||
|
*
|
||||||
|
* @param removed the removed object
|
||||||
|
* @return the removed object, for convenience
|
||||||
|
*/
|
||||||
|
public static Object afterRemove(ProxyCollection coll, int index,
|
||||||
|
Object removed) {
|
||||||
|
if (coll.getChangeTracker() != null)
|
||||||
|
((CollectionChangeTracker)coll.getChangeTracker()).removed(removed);
|
||||||
|
removed(coll, removed, false);
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Vector#removeElementAt(int)} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeRemoveElementAt(ProxyCollection coll, int index) {
|
||||||
|
beforeRemove(coll, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Collection#remove} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeRemove(ProxyCollection coll, Object o) {
|
||||||
|
dirty(coll, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Collection#remove} on super.
|
||||||
|
*
|
||||||
|
* @param removed whether the object was removed
|
||||||
|
* @return whether the object was removed, for convenience
|
||||||
|
*/
|
||||||
|
public static boolean afterRemove(ProxyCollection coll, Object o,
|
||||||
|
boolean removed){
|
||||||
|
if (!removed)
|
||||||
|
return false;
|
||||||
|
if (coll.getChangeTracker() != null)
|
||||||
|
((CollectionChangeTracker) coll.getChangeTracker()).removed(o);
|
||||||
|
removed(coll, o, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Vector#removeElement} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeRemoveElement(ProxyCollection coll, Object o) {
|
||||||
|
beforeRemove(coll, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Vector#removeElement} on super.
|
||||||
|
*/
|
||||||
|
public static boolean afterRemoveElement(ProxyCollection coll, Object o,
|
||||||
|
boolean removed) {
|
||||||
|
return afterRemove(coll, o, removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link LinkedList#removeFirst} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeRemoveFirst(ProxyCollection coll) {
|
||||||
|
beforeRemove(coll, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link LinkedList#removeFirst} on super.
|
||||||
|
*/
|
||||||
|
public static Object afterRemoveFirst(ProxyCollection coll, Object removed){
|
||||||
|
return afterRemove(coll, 0, removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link LinkedList#removeLast} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeRemoveLast(ProxyCollection coll) {
|
||||||
|
beforeRemove(coll, coll.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link LinkedList#removeLast} on super.
|
||||||
|
*/
|
||||||
|
public static Object afterRemoveLast(ProxyCollection coll, Object removed) {
|
||||||
|
return afterRemove(coll, coll.size(), removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Queue#remove} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeRemove(ProxyCollection coll) {
|
||||||
|
beforeRemove(coll, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Queue#remove} on super.
|
||||||
|
*/
|
||||||
|
public static Object afterRemove(ProxyCollection coll, Object removed){
|
||||||
|
return afterRemove(coll, 0, removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Queue#poll} on super.
|
||||||
|
*/
|
||||||
|
public static void beforePoll(ProxyCollection coll) {
|
||||||
|
if (!coll.isEmpty())
|
||||||
|
beforeRemove(coll, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Queue#poll} on super.
|
||||||
|
*/
|
||||||
|
public static Object afterPoll(ProxyCollection coll, Object removed) {
|
||||||
|
if (removed != null)
|
||||||
|
afterRemove(coll, 0, removed);
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for {@link Collection#removeAll}.
|
||||||
|
*/
|
||||||
|
public static boolean removeAll(ProxyCollection coll, Collection vals) {
|
||||||
|
boolean removed = false;
|
||||||
|
for (Iterator itr = vals.iterator(); itr.hasNext();)
|
||||||
|
removed |= coll.remove(itr.next());
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for {@link Collection#retainAll}.
|
||||||
|
*/
|
||||||
|
public static boolean retainAll(ProxyCollection coll, Collection vals) {
|
||||||
|
int size = coll.size();
|
||||||
|
for (Iterator itr = coll.iterator(); itr.hasNext();)
|
||||||
|
if (!vals.contains(itr.next()))
|
||||||
|
itr.remove();
|
||||||
|
return coll.size() < size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link List#set} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeSet(ProxyCollection coll, int index,
|
||||||
|
Object element) {
|
||||||
|
assertAllowedType(element, coll.getElementType());
|
||||||
|
dirty(coll, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link List#set} on super.
|
||||||
|
*
|
||||||
|
* @param replaced the replaced object
|
||||||
|
* @return the replaced object, for convenience
|
||||||
|
*/
|
||||||
|
public static Object afterSet(ProxyCollection coll, int index,
|
||||||
|
Object element, Object replaced) {
|
||||||
|
if (replaced != element)
|
||||||
|
removed(coll, replaced, false);
|
||||||
|
return replaced;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Vector#setElementAt} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeSetElementAt(ProxyCollection coll, Object element,
|
||||||
|
int index) {
|
||||||
|
beforeSet(coll, index, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Vector#setElementAt} on super.
|
||||||
|
*/
|
||||||
|
public static Object afterSetElementAt(ProxyCollection coll, Object element,
|
||||||
|
int index, Object replaced) {
|
||||||
|
return afterSet(coll, index, element, replaced);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for a proxied iterator.
|
||||||
|
*/
|
||||||
|
public static interface ProxyIterator
|
||||||
|
extends Iterator {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for a proxied list iterator.
|
||||||
|
*/
|
||||||
|
public static interface ProxyListIterator
|
||||||
|
extends ProxyIterator, ListIterator {
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@
|
||||||
package org.apache.openjpa.util;
|
package org.apache.openjpa.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by all built-in proxies on {@link java.util.Date}
|
* Interface implemented by all generated proxies on {@link java.util.Date}
|
||||||
* types.
|
* types.
|
||||||
*
|
*
|
||||||
* @author Abe White
|
* @author Abe White
|
||||||
|
|
|
@ -1,177 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Calendar} type that calls the <code>dirty</code>
|
|
||||||
* method on its owning persistence capable instance on modification. This
|
|
||||||
* class does not support modification via any deprecated method of the
|
|
||||||
* date class.
|
|
||||||
*
|
|
||||||
* @author Marc Prud'hommeaux
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyGregorianCalendar
|
|
||||||
extends GregorianCalendar
|
|
||||||
implements ProxyCalendar {
|
|
||||||
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
|
|
||||||
public ProxyGregorianCalendar() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyGregorianCalendar(int year, int month, int dayOfMonth) {
|
|
||||||
super(year, month, dayOfMonth);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyGregorianCalendar(int year, int month, int dayOfMonth,
|
|
||||||
int hourOfDay, int minute) {
|
|
||||||
super(year, month, dayOfMonth, hourOfDay, minute);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyGregorianCalendar(int year, int month, int dayOfMonth,
|
|
||||||
int hourOfDay, int minute, int second) {
|
|
||||||
super(year, month, dayOfMonth, hourOfDay, minute, second);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyGregorianCalendar(Locale aLocale) {
|
|
||||||
super(aLocale);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyGregorianCalendar(TimeZone zone) {
|
|
||||||
super(zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyGregorianCalendar(TimeZone zone, Locale aLocale) {
|
|
||||||
super(zone, aLocale);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyCalendar newInstance(TimeZone timeZone) {
|
|
||||||
if (timeZone == null)
|
|
||||||
return new ProxyGregorianCalendar();
|
|
||||||
else
|
|
||||||
return new ProxyGregorianCalendar(timeZone);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
Calendar origCal = (Calendar) orig;
|
|
||||||
|
|
||||||
GregorianCalendar cal = new GregorianCalendar(origCal.getTimeZone());
|
|
||||||
cal.setTime(origCal.getTime());
|
|
||||||
|
|
||||||
return cal;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void computeFields() {
|
|
||||||
// Calendar.computeFields() is called whenever a mutation
|
|
||||||
// occurs in order to recalculate all the fields
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.computeFields();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimeInMillis(long millis) {
|
|
||||||
if (millis != getTimeInMillis()) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setTimeInMillis(millis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(int field, int value) {
|
|
||||||
if (get(field) != value) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.set(field, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(int field, int amount) {
|
|
||||||
if (amount != 0) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.add(field, amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void roll(int field, boolean up) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.roll(field, up);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void roll(int field, int amount) {
|
|
||||||
if (amount != 0) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.roll(field, amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimeZone(TimeZone value) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setTimeZone(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLenient(boolean lenient) {
|
|
||||||
if (isLenient() != lenient) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setLenient(lenient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFirstDayOfWeek(int value) {
|
|
||||||
if (getFirstDayOfWeek() != value) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setFirstDayOfWeek(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinimalDaysInFirstWeek(int value) {
|
|
||||||
if (getMinimalDaysInFirstWeek() != value) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMinimalDaysInFirstWeek(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link HashMap} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyHashMap
|
|
||||||
extends HashMap
|
|
||||||
implements ProxyMap {
|
|
||||||
|
|
||||||
private transient Class _keyType = null;
|
|
||||||
private transient Class _valueType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient MapChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyHashMap() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyHashMap(Class keyType, Class valueType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_keyType = keyType;
|
|
||||||
_valueType = valueType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new MapChangeTrackerImpl(this, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new HashMap((Map) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyMap newInstance(Class keyType, Class valueType,
|
|
||||||
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
return new ProxyHashMap(keyType, valueType, trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
Proxies.removed(this, entry.getKey(), true);
|
|
||||||
Proxies.removed(this, entry.getValue(), false);
|
|
||||||
}
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set keySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection values() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set entrySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object put(Object key, Object value) {
|
|
||||||
Proxies.assertAllowedType(key, _keyType);
|
|
||||||
Proxies.assertAllowedType(value, _valueType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.put(key, value);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.changed(key, old, value);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
} else if (_ct != null)
|
|
||||||
_ct.added(key, value);
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putAll(Map m) {
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object remove(Object key) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.remove(key);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(key, old);
|
|
||||||
Proxies.removed(this, key, true);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
}
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link HashSet} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyHashSet
|
|
||||||
extends HashSet
|
|
||||||
implements ProxyCollection {
|
|
||||||
|
|
||||||
private transient Class _elementType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient CollectionChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyHashSet() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyHashSet(Class elementType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_elementType = elementType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new CollectionChangeTrackerImpl(this, false, false, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new HashSet((Collection) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyCollection newInstance(Class elementType, Comparator compare,
|
|
||||||
boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
return new ProxyHashSet(elementType, trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean add(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.add(value)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.added(value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(Collection values) {
|
|
||||||
boolean added = false;
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext();)
|
|
||||||
added = add(itr.next()) || added;
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
for (Iterator itr = super.iterator(); itr.hasNext();)
|
|
||||||
Proxies.removed(this, itr.next(), false);
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator iterator() {
|
|
||||||
return Proxies.iterator(this, super.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.remove(o)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(o);
|
|
||||||
Proxies.removed(this, o, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean removeAll(Collection c) {
|
|
||||||
boolean removed = false;
|
|
||||||
for (Iterator itr = c.iterator(); itr.hasNext();)
|
|
||||||
removed = remove(itr.next()) || removed;
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean retainAll(Collection c) {
|
|
||||||
int size = size();
|
|
||||||
for (Iterator itr = iterator(); itr.hasNext();)
|
|
||||||
if (!c.contains(itr.next()))
|
|
||||||
itr.remove();
|
|
||||||
return size() < size;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Hashtable} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyHashtable
|
|
||||||
extends Hashtable
|
|
||||||
implements ProxyMap {
|
|
||||||
|
|
||||||
private transient Class _keyType = null;
|
|
||||||
private transient Class _valueType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient MapChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyHashtable() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyHashtable(Class keyType, Class valueType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_keyType = keyType;
|
|
||||||
_valueType = valueType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new MapChangeTrackerImpl(this, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new Hashtable((Map) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyMap newInstance(Class keyType, Class valueType,
|
|
||||||
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
return new ProxyHashtable(keyType, valueType, trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
Proxies.removed(this, entry.getKey(), true);
|
|
||||||
Proxies.removed(this, entry.getValue(), false);
|
|
||||||
}
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set keySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection values() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set entrySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object put(Object key, Object value) {
|
|
||||||
Proxies.assertAllowedType(key, _keyType);
|
|
||||||
Proxies.assertAllowedType(value, _valueType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.put(key, value);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.changed(key, old, value);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
} else if (_ct != null)
|
|
||||||
_ct.added(key, value);
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putAll(Map m) {
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object remove(Object key) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.remove(key);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(key, old);
|
|
||||||
Proxies.removed(this, key, true);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
}
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,224 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link LinkedList} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyLinkedList
|
|
||||||
extends LinkedList
|
|
||||||
implements ProxyCollection {
|
|
||||||
|
|
||||||
private transient Class _elementType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient CollectionChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyLinkedList() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyLinkedList(Class elementType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_elementType = elementType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new CollectionChangeTrackerImpl(this, true, true, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new LinkedList((Collection) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyCollection newInstance(Class elementType, Comparator compare,
|
|
||||||
boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
return new ProxyLinkedList(elementType, trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(int index, Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
super.add(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean add(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.add(value)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.added(value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addFirst(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.addFirst(value);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addLast(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.addLast(value);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.added(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(int index, Collection values) {
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
|
|
||||||
add(index, itr.next());
|
|
||||||
return values.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(Collection values) {
|
|
||||||
boolean added = false;
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext();)
|
|
||||||
added = add(itr.next()) || added;
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
for (Iterator itr = super.iterator(); itr.hasNext();)
|
|
||||||
Proxies.removed(this, itr.next(), false);
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator iterator() {
|
|
||||||
return Proxies.iterator(this, super.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListIterator listIterator() {
|
|
||||||
return Proxies.listIterator(this, super.listIterator(), _elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListIterator listIterator(int index) {
|
|
||||||
return Proxies.listIterator(this, super.listIterator(index),
|
|
||||||
_elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object remove(int index) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
Object rem = super.remove(index);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(rem);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.remove(o)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(o);
|
|
||||||
Proxies.removed(this, o, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object removeFirst() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
Object rem = super.removeFirst();
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(rem);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object removeLast() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
Object rem = super.removeLast();
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(rem);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean removeAll(Collection c) {
|
|
||||||
boolean removed = false;
|
|
||||||
for (Iterator itr = c.iterator(); itr.hasNext();)
|
|
||||||
removed = remove(itr.next()) || removed;
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean retainAll(Collection c) {
|
|
||||||
int size = size();
|
|
||||||
for (Iterator itr = iterator(); itr.hasNext();)
|
|
||||||
if (!c.contains(itr.next()))
|
|
||||||
itr.remove();
|
|
||||||
return size() < size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object set(int index, Object element) {
|
|
||||||
Proxies.assertAllowedType(element, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Object rem = super.set(index, element);
|
|
||||||
if (rem != element)
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -40,32 +40,6 @@ import java.util.TimeZone;
|
||||||
*/
|
*/
|
||||||
public interface ProxyManager {
|
public interface ProxyManager {
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a copy of the given date with the same information.
|
|
||||||
*/
|
|
||||||
public Date copyDate(Date orig);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a copy of the given Calendar with the same information.
|
|
||||||
*/
|
|
||||||
public Calendar copyCalendar(Calendar orig);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a new collection of the same type as the given one
|
|
||||||
* with a copy of all contained elements.
|
|
||||||
* If the given owner is non-null, the returned value should be a proxy
|
|
||||||
* for the given owner, otherwise it should not be a proxy.
|
|
||||||
*/
|
|
||||||
public Collection copyCollection(Collection orig);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a new map of the same type as the given one
|
|
||||||
* with a copy of all contained key/value pairs.
|
|
||||||
* If the given owner is non-null, the returned value should be a proxy
|
|
||||||
* for the given owner, otherwise it should not be a proxy.
|
|
||||||
*/
|
|
||||||
public Map copyMap(Map orig);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new array of the same component type as the given array
|
* Return a new array of the same component type as the given array
|
||||||
* and containing the same elements. Works for both primitive and
|
* and containing the same elements. Works for both primitive and
|
||||||
|
@ -74,25 +48,31 @@ public interface ProxyManager {
|
||||||
public Object copyArray(Object orig);
|
public Object copyArray(Object orig);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a copy of the given object with the same
|
* Return a copy of the given date with the same information.
|
||||||
* information. If this manager cannot proxy the given type, return null.
|
|
||||||
* If the given owner is non-null, the returned value should be a proxy
|
|
||||||
* for the given owner, otherwise it should not be a proxy.
|
|
||||||
*
|
|
||||||
* @since 0.2.5
|
|
||||||
*/
|
*/
|
||||||
public Object copyCustom(Object orig);
|
public Date copyDate(Date orig);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new date proxy.
|
* Return a new date proxy.
|
||||||
*/
|
*/
|
||||||
public Proxy newDateProxy(Class type);
|
public Proxy newDateProxy(Class type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a copy of the given calendar with the same information.
|
||||||
|
*/
|
||||||
|
public Calendar copyCalendar(Calendar orig);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new calendar proxy.
|
* Return a new calendar proxy.
|
||||||
*/
|
*/
|
||||||
public Proxy newCalendarProxy(Class type, TimeZone timeZone);
|
public Proxy newCalendarProxy(Class type, TimeZone timeZone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new collection of the same type as the given one
|
||||||
|
* with a copy of all contained elements.
|
||||||
|
*/
|
||||||
|
public Collection copyCollection(Collection orig);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a proxy for the given collection type. The returned collection
|
* Return a proxy for the given collection type. The returned collection
|
||||||
* will allow only addition of elements assignable from the given
|
* will allow only addition of elements assignable from the given
|
||||||
|
@ -101,6 +81,12 @@ public interface ProxyManager {
|
||||||
public Proxy newCollectionProxy(Class type, Class elementType,
|
public Proxy newCollectionProxy(Class type, Class elementType,
|
||||||
Comparator compare);
|
Comparator compare);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new map of the same type as the given one
|
||||||
|
* with a copy of all contained key/value pairs.
|
||||||
|
*/
|
||||||
|
public Map copyMap(Map orig);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a proxy for the given map type. The returned map will
|
* Return a proxy for the given map type. The returned map will
|
||||||
* allow only addition of keys/values assignable from the given
|
* allow only addition of keys/values assignable from the given
|
||||||
|
@ -109,6 +95,14 @@ public interface ProxyManager {
|
||||||
public Proxy newMapProxy(Class type, Class keyType, Class valueType,
|
public Proxy newMapProxy(Class type, Class keyType, Class valueType,
|
||||||
Comparator compare);
|
Comparator compare);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a copy of the given object with the same information, or null if
|
||||||
|
* this manager cannot copy the object.
|
||||||
|
*
|
||||||
|
* @since 0.2.5
|
||||||
|
*/
|
||||||
|
public Object copyCustom(Object orig);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a proxy for the given object, or null if this manager cannot
|
* Return a proxy for the given object, or null if this manager cannot
|
||||||
* proxy the object.
|
* proxy the object.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,23 +18,27 @@ package org.apache.openjpa.util;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by all built-in proxies on {@link Map} types.
|
* Interface implemented by proxies on {@link Map} types.
|
||||||
*
|
*
|
||||||
* @author Abe White
|
* @author Abe White
|
||||||
*/
|
*/
|
||||||
public interface ProxyMap
|
public interface ProxyMap
|
||||||
extends Proxy {
|
extends Proxy, Map {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method should return a new proxy of the same concrete type as the
|
* The map key type.
|
||||||
* implementing class. Used by the {@link ProxyManager} factories: one
|
*/
|
||||||
* template instance of each type is created for the purpose of producing
|
public Class getKeyType();
|
||||||
* new instances via this method. Overcomes the performance
|
|
||||||
* penalties of reflection.
|
/**
|
||||||
|
* The map value type.
|
||||||
|
*/
|
||||||
|
public Class getValueType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of this proxy type.
|
||||||
*/
|
*/
|
||||||
public ProxyMap newInstance(Class keyType, Class valueType,
|
public ProxyMap newInstance(Class keyType, Class valueType,
|
||||||
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf);
|
Comparator compare, boolean trackChanges);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.apache.openjpa.util;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.ObjectStreamException;
|
||||||
|
import java.util.AbstractSet;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods used by map proxies.
|
||||||
|
*
|
||||||
|
* @author Abe White
|
||||||
|
* @nojavadoc
|
||||||
|
*/
|
||||||
|
public class ProxyMaps
|
||||||
|
extends Proxies {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Map#clear} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeClear(ProxyMap map) {
|
||||||
|
dirty(map, true);
|
||||||
|
Map.Entry entry;
|
||||||
|
for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) {
|
||||||
|
entry = (Map.Entry) itr.next();
|
||||||
|
removed(map, entry.getKey(), true);
|
||||||
|
removed(map, entry.getValue(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for {@link Map#keySet}.
|
||||||
|
*/
|
||||||
|
public static Set keySet(ProxyMap map) {
|
||||||
|
ProxyEntrySet entries = (ProxyEntrySet) map.entrySet();
|
||||||
|
entries.setView(ProxyEntrySet.VIEW_KEYS);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for {@link Map#values}.
|
||||||
|
*/
|
||||||
|
public static Collection values(ProxyMap map) {
|
||||||
|
ProxyEntrySet entries = (ProxyEntrySet) map.entrySet();
|
||||||
|
entries.setView(ProxyEntrySet.VIEW_VALUES);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap the given entry set in a proxy.
|
||||||
|
*/
|
||||||
|
public static Set afterEntrySet(ProxyMap map, Set entries) {
|
||||||
|
return new ProxyEntrySetImpl(map, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Map#put} on super.
|
||||||
|
*/
|
||||||
|
public static boolean beforePut(ProxyMap map, Object key, Object value) {
|
||||||
|
assertAllowedType(key, map.getKeyType());
|
||||||
|
assertAllowedType(value, map.getValueType());
|
||||||
|
dirty(map, false);
|
||||||
|
return map.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Map#put} on super.
|
||||||
|
*
|
||||||
|
* @param ret the return value from the super's method
|
||||||
|
* @param before the return value from {@link #beforePut}
|
||||||
|
* @return the value to return from {@link Map#put}
|
||||||
|
*/
|
||||||
|
public static Object afterPut(ProxyMap map, Object key, Object value,
|
||||||
|
Object ret, boolean before) {
|
||||||
|
if (before) {
|
||||||
|
if (map.getChangeTracker() != null)
|
||||||
|
((MapChangeTracker) map.getChangeTracker()).changed(key, ret,
|
||||||
|
value);
|
||||||
|
removed(map, ret, false);
|
||||||
|
} else if (map.getChangeTracker() != null)
|
||||||
|
((MapChangeTracker) map.getChangeTracker()).added(key, value);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Properties#setProperty} on super.
|
||||||
|
*/
|
||||||
|
public static boolean beforeSetProperty(ProxyMap map, String key,
|
||||||
|
String value) {
|
||||||
|
return beforePut(map, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Properties#setProperty} on super.
|
||||||
|
*
|
||||||
|
* @param ret the return value from the super's method
|
||||||
|
* @param before the return value from {@link #beforeSetProperty}
|
||||||
|
* @return the value to return from {@link Properties#setProperty}
|
||||||
|
*/
|
||||||
|
public static Object afterSetProperty(ProxyMap map, String key,
|
||||||
|
String value, Object ret, boolean before) {
|
||||||
|
return afterPut(map, key, value, ret, before);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Properties#load} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeLoad(ProxyMap map, InputStream in) {
|
||||||
|
dirty(map, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Properties#loadXML} on super.
|
||||||
|
*/
|
||||||
|
public static void beforeLoadFromXML(ProxyMap map, InputStream in) {
|
||||||
|
dirty(map, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overload for {@link Map#putAll}.
|
||||||
|
*/
|
||||||
|
public static void putAll(ProxyMap map, Map values) {
|
||||||
|
Map.Entry entry;
|
||||||
|
for (Iterator itr = values.entrySet().iterator(); itr.hasNext();) {
|
||||||
|
entry = (Map.Entry) itr.next();
|
||||||
|
map.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call before invoking {@link Map#remove} on super.
|
||||||
|
*/
|
||||||
|
public static boolean beforeRemove(ProxyMap map, Object key) {
|
||||||
|
dirty(map, false);
|
||||||
|
return map.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after invoking {@link Map#remove} on super.
|
||||||
|
*
|
||||||
|
* @param ret the return value from the super's method
|
||||||
|
* @param before the return value from {@link #beforeRemove}
|
||||||
|
* @return the value to return from {@link Map#remove}
|
||||||
|
*/
|
||||||
|
public static Object afterRemove(ProxyMap map, Object key, Object ret,
|
||||||
|
boolean before) {
|
||||||
|
if (before) {
|
||||||
|
if (map.getChangeTracker() != null)
|
||||||
|
((MapChangeTracker) map.getChangeTracker()).removed(key, ret);
|
||||||
|
removed(map, key, true);
|
||||||
|
removed(map, ret, false);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for a proxy entry set.
|
||||||
|
*/
|
||||||
|
public static interface ProxyEntrySet
|
||||||
|
extends Set {
|
||||||
|
|
||||||
|
public static final int VIEW_KEYS = 0;
|
||||||
|
public static final int VIEW_VALUES = 1;
|
||||||
|
public static final int VIEW_ENTRIES = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set what entry view this set exposes.
|
||||||
|
*/
|
||||||
|
public void setView(int view);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dirtying proxy for map entry set.
|
||||||
|
*/
|
||||||
|
private static class ProxyEntrySetImpl
|
||||||
|
extends AbstractSet
|
||||||
|
implements ProxyEntrySet {
|
||||||
|
|
||||||
|
private final ProxyMap _map;
|
||||||
|
private final Set _entries;
|
||||||
|
private int _view = VIEW_ENTRIES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supply owning map and delegate entry set on construction.
|
||||||
|
*/
|
||||||
|
public ProxyEntrySetImpl(ProxyMap map, Set entries) {
|
||||||
|
_map = map;
|
||||||
|
_entries = entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View mode.
|
||||||
|
*/
|
||||||
|
public int getView() {
|
||||||
|
return _view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View mode.
|
||||||
|
*/
|
||||||
|
public void setView(int view) {
|
||||||
|
_view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return _entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
if (_view != VIEW_KEYS)
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
if (!_map.containsKey(o))
|
||||||
|
return false;
|
||||||
|
_map.remove(o);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator iterator() {
|
||||||
|
final Iterator itr = _entries.iterator();
|
||||||
|
return new Iterator() {
|
||||||
|
private Map.Entry _last = null;
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return itr.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object next() {
|
||||||
|
_last = (Map.Entry) itr.next();
|
||||||
|
switch (_view) {
|
||||||
|
case VIEW_KEYS:
|
||||||
|
return _last.getKey();
|
||||||
|
case VIEW_VALUES:
|
||||||
|
return _last.getValue();
|
||||||
|
default:
|
||||||
|
return _last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
dirty(_map, false);
|
||||||
|
itr.remove();
|
||||||
|
if (_map.getChangeTracker() != null)
|
||||||
|
((MapChangeTracker) _map.getChangeTracker()).
|
||||||
|
removed(_last.getKey(), _last.getValue());
|
||||||
|
Proxies.removed(_map, _last.getKey(), true);
|
||||||
|
Proxies.removed(_map, _last.getValue(), false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object writeReplace()
|
||||||
|
throws ObjectStreamException {
|
||||||
|
switch (_view) {
|
||||||
|
case VIEW_KEYS:
|
||||||
|
return ((Map) _map).keySet();
|
||||||
|
case VIEW_VALUES:
|
||||||
|
return ((Map) _map).values();
|
||||||
|
default:
|
||||||
|
return ((Map) _map).entrySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,162 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Properties} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyProperties
|
|
||||||
extends Properties
|
|
||||||
implements ProxyMap {
|
|
||||||
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient MapChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyProperties() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyProperties(boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new MapChangeTrackerImpl(this, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
Properties props = new Properties();
|
|
||||||
props.putAll((Map) orig);
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyMap newInstance(Class keyType, Class valueType,
|
|
||||||
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
return new ProxyProperties(trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
Proxies.removed(this, entry.getKey(), true);
|
|
||||||
Proxies.removed(this, entry.getValue(), false);
|
|
||||||
}
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set keySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection values() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set entrySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object put(Object key, Object value) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.put(key, value);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.changed(key, old, value);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
} else if (_ct != null)
|
|
||||||
_ct.added(key, value);
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putAll(Map m) {
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object remove(Object key) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.remove(key);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(key, old);
|
|
||||||
Proxies.removed(this, key, true);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
}
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object setProperty(String key, String value) {
|
|
||||||
return put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(InputStream in)
|
|
||||||
throws IOException {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
super.load(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.sql.Date;
|
|
||||||
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Date} type that calls the <code>dirty</code>
|
|
||||||
* method on its owning persistence capable instance on modification. This
|
|
||||||
* class does not support modification via any deprecated method of the
|
|
||||||
* date class.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxySQLDate
|
|
||||||
extends Date
|
|
||||||
implements ProxyDate {
|
|
||||||
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
|
|
||||||
public ProxySQLDate() {
|
|
||||||
super(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxySQLDate(long time) {
|
|
||||||
super(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyDate newInstance() {
|
|
||||||
return new ProxySQLDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new Date(((Date) orig).getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setYear(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setYear(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMonth(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMonth(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDate(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setDate(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHours(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setHours(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinutes(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMinutes(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSeconds(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setSeconds(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long millis) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setTime(millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return new Date(getTime());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.sql.Time;
|
|
||||||
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Time} type that calls the <code>dirty</code>
|
|
||||||
* method on its owning persistence capable instance on modification. This
|
|
||||||
* class does not support modification via any deprecated method of the
|
|
||||||
* date class.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyTime
|
|
||||||
extends Time
|
|
||||||
implements ProxyDate {
|
|
||||||
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
|
|
||||||
public ProxyTime() {
|
|
||||||
super(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyTime(long time) {
|
|
||||||
super(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyDate newInstance() {
|
|
||||||
return new ProxyTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new Time(((Time) orig).getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setYear(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setYear(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMonth(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMonth(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDate(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setDate(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHours(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setHours(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinutes(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMinutes(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSeconds(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setSeconds(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long millis) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setTime(millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return new Time(getTime());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Timestamp} type that calls the <code>dirty</code>
|
|
||||||
* method on its owning persistence capable instance on modification. This
|
|
||||||
* class does not support modification via any deprecated method of the
|
|
||||||
* date class.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyTimestamp
|
|
||||||
extends Timestamp
|
|
||||||
implements ProxyDate {
|
|
||||||
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
|
|
||||||
public ProxyTimestamp() {
|
|
||||||
super(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyTimestamp(long time) {
|
|
||||||
super(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyDate newInstance() {
|
|
||||||
return new ProxyTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
Timestamp origTimestamp = (Timestamp)orig;
|
|
||||||
Timestamp copy = new Timestamp(origTimestamp.getTime());
|
|
||||||
copy.setNanos(origTimestamp.getNanos());
|
|
||||||
return copy;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setYear(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setYear(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMonth(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMonth(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDate(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setDate(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHours(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setHours(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinutes(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMinutes(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSeconds(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setSeconds(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long millis) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setTime(millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNanos(int nanos) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setNanos(nanos);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
Timestamp t = new Timestamp(getTime());
|
|
||||||
t.setNanos(getNanos());
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,169 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.SortedMap;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link TreeMap} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyTreeMap
|
|
||||||
extends TreeMap
|
|
||||||
implements ProxyMap {
|
|
||||||
|
|
||||||
private transient Class _keyType = null;
|
|
||||||
private transient Class _valueType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient MapChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyTreeMap() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyTreeMap(Class keyType, Class valueType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_keyType = keyType;
|
|
||||||
_valueType = valueType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new MapChangeTrackerImpl(this, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyTreeMap(Class keyType, Class valueType, Comparator compare,
|
|
||||||
boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
super(compare);
|
|
||||||
_keyType = keyType;
|
|
||||||
_valueType = valueType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new MapChangeTrackerImpl(this, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
if (orig instanceof SortedMap)
|
|
||||||
return new TreeMap((SortedMap) orig);
|
|
||||||
return new TreeMap((Map) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyMap newInstance(Class keyType, Class valueType,
|
|
||||||
Comparator compare, boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
if (compare == null)
|
|
||||||
return new ProxyTreeMap(keyType, valueType, trackChanges, conf);
|
|
||||||
return new ProxyTreeMap(keyType, valueType, compare, trackChanges,
|
|
||||||
conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = super.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
Proxies.removed(this, entry.getKey(), true);
|
|
||||||
Proxies.removed(this, entry.getValue(), false);
|
|
||||||
}
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set keySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection values() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set entrySet() {
|
|
||||||
return Proxies.entrySet(this, super.entrySet(), Proxies.MODE_ENTRY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object put(Object key, Object value) {
|
|
||||||
Proxies.assertAllowedType(key, _keyType);
|
|
||||||
Proxies.assertAllowedType(value, _valueType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.put(key, value);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.changed(key, old, value);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
} else if (_ct != null)
|
|
||||||
_ct.added(key, value);
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putAll(Map m) {
|
|
||||||
Map.Entry entry;
|
|
||||||
for (Iterator itr = m.entrySet().iterator(); itr.hasNext();) {
|
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object remove(Object key) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
boolean had = containsKey(key);
|
|
||||||
Object old = super.remove(key);
|
|
||||||
if (had) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(key, old);
|
|
||||||
Proxies.removed(this, key, true);
|
|
||||||
Proxies.removed(this, old, false);
|
|
||||||
}
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,159 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link TreeSet} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyTreeSet
|
|
||||||
extends TreeSet
|
|
||||||
implements ProxyCollection {
|
|
||||||
|
|
||||||
private transient Class _elementType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient CollectionChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyTreeSet() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyTreeSet(Class elementType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_elementType = elementType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new CollectionChangeTrackerImpl(this, false, false, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyTreeSet(Class elementType, Comparator compare,
|
|
||||||
boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
super(compare);
|
|
||||||
_elementType = elementType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new CollectionChangeTrackerImpl(this, false, false, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
if (orig instanceof SortedSet)
|
|
||||||
return new TreeSet((SortedSet) orig);
|
|
||||||
return new TreeSet((Collection) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyCollection newInstance(Class elementType, Comparator compare,
|
|
||||||
boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
if (compare == null)
|
|
||||||
return new ProxyTreeSet(elementType, trackChanges, conf);
|
|
||||||
return new ProxyTreeSet(elementType, compare, trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean add(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.add(value)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.added(value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(Collection values) {
|
|
||||||
boolean added = false;
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext();)
|
|
||||||
added = add(itr.next()) || added;
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
for (Iterator itr = super.iterator(); itr.hasNext();)
|
|
||||||
Proxies.removed(this, itr.next(), false);
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator iterator() {
|
|
||||||
return Proxies.iterator(this, super.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.remove(o)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(o);
|
|
||||||
Proxies.removed(this, o, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean removeAll(Collection c) {
|
|
||||||
boolean removed = false;
|
|
||||||
for (Iterator itr = c.iterator(); itr.hasNext();)
|
|
||||||
removed = remove(itr.next()) || removed;
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean retainAll(Collection c) {
|
|
||||||
int size = size();
|
|
||||||
for (Iterator itr = iterator(); itr.hasNext();)
|
|
||||||
if (!c.contains(itr.next()))
|
|
||||||
itr.remove();
|
|
||||||
return size() < size;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Date} type that calls the <code>dirty</code>
|
|
||||||
* method on its owning persistence capable instance on modification. This
|
|
||||||
* class does not support modification via any deprecated method of the
|
|
||||||
* date class.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyUtilDate
|
|
||||||
extends Date
|
|
||||||
implements ProxyDate {
|
|
||||||
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
|
|
||||||
public ProxyUtilDate() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyUtilDate(long time) {
|
|
||||||
super(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyDate newInstance() {
|
|
||||||
return new ProxyUtilDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new Date(((Date) orig).getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setYear(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setYear(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMonth(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMonth(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDate(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setDate(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHours(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setHours(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinutes(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setMinutes(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSeconds(int val) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setSeconds(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTime(long millis) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.setTime(millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return new Date(getTime());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,246 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
|
||||||
*
|
|
||||||
* Licensed 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.apache.openjpa.util;
|
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension of the {@link Vector} type that dirties the
|
|
||||||
* persistent/transactional field it is assigned to on modification.
|
|
||||||
* The need to dirty the field on <b>any</b> modification mandates that
|
|
||||||
* this class must override all mutator methods of the base type.
|
|
||||||
* This may lead to multiple calls to <code>dirty</code> for one state
|
|
||||||
* change if one mutator method of the base type calls another.
|
|
||||||
*
|
|
||||||
* @author Abe White
|
|
||||||
* @nojavadoc
|
|
||||||
*/
|
|
||||||
public class ProxyVector
|
|
||||||
extends Vector
|
|
||||||
implements ProxyCollection {
|
|
||||||
|
|
||||||
private transient Class _elementType = null;
|
|
||||||
private transient OpenJPAStateManager _sm = null;
|
|
||||||
private transient int _field = -1;
|
|
||||||
private transient CollectionChangeTracker _ct = null;
|
|
||||||
|
|
||||||
public ProxyVector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyVector(Class elementType, boolean trackChanges,
|
|
||||||
OpenJPAConfiguration conf) {
|
|
||||||
_elementType = elementType;
|
|
||||||
if (trackChanges)
|
|
||||||
_ct = new CollectionChangeTrackerImpl(this, true, true, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(OpenJPAStateManager sm, int field) {
|
|
||||||
_sm = sm;
|
|
||||||
_field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OpenJPAStateManager getOwner() {
|
|
||||||
return _sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOwnerField() {
|
|
||||||
return _field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChangeTracker getChangeTracker() {
|
|
||||||
return _ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object copy(Object orig) {
|
|
||||||
return new Vector((Collection) orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyCollection newInstance(Class elementType, Comparator compare,
|
|
||||||
boolean trackChanges, OpenJPAConfiguration conf) {
|
|
||||||
return new ProxyVector(elementType, trackChanges, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(int index, Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
super.add(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insertElementAt(Object value, int index) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
super.insertElementAt(value, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean add(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.add(value)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.added(value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addElement(Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
super.addElement(value);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.added(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(int index, Collection values) {
|
|
||||||
ensureCapacity(size() + values.size());
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext(); index++)
|
|
||||||
add(index, itr.next());
|
|
||||||
return values.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addAll(Collection values) {
|
|
||||||
ensureCapacity(size() + values.size());
|
|
||||||
boolean added = false;
|
|
||||||
for (Iterator itr = values.iterator(); itr.hasNext();)
|
|
||||||
added = add(itr.next()) || added;
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
for (int i = 0; i < size(); i++)
|
|
||||||
Proxies.removed(this, get(i), false);
|
|
||||||
super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAllElements() {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
for (int i = 0; i < size(); i++)
|
|
||||||
Proxies.removed(this, get(i), false);
|
|
||||||
super.removeAllElements();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator iterator() {
|
|
||||||
return Proxies.iterator(this, super.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListIterator listIterator() {
|
|
||||||
return Proxies.listIterator(this, super.listIterator(), _elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListIterator listIterator(int index) {
|
|
||||||
return Proxies.listIterator(this, super.listIterator(index),
|
|
||||||
_elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object remove(int index) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
Object rem = super.remove(index);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(rem);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeElementAt(int index) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
Object rem = get(index);
|
|
||||||
super.removeElementAt(index);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(rem);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.remove(o)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(o);
|
|
||||||
Proxies.removed(this, o, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean removeElement(Object o) {
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (super.removeElement(o)) {
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.removed(o);
|
|
||||||
Proxies.removed(this, o, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean removeAll(Collection c) {
|
|
||||||
boolean removed = false;
|
|
||||||
for (Iterator itr = c.iterator(); itr.hasNext();)
|
|
||||||
removed = remove(itr.next()) || removed;
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean retainAll(Collection c) {
|
|
||||||
int size = size();
|
|
||||||
for (Iterator itr = iterator(); itr.hasNext();)
|
|
||||||
if (!c.contains(itr.next()))
|
|
||||||
itr.remove();
|
|
||||||
return size() < size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object set(int index, Object value) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Object rem = super.set(index, value);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
return rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setElementAt(Object value, int index) {
|
|
||||||
Proxies.assertAllowedType(value, _elementType);
|
|
||||||
Proxies.dirty(this);
|
|
||||||
if (_ct != null)
|
|
||||||
_ct.stopTracking();
|
|
||||||
Object rem = get(index);
|
|
||||||
super.setElementAt(value, index);
|
|
||||||
Proxies.removed(this, rem, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object writeReplace()
|
|
||||||
throws ObjectStreamException {
|
|
||||||
if (_sm != null && _sm.isDetached())
|
|
||||||
return this;
|
|
||||||
return copy(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -42,16 +42,20 @@ opt-lock-nested: Optimistic locking errors were detected when \
|
||||||
concurrently modified in another transaction. Each exception in \
|
concurrently modified in another transaction. Each exception in \
|
||||||
the nested throwables array contains a failed object representing \
|
the nested throwables array contains a failed object representing \
|
||||||
a concurrently modified object.
|
a concurrently modified object.
|
||||||
bad-proxy: Unable to create second class object proxy for type: "{0}".
|
|
||||||
bad-array: Unable to copy array: {0}.
|
bad-array: Unable to copy array: {0}.
|
||||||
|
no-proxy-intf: Unable to create a second class object proxy for interface \
|
||||||
|
"{0}". No corresponding concrete types are known.
|
||||||
|
no-proxy-abstract: Unable to create a second class object proxy for abstract \
|
||||||
|
type "{0}". You must use a concrete type or a recognized interface.
|
||||||
|
cant-classforname: Unable to instantiate proxy for type "{0}". Make sure the \
|
||||||
|
class has a default constructor.
|
||||||
|
no-date-cons: Custom date type "{0}" needs a default constructor or a \
|
||||||
|
millisecond constructor.
|
||||||
bad-elem-type: The given element does not meet the requirements for this \
|
bad-elem-type: The given element does not meet the requirements for this \
|
||||||
field. The container requires that all non-null objects are of the type \
|
field. The container requires that all non-null objects are of the type \
|
||||||
declared in the XML metadata for this container. \
|
declared in the XML metadata for this container. \
|
||||||
"{1}(loader={0}).isAssignableFrom ({3}(loader={2}))" failed.
|
"{1}(loader={0}).isAssignableFrom ({3}(loader={2}))" failed.
|
||||||
string-id: Unable to create a valid id from string "{0}".
|
string-id: Unable to create a valid id from string "{0}".
|
||||||
no-proxy-cons: An exception was thrown while creating a new instance of \
|
|
||||||
custom proxy collection type "{0}". This could mean that there is no \
|
|
||||||
public no-args constructor for this type.
|
|
||||||
bad-single-id: Invalid single identity declaration for type "{0}". Only \
|
bad-single-id: Invalid single identity declaration for type "{0}". Only \
|
||||||
a single field can be declared for single field identity.
|
a single field can be declared for single field identity.
|
||||||
not-single: The given type "{0}" does not use single field identity.
|
not-single: The given type "{0}" does not use single field identity.
|
||||||
|
|
|
@ -0,0 +1,971 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.apache.openjpa.util;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.AbstractSequentialList;
|
||||||
|
import java.util.AbstractSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.textui.TestRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test proxies generated by the proxy manager.
|
||||||
|
*
|
||||||
|
* @author Abe White
|
||||||
|
*/
|
||||||
|
public class TestProxyManager
|
||||||
|
extends TestCase {
|
||||||
|
|
||||||
|
private ProxyManagerImpl _mgr;
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
_mgr = new ProxyManagerImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyLists() {
|
||||||
|
List orig = new ArrayList();
|
||||||
|
populate(orig);
|
||||||
|
assertListsEqual(orig, (List) _mgr.copyCollection(orig));
|
||||||
|
|
||||||
|
orig = new LinkedList();
|
||||||
|
populate(orig);
|
||||||
|
assertListsEqual(orig, (List) _mgr.copyCollection(orig));
|
||||||
|
|
||||||
|
orig = new CustomList();
|
||||||
|
populate(orig);
|
||||||
|
assertListsEqual(orig, (List) _mgr.copyCollection(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the given list with arbitrary data.
|
||||||
|
*/
|
||||||
|
private static void populate(Collection coll) {
|
||||||
|
coll.add(new Integer(1));
|
||||||
|
coll.add("foo");
|
||||||
|
coll.add(new Long(99));
|
||||||
|
coll.add("bar");
|
||||||
|
coll.add(new Short((short) 50));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given lists are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertListsEqual(List l1, List l2) {
|
||||||
|
assertTrue(l1.getClass() == l2.getClass());
|
||||||
|
assertEquals(l1.size(), l2.size());
|
||||||
|
for (int i = 0; i < l1.size(); i++)
|
||||||
|
assertTrue(l1.get(i) + " != " + l2.get(i), l1.get(i) == l2.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopySets() {
|
||||||
|
Set orig = new HashSet();
|
||||||
|
populate(orig);
|
||||||
|
assertSetsEqual(orig, (Set) _mgr.copyCollection(orig));
|
||||||
|
|
||||||
|
orig = new CustomSet();
|
||||||
|
populate(orig);
|
||||||
|
assertSetsEqual(orig, (Set) _mgr.copyCollection(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given sets are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertSetsEqual(Set s1, Set s2) {
|
||||||
|
assertTrue(s1.getClass() == s2.getClass());
|
||||||
|
assertEquals(s1.size(), s2.size());
|
||||||
|
assertEquals(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopySortedSets() {
|
||||||
|
SortedSet orig = new TreeSet();
|
||||||
|
populate(orig);
|
||||||
|
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
|
||||||
|
|
||||||
|
orig = new TreeSet(new CustomComparator());
|
||||||
|
populate(orig);
|
||||||
|
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
|
||||||
|
|
||||||
|
orig = new CustomSortedSet();
|
||||||
|
populate(orig);
|
||||||
|
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
|
||||||
|
|
||||||
|
orig = new CustomComparatorSortedSet(new CustomComparator());
|
||||||
|
populate(orig);
|
||||||
|
assertSortedSetsEqual(orig, (SortedSet) _mgr.copyCollection(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the given sorted set with arbitrary data.
|
||||||
|
*/
|
||||||
|
private static void populate(SortedSet coll) {
|
||||||
|
coll.add(new Integer(1));
|
||||||
|
coll.add(new Integer(99));
|
||||||
|
coll.add(new Integer(50));
|
||||||
|
coll.add(new Integer(-5));
|
||||||
|
coll.add(new Integer(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given sets are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertSortedSetsEqual(SortedSet s1, SortedSet s2) {
|
||||||
|
assertTrue(s1.getClass() == s2.getClass());
|
||||||
|
assertEquals(s1.comparator(), s2.comparator());
|
||||||
|
assertEquals(s1.size(), s2.size());
|
||||||
|
Iterator itr1 = s1.iterator();
|
||||||
|
Iterator itr2 = s2.iterator();
|
||||||
|
while (itr1.hasNext())
|
||||||
|
assertTrue(itr1.next() == itr2.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyNullCollection() {
|
||||||
|
assertNull(_mgr.copyCollection(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyProxyCollection() {
|
||||||
|
List orig = (List) _mgr.newCollectionProxy(ArrayList.class, null, null);
|
||||||
|
populate(orig);
|
||||||
|
assertListsEqual(new ArrayList(orig), (List) _mgr.copyCollection(orig));
|
||||||
|
|
||||||
|
TreeSet torig = (TreeSet) _mgr.newCollectionProxy(TreeSet.class, null,
|
||||||
|
new CustomComparator());
|
||||||
|
assertTrue(torig.comparator() instanceof CustomComparator);
|
||||||
|
populate(torig);
|
||||||
|
assertSortedSetsEqual(new TreeSet(torig), (SortedSet)
|
||||||
|
_mgr.copyCollection(torig));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newCollectionProxy(ArrayList.class, null, null).
|
||||||
|
getClass();
|
||||||
|
assertListMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newCollectionProxy(CustomList.class, null, null).
|
||||||
|
getClass();
|
||||||
|
assertListMethodsProxied(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the methods we need to override to dirty the collection are
|
||||||
|
* proxied appropriately.
|
||||||
|
*/
|
||||||
|
private void assertCollectionMethodsProxied(Class cls)
|
||||||
|
throws Exception {
|
||||||
|
assertNotNull(cls.getDeclaredMethod("add", new Class[] {Object.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("addAll",
|
||||||
|
new Class[] {Collection.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("clear", (Class[]) null));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("iterator", (Class[]) null));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("remove",
|
||||||
|
new Class[] {Object.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("removeAll",
|
||||||
|
new Class[] {Collection.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("retainAll",
|
||||||
|
new Class[] {Collection.class}));
|
||||||
|
|
||||||
|
// check a non-mutating method to make sure we're not just proxying
|
||||||
|
// everything
|
||||||
|
try {
|
||||||
|
cls.getDeclaredMethod("contains", new Class[] {Object.class});
|
||||||
|
fail("Proxied non-mutating method.");
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the methods we need to override to dirty the list are
|
||||||
|
* proxied appropriately.
|
||||||
|
*/
|
||||||
|
private void assertListMethodsProxied(Class cls)
|
||||||
|
throws Exception {
|
||||||
|
assertCollectionMethodsProxied(cls);
|
||||||
|
assertNotNull(cls.getDeclaredMethod("add",
|
||||||
|
new Class[] {int.class, Object.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("addAll",
|
||||||
|
new Class[] {int.class, Collection.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("listIterator", (Class[]) null));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("listIterator",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("remove", new Class[] {int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("set",
|
||||||
|
new Class[] {int.class, Object.class}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newCollectionProxy(HashSet.class, null, null).
|
||||||
|
getClass();
|
||||||
|
assertCollectionMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newCollectionProxy(CustomSet.class, null, null).getClass();
|
||||||
|
assertCollectionMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newCollectionProxy(CustomSortedSet.class, null, null).
|
||||||
|
getClass();
|
||||||
|
assertCollectionMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newCollectionProxy(CustomComparatorSortedSet.class, null,
|
||||||
|
new CustomComparator()).getClass();
|
||||||
|
assertCollectionMethodsProxied(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQueueMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class queue = getQueueClass();
|
||||||
|
if (queue == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Class proxy = _mgr.newCollectionProxy(LinkedList.class, null, null).
|
||||||
|
getClass();
|
||||||
|
assertTrue(queue.isAssignableFrom(proxy));
|
||||||
|
assertCollectionMethodsProxied(proxy);
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("offer",
|
||||||
|
new Class[] {Object.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("poll", (Class[]) null));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("remove", (Class[]) null));
|
||||||
|
try {
|
||||||
|
proxy.getDeclaredMethod("peek", (Class[]) null);
|
||||||
|
fail("Proxied non-mutating method.");
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLinkedListMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newCollectionProxy(LinkedList.class, null, null).
|
||||||
|
getClass();
|
||||||
|
assertListMethodsProxied(proxy);
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("addFirst",
|
||||||
|
new Class[] {Object.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("addLast",
|
||||||
|
new Class[] {Object.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("removeFirst", (Class[]) null));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("removeLast", (Class[]) null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testVectorMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newCollectionProxy(Vector.class, null, null).
|
||||||
|
getClass();
|
||||||
|
assertListMethodsProxied(proxy);
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("addElement",
|
||||||
|
new Class[] {Object.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("insertElementAt",
|
||||||
|
new Class[] {Object.class, int.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("removeAllElements",
|
||||||
|
(Class[]) null));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("removeElement",
|
||||||
|
new Class[] {Object.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("removeElementAt",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("setElementAt",
|
||||||
|
new Class[] {Object.class, int.class}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListChangeTracker() {
|
||||||
|
Proxy coll = _mgr.newCollectionProxy(ArrayList.class, null, null);
|
||||||
|
assertNotNull(coll);
|
||||||
|
assertNotNull(coll.getChangeTracker());
|
||||||
|
assertTrue(coll.getChangeTracker()
|
||||||
|
instanceof CollectionChangeTrackerImpl);
|
||||||
|
CollectionChangeTrackerImpl ct = (CollectionChangeTrackerImpl)
|
||||||
|
coll.getChangeTracker();
|
||||||
|
assertTrue(ct.allowsDuplicates());
|
||||||
|
assertTrue(ct.isOrdered());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetChangeTracker() {
|
||||||
|
Proxy coll = _mgr.newCollectionProxy(HashSet.class, null, null);
|
||||||
|
assertNotNull(coll);
|
||||||
|
assertNotNull(coll.getChangeTracker());
|
||||||
|
assertTrue(coll.getChangeTracker()
|
||||||
|
instanceof CollectionChangeTrackerImpl);
|
||||||
|
CollectionChangeTrackerImpl ct = (CollectionChangeTrackerImpl)
|
||||||
|
coll.getChangeTracker();
|
||||||
|
assertFalse(ct.allowsDuplicates());
|
||||||
|
assertFalse(ct.isOrdered());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCollectionInterfaceProxy() {
|
||||||
|
Proxy coll = _mgr.newCollectionProxy(Collection.class, null, null);
|
||||||
|
assertNotNull(coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListInterfaceProxy() {
|
||||||
|
Proxy coll = _mgr.newCollectionProxy(List.class, null, null);
|
||||||
|
assertNotNull(coll);
|
||||||
|
assertTrue(coll instanceof List);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetInterfaceProxy() {
|
||||||
|
Proxy coll = _mgr.newCollectionProxy(Set.class, null, null);
|
||||||
|
assertNotNull(coll);
|
||||||
|
assertTrue(coll instanceof Set);
|
||||||
|
assertFalse(coll instanceof SortedSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSortedSetInterfaceProxy() {
|
||||||
|
Proxy coll = _mgr.newCollectionProxy(SortedSet.class, null, null);
|
||||||
|
assertNotNull(coll);
|
||||||
|
assertTrue(coll instanceof SortedSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQueueInterfaceProxy() {
|
||||||
|
Class queue = getQueueClass();
|
||||||
|
if (queue == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Proxy coll = _mgr.newCollectionProxy(queue, null, null);
|
||||||
|
assertNotNull(coll);
|
||||||
|
assertTrue(queue.isInstance(coll));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@link java.util.Queue} class if avaialble.
|
||||||
|
*/
|
||||||
|
private static Class getQueueClass() {
|
||||||
|
try {
|
||||||
|
return Class.forName("java.util.Queue");
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyMaps() {
|
||||||
|
Map orig = new HashMap();
|
||||||
|
populate(orig);
|
||||||
|
assertMapsEqual(orig, (Map) _mgr.copyMap(orig));
|
||||||
|
|
||||||
|
orig = new CustomMap();
|
||||||
|
populate(orig);
|
||||||
|
assertMapsEqual(orig, (Map) _mgr.copyMap(orig));
|
||||||
|
|
||||||
|
Properties porig = new Properties();
|
||||||
|
porig.setProperty("foo", "bar");
|
||||||
|
porig.setProperty("bar", "biz");
|
||||||
|
porig.setProperty("biz", "baz");
|
||||||
|
assertMapsEqual(orig, (Map) _mgr.copyMap(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the given map with arbitrary data.
|
||||||
|
*/
|
||||||
|
private static void populate(Map map) {
|
||||||
|
map.put(new Integer(1), "1");
|
||||||
|
map.put(new Integer(99), "99");
|
||||||
|
map.put(new Integer(-2), "-2");
|
||||||
|
map.put(new Integer(50), "50");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given maps are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertMapsEqual(Map m1, Map m2) {
|
||||||
|
assertTrue(m1.getClass() == m2.getClass());
|
||||||
|
assertEquals(m1.size(), m2.size());
|
||||||
|
assertEquals(m1, m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopySortedMaps() {
|
||||||
|
SortedMap orig = new TreeMap();
|
||||||
|
populate(orig);
|
||||||
|
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
|
||||||
|
|
||||||
|
orig = new TreeMap(new CustomComparator());
|
||||||
|
populate(orig);
|
||||||
|
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
|
||||||
|
|
||||||
|
orig = new CustomSortedMap();
|
||||||
|
populate(orig);
|
||||||
|
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
|
||||||
|
|
||||||
|
orig = new CustomComparatorSortedMap(new CustomComparator());
|
||||||
|
populate(orig);
|
||||||
|
assertSortedMapsEqual(orig, (SortedMap) _mgr.copyMap(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given maps are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertSortedMapsEqual(SortedMap m1, SortedMap m2) {
|
||||||
|
assertTrue(m1.getClass() == m2.getClass());
|
||||||
|
assertEquals(m1.comparator(), m2.comparator());
|
||||||
|
assertEquals(m1.size(), m2.size());
|
||||||
|
Map.Entry entry1;
|
||||||
|
Map.Entry entry2;
|
||||||
|
Iterator itr1 = m1.entrySet().iterator();
|
||||||
|
Iterator itr2 = m2.entrySet().iterator();
|
||||||
|
while (itr1.hasNext()) {
|
||||||
|
entry1 = (Map.Entry) itr1.next();
|
||||||
|
entry2 = (Map.Entry) itr2.next();
|
||||||
|
assertTrue(entry1.getKey() == entry2.getKey());
|
||||||
|
assertTrue(entry1.getValue() == entry2.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyNullMap() {
|
||||||
|
assertNull(_mgr.copyMap(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyProxyMap() {
|
||||||
|
Map orig = (Map) _mgr.newMapProxy(HashMap.class, null, null, null);
|
||||||
|
populate(orig);
|
||||||
|
assertMapsEqual(new HashMap(orig), (Map) _mgr.copyMap(orig));
|
||||||
|
|
||||||
|
TreeMap torig = (TreeMap) _mgr.newMapProxy(TreeMap.class, null, null,
|
||||||
|
new CustomComparator());
|
||||||
|
assertTrue(torig.comparator() instanceof CustomComparator);
|
||||||
|
populate(torig);
|
||||||
|
assertSortedMapsEqual(new TreeMap(torig), (SortedMap)
|
||||||
|
_mgr.copyMap(torig));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMapMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newMapProxy(HashMap.class, null, null, null).
|
||||||
|
getClass();
|
||||||
|
assertMapMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newMapProxy(TreeMap.class, null, null, null).getClass();
|
||||||
|
assertMapMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newMapProxy(TreeMap.class, null, null,
|
||||||
|
new CustomComparator()).getClass();
|
||||||
|
assertMapMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newMapProxy(CustomMap.class, null, null, null).getClass();
|
||||||
|
assertMapMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newMapProxy(CustomSortedMap.class, null, null, null).
|
||||||
|
getClass();
|
||||||
|
assertMapMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newMapProxy(CustomComparatorSortedMap.class, null, null,
|
||||||
|
new CustomComparator()).getClass();
|
||||||
|
assertMapMethodsProxied(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the methods we need to override to dirty the collection are
|
||||||
|
* proxied appropriately.
|
||||||
|
*/
|
||||||
|
private void assertMapMethodsProxied(Class cls)
|
||||||
|
throws Exception {
|
||||||
|
assertNotNull(cls.getDeclaredMethod("put",
|
||||||
|
new Class[] {Object.class, Object.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("putAll", new Class[] {Map.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("clear", (Class[]) null));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("remove",
|
||||||
|
new Class[] {Object.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("keySet", (Class[]) null));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("values", (Class[]) null));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("entrySet", (Class[]) null));
|
||||||
|
|
||||||
|
// check a non-mutating method to make sure we're not just proxying
|
||||||
|
// everything
|
||||||
|
try {
|
||||||
|
cls.getDeclaredMethod("containsKey", new Class[] {Object.class});
|
||||||
|
fail("Proxied non-mutating method.");
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPropertiesMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newMapProxy(Properties.class, null, null, null).
|
||||||
|
getClass();
|
||||||
|
assertMapMethodsProxied(proxy);
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("setProperty",
|
||||||
|
new Class[] {String.class, String.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("load",
|
||||||
|
new Class[] {InputStream.class}));
|
||||||
|
assertNotNull(proxy.getDeclaredMethod("loadFromXML",
|
||||||
|
new Class[] {InputStream.class}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyDates() {
|
||||||
|
Date orig = new Date(1999);
|
||||||
|
assertDatesEqual(orig, (Date) _mgr.copyDate(orig));
|
||||||
|
|
||||||
|
orig = new java.sql.Date(1999);
|
||||||
|
assertDatesEqual(orig, (Date) _mgr.copyDate(orig));
|
||||||
|
|
||||||
|
orig = new Time(1999);
|
||||||
|
assertDatesEqual(orig, (Date) _mgr.copyDate(orig));
|
||||||
|
|
||||||
|
Timestamp torig = new Timestamp(1999);
|
||||||
|
torig.setNanos(2001);
|
||||||
|
assertDatesEqual(torig, (Date) _mgr.copyDate(torig));
|
||||||
|
|
||||||
|
torig = new CustomDate(1999);
|
||||||
|
torig.setNanos(2001);
|
||||||
|
assertDatesEqual(torig, (Date) _mgr.copyDate(torig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given dates are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertDatesEqual(Date d1, Date d2) {
|
||||||
|
assertTrue(d1.getClass() == d1.getClass());
|
||||||
|
assertEquals(d1, d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyNullDate() {
|
||||||
|
assertNull(_mgr.copyDate(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyProxyDate() {
|
||||||
|
Date orig = (Date) _mgr.newDateProxy(Time.class);
|
||||||
|
orig.setTime(1999);
|
||||||
|
assertDatesEqual(new Date(orig.getTime()), (Date) _mgr.copyDate(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDateMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newDateProxy(Date.class).getClass();
|
||||||
|
assertDateMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newDateProxy(java.sql.Date.class).getClass();
|
||||||
|
assertDateMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newDateProxy(Time.class).getClass();
|
||||||
|
assertDateMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newDateProxy(Timestamp.class).getClass();
|
||||||
|
assertTimestampMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newDateProxy(CustomDate.class).getClass();
|
||||||
|
assertTimestampMethodsProxied(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the methods we need to override to dirty the date are
|
||||||
|
* proxied appropriately.
|
||||||
|
*/
|
||||||
|
private void assertDateMethodsProxied(Class cls)
|
||||||
|
throws Exception {
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setDate",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setHours",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setMinutes",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setMonth",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setSeconds",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setTime",
|
||||||
|
new Class[] {long.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setYear",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
|
||||||
|
// check a non-mutating method to make sure we're not just proxying
|
||||||
|
// everything
|
||||||
|
try {
|
||||||
|
cls.getDeclaredMethod("getTime", (Class[]) null);
|
||||||
|
fail("Proxied non-mutating method.");
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the methods we need to override to dirty the timestamp are
|
||||||
|
* proxied appropriately.
|
||||||
|
*/
|
||||||
|
private void assertTimestampMethodsProxied(Class cls)
|
||||||
|
throws Exception {
|
||||||
|
assertDateMethodsProxied(cls);
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setNanos",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyCalendars() {
|
||||||
|
Calendar orig = new GregorianCalendar();
|
||||||
|
populate(orig);
|
||||||
|
assertCalendarsEqual(orig, _mgr.copyCalendar(orig));
|
||||||
|
|
||||||
|
orig = new CustomCalendar();
|
||||||
|
populate(orig);
|
||||||
|
assertCalendarsEqual(orig, _mgr.copyCalendar(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate calendar with arbitrary data.
|
||||||
|
*/
|
||||||
|
private static void populate(Calendar cal) {
|
||||||
|
cal.setTimeInMillis(1999);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("CST"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given dates are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertCalendarsEqual(Calendar c1, Calendar c2) {
|
||||||
|
assertTrue(c1.getClass() == c1.getClass());
|
||||||
|
assertEquals(c1, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyNullCalendar() {
|
||||||
|
assertNull(_mgr.copyCalendar(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyProxyCalendar() {
|
||||||
|
Calendar orig = (Calendar) _mgr.newCalendarProxy
|
||||||
|
(GregorianCalendar.class, TimeZone.getTimeZone("CST"));
|
||||||
|
populate(orig);
|
||||||
|
Calendar cal = new GregorianCalendar();
|
||||||
|
populate(cal);
|
||||||
|
assertCalendarsEqual(cal, _mgr.copyCalendar(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCalendarAbstractClassProxy() {
|
||||||
|
Proxy cal = _mgr.newCalendarProxy(Calendar.class, null);
|
||||||
|
assertNotNull(cal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCalendarMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newCalendarProxy(GregorianCalendar.class,
|
||||||
|
TimeZone.getDefault()).getClass();
|
||||||
|
assertCalendarMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newCalendarProxy(CustomCalendar.class,
|
||||||
|
TimeZone.getDefault()).getClass();
|
||||||
|
assertCalendarMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newCalendarProxy(Calendar.class,
|
||||||
|
TimeZone.getDefault()).getClass();
|
||||||
|
assertCalendarMethodsProxied(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the methods we need to override to dirty the calendar are
|
||||||
|
* proxied appropriately.
|
||||||
|
*/
|
||||||
|
private void assertCalendarMethodsProxied(Class cls)
|
||||||
|
throws Exception {
|
||||||
|
assertNotNull(cls.getDeclaredMethod("set",
|
||||||
|
new Class[] {int.class, int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("roll",
|
||||||
|
new Class[] {int.class, int.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setTimeInMillis",
|
||||||
|
new Class[] {long.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setTimeZone",
|
||||||
|
new Class[] {TimeZone.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("computeFields", (Class[]) null));
|
||||||
|
|
||||||
|
// check a non-mutating method to make sure we're not just proxying
|
||||||
|
// everything
|
||||||
|
try {
|
||||||
|
cls.getDeclaredMethod("getTimeInMillis", (Class[]) null);
|
||||||
|
fail("Proxied non-mutating method.");
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyBeans() {
|
||||||
|
CustomBean orig = new CustomBean();
|
||||||
|
populate(orig);
|
||||||
|
assertBeansEqual(orig, (CustomBean) _mgr.copyCustom(orig));
|
||||||
|
|
||||||
|
orig = new CustomCopyConstructorBean(orig);
|
||||||
|
assertBeansEqual(orig, (CustomBean) _mgr.copyCustom(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the given bean with arbitrary data.
|
||||||
|
*/
|
||||||
|
private void populate(CustomBean bean) {
|
||||||
|
bean.setString("foo");
|
||||||
|
bean.setNumber(99);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNonproxyableBean() {
|
||||||
|
NonproxyableBean orig = new NonproxyableBean(1);
|
||||||
|
populate(orig);
|
||||||
|
assertNull(_mgr.copyCustom(orig));
|
||||||
|
assertNull(_mgr.newCustomProxy(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the given beans are exactly the same.
|
||||||
|
*/
|
||||||
|
private static void assertBeansEqual(CustomBean b1, CustomBean b2) {
|
||||||
|
assertTrue(b1.getClass() == b2.getClass());
|
||||||
|
assertTrue(b1.getString() == b2.getString());
|
||||||
|
assertTrue(b1.getNumber() == b2.getNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyNullBean() {
|
||||||
|
assertNull(_mgr.copyCustom(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyProxyBean() {
|
||||||
|
CustomBean orig = (CustomBean) _mgr.newCustomProxy(new CustomBean());
|
||||||
|
populate(orig);
|
||||||
|
CustomBean comp = new CustomBean();
|
||||||
|
populate(comp);
|
||||||
|
assertBeansEqual(comp, (CustomBean) _mgr.copyCustom(orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBeanMethodsProxied()
|
||||||
|
throws Exception {
|
||||||
|
Class proxy = _mgr.newCustomProxy(new CustomBean()).getClass();
|
||||||
|
assertBeanMethodsProxied(proxy);
|
||||||
|
|
||||||
|
proxy = _mgr.newCustomProxy(new CustomCopyConstructorBean
|
||||||
|
(new CustomBean())).getClass();
|
||||||
|
assertBeanMethodsProxied(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the methods we need to override to dirty the bean are
|
||||||
|
* proxied appropriately.
|
||||||
|
*/
|
||||||
|
private void assertBeanMethodsProxied(Class cls)
|
||||||
|
throws Exception {
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setString",
|
||||||
|
new Class[] {String.class}));
|
||||||
|
assertNotNull(cls.getDeclaredMethod("setNumber",
|
||||||
|
new Class[] {int.class}));
|
||||||
|
|
||||||
|
// check a non-mutating method to make sure we're not just proxying
|
||||||
|
// everything
|
||||||
|
try {
|
||||||
|
cls.getDeclaredMethod("getString", (Class[]) null);
|
||||||
|
fail("Proxied non-mutating method.");
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TestRunner.run(TestProxyManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom list handling. Copy constructor intentionally
|
||||||
|
* ommitted.
|
||||||
|
*/
|
||||||
|
public static class CustomList
|
||||||
|
extends AbstractSequentialList {
|
||||||
|
|
||||||
|
private final List _delegate = new ArrayList();
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return _delegate.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListIterator listIterator(int idx) {
|
||||||
|
return _delegate.listIterator(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom set handling. Copy constructor intentionally
|
||||||
|
* ommitted.
|
||||||
|
*/
|
||||||
|
public static class CustomSet
|
||||||
|
extends AbstractSet {
|
||||||
|
|
||||||
|
private final Set _delegate = new HashSet();
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return _delegate.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator iterator() {
|
||||||
|
return _delegate.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(Object o) {
|
||||||
|
return _delegate.add(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom set handling. Copy constructor intentionally
|
||||||
|
* ommitted.
|
||||||
|
*/
|
||||||
|
public static class CustomSortedSet
|
||||||
|
extends TreeSet {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom set handling. Copy constructor intentionally
|
||||||
|
* ommitted.
|
||||||
|
*/
|
||||||
|
public static class CustomComparatorSortedSet
|
||||||
|
extends TreeSet {
|
||||||
|
|
||||||
|
public CustomComparatorSortedSet() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomComparatorSortedSet(Comparator comp) {
|
||||||
|
super(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom map handling. Copy constructor intentionally
|
||||||
|
* ommitted.
|
||||||
|
*/
|
||||||
|
public static class CustomMap
|
||||||
|
extends AbstractMap {
|
||||||
|
|
||||||
|
private final Map _delegate = new HashMap();
|
||||||
|
|
||||||
|
public Object put(Object key, Object value) {
|
||||||
|
return _delegate.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set entrySet() {
|
||||||
|
return _delegate.entrySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom map handling. Copy constructor intentionally
|
||||||
|
* ommitted.
|
||||||
|
*/
|
||||||
|
public static class CustomSortedMap
|
||||||
|
extends TreeMap {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom map handling. Copy constructor intentionally
|
||||||
|
* ommitted.
|
||||||
|
*/
|
||||||
|
public static class CustomComparatorSortedMap
|
||||||
|
extends TreeMap {
|
||||||
|
|
||||||
|
public CustomComparatorSortedMap() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomComparatorSortedMap(Comparator comp) {
|
||||||
|
super(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test transfer of comparators to proxies.
|
||||||
|
*/
|
||||||
|
private static class CustomComparator
|
||||||
|
implements Comparator {
|
||||||
|
|
||||||
|
public int compare(Object o1, Object o2) {
|
||||||
|
return ((Comparable) o1).compareTo(o2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom date handling.
|
||||||
|
*/
|
||||||
|
public static class CustomDate
|
||||||
|
extends Timestamp {
|
||||||
|
|
||||||
|
public CustomDate(long time) {
|
||||||
|
super(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom bean handling.
|
||||||
|
*/
|
||||||
|
public static class CustomBean {
|
||||||
|
private String _string;
|
||||||
|
private int _number;
|
||||||
|
|
||||||
|
public String getString() {
|
||||||
|
return _string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setString(String str) {
|
||||||
|
_string = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumber() {
|
||||||
|
return _number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumber(int number) {
|
||||||
|
_number = number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom bean handling.
|
||||||
|
*/
|
||||||
|
public static class CustomCopyConstructorBean
|
||||||
|
extends CustomBean {
|
||||||
|
|
||||||
|
public CustomCopyConstructorBean(CustomBean bean) {
|
||||||
|
setString(bean.getString());
|
||||||
|
setNumber(bean.getNumber());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to non-proxyable custom bean handling.
|
||||||
|
*/
|
||||||
|
public static class NonproxyableBean
|
||||||
|
extends CustomBean {
|
||||||
|
|
||||||
|
public NonproxyableBean(long x) {
|
||||||
|
// single non-default, non-copy constructor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test custom calendar handling.
|
||||||
|
*/
|
||||||
|
public static class CustomCalendar
|
||||||
|
extends GregorianCalendar {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue