openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jrba...@apache.org
Subject svn commit: r1335720 [2/5] - in /openjpa/branches/2.2.x: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-jdbc/sr...
Date Tue, 08 May 2012 19:46:23 GMT
Added: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedListProxy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedListProxy.java?rev=1335720&view=auto
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedListProxy.java (added)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedListProxy.java Tue May  8 19:46:20 2012
@@ -0,0 +1,701 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.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.List;
+import java.util.ListIterator;
+
+import org.apache.openjpa.kernel.AutoDetach;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.BrokerFactory;
+import org.apache.openjpa.kernel.DetachedStateManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * LinkedList proxy with delay loading capability.  Allows non-indexed
+ * add and remove operations to occur on an unloaded collection.  Operations
+ * that require a load will trigger a load.
+ */
+@SuppressWarnings({"rawtypes","unchecked"})
+public class DelayedLinkedListProxy extends LinkedList implements ProxyCollection, DelayedProxy {
+
+    private transient OpenJPAStateManager sm;
+    private transient int field;
+    private transient CollectionChangeTracker changeTracker;
+    private transient Class elementType;
+
+    private transient OpenJPAStateManager _ownerSm;
+    private transient boolean _directAccess = false;
+    private transient BrokerFactory _brokerFactory = null;
+    private transient Broker _broker = null;
+    private transient OpenJPAStateManager _delayedSm;
+    private transient int _delayedField;
+    private transient boolean _detached = false;
+
+    public DelayedLinkedListProxy(Collection paramCollection) {
+        super(paramCollection);
+    }
+
+    public DelayedLinkedListProxy() {
+    }
+
+    @Override
+    public void setOwner(OpenJPAStateManager paramOpenJPAStateManager,
+            int paramInt) {
+        // If clearing the owner of this proxy, store away what is necessary for
+        // delayed loading
+        if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) {
+            _detached = true;
+            _delayedSm = sm;
+            _delayedField = field;
+        } else {
+            _detached = false;
+        }
+
+        this.sm = paramOpenJPAStateManager;
+        if (sm != null && sm.getPersistenceCapable() != null) {
+            _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable()
+                    .pcGetStateManager();
+        }
+        this.field = paramInt;
+        if (sm != null && sm.getContext() != null) {
+            _brokerFactory = sm.getContext().getBroker().getBrokerFactory();
+        }
+    }
+
+    private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager,
+            int paramInt) {
+        if ((paramOpenJPAStateManager == null && paramInt == -1)
+                || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public OpenJPAStateManager getOwner() {
+        return this.sm;
+    }
+
+    @Override
+    public int getOwnerField() {
+        return this.field;
+    }
+
+    @Override
+    public ChangeTracker getChangeTracker() {
+        return this.changeTracker;
+    }
+
+    @Override
+    public Object copy(Object paramObject) {
+        return new LinkedList((Collection) paramObject);
+    }
+
+    @Override
+    public Class getElementType() {
+        return this.elementType;
+    }
+
+    @Override
+    public ProxyCollection newInstance(Class paramClass,
+            Comparator paramComparator, boolean paramBoolean1,
+            boolean paramBoolean2) {
+        DelayedLinkedListProxy localproxy = new DelayedLinkedListProxy();
+        localproxy.elementType = paramClass;
+        if (paramBoolean1)
+            localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl(
+                    localproxy, true, true, paramBoolean2);
+        return localproxy;
+    }
+
+    // //////////////////////////////////////
+    // DelayedProxy methods
+    // //////////////////////////////////////
+    @Override
+    public int getDelayedField() {
+        if (field == -1 || _detached) {
+            return _delayedField;
+        }
+        return field;
+    }
+
+    @Override
+    public OpenJPAStateManager getDelayedOwner() {
+        if (sm == null || _detached) {
+            return _delayedSm;
+        }
+        return sm;
+    }
+
+    @Override
+    public boolean isDirectAccess() {
+        return _directAccess;
+    }
+
+    @Override
+    public void setDirectAccess(boolean direct) {
+        _directAccess = direct;
+    }
+
+    public BrokerFactory getBrokerFactory() {
+        return _brokerFactory;
+    }
+
+    @Override
+    public void load() {
+        ProxyCollections.loadCollection(this);
+    }
+
+    @Override
+    public Broker getBroker() {
+        if (_broker == null || _broker.isClosed()) {
+            if (_brokerFactory != null) {
+                _broker = _brokerFactory.newBroker();
+            }
+        }
+        return _broker;
+    }
+
+    @Override
+    public void closeBroker() {
+        if (_broker != null && !_broker.isClosed()) {
+            _broker.setAutoDetach(AutoDetach.DETACH_CLOSE);
+            _broker.close();
+            _broker = null;
+        }
+    }
+
+    @Override
+    public OpenJPAStateManager getOwnerStateManager() {
+        return _ownerSm;
+    }
+
+    @Override
+    public boolean isDetached() {
+        return _detached;
+    }
+
+    public boolean isDelayLoad() {
+        return ProxyCollections.isDelayed(this);
+    }
+
+    // //////////////////////////////////////
+    // Implementation method wrappers
+    // //////////////////////////////////////
+
+    @Override
+    public Object clone() {
+        if (_directAccess) {
+            return super.clone();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Proxy localProxy = (Proxy) super.clone();
+        localProxy.setOwner(null, 0);
+        return localProxy;
+    }
+
+    @Override
+    public void add(int paramInt, Object paramObject) {
+        if (!_directAccess) {
+            if (isDelayLoad()) {
+                load();
+            }
+        }
+        ProxyCollections.beforeAdd(this, paramInt, paramObject);
+        super.add(paramInt, paramObject);
+    }
+
+    @Override
+    public boolean add(Object paramObject) {
+        if (_directAccess) {
+            return super.add(paramObject);
+        }
+        ProxyCollections.beforeAdd(this, paramObject);
+        boolean bool = super.add(paramObject);
+        return ProxyCollections.afterAdd(this, paramObject, bool);
+    }
+
+    @Override
+    public void clear() {
+        if (!_directAccess) {
+            if (isDelayLoad()) {
+                load();
+            }
+            ProxyCollections.beforeClear(this);
+        }
+        super.clear();
+    }
+
+    @Override
+    public boolean addAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.addAll(paramCollection);
+        }
+        return ProxyCollections.addAll(this, paramCollection);
+    }
+
+    @Override
+    public boolean addAll(int paramInt, Collection paramCollection) {
+        if (_directAccess) {
+            return super.addAll(paramInt, paramCollection);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return ProxyCollections.addAll(this, paramInt, paramCollection);
+    }
+
+    @Override
+    public boolean remove(Object paramObject) {
+        if (_directAccess) {
+            return super.remove(paramObject);
+        }
+        ProxyCollections.beforeRemove(this, paramObject);
+        setDirectAccess(true);
+        boolean bool = super.remove(paramObject);
+        setDirectAccess(false);
+        return ProxyCollections.afterRemove(this, paramObject, bool);
+    }
+
+    @Override
+    public Object remove(int paramInt) {
+        if (_directAccess) {
+            return super.remove(paramInt);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeRemove(this, paramInt);
+        Object localObject = super.remove(paramInt);
+        return ProxyCollections.afterRemove(this, paramInt, localObject);
+    }
+
+    @Override
+    public Object remove() {
+        if (_directAccess) {
+            return super.remove();
+        }
+        // queue operations require proper ordering. the collection
+        // must be loaded in order to ensure order.
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeRemove(this);
+        Object localObject = super.remove();
+        return ProxyCollections.afterRemove(this, localObject);
+    }
+
+    @Override
+    public Object set(int paramInt, Object paramObject) {
+        if (_directAccess) {
+            return super.set(paramInt, paramObject);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeSet(this, paramInt, paramObject);
+        Object localObject = super.set(paramInt, paramObject);
+        return ProxyCollections.afterSet(this, paramInt, paramObject,
+                localObject);
+    }
+
+    @Override
+    public Object poll() {
+        if (_directAccess) {
+            return super.poll();
+        }
+        // queue operations require proper ordering. the collection
+        // must be loaded in order to ensure order.
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforePoll(this);
+        Object localObject = super.poll();
+        return ProxyCollections.afterPoll(this, localObject);
+    }
+
+    @Override
+    public ListIterator listIterator(int paramInt) {
+        if (_directAccess) {
+            return super.listIterator(paramInt);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ListIterator localListIterator = super.listIterator(paramInt);
+        return ProxyCollections.afterListIterator(this, paramInt,
+                localListIterator);
+    }
+
+    @Override
+    public void addFirst(Object paramObject) {
+        if (_directAccess) {
+            super.addFirst(paramObject);
+            return;
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeAddFirst(this, paramObject);
+        super.addFirst(paramObject);
+    }
+
+    @Override
+    public void addLast(Object paramObject) {
+        if (_directAccess) {
+            super.addLast(paramObject);
+            return;
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeAddLast(this, paramObject);
+        super.addLast(paramObject);
+        ProxyCollections.afterAddLast(this, paramObject);
+    }
+
+    @Override
+    public boolean offer(Object paramObject) {
+        if (_directAccess) {
+            return super.offer(paramObject);
+        }
+        ProxyCollections.beforeOffer(this, paramObject);
+        boolean bool = super.offer(paramObject);
+        return ProxyCollections.afterOffer(this, paramObject, bool);
+    }
+
+    @Override
+    public Object removeFirst() {
+        if (_directAccess) {
+            return super.removeFirst();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeRemoveFirst(this);
+        Object localObject = super.removeFirst();
+        return ProxyCollections.afterRemoveFirst(this, localObject);
+    }
+
+    @Override
+    public Object removeLast() {
+        if (_directAccess) {
+            return super.removeLast();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeRemoveLast(this);
+        Object localObject = super.removeLast();
+        return ProxyCollections.afterRemoveLast(this, localObject);
+    }
+
+    @Override
+    public Iterator iterator() {
+        if (_directAccess) {
+            return super.iterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Iterator localIterator = super.iterator();
+        return ProxyCollections.afterIterator(this, localIterator);
+    }
+
+    @Override
+    public ListIterator listIterator() {
+        if (_directAccess) {
+            return super.listIterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ListIterator localListIterator = super.listIterator();
+        return ProxyCollections.afterListIterator(this, localListIterator);
+    }
+
+    @Override
+    public boolean removeAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.removeAll(paramCollection);
+        }
+        return ProxyCollections.removeAll(this, paramCollection);
+    }
+
+    @Override
+    public boolean retainAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.retainAll(paramCollection);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return ProxyCollections.retainAll(this, paramCollection);
+    }
+
+    @Override
+    public boolean removeFirstOccurrence(Object paramObject) {
+        if (_directAccess) {
+            return super.removeFirstOccurrence(paramObject);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Proxies.dirty(this, true);
+        return super.removeFirstOccurrence(paramObject);
+    }
+
+    @Override
+    public boolean removeLastOccurrence(Object paramObject) {
+        if (_directAccess) {
+            return super.removeLastOccurrence(paramObject);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Proxies.dirty(this, true);
+        return super.removeLastOccurrence(paramObject);
+    }
+
+    protected Object writeReplace() throws ObjectStreamException {
+        if (isDelayLoad()) {
+            load();
+        }
+        return Proxies.writeReplace(this, true);
+    }
+
+    @Override
+    public boolean equals(Object paramObject) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.equals(paramObject);
+    }
+
+    @Override
+    public int hashCode() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.hashCode();
+    }
+
+    @Override
+    public List subList(int fromIndex, int toIndex) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.subList(fromIndex, toIndex);
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.lastIndexOf(o);
+    }
+
+    @Override
+    public int indexOf(Object o) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.indexOf(o);
+    }
+
+    @Override
+    public Object get(int index) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.get(index);
+    }
+
+    @Override
+    public boolean containsAll(Collection c) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.containsAll(c);
+    }
+
+    @Override
+    public Object[] toArray() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray();
+    }
+
+    @Override
+    public Object[] toArray(Object[] array) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray(array);
+    }
+
+    @Override
+    public boolean contains(Object object) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.contains(object);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.isEmpty();
+    }
+
+    @Override
+    public int size() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.size();
+    }
+
+    @Override
+    public boolean offerFirst(Object paramObject) {
+        if (_directAccess) {
+            return super.offerFirst(paramObject);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return super.offerFirst(paramObject);
+    }
+
+    @Override
+    public boolean offerLast(Object paramObject) {
+        if (_directAccess) {
+            return super.offerLast(paramObject);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return super.offerLast(paramObject);
+    }
+
+    @Override
+    public Object pollFirst() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.pollFirst();
+        
+    }
+
+    @Override
+    public Object pollLast() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.pollLast();
+    }
+    
+    @Override
+    public Object getFirst() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.getFirst();        
+    }
+
+    @Override
+    public Object getLast() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.getLast();
+    }
+    
+    @Override
+    public Object peekFirst() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.peekFirst();
+    }
+    
+    @Override
+    public Object peekLast() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.peekLast();
+    }
+
+    @Override
+    public Object element() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.element();
+    }
+    
+    @Override
+    public Object peek() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.peek();
+    }
+    
+    @Override
+    public void push(Object o) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        super.push(o);
+    }
+    
+    @Override
+    public Object pop() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.pop();
+    }
+
+    @Override
+    public Iterator descendingIterator() {
+        if (_directAccess) {
+            return super.descendingIterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Iterator localIterator = super.descendingIterator();
+        return ProxyCollections.afterIterator(this, localIterator);
+    }
+}

