![JAR search and dependency download from the Maven repository](/logo.png)
com.gs.fw.common.mithra.list.DelegatingList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of reladomo Show documentation
Show all versions of reladomo Show documentation
Reladomo is an object-relational mapping framework.
/*
Copyright 2016 Goldman Sachs.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package com.gs.fw.common.mithra.list;
import com.gs.collections.api.block.procedure.Procedure;
import com.gs.collections.api.block.procedure.Procedure2;
import com.gs.collections.api.block.procedure.primitive.ObjectIntProcedure;
import com.gs.collections.impl.list.mutable.FastList;
import com.gs.fw.common.mithra.*;
import com.gs.fw.common.mithra.attribute.*;
import com.gs.fw.common.mithra.cache.ExtractorBasedHashStrategy;
import com.gs.fw.common.mithra.cache.Index;
import com.gs.fw.common.mithra.extractor.EmbeddedValueExtractor;
import com.gs.fw.common.mithra.finder.*;
import com.gs.fw.common.mithra.list.merge.TopLevelMergeOptions;
import com.gs.fw.common.mithra.notification.listener.MithraApplicationNotificationListener;
import com.gs.fw.common.mithra.tempobject.TupleTempContext;
import com.gs.fw.common.mithra.util.*;
import com.gs.fw.finder.Navigation;
import com.gs.fw.finder.OrderBy;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
public abstract class DelegatingList implements MithraList
{
private static final int REFRESH_BULK_INSERT_THRESHOLD = 1000;
protected static final int REFRESH_PARAMETER_THRESHOLD = REFRESH_BULK_INSERT_THRESHOLD;
protected static final int OR_CLAUSE_THRESHOLD = 200;
private MithraDelegatedList delegated;
private Operation operation;
private transient volatile Object fastListOrCachedQuery;
private volatile ListOptions listOptions;
private boolean bypassCache = false;
private boolean forRelationship = false;
protected DelegatingList()
{
}
public DelegatingList(Operation operation)
{
this.operation = operation;
}
public DelegatingList(com.gs.fw.finder.Operation operation)
{
this((Operation) operation);
}
protected Object zGetFastListOrCachedQuery()
{
return fastListOrCachedQuery;
}
protected void zSetFastListOrCachedQuery(Object fastListOrCachedQuery)
{
this.fastListOrCachedQuery = fastListOrCachedQuery;
}
protected void zSetCurrentTransaction(Object currentTransactionOrRemovedItems)
{
getOrCreateListOptions().currentTransaction = currentTransactionOrRemovedItems;
}
private ListOptions getOrCreateListOptions()
{
if (this.listOptions == null)
{
this.listOptions = new ListOptions();
}
return this.listOptions;
}
protected Object zGetCurrentTransaction()
{
if (this.listOptions == null) return null;
return this.listOptions.currentTransaction;
}
public Operation getOperation()
{
return operation;
}
public void setNumberOfParallelThreads(int numberOfThreads)
{
this.delegated = this.delegated.setNumberOfParallelThreads(this, numberOfThreads);
}
public int getNumberOfParallelThreads()
{
return this.delegated.getNumberOfParallelThreads();
}
public com.gs.fw.common.mithra.finder.orderby.OrderBy getOrderBy()
{
if (this.listOptions == null) return null;
return (com.gs.fw.common.mithra.finder.orderby.OrderBy) this.listOptions.orderBy;
}
public void setOrderBy(OrderBy orderBy)
{
getOrCreateListOptions().orderBy = orderBy;
this.getDelegated().sortWith(this, (com.gs.fw.common.mithra.finder.orderby.OrderBy) orderBy);
}
protected DeepFetchNode getDeepFetchedRelationships()
{
if (this.listOptions == null) return null;
return this.listOptions.deepFetchRoot;
}
@Override
public DeepFetchTree getDeepFetchTree()
{
if (this.listOptions == null) return null;
return this.listOptions.deepFetchRoot;
}
public int hashCode()
{
return delegated.hashCode(this);
}
public int size()
{
return delegated.size(this);
}
public void clear()
{
delegated.clear(this);
}
public boolean isEmpty()
{
return this.size() == 0;
}
public boolean notEmpty()
{
return !isEmpty();
}
public Object[] toArray()
{
return delegated.toArray(this);
}
public E get(int index)
{
return delegated.get(this, index);
}
public E remove(int index)
{
return delegated.remove(this, index);
}
public void add(int index, E element)
{
delegated.add(this, index, element);
}
public int indexOf(Object o)
{
return delegated.indexOf(this, o);
}
public int lastIndexOf(Object o)
{
return delegated.lastIndexOf(this, o);
}
public boolean add(E o)
{
return delegated.add(this, o);
}
public boolean contains(Object o)
{
return delegated.contains(this, o);
}
public boolean equals(Object o)
{
return delegated.equals(this, o);
}
public boolean remove(Object o)
{
return delegated.remove(this, o);
}
public boolean addAll(int index, Collection extends E> c)
{
return delegated.addAll(this, index, c);
}
public boolean addAll(Collection extends E> c)
{
return delegated.addAll(this, c);
}
public boolean containsAll(Collection> c)
{
return delegated.containsAll(this, c);
}
public boolean removeAll(Collection> c)
{
return delegated.removeAll(this, c);
}
public boolean retainAll(Collection> c)
{
return delegated.retainAll(this, c);
}
public void forEachWithCursor(DoWhileProcedure closure)
{
if (this.listOptions != null && this.listOptions.deepFetchRoot != null)
{
throw new MithraBusinessException("The list cursor iteration doesn't support the deep-fetch feature.");
}
delegated.forEachWithCursor(this, closure);
}
public void forEachWithCursor(DoWhileProcedure closure, Operation postLoadFilter)
{
forEachWithCursor(closure, new OperationBasedFilter(postLoadFilter));
}
public void forEachWithCursor(DoWhileProcedure closure, Filter postLoadFilter)
{
if (this.listOptions != null && this.listOptions.deepFetchRoot != null)
{
throw new MithraBusinessException("The list cursor iteration doesn't support the deep-fetch feature.");
}
delegated.forEachWithCursor(this, closure, postLoadFilter);
}
public Iterator iterator()
{
return delegated.iterator(this);
}
public List subList(int fromIndex, int toIndex)
{
return delegated.subList(this, fromIndex, toIndex);
}
public ListIterator listIterator()
{
return delegated.listIterator(this);
}
public ListIterator listIterator(int index)
{
return delegated.listIterator(this, index);
}
public E set(int index, E element)
{
return delegated.set(this, index, element);
}
public T[] toArray(T[] a)
{
return delegated.toArray(this, a);
}
protected MithraDelegatedList getDelegated()
{
return delegated;
}
protected void setDelegated(MithraDelegatedList delegated)
{
this.delegated = delegated;
}
public void deepFetch(Navigation navigation)
{
DeepRelationshipAttribute deepRelationshipAttribute = (DeepRelationshipAttribute) navigation;
getOrCreateListOptions();
if (this.listOptions.deepFetchRoot == null)
{
this.listOptions.deepFetchRoot = new DeepFetchNode(null, (AbstractRelatedFinder) this.getMithraObjectPortal().getFinder());
}
boolean added = this.listOptions.deepFetchRoot.add(deepRelationshipAttribute);
if (added)
{
this.getDelegated().incrementalDeepFetch(this);
}
}
public void zSetForRelationship()
{
this.forRelationship = true;
}
protected boolean zIsForRelationship()
{
return this.forRelationship;
}
public void zSetRemoveHandler(DependentRelationshipRemoveHandler removeHandler)
{
this.delegated = ((MithraDelegatedTransactionalList) this.getDelegated()).zSetRemoveHandler(this, removeHandler);
}
public void zSetAddHandler(DependentRelationshipAddHandler addHandler)
{
this.delegated = ((MithraDelegatedTransactionalList) this.getDelegated()).zSetAddHandler(this, addHandler);
}
public void addOrderBy(OrderBy orderBy)
{
getOrCreateListOptions();
if (this.listOptions.orderBy == null)
{
this.listOptions.orderBy = orderBy;
}
else
{
this.listOptions.orderBy = this.listOptions.orderBy.and(orderBy);
}
this.getDelegated().sortWith(this, (com.gs.fw.common.mithra.finder.orderby.OrderBy) orderBy);
}
public void setMaxObjectsToRetrieve(int count)
{
this.delegated = this.getDelegated().setMaxObjectsToRetrieve(this, count);
}
public boolean reachedMaxObjectsToRetrieve()
{
return this.getDelegated().reachedMaxObjectsToRetrieve(this);
}
public boolean isOperationBased()
{
return this.getDelegated().isOperationBased();
}
public void forceResolve()
{
this.getDelegated().forceResolve(this);
}
public void forceRefresh()
{
this.getDelegated().forceRefresh(this);
}
public boolean isStale()
{
return this.getDelegated().isStale(this);
}
public void setBypassCache(boolean bypassCache)
{
this.bypassCache = bypassCache;
}
public boolean isBypassCache()
{
return bypassCache;
}
public int count()
{
this.delegated = this.delegated.prepareForCount();
return this.getDelegated().count(this);
}
public void insertAll()
{
this.generateAndSetPrimaryKeys();
((MithraDelegatedTransactionalList) this.getDelegated()).insertAll(this);
}
public void bulkInsertAll()
{
this.generateAndSetPrimaryKeys();
((MithraDelegatedTransactionalList) this.getDelegated()).bulkInsertAll(this);
}
public void cascadeInsertAll()
{
this.generateAndSetPrimaryKeys();
((MithraDelegatedTransactionalList) this.getDelegated()).cascadeInsertAll(this);
}
public void zCascadeCopyThenInsertAll()
{
this.generateAndSetPrimaryKeys();
for (int i = 0; i < this.size(); i++)
{
MithraTransactionalObject obj = (MithraTransactionalObject) this.get(i);
obj.zCascadeCopyThenInsert();
}
}
public Map zCascadeAddNavigatedRelationshipsStats(RelatedFinder finder, Map navigationStats)
{
for (int i = 0; i < this.size(); i++)
{
MithraTransactionalObject obj = (MithraTransactionalObject) this.get(i);
obj.zAddNavigatedRelationshipsStats(finder, navigationStats);
}
return navigationStats;
}
public void cascadeInsertAllUntil(Timestamp exclusiveUntil)
{
this.generateAndSetPrimaryKeys();
((MithraDelegatedTransactionalList) this.getDelegated()).cascadeInsertAllUntil(this, exclusiveUntil);
}
public void cascadeDeleteAll()
{
((MithraDelegatedTransactionalList) this.getDelegated()).cascadeDeleteAll(this);
}
public void deleteAll()
{
((MithraDelegatedTransactionalList) this.getDelegated()).deleteAll(this);
}
public void deleteAllInBatches(int batchSize)
{
if (batchSize <= 0)
{
throw new MithraBusinessException(batchSize + " is an invalid batchSize, batchSize must be > 0");
}
((MithraDelegatedTransactionalList) this.getDelegated()).deleteAllInBatches(this, batchSize);
}
protected void terminateAll()
{
((MithraDelegatedTransactionalList) this.getDelegated()).terminateAll(this);
}
protected void purgeAll()
{
((MithraDelegatedTransactionalList) this.getDelegated()).purgeAll(this);
}
public void purgeAllInBatches(int batchSize)
{
if (batchSize <= 0)
{
throw new MithraBusinessException(batchSize + " is an invalid batchSize, batchSize must be > 0");
}
((MithraDelegatedTransactionalList) this.getDelegated()).purgeAllInBatches(this, batchSize);
}
public void cascadeTerminateAll()
{
((MithraDelegatedTransactionalList) this.getDelegated()).cascadeTerminateAll(this);
}
public void cascadeTerminateAllUntil(Timestamp exclusiveUntil)
{
((MithraDelegatedTransactionalList) this.getDelegated()).cascadeTerminateAllUntil(this, exclusiveUntil);
}
public void copyDetachedValuesToOriginalOrInsertIfNewOrDeleteIfRemoved()
{
((MithraDelegatedTransactionalList) this.getDelegated()).copyDetachedValuesToOriginalOrInsertIfNewOrDeleteIfRemoved(this);
}
public void zCopyDetachedValuesDeleteIfRemovedOnly()
{
((MithraDelegatedTransactionalList) this.getDelegated()).zCopyDetachedValuesDeleteIfRemovedOnly(this);
}
public void copyDetachedValuesToOriginalOrInsertIfNewOrTerminateIfRemoved()
{
((MithraDelegatedTransactionalList) this.getDelegated()).copyDetachedValuesToOriginalOrInsertIfNewOrTerminateIfRemoved(this);
}
public void zCascadeUpdateInPlaceBeforeTerminate()
{
((MithraDelegatedTransactionalList) this.getDelegated()).cascadeUpdateInPlaceBeforeTerminate(this);
}
public void copyDetachedValuesToOriginalUntilOrInsertIfNewUntilOrTerminateIfRemoved(Timestamp exclusiveUntil)
{
((MithraDelegatedTransactionalList) this.getDelegated()).copyDetachedValuesToOriginalUntilOrInsertIfNewUntilOrTerminateIfRemoved(this, exclusiveUntil);
}
public void clearResolvedReferences()
{
this.getDelegated().clearResolvedReferences(this);
}
public boolean isModifiedSinceDetachment()
{
return this.getDelegated().isModifiedSinceDetachment(this);
}
public void restrictRetrievalTo(com.gs.fw.finder.Attribute attribute)
{
}
protected void forceRefreshForSimpleList()
{
if (this.size() == 0)
{
return;
}
RelatedFinder finder = this.getMithraObjectPortal().getFinder();
Attribute[] pkAttributes = finder.getPrimaryKeyAttributes();
Attribute sourceAttribute = finder.getSourceAttribute();
AsOfAttribute[] asOfAttributes = finder.getAsOfAttributes();
MithraTransaction tx = MithraManagerProvider.getMithraManager().getCurrentTransaction();
boolean oldEvaluationMode = tx != null && tx.zIsInOperationEvaluationMode();
if (asOfAttributes != null)
{
List extends List> segregatedByDate;
try
{
if (tx != null) tx.zSetOperationEvaluationMode(true);
segregatedByDate = segregateByAsOfAttribute(asOfAttributes);
}
finally
{
if (tx != null) tx.zSetOperationEvaluationMode(oldEvaluationMode);
}
for (int i = 0; i < segregatedByDate.size(); i++)
{
List list = segregatedByDate.get(i);
Operation dateOp;
try
{
if (tx != null) tx.zSetOperationEvaluationMode(true);
dateOp = asOfAttributes[0].nonPrimitiveEq(asOfAttributes[0].valueOf(list.get(0)));
if (asOfAttributes.length == 2)
{
dateOp = dateOp.and(asOfAttributes[1].nonPrimitiveEq(asOfAttributes[1].valueOf(list.get(0))));
}
}
finally
{
if (tx != null)
{
tx.zSetOperationEvaluationMode(oldEvaluationMode);
}
}
if (pkAttributes.length == 1 || (pkAttributes.length == 2 && sourceAttribute != null))
{
forceRefreshWithOnePk(list, pkAttributes, dateOp, tx, oldEvaluationMode);
}
else
{
forceRefreshWithMultiplePk(list, pkAttributes, dateOp, tx, oldEvaluationMode);
}
}
}
else
{
if (pkAttributes.length == 1 || (pkAttributes.length == 2 && sourceAttribute != null))
{
forceRefreshWithOnePk(this, pkAttributes, null, tx, oldEvaluationMode);
}
else
{
forceRefreshWithMultiplePk(this, pkAttributes, null, tx, oldEvaluationMode);
}
}
}
private List extends List> segregateBySourceAttribute(List listToSegregate)
{
Attribute sourceAttribute = this.getMithraObjectPortal().getFinder().getSourceAttribute();
if (sourceAttribute == null)
{
return ListFactory.create(listToSegregate);
}
//todo: optimize this for non-repeated source attribute
MultiHashMap map = new MultiHashMap();
for (int i = 0; i < listToSegregate.size(); i++)
{
Object o = listToSegregate.get(i);
map.put(sourceAttribute.valueOf(o), o);
}
if (map.size() > 1)
{
return map.valuesAsList();
}
else
{
return ListFactory.create(listToSegregate);
}
}
private List extends List> segregateByAsOfAttribute(AsOfAttribute[] asOfAttributes)
{
ExtractorBasedHashStrategy hashStrategy = ExtractorBasedHashStrategy.create(asOfAttributes);
//todo: optimize this for non-repeated asOfAttributes
MultiHashMap map = new MultiHashMap();
for (int i = 0; i < this.size(); i++)
{
Object o = this.get(i);
map.put(new KeyWithHashStrategy(o, hashStrategy), o);
}
if (map.size() > 1)
{
return map.valuesAsList();
}
else
{
return ListFactory.create(this);
}
}
private void forceRefreshWithMultiplePk(List listToRefresh, Attribute[] pkAttributes, Operation extraOp, MithraTransaction tx, boolean oldEvaluationMode)
{
List extends List> lists;
try
{
if (tx != null) tx.zSetOperationEvaluationMode(true);
lists = segregateBySourceAttribute(listToRefresh);
}
finally
{
if (tx != null) tx.zSetOperationEvaluationMode(oldEvaluationMode);
}
MithraObjectPortal portal = this.getMithraObjectPortal();
Attribute sourceAttribute = portal.getFinder().getSourceAttribute();
for (int i = 0; i < lists.size(); i++)
{
TupleTempContext tempContext = new TupleTempContext(pkAttributes, true);
tempContext.enableRetryHook();
try
{
List segregatedList = lists.get(i);
Object source;
try
{
if (tx != null) tx.zSetOperationEvaluationMode(true);
source = sourceAttribute != null ? sourceAttribute.valueOf(segregatedList.get(0)) : null;
tempContext.insert(segregatedList, portal, REFRESH_BULK_INSERT_THRESHOLD, false);
}
finally
{
if (tx != null) tx.zSetOperationEvaluationMode(oldEvaluationMode);
}
Operation op = tempContext.exists(source);
if (extraOp != null) op = op.and(extraOp);
portal.findAsCachedQuery(op, null, true, false, 0, false);
}
finally
{
tempContext.destroy();
}
}
}
private void forceRefreshWithOnePk(List listToRefresh, Attribute[] pkAttributes, Operation extraOp, MithraTransaction tx, boolean oldEvaluationMode)
{
//todo: segregate by source attribute first
int batches = listToRefresh.size() / REFRESH_PARAMETER_THRESHOLD;
if (listToRefresh.size() % REFRESH_PARAMETER_THRESHOLD > 0) batches++;
for (int b = 0; b < batches; b++)
{
Operation op;
try
{
if (tx != null) tx.zSetOperationEvaluationMode(true);
int end = Math.min(this.size(), (b + 1) * REFRESH_PARAMETER_THRESHOLD);
op = pkAttributes[0].in(listToRefresh.subList(b * REFRESH_PARAMETER_THRESHOLD, end), pkAttributes[0]);
if (pkAttributes.length == 2)
{
op = op.and(pkAttributes[1].in(listToRefresh.subList(b * REFRESH_PARAMETER_THRESHOLD, end), pkAttributes[1]));
}
if (extraOp != null) op = op.and(extraOp);
}
finally
{
if (tx != null) tx.zSetOperationEvaluationMode(oldEvaluationMode);
}
this.getMithraObjectPortal().findAsCachedQuery(op, null, true, false, 0, false);
}
}
public MithraObjectPortal getMithraObjectPortal()
{
throw new RuntimeException("subclass must override");
}
protected List intersection(DelegatingList other)
{
RelatedFinder finder = this.getMithraObjectPortal().getFinder();
if (other.isOperationBased() && this.isOperationBased())
{
return finder.findMany(new AndOperation(this.getOperation(), other.getOperation()));
}
else
{
List result = finder.constructEmptyList();
result.addAll(this);
result.retainAll(other);
return result;
}
}
protected void generateAndSetPrimaryKeys()
{
// subclass to override when needed
}
protected void zGenerateAndSetPrimaryKeysWithSourceAttribute(SequenceAttribute attribute,
boolean sequenceHasSourceAttribute, String sequenceName, String factoryName)
{
com.gs.fw.common.mithra.attribute.Attribute sourceAttribute = this.getMithraObjectPortal().getFinder().getSourceAttribute();
Object firstNotSet = null;
boolean isMultiSource = false;
for (int i = 0; i < this.getDelegated().size(this); i++)
{
Object obj = this.getDelegated().get(this, i);
if (!attribute.isSequenceSet(obj))
{
if (firstNotSet == null)
{
firstNotSet = obj;
}
else if (!sourceAttribute.valueEquals(firstNotSet, obj))
{
isMultiSource = true;
break;
}
}
}
if (firstNotSet == null) return; // everything is set already
if (isMultiSource)
{
Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy