blob: 77562c628917f56f05e19e6d6bb028235980d46a [file] [log] [blame]
/*
* 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 java.util.function.IntFunction;
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;
}
protected void setChangeTracker(CollectionChangeTracker ct) {
changeTracker = ct;
}
@Override
public Object copy(Object paramObject) {
return new LinkedList((Collection) paramObject);
}
@Override
public Class getElementType() {
return this.elementType;
}
protected void setElementType(Class<?> elemType) {
elementType = elemType;
}
@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 Object[] toArray(IntFunction generator) {
if (!_directAccess && isDelayLoad()) {
load();
}
return super.toArray(generator);
}
@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);
}
}