Propchange: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedLinkedListProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedPriorityQueueProxy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedPriorityQueueProxy.java?rev=1335720&view=auto
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedPriorityQueueProxy.java (added)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedPriorityQueueProxy.java Tue May  8 19:46:20 2012
@@ -0,0 +1,429 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.util;
+
+import java.io.ObjectStreamException;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.PriorityQueue;
+import java.util.SortedSet;
+
+import org.apache.openjpa.kernel.AutoDetach;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.BrokerFactory;
+import org.apache.openjpa.kernel.DetachedStateManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * PriorityQueue proxy with delay loading capability.  Allows non-indexed
+ * add and remove operations to occur on an unloaded collection.  Operations
+ * that require a load will trigger a load.
+ */
+@SuppressWarnings({"rawtypes","unchecked"})
+public class DelayedPriorityQueueProxy extends PriorityQueue implements ProxyCollection, DelayedProxy {
+    private transient OpenJPAStateManager sm;
+    private transient int field;
+    private transient CollectionChangeTracker changeTracker;
+    private transient Class elementType;
+
+    private transient OpenJPAStateManager _ownerSm;
+    private transient boolean _directAccess = false;
+    private transient BrokerFactory _brokerFactory = null;
+    private transient Broker _broker = null;
+    private transient OpenJPAStateManager _delayedSm;
+    private transient int _delayedField;
+    private transient boolean _detached = false;
+
+    public DelayedPriorityQueueProxy(int paramInt) {
+        super(paramInt);
+    }
+
+    public DelayedPriorityQueueProxy(int paramInt, Comparator paramComparator) {
+        super(paramInt, paramComparator);
+    }
+
+    public DelayedPriorityQueueProxy(Collection paramCollection) {
+        super(paramCollection);
+    }
+
+    public DelayedPriorityQueueProxy(PriorityQueue paramPriorityQueue) {
+        super(paramPriorityQueue);
+    }
+
+    public DelayedPriorityQueueProxy(SortedSet paramSortedSet) {
+        super(paramSortedSet);
+    }
+
+    public DelayedPriorityQueueProxy() {
+    }
+
+    @Override
+    public void setOwner(OpenJPAStateManager paramOpenJPAStateManager,
+            int paramInt) {
+        // If clearing the owner of this proxy, store away what is necessary for
+        // delayed loading
+        if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) {
+            _detached = true;
+            _delayedSm = sm;
+            _delayedField = field;
+        } else {
+            _detached = false;
+        }
+
+        this.sm = paramOpenJPAStateManager;
+        if (sm != null && sm.getPersistenceCapable() != null) {
+            _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable()
+                    .pcGetStateManager();
+        }
+        this.field = paramInt;
+        if (sm != null && sm.getContext() != null) {
+            _brokerFactory = sm.getContext().getBroker().getBrokerFactory();
+        }
+    }
+
+    private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager,
+            int paramInt) {
+        if ((paramOpenJPAStateManager == null && paramInt == -1)
+                || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) {
+            return true;
+        }
+        return false;
+    }
+
+    public OpenJPAStateManager getOwner() {
+        return this.sm;
+    }
+
+    public int getOwnerField() {
+        return this.field;
+    }
+
+    @Override
+    public Object clone() throws CloneNotSupportedException {
+        if (_directAccess) {
+            return super.clone();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Proxy localProxy = (Proxy) super.clone();
+        localProxy.setOwner(null, 0);
+        return localProxy;
+    }
+
+    public ChangeTracker getChangeTracker() {
+        return this.changeTracker;
+    }
+
+    public Object copy(Object paramObject) {
+        return new PriorityQueue((PriorityQueue) paramObject);
+    }
+
+    public Class getElementType() {
+        return this.elementType;
+    }
+
+    public ProxyCollection newInstance(Class paramClass,
+            Comparator paramComparator, boolean paramBoolean1,
+            boolean paramBoolean2) {
+        DelayedPriorityQueueProxy localproxy = new DelayedPriorityQueueProxy();
+        localproxy.elementType = paramClass;
+        if (paramBoolean1)
+            localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl(
+                    localproxy, true, false, paramBoolean2);
+        return localproxy;
+    }
+
+    @Override
+    public boolean add(Object paramObject) {
+        if (_directAccess) {
+            return super.add(paramObject);
+        }
+        ProxyCollections.beforeAdd(this, paramObject);
+        boolean bool = false;
+        try {
+            setDirectAccess(true);
+            bool = super.add(paramObject);
+        } finally {
+            setDirectAccess(false);
+        }
+        return ProxyCollections.afterAdd(this, paramObject, bool);
+    }
+
+    @Override
+    public void clear() {
+        if (!_directAccess) {
+            if (isDelayLoad()) {
+                load();
+            }
+            ProxyCollections.beforeClear(this);
+        }
+        super.clear();
+    }
+
+    @Override
+    public Iterator iterator() {
+        if (_directAccess) {
+            return super.iterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Iterator localIterator = super.iterator();
+        return ProxyCollections.afterIterator(this, localIterator);
+    }
+
+    @Override
+    public boolean remove(Object paramObject) {
+        if (_directAccess) {
+            return super.remove(paramObject);
+        }
+        ProxyCollections.beforeRemove(this, paramObject);
+        setDirectAccess(true);
+        boolean bool = super.remove(paramObject);
+        setDirectAccess(false);
+        return ProxyCollections.afterRemove(this, paramObject, bool);
+    }
+
+    @Override
+    public Object poll() {
+        if (_directAccess) {
+            return super.poll();
+        }
+        // queue operations require proper ordering. the collection
+        // must be loaded in order to ensure order.
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforePoll(this);
+        Object localObject = super.poll();
+        return ProxyCollections.afterPoll(this, localObject);
+    }
+
+    @Override
+    public boolean offer(Object paramObject) {
+        if (_directAccess) {
+            return super.offer(paramObject);
+        }
+        ProxyCollections.beforeOffer(this, paramObject);
+        boolean bool = super.offer(paramObject);
+        return ProxyCollections.afterOffer(this, paramObject, bool);
+    }
+
+    @Override
+    public boolean addAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.addAll(paramCollection);
+        }
+        return ProxyCollections.addAll(this, paramCollection);
+    }
+
+    @Override
+    public Object remove() {
+        if (_directAccess) {
+            return super.remove();
+        }
+        // queue operations require proper ordering. the collection
+        // must be loaded in order to ensure order.
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeRemove(this);
+        Object localObject = super.remove();
+        return ProxyCollections.afterRemove(this, localObject);
+    }
+
+    @Override
+    public boolean removeAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.removeAll(paramCollection);
+        }
+        return ProxyCollections.removeAll(this, paramCollection);
+    }
+
+    @Override
+    public boolean retainAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.retainAll(paramCollection);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return ProxyCollections.retainAll(this, paramCollection);
+    }
+
+    protected Object writeReplace() throws ObjectStreamException {
+        if (isDelayLoad()) {
+            load();
+        }
+        return Proxies.writeReplace(this, true);
+    }
+
+    @Override
+    public int size() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object object) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.contains(object);
+    }
+
+    @Override
+    public Object[] toArray() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray();
+    }
+
+    @Override
+    public Object[] toArray(Object[] array) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray(array);
+    }
+
+    @Override
+    public boolean containsAll(Collection c) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.containsAll(c);
+    }
+
+    @Override
+    public Object element() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.element();
+    }
+
+    @Override
+    public Object peek() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.peek();
+    }
+
+    @Override
+    public boolean equals(Object paramObject) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.equals(paramObject);
+    }
+
+    @Override
+    public int hashCode() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.hashCode();
+    }
+
+    // //////////////////////////////////////
+    // DelayedProxy methods
+    // //////////////////////////////////////
+    @Override
+    public int getDelayedField() {
+        if (field == -1 || _detached) {
+            return _delayedField;
+        }
+        return field;
+    }
+
+    @Override
+    public OpenJPAStateManager getDelayedOwner() {
+        if (sm == null || _detached) {
+            return _delayedSm;
+        }
+        return sm;
+    }
+
+    @Override
+    public boolean isDirectAccess() {
+        return _directAccess;
+    }
+
+    @Override
+    public void setDirectAccess(boolean direct) {
+        _directAccess = direct;
+    }
+
+    public BrokerFactory getBrokerFactory() {
+        return _brokerFactory;
+    }
+
+    @Override
+    public void load() {
+        ProxyCollections.loadCollection(this);
+    }
+
+    @Override
+    public Broker getBroker() {
+        if (_broker == null || _broker.isClosed()) {
+            if (_brokerFactory != null) {
+                _broker = _brokerFactory.newBroker();
+            }
+        }
+        return _broker;
+    }
+
+    @Override
+    public void closeBroker() {
+        if (_broker != null && !_broker.isClosed()) {
+            _broker.setAutoDetach(AutoDetach.DETACH_CLOSE);
+            _broker.close();
+            _broker = null;
+        }
+    }
+
+    @Override
+    public OpenJPAStateManager getOwnerStateManager() {
+        return _ownerSm;
+    }
+
+    @Override
+    public boolean isDetached() {
+        return _detached;
+    }
+
+    public boolean isDelayLoad() {
+        return ProxyCollections.isDelayed(this);
+    }
+}

Propchange: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedPriorityQueueProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedProxy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedProxy.java?rev=1335720&view=auto
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedProxy.java (added)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedProxy.java Tue May  8 19:46:20 2012
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.util;
+
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * Implemented by proxy classes which are delay-load capable. Delay-load
+ * proxies are lazily loaded and provide some operations
+ * which allow manipulation of proxy without necessarily needing to
+ * load the proxied object. 
+ */
+public interface DelayedProxy {
+    
+    /**
+     * Load the proxy if it was delay-loaded.
+     */
+    void load();
+
+    /**
+     * Returns whether the caller has direct-call access to the proxied
+     * object.  Direct access allows calls to be made on the object
+     * without triggering a load or proxy state tracking callbacks. 
+     */
+    boolean isDirectAccess();
+    
+    /**
+     * Sets whether the caller has direct-call access to the proxied
+     * object.  Direct access allows calls to be made on the object
+     * without triggering a load or proxy state tracking callbacks. 
+     */
+    void setDirectAccess(boolean direct);
+        
+    /**
+     * Get the broker that is used to service this proxy.
+     */
+    Broker getBroker();
+
+    /**
+     * Close the broker that is used to service this proxy.
+     */
+    void closeBroker();
+
+    /**
+     * Returns the state manager of the owning instance.
+     */
+    OpenJPAStateManager getOwnerStateManager();
+    
+    /**
+     * Returns a state manager that can service this proxy even if
+     * the collection was detached.
+     */
+    OpenJPAStateManager getDelayedOwner();
+    
+    /**
+     * Returns the expected field index even if this collection
+     * was detached.
+     * @return
+     */
+    int getDelayedField();
+    
+    /**
+     * Returns whether the proxy is detached.
+     * @return
+     */
+    boolean isDetached();
+}

