/** INTERNAL: Build and return a new element based on the change set. */
  public Object buildRemovedElementFromChangeSet(Object changeSet, MergeManager mergeManager) {
    ObjectChangeSet objectChangeSet = (ObjectChangeSet) changeSet;

    if (!mergeManager.shouldMergeChangesIntoDistributedCache()) {
      mergeManager.registerRemovedNewObjectIfRequired(objectChangeSet.getUnitOfWorkClone());
    }

    return this.buildElementFromChangeSet(changeSet, mergeManager);
  }
 /** Remove stuff from an unordered collection. */
 private void simpleRemoveFromCollectionChangeRecordWithoutOrder(
     Object referenceKey,
     Object changeSetToRemove,
     ObjectChangeSet changeSet,
     AbstractSession session) {
   EISCollectionChangeRecord changeRecord =
       (EISCollectionChangeRecord) changeSet.getChangesForAttributeNamed(this.getAttributeName());
   if (changeRecord == null) {
     changeRecord =
         new EISCollectionChangeRecord(
             changeSet, this.getAttributeName(), this.getDatabaseMapping());
     changeSet.addChange(changeRecord);
   }
   changeRecord.simpleRemoveChangeSet(changeSetToRemove);
 }
  /** INTERNAL: Build and return a new element based on the change set. */
  public Object buildAddedElementFromChangeSet(Object changeSet, MergeManager mergeManager) {
    ObjectChangeSet objectChangeSet = (ObjectChangeSet) changeSet;

    if (this.shouldMergeCascadeParts(mergeManager)) {
      Object targetElement = null;
      if (mergeManager.shouldMergeChangesIntoDistributedCache()) {
        targetElement =
            objectChangeSet.getTargetVersionOfSourceObject(mergeManager.getSession(), true);
      } else {
        targetElement = objectChangeSet.getUnitOfWorkClone();
      }
      mergeManager.mergeChanges(targetElement, objectChangeSet);
    }

    return this.buildElementFromChangeSet(changeSet, mergeManager);
  }
  /** INTERNAL: Get a value from the object and set that in the respective field of the row. */
  public void writeFromObjectIntoRowWithChangeRecord(
      ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) {
    if (isReadOnly()) {
      return;
    }

    ObjectChangeSet changeSet =
        (ObjectChangeSet) ((ObjectReferenceChangeRecord) changeRecord).getNewValue();
    Object referenceObject = changeSet.getUnitOfWorkClone();

    if (referenceObject == null) {
      return;
    }

    Ref ref =
        ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor())
            .getRef(referenceObject, session);

    record.put(getField(), ref);
  }
  /**
   * INTERNAL: Get a value from the object and set that in the respective field of the row. If the
   * mapping id target foreign key, you must only write the type into the roe, the rest will be
   * updated when the object itself is written
   */
  @Override
  public void writeFromObjectIntoRowWithChangeRecord(
      ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) {
    if (isReadOnly()) {
      return;
    }

    ObjectChangeSet changeSet =
        (ObjectChangeSet) ((ObjectReferenceChangeRecord) changeRecord).getNewValue();
    if (changeSet == null) {
      writeFromNullObjectIntoRow(record);
    } else {
      Object referenceObject = changeSet.getUnitOfWorkClone();
      if (isForeignKeyRelationship()) {
        Enumeration sourceFields = getForeignKeyFields().elements();
        ClassDescriptor descriptor = session.getDescriptor(referenceObject.getClass());
        while (sourceFields.hasMoreElements()) {
          DatabaseField sourceKey = (DatabaseField) sourceFields.nextElement();
          String targetQueryKey = (String) getSourceToTargetQueryKeyNames().get(sourceKey);
          DatabaseField targetKeyField =
              descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey);
          if (targetKeyField == null) {
            throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly(
                this, descriptor, targetQueryKey);
          }
          Object referenceValue =
              descriptor
                  .getObjectBuilder()
                  .extractValueFromObjectForField(referenceObject, targetKeyField, session);
          record.put(sourceKey, referenceValue);
        }
      }
      if (getTypeField() != null) {
        record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass()));
      }
    }
  }
  /**
   * INTERNAL: Build and return the change record that results from comparing the two collection
   * attributes.
   */
  public ChangeRecord compareForChange(
      Object clone, Object backup, ObjectChangeSet owner, AbstractSession session) {
    ContainerPolicy cp = this.getContainerPolicy();
    Object cloneCollection = this.getRealCollectionAttributeValueFromObject(clone, session);

    Object backupCollection = null;
    if (owner.isNew()) {
      backupCollection = cp.containerInstance(1);
    } else {
      backupCollection = this.getRealCollectionAttributeValueFromObject(backup, session);
    }

    if (cp.hasOrder()) {
      return this.compareAttributeValuesForChangeWithOrder(
          cloneCollection, backupCollection, owner, session);
    } else {
      return this.compareAttributeValuesForChangeWithoutOrder(
          cloneCollection, backupCollection, owner, session);
    }
  }
 /** INTERNAL: Build and return a change set for the specified element. */
 public Object buildChangeSet(Object element, ObjectChangeSet owner, AbstractSession session) {
   ObjectBuilder objectBuilder = session.getDescriptor(element).getObjectBuilder();
   return objectBuilder.createObjectChangeSet(
       element, (UnitOfWorkChangeSet) owner.getUOWChangeSet(), session);
 }