Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// // 30/05/2012-2.4 Guy Pelletier
// - 354678: Temp classloader is still being used during metadata processing
package org.eclipse.persistence.mappings.foundation;
import java.util.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.descriptors.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.queries.*;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.internal.sessions.remote.ObjectDescriptor;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.mappings.structures.ArrayCollectionMapping;
import org.eclipse.persistence.mappings.structures.ArrayCollectionMappingHelper;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.sessions.remote.*;
import org.eclipse.persistence.sessions.CopyGroup;
/**
* Define an embedded collection of objects.
* This is used in structured data-types, such as EIS, NoSQL and object-relational Array (varray, nested table) data-types.
* The target objects must be aggregate (embedded) and are stored with the parent object.
*/
public abstract class AbstractCompositeCollectionMapping extends AggregateMapping implements ContainerMapping, ArrayCollectionMapping {
/** The aggregate objects are stored in a single field. */
protected DatabaseField field;
/** This determines the type of container used to hold the aggregate objects. */
private ContainerPolicy containerPolicy;
/** Allows user defined conversion between the object attribute value and the database value. */
protected Converter converter;
/**
* Default constructor.
*/
protected AbstractCompositeCollectionMapping() {
super();
this.containerPolicy = ContainerPolicy.buildDefaultPolicy();
}
/**
* INTERNAL:
* Build and return a new element based on the change set.
*/
@Override
public Object buildAddedElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
return this.buildElementFromChangeSet(changeSet, mergeManager, targetSession);
}
/**
* Build and return a backup clone of the attribute.
*/
@Override
protected Object buildBackupClonePart(Object attributeValue, UnitOfWorkImpl unitOfWork) {
ContainerPolicy cp = this.getContainerPolicy();
if (attributeValue == null) {
return cp.containerInstance();
}
Object backupAttributeValue = cp.containerInstance(cp.sizeFor(attributeValue));
for (Object iter = cp.iteratorFor(attributeValue); cp.hasNext(iter);) {
Object backupElement = super.buildBackupClonePart(cp.next(iter, unitOfWork), unitOfWork);
cp.addInto(backupElement, backupAttributeValue, unitOfWork);
}
return backupAttributeValue;
}
/**
* INTERNAL:
* Build and return a change set for the specified element.
*/
@Override
public Object buildChangeSet(Object element, ObjectChangeSet owner, AbstractSession session) {
ObjectBuilder objectBuilder = this.getObjectBuilder(element, session);
return objectBuilder.compareForChange(element, null, (UnitOfWorkChangeSet)owner.getUOWChangeSet(), session);
}
/**
* Build and return a clone of the attribute.
*/
@Override
protected Object buildClonePart(Object original, Object clone, CacheKey cacheKey, Object attributeValue, Integer refreshCascade, AbstractSession clonningSession) {
ContainerPolicy cp = this.getContainerPolicy();
if (attributeValue == null) {
return cp.containerInstance();
}
Object clonedAttributeValue = cp.containerInstance(cp.sizeFor(attributeValue));
for (Object iter = cp.iteratorFor(attributeValue); cp.hasNext(iter);) {
Object cloneElement = super.buildClonePart(original, clone, cacheKey, cp.next(iter, clonningSession), refreshCascade, clonningSession);
cp.addInto(cloneElement, clonedAttributeValue, clonningSession);
}
return clonedAttributeValue;
}
/**
* Copy of the attribute of the object.
* This is NOT used for unit of work but for templatizing an object.
*/
@Override
protected Object buildCopyOfAttributeValue(Object attributeValue, CopyGroup group) {
ContainerPolicy cp = this.getContainerPolicy();
if (attributeValue == null) {
return cp.containerInstance();
}
Object attributeValueCopy = cp.containerInstance(cp.sizeFor(attributeValue));
for (Object iter = cp.iteratorFor(attributeValue); cp.hasNext(iter);) {
Object copyElement = super.buildCopyOfAttributeValue(cp.next(iter, group.getSession()), group);
cp.addInto(copyElement, attributeValueCopy, group.getSession());
}
return attributeValueCopy;
}
/**
* Build and return a new element based on the change set.
*/
protected Object buildElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
ObjectChangeSet objectChangeSet = (ObjectChangeSet)changeSet;
ObjectBuilder objectBuilder = this.getObjectBuilderForClass(objectChangeSet.getClassType(mergeManager.getSession()), mergeManager.getSession());
Object result = objectBuilder.buildNewInstance();
objectBuilder.mergeChangesIntoObject(result, objectChangeSet, null, mergeManager, targetSession);
return result;
}
/**
* INTERNAL:
* Build and return a new element based on the specified element.
*/
@Override
public Object buildElementFromElement(Object element, MergeManager mergeManager, AbstractSession targetSession) {
ObjectBuilder objectBuilder = this.getObjectBuilder(element, mergeManager.getSession());
Object result = objectBuilder.buildNewInstance();
objectBuilder.mergeIntoObject(result, true, element, mergeManager, targetSession);
return result;
}
/**
* INTERNAL:
* In case Query By Example is used, this method builds and returns an expression that
* corresponds to a single attribute and it's value.
*/
@Override
public Expression buildExpression(Object queryObject, QueryByExamplePolicy policy, Expression expressionBuilder, Map processedObjects, AbstractSession session) {
if (policy.shouldValidateExample()){
throw QueryException.unsupportedMappingQueryByExample(queryObject.getClass().getName(), this);
}
return null;
}
/**
* INTERNAL:
* Build and return a new element based on the change set.
*/
@Override
public Object buildRemovedElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
return this.buildElementFromChangeSet(changeSet, mergeManager, targetSession);
}
/**
* INTERNAL:
* Cascade perform delete through mappings that require the cascade
*/
@Override
public void cascadePerformRemoveIfRequired(Object object, UnitOfWorkImpl uow, Map visitedObjects){
Object cloneAttribute = null;
cloneAttribute = getAttributeValueFromObject(object);
if ( cloneAttribute == null ) {
return;
}
ContainerPolicy cp = getContainerPolicy();
Object cloneObjectCollection = null;
cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow);
Object cloneIter = cp.iteratorFor(cloneObjectCollection);
while (cp.hasNext(cloneIter)) {
Object objectToCascadeOn = cp.next(cloneIter, uow);
if (objectToCascadeOn != null && (!visitedObjects.containsKey(objectToCascadeOn)) ) {
visitedObjects.put(objectToCascadeOn, objectToCascadeOn);
ObjectBuilder builder = getReferenceDescriptor(objectToCascadeOn.getClass(), uow).getObjectBuilder();
builder.cascadePerformRemove(objectToCascadeOn, uow, visitedObjects);
}
}
}
/**
* INTERNAL:
* Cascade discover and persist new objects during commit.
*/
@Override
public void cascadeDiscoverAndPersistUnregisteredNewObjects(Object object, Map newObjects, Map unregisteredExistingObjects, Map visitedObjects, UnitOfWorkImpl uow, Set cascadeErrors) {
Object cloneAttribute = getAttributeValueFromObject(object);
if (cloneAttribute == null ) {
return;
}
ContainerPolicy containerPolicy = getContainerPolicy();
Object cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow);
Object iterator = containerPolicy.iteratorFor(cloneObjectCollection);
while (containerPolicy.hasNext(iterator)) {
Object nextObject = containerPolicy.next(iterator, uow);
if (nextObject != null) {
ObjectBuilder builder = getReferenceDescriptor(nextObject.getClass(), uow).getObjectBuilder();
builder.cascadeDiscoverAndPersistUnregisteredNewObjects(nextObject, newObjects, unregisteredExistingObjects, visitedObjects, uow, cascadeErrors);
}
}
}
/**
* INTERNAL:
* Cascade registerNew for Create through mappings that require the cascade
*/
@Override
public void cascadeRegisterNewIfRequired(Object object, UnitOfWorkImpl uow, Map visitedObjects){
//aggregate objects are not registered but their mappings should be.
Object cloneAttribute = null;
cloneAttribute = getAttributeValueFromObject(object);
if ( cloneAttribute == null ) {
return;
}
ObjectBuilder builder = null;
ContainerPolicy cp = getContainerPolicy();
Object cloneObjectCollection = null;
cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow);
Object cloneIter = cp.iteratorFor(cloneObjectCollection);
while (cp.hasNext(cloneIter)) {
Object nextObject = cp.next(cloneIter, uow);
if (nextObject != null && (! visitedObjects.containsKey(nextObject)) ) {
visitedObjects.put(nextObject, nextObject);
builder = getReferenceDescriptor(nextObject.getClass(), uow).getObjectBuilder();
builder.cascadeRegisterNewForCreate(nextObject, uow, visitedObjects);
}
}
}
/**
* Return the fields handled by the mapping.
*/
@Override
protected Vector collectFields() {
Vector fields = new Vector(1);
fields.addElement(this.getField());
return fields;
}
/**
* INTERNAL:
* Compare the non-null elements and return true if they are alike.
*/
@Override
public boolean compareElements(Object element1, Object element2, AbstractSession session) {
if (element1.getClass() != element2.getClass()) {
return false;
}
return this.getObjectBuilder(element1, session).compareObjects(element1, element2, session);
}
/**
* INTERNAL:
* Compare the non-null elements and return true if they are alike.
*/
@Override
public boolean compareElementsForChange(Object element1, Object element2, AbstractSession session) {
return this.compareElements(element1, element2, session);
}
/**
* INTERNAL:
* Convert all the class-name-based settings in this mapping to actual class-based
* settings. This method is used when converting a project that has been built
* with class names to a project with classes.
*/
@Override
public void convertClassNamesToClasses(ClassLoader classLoader){
super.convertClassNamesToClasses(classLoader);
containerPolicy.convertClassNamesToClasses(classLoader);
}
protected ChangeRecord convertToChangeRecord(Object cloneCollection, ObjectChangeSet owner, AbstractSession session) {
ContainerPolicy cp = getContainerPolicy();
Object cloneIter = cp.iteratorFor(cloneCollection);
Vector collectionChanges = new Vector(2);
while (cp.hasNext(cloneIter)) {
Object aggregateObject = cp.next(cloneIter, session);
// For CR#2258 quietly ignore nulls inserted into a collection.
if (aggregateObject != null) {
ObjectChangeSet changes = getReferenceDescriptor(aggregateObject.getClass(), session).getObjectBuilder().compareForChange(aggregateObject, null, (UnitOfWorkChangeSet)owner.getUOWChangeSet(), session);
collectionChanges.addElement(changes);
}
}
//cr 3013 Removed if collection is empty return null block, which prevents recording clear() change
AggregateCollectionChangeRecord changeRecord = new AggregateCollectionChangeRecord(owner);
changeRecord.setAttribute(getAttributeName());
changeRecord.setMapping(this);
changeRecord.setChangedValues(collectionChanges);
return changeRecord;
}
/**
* An object has been serialized from the server to the remote client.
* Replace the transient attributes of the remote value holders
* with client-side objects.
*/
@Override
protected void fixAttributeValue(Object attributeValue, Map