Propchange: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedTreeSetProxy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedTreeSetProxy.java?rev=1335720&view=auto
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedTreeSetProxy.java (added)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedTreeSetProxy.java Tue May  8 19:46:20 2012
@@ -0,0 +1,500 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.util;
+
+import java.io.ObjectStreamException;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.NavigableSet;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.openjpa.kernel.AutoDetach;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.BrokerFactory;
+import org.apache.openjpa.kernel.DetachedStateManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * TreeSet proxy with delay loading capability.  Allows non-indexed
+ * add and remove operations to occur on an unloaded collection.  Operations
+ * that require a load will trigger a load.
+ */
+@SuppressWarnings({"rawtypes","unchecked"})
+public class DelayedTreeSetProxy extends TreeSet implements ProxyCollection, DelayedProxy {
+    private transient OpenJPAStateManager sm;
+    private transient int field;
+    private transient CollectionChangeTracker changeTracker;
+    private transient Class elementType;
+
+    private transient OpenJPAStateManager _ownerSm;
+    private transient boolean _directAccess = false;
+    private transient BrokerFactory _brokerFactory = null;
+    private transient Broker _broker = null;
+    private transient OpenJPAStateManager _delayedSm;
+    private transient int _delayedField; 
+    private transient boolean _detached = false;
+    
+    public DelayedTreeSetProxy() {
+    }
+
+    public DelayedTreeSetProxy(Comparator paramComparator) {
+        super(paramComparator);
+    }
+
+    public DelayedTreeSetProxy(Collection paramCollection) {
+        super(paramCollection);
+    }
+
+    public DelayedTreeSetProxy(SortedSet paramSortedSet) {
+        super(paramSortedSet);
+    }
+
+    public void setOwner(OpenJPAStateManager paramOpenJPAStateManager, int paramInt)
+    {
+      // If clearing the owner of this proxy, store away what is necessary for 
+      // delayed loading 
+      if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) {
+          _detached = true;
+          _delayedSm = sm;
+          _delayedField = field;
+      } else {
+          _detached = false;
+      }
+      
+      this.sm = paramOpenJPAStateManager;
+      if (sm != null && sm.getPersistenceCapable() != null) {
+          _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable().pcGetStateManager();
+      }
+      this.field = paramInt;
+      if (sm != null && sm.getContext() != null) {
+          _brokerFactory = sm.getContext().getBroker().getBrokerFactory();
+      }
+    }
+    
+    private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager, int paramInt) {
+        if ((paramOpenJPAStateManager == null && paramInt == -1) || 
+            (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) {
+            return true;
+        }
+        return false;
+    }
+
+    public OpenJPAStateManager getOwner() {
+        return this.sm;
+    }
+
+    public int getOwnerField() {
+        return this.field;
+    }
+
+    public ChangeTracker getChangeTracker() {
+        return this.changeTracker;
+    }
+
+    public Object copy(Object paramObject) {
+        return new TreeSet((SortedSet) paramObject);
+    }
+
+    public Class getElementType() {
+        return this.elementType;
+    }
+
+    public ProxyCollection newInstance(Class paramClass,
+            Comparator paramComparator, boolean paramBoolean1,
+            boolean paramBoolean2) {
+        DelayedTreeSetProxy localproxy = new DelayedTreeSetProxy(
+                paramComparator);
+        localproxy.elementType = paramClass;
+        if (paramBoolean1)
+            localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl(
+                    localproxy, false, false, paramBoolean2);
+        return localproxy;
+    }
+
+    @Override
+    public Object clone() {
+        if (_directAccess) {
+            return super.clone();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Proxy localProxy = (Proxy) super.clone();
+        localProxy.setOwner(null, 0);
+        return localProxy;
+    }
+
+
+    protected Object writeReplace() throws ObjectStreamException {
+        if (isDelayLoad()) {
+            load();
+        }
+        return Proxies.writeReplace(this, true);
+    }
+    
+    ////////////////////////////////////////
+    // DelayedProxy methods
+    ////////////////////////////////////////
+    public int getDelayedField() {
+        if (field == -1 || _detached) {
+            return _delayedField;
+        }
+        return field;
+    }
+    
+    public OpenJPAStateManager getDelayedOwner() {
+        if (sm == null || _detached) {
+            return _delayedSm;
+        }
+        return sm;
+    }
+
+    public boolean isDirectAccess() {
+        return _directAccess;
+    }
+    
+    public void setDirectAccess(boolean direct) {
+        _directAccess = direct;
+    }
+    
+    public BrokerFactory getBrokerFactory() {
+        return _brokerFactory;
+    }
+
+    @Override
+    public void load() {
+        ProxyCollections.loadCollection(this);
+    }
+
+    @Override
+    public Broker getBroker() {
+      if (_broker == null || _broker.isClosed()) {
+          if (_brokerFactory != null) {
+              _broker = _brokerFactory.newBroker();
+          }
+      }
+      return _broker;
+    }
+    
+    @Override
+    public void closeBroker() {
+        if (_broker != null && !_broker.isClosed()) {
+            _broker.setAutoDetach(AutoDetach.DETACH_CLOSE);
+            _broker.close();
+            _broker = null;
+        }
+    }
+
+    @Override
+    public OpenJPAStateManager getOwnerStateManager() {
+      return _ownerSm;
+    }
+    
+    @Override
+    public boolean isDetached() {
+        return _detached;
+    }
+
+    public boolean isDelayLoad() {
+        return ProxyCollections.isDelayed(this);
+    }
+
+    ////////////////////////////////////////
+    // TreeSet methods
+    ////////////////////////////////////////
+
+    @Override
+    public void clear() {
+        if (!_directAccess) {
+            if (isDelayLoad()) {
+                load();
+            }
+            ProxyCollections.beforeClear(this);
+        }
+        super.clear();
+    }
+
+    @Override
+    public Iterator iterator() {
+        if (_directAccess) {
+            return super.iterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Iterator localIterator = super.iterator();
+        return ProxyCollections.afterIterator(this, localIterator);
+    }
+
+    @Override
+    public boolean remove(Object paramObject) {
+        if (_directAccess) {
+            return super.remove(paramObject);
+        }
+        ProxyCollections.beforeRemove(this, paramObject);
+        setDirectAccess(true);
+        boolean bool = super.remove(paramObject);
+        setDirectAccess(false);
+        return ProxyCollections.afterRemove(this, paramObject, bool);
+    }
+
+    @Override
+    public int size() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object object) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.contains(object);
+    }
+
+    @Override
+    public Object[] toArray() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray();
+    }
+
+    @Override
+    public Object[] toArray(Object[] array) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray(array);
+    }
+
+    @Override
+    public Comparator comparator() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.comparator();
+    }
+
+    @Override
+    public Object first() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.first();
+    }
+
+    @Override
+    public Object last() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.last();
+    }
+
+    @Override
+    public boolean add(Object paramObject) {
+        if (_directAccess) {
+            return super.add(paramObject);
+        }
+        ProxyCollections.beforeAdd(this, paramObject);
+        boolean bool = super.add(paramObject);
+        return ProxyCollections.afterAdd(this, paramObject, bool);
+    }
+
+    @Override
+    public boolean containsAll(Collection c) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.addAll(paramCollection);
+        }
+        return ProxyCollections.addAll(this, paramCollection);
+    }
+
+    @Override
+    public boolean retainAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.retainAll(paramCollection);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return ProxyCollections.retainAll(this, paramCollection);
+    }
+
+    @Override
+    public boolean removeAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.removeAll(paramCollection);
+        }
+        return ProxyCollections.removeAll(this, paramCollection);
+    }
+
+    @Override
+    public Object lower(Object e) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.lower(e);
+    }
+
+    @Override
+    public Object floor(Object e) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.floor(e);
+    }
+
+    @Override
+    public Object ceiling(Object e) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.ceiling(e);
+    }
+
+    @Override
+    public Object higher(Object e) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.higher(e);
+    }
+
+    @Override
+    public Object pollFirst() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.pollFirst();
+    }
+
+    @Override
+    public Object pollLast() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.pollLast();
+    }
+
+    @Override
+    public NavigableSet descendingSet() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.descendingSet();
+    }
+
+    @Override
+    public Iterator descendingIterator() {
+        if (_directAccess) {
+            return super.descendingIterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Iterator localIterator = super.descendingIterator();
+        return ProxyCollections.afterIterator(this, localIterator);
+    }
+
+    @Override
+    public NavigableSet subSet(Object fromElement, boolean fromInclusive,
+            Object toElement, boolean toInclusive) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.subSet(fromElement, fromInclusive, toElement, toInclusive);
+    }
+
+    @Override
+    public NavigableSet headSet(Object toElement, boolean inclusive) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.headSet(toElement, inclusive);
+    }
+
+    @Override
+    public NavigableSet tailSet(Object fromElement, boolean inclusive) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.tailSet(fromElement, inclusive);
+    }
+
+    @Override
+    public SortedSet subSet(Object fromElement, Object toElement) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.subSet(fromElement, toElement);
+    }
+
+    @Override
+    public SortedSet headSet(Object toElement) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.headSet(toElement);
+    }
+
+    @Override
+    public SortedSet tailSet(Object fromElement) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.tailSet(fromElement);
+    }
+    
+    @Override
+    public boolean equals(Object paramObject) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.equals(paramObject);
+    }
+
+    @Override
+    public int hashCode() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.hashCode();
+    }
+}

Propchange: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedTreeSetProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedVectorProxy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedVectorProxy.java?rev=1335720&view=auto
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedVectorProxy.java (added)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedVectorProxy.java Tue May  8 19:46:20 2012
@@ -0,0 +1,653 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.util;
+
+import java.io.ObjectStreamException;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Vector;
+
+import org.apache.openjpa.kernel.AutoDetach;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.BrokerFactory;
+import org.apache.openjpa.kernel.DetachedStateManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * Vector proxy with delay loading capability.  Allows non-indexed
+ * add and remove operations to occur on an unloaded collection.  Operations
+ * that require a load will trigger a load.
+ */
+@SuppressWarnings({"rawtypes","unchecked"})
+public class DelayedVectorProxy extends Vector implements ProxyCollection, DelayedProxy {
+    private transient OpenJPAStateManager sm;
+    private transient int field;
+    private transient CollectionChangeTracker changeTracker;
+    private transient Class elementType;
+
+    private transient OpenJPAStateManager _ownerSm;
+    private transient boolean _directAccess = false;
+    private transient BrokerFactory _brokerFactory = null;
+    private transient Broker _broker = null;
+    private transient OpenJPAStateManager _delayedSm;
+    private transient int _delayedField;
+    private transient boolean _detached = false;
+
+    public DelayedVectorProxy(int paramInt) {
+        super(paramInt);
+    }
+
+    public DelayedVectorProxy() {
+    }
+
+    public DelayedVectorProxy(Collection paramCollection) {
+        super(paramCollection);
+    }
+
+    public DelayedVectorProxy(int paramInt1, int paramInt2) {
+        super(paramInt1, paramInt2);
+    }
+
+    @Override
+    public void setOwner(OpenJPAStateManager paramOpenJPAStateManager,
+            int paramInt) {
+        // If clearing the owner of this proxy, store away what is necessary for
+        // delayed loading
+        if (sm != null && detaching(paramOpenJPAStateManager, paramInt)) {
+            _detached = true;
+            _delayedSm = sm;
+            _delayedField = field;
+        } else {
+            _detached = false;
+        }
+
+        this.sm = paramOpenJPAStateManager;
+        if (sm != null && sm.getPersistenceCapable() != null) {
+            _ownerSm = (OpenJPAStateManager) sm.getPersistenceCapable()
+                    .pcGetStateManager();
+        }
+        this.field = paramInt;
+        if (sm != null && sm.getContext() != null) {
+            _brokerFactory = sm.getContext().getBroker().getBrokerFactory();
+        }
+    }
+
+    private boolean detaching(OpenJPAStateManager paramOpenJPAStateManager,
+            int paramInt) {
+        if ((paramOpenJPAStateManager == null && paramInt == -1)
+                || (paramOpenJPAStateManager != null && paramOpenJPAStateManager instanceof DetachedStateManager)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int getDelayedField() {
+        if (field == -1 || _detached) {
+            return _delayedField;
+        }
+        return field;
+    }
+
+    @Override
+    public OpenJPAStateManager getDelayedOwner() {
+        if (sm == null || _detached) {
+            return _delayedSm;
+        }
+        return sm;
+    }
+
+    @Override
+    public OpenJPAStateManager getOwner() {
+        return this.sm;
+    }
+
+    @Override
+    public int getOwnerField() {
+        return this.field;
+    }
+
+    @Override
+    public boolean isDirectAccess() {
+        return _directAccess;
+    }
+
+    @Override
+    public void setDirectAccess(boolean direct) {
+        _directAccess = direct;
+    }
+
+    public BrokerFactory getBrokerFactory() {
+        return _brokerFactory;
+    }
+
+    @Override
+    public void load() {
+        ProxyCollections.loadCollection(this);
+    }
+
+    @Override
+    public Broker getBroker() {
+        if (_broker == null || _broker.isClosed()) {
+            if (_brokerFactory != null) {
+                _broker = _brokerFactory.newBroker();
+            }
+        }
+        return _broker;
+    }
+
+    @Override
+    public void closeBroker() {
+        if (_broker != null && !_broker.isClosed()) {
+            _broker.setAutoDetach(AutoDetach.DETACH_CLOSE);
+            _broker.close();
+            _broker = null;
+        }
+    }
+
+    @Override
+    public OpenJPAStateManager getOwnerStateManager() {
+        return _ownerSm;
+    }
+
+    @Override
+    public boolean isDetached() {
+        return _detached;
+    }
+
+    public boolean isDelayLoad() {
+        return ProxyCollections.isDelayed(this);
+    }
+
+    @Override
+    public synchronized Object clone() {
+        if (isDirectAccess()) {
+            return super.clone();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+
+        Proxy localProxy = (Proxy) super.clone();
+        localProxy.setOwner(null, 0);
+        return localProxy;
+    }
+
+    @Override
+    public ChangeTracker getChangeTracker() {
+        return this.changeTracker;
+    }
+
+    @Override
+    public Object copy(Object paramObject) {
+        if (isDelayLoad()) {
+            load();
+        }
+        return new Vector((Collection) paramObject);
+    }
+
+    @Override
+    public Class getElementType() {
+        return this.elementType;
+    }
+
+    @Override
+    public ProxyCollection newInstance(Class paramClass,
+            Comparator paramComparator, boolean paramBoolean1,
+            boolean paramBoolean2) {
+        DelayedVectorProxy localproxy = new DelayedVectorProxy();
+        localproxy.elementType = paramClass;
+        if (paramBoolean1) {
+            localproxy.changeTracker = new DelayedCollectionChangeTrackerImpl(
+                    localproxy, true, true, paramBoolean2);
+        }
+        return localproxy;
+    }
+
+    @Override
+    public synchronized boolean add(Object paramObject) {
+        if (_directAccess) {
+            return super.add(paramObject);
+        }
+
+        ProxyCollections.beforeAdd(this, paramObject);
+        boolean bool = super.add(paramObject);
+        return ProxyCollections.afterAdd(this, paramObject, bool);
+    }
+
+    @Override
+    public synchronized void add(int paramInt, Object paramObject) {
+        if (!_directAccess) {
+            if (isDelayLoad()) {
+                load();
+            }
+        }
+        ProxyCollections.beforeAdd(this, paramInt, paramObject);
+        super.add(paramInt, paramObject);
+    }
+
+    @Override
+    public void clear() {
+        if (!_directAccess) {
+            if (isDelayLoad()) {
+                load();
+            }
+            ProxyCollections.beforeClear(this);
+        }
+        super.clear();
+    }
+
+    @Override
+    public synchronized boolean addAll(int paramInt, Collection paramCollection) {
+        if (_directAccess) {
+            return super.addAll(paramInt, paramCollection);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return ProxyCollections.addAll(this, paramInt, paramCollection);
+    }
+
+    @Override
+    public synchronized boolean addAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.addAll(paramCollection);
+        }
+        return ProxyCollections.addAll(this, paramCollection);
+    }
+
+    @Override
+    public synchronized void addElement(Object paramObject) {
+        if (_directAccess) {
+            super.addElement(paramObject);
+            return;
+        }
+
+        ProxyCollections.beforeAddElement(this, paramObject);
+        super.addElement(paramObject);
+        ProxyCollections.afterAddElement(this, paramObject);
+    }
+
+    @Override
+    public synchronized Object remove(int paramInt) {
+        if (_directAccess) {
+            return super.remove(paramInt);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+
+        ProxyCollections.beforeRemove(this, paramInt);
+        Object localObject = super.remove(paramInt);
+        return ProxyCollections.afterRemove(this, paramInt, localObject);
+    }
+
+    @Override
+    public synchronized boolean remove(Object paramObject) {
+        if (_directAccess) {
+            return super.remove(paramObject);
+        }
+        ProxyCollections.beforeRemove(this, paramObject);
+        setDirectAccess(true);
+        boolean bool = super.remove(paramObject);
+        setDirectAccess(false);
+        return ProxyCollections.afterRemove(this, paramObject, bool);
+    }
+
+    @Override
+    public synchronized Object set(int paramInt, Object paramObject) {
+        if (_directAccess) {
+            return super.set(paramInt, paramObject);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeSet(this, paramInt, paramObject);
+        Object localObject = super.set(paramInt, paramObject);
+        return ProxyCollections.afterSet(this, paramInt, paramObject,
+                localObject);
+    }
+
+    @Override
+    public synchronized boolean removeAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.removeAll(paramCollection);
+        }
+        return ProxyCollections.removeAll(this, paramCollection);
+    }
+
+    @Override
+    public synchronized boolean retainAll(Collection paramCollection) {
+        if (_directAccess) {
+            return super.retainAll(paramCollection);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        return ProxyCollections.retainAll(this, paramCollection);
+    }
+
+    @Override
+    public synchronized void insertElementAt(Object paramObject, int paramInt) {
+        if (_directAccess) {
+            super.insertElementAt(paramObject, paramInt);
+            return;
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+
+        ProxyCollections.beforeInsertElementAt(this, paramObject, paramInt);
+        super.insertElementAt(paramObject, paramInt);
+    }
+
+    @Override
+    public synchronized void removeAllElements() {
+        if (_directAccess) {
+            super.removeAllElements();
+            return;
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeRemoveAllElements(this);
+        super.removeAllElements();
+    }
+
+    @Override
+    public synchronized boolean removeElement(Object paramObject) {
+        if (_directAccess) {
+            return super.removeElement(paramObject);
+        }
+        ProxyCollections.beforeRemoveElement(this, paramObject);
+        setDirectAccess(true);
+        boolean bool = super.removeElement(paramObject);
+        setDirectAccess(false);
+        return ProxyCollections.afterRemoveElement(this, paramObject, bool);
+    }
+
+    @Override
+    public synchronized void removeElementAt(int paramInt) {
+        if (_directAccess) {
+            super.removeElementAt(paramInt);
+            return;
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeRemoveElementAt(this, paramInt);
+        super.removeElementAt(paramInt);
+    }
+
+    @Override
+    public synchronized void setElementAt(Object paramObject, int paramInt) {
+        if (_directAccess) {
+            super.setElementAt(paramObject, paramInt);
+            return;
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ProxyCollections.beforeSetElementAt(this, paramObject, paramInt);
+        super.setElementAt(paramObject, paramInt);
+    }
+
+    @Override
+    public Iterator iterator() {
+        if (_directAccess) {
+            return super.iterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Iterator localIterator = super.iterator();
+        return ProxyCollections.afterIterator(this, localIterator);
+    }
+
+    @Override
+    public ListIterator listIterator(int paramInt) {
+        if (_directAccess) {
+            return super.listIterator(paramInt);
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ListIterator localListIterator = super.listIterator(paramInt);
+        return ProxyCollections.afterListIterator(this, paramInt,
+                localListIterator);
+    }
+
+    @Override
+    public ListIterator listIterator() {
+        if (_directAccess) {
+            return super.listIterator();
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        ListIterator localListIterator = super.listIterator();
+        return ProxyCollections.afterListIterator(this, localListIterator);
+    }
+
+    @Override
+    public synchronized void setSize(int paramInt) {
+        if (_directAccess) {
+            super.setSize(paramInt);
+            return;
+        }
+        if (isDelayLoad()) {
+            load();
+        }
+        Proxies.dirty(this, true);
+        super.setSize(paramInt);
+    }
+
+    protected synchronized Object writeReplace() throws ObjectStreamException {
+        if (isDelayLoad()) {
+            load();
+        }
+        return Proxies.writeReplace(this, true);
+    }
+
+    @Override
+    public synchronized boolean contains(Object object) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.contains(object);
+    }
+
+    @Override
+    public synchronized boolean containsAll(Collection collection) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.containsAll(collection);
+    }
+
+    @Override
+    public synchronized boolean isEmpty() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.isEmpty();
+    }
+
+    @Override
+    public synchronized int size() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.size();
+    }
+
+    @Override
+    public synchronized Object[] toArray() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray();
+    }
+
+    @Override
+    public synchronized Object[] toArray(Object[] array) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toArray(array);
+    }
+
+    @Override
+    public synchronized boolean equals(Object paramObject) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.equals(paramObject);
+    }
+
+    @Override
+    public synchronized int hashCode() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.hashCode();
+    }
+
+    @Override
+    public synchronized int lastIndexOf(Object object) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.lastIndexOf(object);
+    }
+
+    @Override
+    public synchronized List subList(int start, int end) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.subList(start, end);
+    }
+
+    @Override
+    public synchronized Object get(int location) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.get(location);
+    }
+
+    @Override
+    public synchronized int indexOf(Object object) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.indexOf(object);
+    }
+
+    @Override
+    public synchronized int indexOf(Object object, int index) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.indexOf(object, index);
+    }
+
+    @Override
+    public synchronized void copyInto(Object[] anArray) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        super.copyInto(anArray);
+    }
+
+    public synchronized void trimToSize() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        super.trimToSize();
+    }
+
+    public synchronized void ensureCapacity(int minCapacity) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        super.ensureCapacity(minCapacity);
+    }
+
+    public synchronized int capacity() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.capacity();
+    }
+
+    public Enumeration elements() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.elements();
+    }
+
+    public synchronized int lastIndexOf(Object o, int index) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.lastIndexOf(o, index);
+    }
+
+    public synchronized Object elementAt(int index) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.elementAt(index);
+    }
+
+    public synchronized Object firstElement() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.firstElement();
+    }
+
+    public synchronized Object lastElement() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.lastElement();
+    }
+
+    public synchronized String toString() {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        return super.toString();
+    }
+
+    protected synchronized void removeRange(int fromIndex, int toIndex) {
+        if (!_directAccess && isDelayLoad()) {
+            load();
+        }
+        super.removeRange(fromIndex, toIndex);
+    }
+}

Propchange: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/DelayedVectorProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyCollections.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyCollections.java?rev=1335720&r1=1335719&r2=1335720&view=diff
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyCollections.java (original)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyCollections.java Tue May  8 19:46:20 2012
@@ -18,12 +18,18 @@
  */
 package org.apache.openjpa.util;
 
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.BrokerImpl;
+import org.apache.openjpa.kernel.DetachedValueStateManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.StateManagerImpl;
+
 /**
  * Utility methods used by collection proxies.
  *
@@ -54,7 +60,10 @@ public class ProxyCollections 
      */
     public static void beforeAdd(ProxyCollection coll, Object value) {
         assertAllowedType(value, coll.getElementType());
-        dirty(coll, false);
+        // Must only dirty the collection outside of a delayed load
+        if (!isDirectAccess(coll)) {
+            dirty(coll, false);
+        }
     }
 
     /**
@@ -65,8 +74,11 @@ public class ProxyCollections 
      */
     public static boolean afterAdd(ProxyCollection coll, Object value, 
         boolean added) {
-        if (added && coll.getChangeTracker() != null)
+        if (!isDirectAccess(coll) && added && coll.getChangeTracker() != null) {
+            setDirectAccess(coll,true);
             ((CollectionChangeTracker) coll.getChangeTracker()).added(value);
+            setDirectAccess(coll,false);
+        }
         return added;
     }
 
@@ -139,7 +151,7 @@ public class ProxyCollections 
      */
     public static boolean addAll(ProxyCollection coll, Collection values) {
         boolean added = false;
-        for (Iterator itr = values.iterator(); itr.hasNext();)
+        for (Iterator<?> itr = values.iterator(); itr.hasNext();)
             added |= coll.add(itr.next());
         return added;
     }
@@ -149,7 +161,7 @@ public class ProxyCollections 
      */
     public static void beforeClear(ProxyCollection coll) {
         dirty(coll, true);
-        for (Iterator itr = coll.iterator(); itr.hasNext();)
+        for (Iterator<?> itr = coll.iterator(); itr.hasNext();)
             removed(coll, itr.next(), false);
     }
 
@@ -304,7 +316,10 @@ public class ProxyCollections 
      * Call before invoking {@link Collection#remove} on super.
      */
     public static void beforeRemove(ProxyCollection coll, Object o) {
-        dirty(coll, false);
+        // Must only dirty the collection outside of a delayed load
+        if (!isDirectAccess(coll)) {
+            dirty(coll, false);
+        }
     }
 
     /**
@@ -315,14 +330,40 @@ public class ProxyCollections 
      */ 
     public static boolean afterRemove(ProxyCollection coll, Object o, 
         boolean removed){
-        if (!removed)
-            return false;
-        if (coll.getChangeTracker() != null)
+        boolean isDelayed = isDelayed(coll);
+        boolean direct = isDirectAccess(coll);
+        if (!isDelayed) {
+            if (!removed)
+                return false;
+        }
+        if (!direct && coll.getChangeTracker() != null) {
+            // switch on direct access to prevent the removed op from 
+            // inadvertently loading the collection
+            setDirectAccess(coll, true);
             ((CollectionChangeTracker) coll.getChangeTracker()).removed(o);
-        removed(coll, o, false);
+            setDirectAccess(coll, false);
+        }
+        if (!isDelayed) {
+            removed(coll, o, false);
+        }
         return true;
     }
 
+    private static boolean isDirectAccess(ProxyCollection coll) {
+        if (coll instanceof DelayedProxy) {
+            DelayedProxy dpxy = (DelayedProxy)coll;
+            return dpxy.isDirectAccess();
+        }
+        return false;
+    }
+    
+    private static void setDirectAccess(ProxyCollection coll, boolean direct) {
+        if (coll instanceof DelayedProxy) {
+            DelayedProxy dpxy = (DelayedProxy)coll;
+            dpxy.setDirectAccess(direct);
+        }
+    }
+
     /**
      * Call before invoking {@link Vector#removeElement} on super.
      */
@@ -400,9 +441,9 @@ public class ProxyCollections 
     /**
      * Override for {@link Collection#removeAll}.
      */
-    public static boolean removeAll(ProxyCollection coll, Collection vals) {
+    public static boolean removeAll(ProxyCollection coll, Collection<?> vals) {
         boolean removed = false;
-        for (Iterator itr = vals.iterator(); itr.hasNext();)
+        for (Iterator<?> itr = vals.iterator(); itr.hasNext();)
             removed |= coll.remove(itr.next());
         return removed;
     }
@@ -410,9 +451,9 @@ public class ProxyCollections 
     /**
      * Override for {@link Collection#retainAll}.
      */
-    public static boolean retainAll(ProxyCollection coll, Collection vals) {
+    public static boolean retainAll(ProxyCollection coll, Collection<?> vals) {
         int size = coll.size();
-        for (Iterator itr = coll.iterator(); itr.hasNext();)
+        for (Iterator<?> itr = coll.iterator(); itr.hasNext();)
             if (!vals.contains(itr.next()))
                 itr.remove();
         return coll.size() < size;
@@ -469,4 +510,110 @@ public class ProxyCollections 
     public static interface ProxyListIterator 
         extends ProxyIterator, ListIterator {
     }
+
+    public static void loadCollection(ProxyCollection proxy) {
+        loadCollection(proxy, false);
+    }
+
+    public static void loadCollection(ProxyCollection proxy, boolean detaching) {
+        if (!isDelayed(proxy)) {
+            return;
+        }
+        DelayedProxy dProxy = (DelayedProxy)proxy;
+        if (dProxy.isDirectAccess()) {
+            return;
+        }
+        boolean state[] = new boolean[2];
+        try {
+            dProxy.setDirectAccess(true);
+            state = checkState(proxy);
+            boolean tracking = false;
+            ChangeTracker ct = proxy.getChangeTracker();
+            Collection<?> added = null;
+            Collection<?> removed = null;
+            if (ct != null && ct.isTracking() ) {
+                if (!ct.getAdded().isEmpty()) {
+                    added = new ArrayList(ct.getAdded());
+                }
+                if (!ct.getRemoved().isEmpty()) {
+                    removed = new ArrayList(ct.getRemoved());
+                }
+                tracking = true;
+                ct.stopTracking();
+            }
+            if (proxy.size() > 0) {
+                proxy.clear();
+            }
+            dProxy.getDelayedOwner().loadDelayedField(dProxy.getDelayedField());
+            if (!detaching && tracking && !ct.isTracking()) {
+                ct.startTracking();
+            }
+            // add new elements
+            if (added != null && added.size() > 0) {
+                dProxy.setDirectAccess(false);
+                proxy.addAll(added);
+                added.clear();
+            }
+            // purge removed elements
+            if (removed != null && removed.size() > 0) {
+                dProxy.setDirectAccess(false);
+                proxy.removeAll(removed);
+                removed.clear();
+            }
+        } finally {
+            dProxy.setDirectAccess(false);
+            if (state[0]) {
+                dProxy.closeBroker();
+            }
+            if (state[1]) {
+                clearStateManager(proxy);
+            }
+        }
+    }
+    
+    public static boolean isDelayed(ProxyCollection proxy) {
+        if (proxy instanceof DelayedProxy) {
+            DelayedProxy dProxy = (DelayedProxy)proxy;
+            OpenJPAStateManager sm = dProxy.getDelayedOwner();
+            return (sm != null &&
+                    sm.isDelayed(dProxy.getDelayedField()));
+        }
+        return false;
+    }
+    
+    private static boolean[] checkState(ProxyCollection proxy) {
+        boolean[] state = new boolean[2];
+        DelayedProxy dProxy = (DelayedProxy)proxy;
+
+        OpenJPAStateManager sm = dProxy.getDelayedOwner();
+        if (sm != null) {
+            // If the broker assigned to this proxy is null, closed or no longer
+            // manages the pc, produce a new one
+            Broker broker = sm.getContext().getBroker();
+            if (dProxy.isDetached() || broker == null || broker.isClosed() 
+                || (!broker.isClosed() && !broker.isPersistent(sm.getPersistenceCapable()))) {
+                state[0] = true;
+                broker = dProxy.getBroker();
+                ((StateManagerImpl)sm).setBroker((BrokerImpl)broker);
+            }
+            if (dProxy.isDetached() || sm.getPersistenceCapable().pcGetStateManager() == null) {
+                state[1] = true;
+                if (dProxy.getOwnerStateManager() != null) {
+                    sm.getPersistenceCapable().pcReplaceStateManager(dProxy.getOwnerStateManager());
+                    ((StateManagerImpl)dProxy.getOwnerStateManager()).setBroker((BrokerImpl)broker);
+                } else {
+                    sm.getPersistenceCapable().pcReplaceStateManager(
+                            new DetachedValueStateManager(sm.getPersistenceCapable(), sm.getContext()));
+                }
+            }
+        }
+        return state;
+    }
+    
+    private static void clearStateManager(ProxyCollection proxy) {
+        OpenJPAStateManager sm = proxy.getOwner();
+        if (sm != null) {
+            sm.getPersistenceCapable().pcReplaceStateManager(null);
+        }
+    }
 }

Modified: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManager.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManager.java?rev=1335720&r1=1335719&r2=1335720&view=diff
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManager.java (original)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManager.java Tue May  8 19:46:20 2012
@@ -113,4 +113,15 @@ public interface ProxyManager {
      * @since 0.2.5
      */
     public Proxy newCustomProxy (Object obj, boolean autoOff);
+    
+    /**
+     * Returns whether this proxy manager is enabled for delayed collection
+     * loading.  Delayed collection loading provides the ability to do simple,
+     * non-indexed add or remove operations on a lazy collection without 
+     * loading the collection.  The collection is loaded when necessary, such
+     * as iteration, indexed operations, isEmpty, or size.
+     *  
+     * @since 2.2.1
+     */
+    public boolean getDelayCollectionLoading();
 }

Modified: openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java?rev=1335720&r1=1335719&r2=1335720&view=diff
==============================================================================
--- openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java (original)
+++ openjpa/branches/2.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java Tue May  8 19:46:20 2012
@@ -98,6 +98,7 @@ public class ProxyManagerImpl
     private final Map _proxies = new NullSafeConcurrentHashMap();
     private boolean _trackChanges = true;
     private boolean _assertType = false;
+    private boolean _delayedCollectionLoading = false;
 
     public ProxyManagerImpl() {
         _unproxyable.add(TimeZone.class.getName());
@@ -138,7 +139,26 @@ public class ProxyManagerImpl
     public void setAssertAllowedType(boolean assertType) {
         _assertType = assertType;
     }
-
+    
+    /**
+     * Whether loading of collections should be delayed until an operation
+     * is performed that requires them to be loaded.  This property only
+     * applies to proxies that implement java.util.Collection (ie. not arrays
+     * or maps).  Defaults to false.
+     * @return 
+     */
+    public boolean getDelayCollectionLoading() {
+        return _delayedCollectionLoading;
+    }
+    
+    /**
+     * Whether loading of collections should be delayed until an operation
+     * is performed that requires them to be loaded.  Defaults to false.
+     */
+    public void setDelayCollectionLoading(boolean delay) {
+        _delayedCollectionLoading = delay;
+    }
+       
     /**
      * Return a mutable view of class names we know cannot be proxied  
      * correctly by this manager.
@@ -477,11 +497,43 @@ public class ProxyManagerImpl
      */
     protected Class loadBuildTimeProxy(Class type, ClassLoader loader) {
         try {
+            Class<?> proxyClass = null;
+            if (_delayedCollectionLoading) {
+                proxyClass = loadDelayedProxy(type);
+                if (proxyClass != null) {
+                    return proxyClass;
+                }
+            }
             return Class.forName(getProxyClassName(type, false), true, loader);
         } catch (Throwable t) {
             return null;
         }
     }
+    
+    protected Class<?> loadDelayedProxy(Class<?> type) {
+        if (type.equals(java.util.ArrayList.class)) {
+            return org.apache.openjpa.util.DelayedArrayListProxy.class;
+        }
+        if (type.equals(java.util.HashSet.class)) {
+            return org.apache.openjpa.util.DelayedHashSetProxy.class;
+        }
+        if (type.equals(java.util.LinkedList.class)) {
+            return org.apache.openjpa.util.DelayedLinkedListProxy.class;
+        }
+        if (type.equals(java.util.Vector.class)) {
+            return org.apache.openjpa.util.DelayedVectorProxy.class;
+        }
+        if (type.equals(java.util.LinkedHashSet.class)) {
+            return org.apache.openjpa.util.DelayedLinkedHashSetProxy.class;
+        }
+        if (type.equals(java.util.SortedSet.class) || type.equals(java.util.TreeSet.class)) {
+            return org.apache.openjpa.util.DelayedTreeSetProxy.class;
+        }
+        if (type.equals(java.util.PriorityQueue.class)) {
+            return org.apache.openjpa.util.DelayedPriorityQueueProxy.class;
+        }
+        return null;
+    }
 
     /**
      * Instantiate the given proxy class.

Added: openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/delayed/Award.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/delayed/Award.java?rev=1335720&view=auto
==============================================================================
--- openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/delayed/Award.java (added)
+++ openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/delayed/Award.java Tue May  8 19:46:20 2012
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.proxy.delayed;
+
+import java.io.Serializable;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class Award implements Serializable, Comparable<Award>{
+
+    private static final long serialVersionUID = -1110613520812966568L;
+
+    private String awdName;
+    
+    private String awdType;
+
+    public void setAwdName(String awdName) {
+        this.awdName = awdName;
+    }
+
+    public String getAwdName() {
+        return awdName;
+    }
+
+    public void setAwdType(String awdType) {
+        this.awdType = awdType;
+    }
+
+    public String getAwdType() {
+        return awdType;
+    }
+
+    @Override
+    public int compareTo(Award o) {
+        String nameType = awdName+awdType;
+        String nameType2 = o.getAwdName()+o.getAwdType();
+        return nameType.compareTo(nameType2);
+    }
+}

Propchange: openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/delayed/Award.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message