Search in sources :

Example 1 with ListWrapper

use of org.eclipse.persistence.sdo.helper.ListWrapper in project eclipselink by eclipse-ee4j.

the class SDODataObject method undoChanges.

/**
 * INTERNAL:
 * This function reverses any operations that were performed on this object since change tracking
 * was turned on.  The object is returned to the state when logging was first started.<br>
 * @param isCSRoot
 * @param cs
 * @param origContainer
 * @param origContainmentPropName
 */
public // 
void undoChanges(// 
boolean isCSRoot, // 
ChangeSummary cs, SDODataObject origContainer, String origContainmentPropName) {
    // dont do anything if the changeSummary is null
    if (null == cs) {
        return;
    }
    // base step: swap valueStores at the current node
    if (((SDOChangeSummary) cs).isDirty(this)) {
        // reset only if changes were done
        if (!isCSRoot) {
            // reset changeSummary
            if (null == changeSummary) {
                // we are not recursively setting cs - so don't use the set function as child nodes will be replaced later
                changeSummary = (SDOChangeSummary) cs;
            }
            // reset container
            if (null == container) {
                _setContainer(origContainer);
            }
            // reset containmentProperty name
            if (null == containmentPropertyName) {
                _setContainmentPropertyName(origContainmentPropName);
            }
        }
        // swap valueStores
        _setCurrentValueStore((ValueStore) ((SDOChangeSummary) cs).getOriginalValueStores().get(this));
        // return original to null (no changes)
        ((SDOChangeSummary) cs).getOriginalValueStores().remove(this);
    }
    // swap sequences (may be UC2(DataObject and sequence change) or UC4 (sequence change only)
    if (getType().isSequenced()) {
        // perform sequence.isDirty check independent of a dataObject.isDirty check
        if (((SDOChangeSummary) cs).isDirty(sequence)) {
            Sequence currentSequence = sequence;
            SDOSequence originalSequence = (SDOSequence) ((SDOChangeSummary) cs).getOriginalSequences().get(this);
            // both sequences are either null or set
            if ((null == originalSequence) && (null != currentSequence)) {
                throw SDOException.oldSequenceNotFound();
            } else {
                sequence = originalSequence;
            }
            // reset the cache map
            ((SDOChangeSummary) cs).getOldSequences().remove(this);
            // rest the primary map
            ((SDOChangeSummary) cs).getOriginalSequences().remove(this);
        }
    }
    // restore any open content properties to the 3 data structures on SDODataObject, and remove from cs.unsetOCPropsMap
    // see openContentPropertiesMap<String,Property>, openContentProperties(List<Property>). instanceProperties (List<Property>)
    List oldUnsetOCList = ((SDOChangeSummary) cs).getUnsetOCProperties(this);
    for (int i = 0, size = oldUnsetOCList.size(); i < size; i++) {
        // it is essential that the oc property is removed from the cs or we will get an unsupported op during resetChanges()
        // the property will be added only when logging=true, we reference the first item in the list as it reduces in size
        addOpenContentProperty((Property) oldUnsetOCList.get(0));
    }
    // recursive step: swap valueStores on every contained subtree
    for (Iterator iterProperties = getInstanceProperties().iterator(); iterProperties.hasNext(); ) {
        SDOProperty property = (SDOProperty) iterProperties.next();
        if (!property.getType().isChangeSummaryType()) {
            Object value = get(property);
            if ((null == value) && (null != getChangeSummary())) {
            // no changes for null properties
            } else {
                if (property.isMany()) {
                    // assumption that we never have a null ListWrapper should still avoid a possible NPE
                    if (null != value) {
                        ((ListWrapper) value).undoChanges(getChangeSummary());
                        if (!property.getType().isDataType()) {
                            for (Iterator iterMany = ((List) value).iterator(); iterMany.hasNext(); ) {
                                Object valueMany = iterMany.next();
                                if (null != valueMany) {
                                    // handle micro-corner case ListWrapper is null
                                    ((SDODataObject) valueMany).undoChanges(false, changeSummary, this, property.getName());
                                }
                            }
                        }
                    }
                } else {
                    if (!property.getType().isDataType() && (null != value)) {
                        ((SDODataObject) value).undoChanges(false, changeSummary, this, property.getName());
                    }
                }
            }
        }
    }
}
Also used : Iterator(java.util.Iterator) ListWrapper(org.eclipse.persistence.sdo.helper.ListWrapper) ArrayList(java.util.ArrayList) List(java.util.List) DataObject(commonj.sdo.DataObject) SequencedObject(org.eclipse.persistence.oxm.sequenced.SequencedObject) Sequence(commonj.sdo.Sequence)

Example 2 with ListWrapper

use of org.eclipse.persistence.sdo.helper.ListWrapper in project eclipselink by eclipse-ee4j.

the class SDODataObject method setInternal.

public void setInternal(SDOProperty property, Object value, boolean updateSequence) throws UnsupportedOperationException, IllegalArgumentException {
    if (null == getType()) {
        throw new UnsupportedOperationException("Type is null");
    }
    if (property.isOpenContent() && !getType().isOpen()) {
        // not open and not in types currentValueStore
        throw new IllegalArgumentException("DataObject " + this + " is not Open for property " + property.getName());
    }
    // Note: get() will call setPropertyInternal() if the list is null = not set yet - we need to propagate the updateSequence flag
    Object oldValue = get(property);
    boolean wasSet = isSet(property);
    if (wasSet && (oldValue == value)) {
        return;
    } else {
        _setModified(true);
    }
    if (property.isMany()) {
        List listValue;
        if (null == value) {
            listValue = new ListWrapper(this, property);
        } else {
            try {
                listValue = (List) value;
            } catch (ClassCastException e) {
                throw new IllegalArgumentException("Properties with isMany = true can only be set on list values.");
            }
        }
        if (property.isContainment() || isContainedByDataGraph(property)) {
            for (Object next : listValue) {
                if (next instanceof SDODataObject) {
                    if (parentContains(next)) {
                        throw new IllegalArgumentException("Circular reference.");
                    }
                }
            }
        }
        ListWrapper oldValueListWrapper = (ListWrapper) oldValue;
        // 20060529: v33: Move clear() out of ListWrapper.addAll()
        // handle clearing of elements which also calls removeContainment(prop) outside of addAll()
        oldValueListWrapper.clear(updateSequence);
        // handle updateContainment and sequences inside addAll()
        // for non-default Pluggable impl this function is not required
        oldValueListWrapper.addAll((Collection) value, updateSequence);
    } else {
        if (property.isContainment() || isContainedByDataGraph(property)) {
            if (parentContains(value)) {
                throw new IllegalArgumentException("Circular reference.");
            }
            // detach the oldValue from this dataObject
            if (null != oldValue) {
                detach(property, oldValue);
            }
            // sets the new value's container and containment prop to this dataobject, detaches from other owner...not right
            /**
             * Case: set(do) is actually a move(do) between two CS - detach required
             * Case: set(do) is actually an add(do) on a single CS - detach not required
             */
            SDODataObject dataObjectValue = (SDODataObject) value;
            if (dataObjectValue != null) {
                updateContainment(property, dataObjectValue);
            }
        }
        // process pluggable currentValueStore and set [value] as a property of [this] as well as sequences
        setPropertyInternal(property, value, updateSequence);
    }
    if (getType().isOpen() && property.isOpenContent()) {
        addOpenContentProperty(property);
    }
}
Also used : ListWrapper(org.eclipse.persistence.sdo.helper.ListWrapper) DataObject(commonj.sdo.DataObject) SequencedObject(org.eclipse.persistence.oxm.sequenced.SequencedObject) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with ListWrapper

use of org.eclipse.persistence.sdo.helper.ListWrapper in project eclipselink by eclipse-ee4j.

the class SDODataObject method updateDataGraph.

/**
 * INTERNAL:
 * Recursively set this DataObject's DataGraph
 * This function serves as a copy of updateChangeSummaryAndDataGraph() to recursively walk and set the dataGraph.
 * that will be run when no recursion occurs in the case that an object (with a changeSummary)
 * is set internally to a tree (without a changeSummary).
 * Callers: Typically updateContainment (during a set) or delete/detach
 *   when the current object is internal with its own changeSummary property.
 * @param aDataGraph
 */
private void updateDataGraph(DataGraph aDataGraph) {
    Iterator iterProperties = getInstanceProperties().iterator();
    Property property;
    Object object;
    Object listContainedObject;
    // Add back pointer to containing DataGraph - in preOrder sequence before recursing
    setDataGraph(aDataGraph);
    // Recurse currentValueStore
    while (iterProperties.hasNext()) {
        property = (Property) iterProperties.next();
        // do not recurse bidirectional currentValueStore that are non-containment
        if (property.isContainment() || isContainedByDataGraph(property)) {
            object = get(property);
            if (object instanceof SDODataObject) {
                // DataObject child of this DataObject
                ((SDODataObject) object).updateDataGraph(aDataGraph);
            }
            if (object instanceof ListWrapper) {
                // ListWrapper child of this DataObject
                Iterator anIterator = ((ListWrapper) object).iterator();
                while (anIterator.hasNext()) {
                    listContainedObject = anIterator.next();
                    if (listContainedObject instanceof SDODataObject) {
                        ((SDODataObject) listContainedObject).updateDataGraph(aDataGraph);
                    }
                }
            }
        }
    }
}
Also used : Iterator(java.util.Iterator) ListWrapper(org.eclipse.persistence.sdo.helper.ListWrapper) DataObject(commonj.sdo.DataObject) SequencedObject(org.eclipse.persistence.oxm.sequenced.SequencedObject) Property(commonj.sdo.Property)

Example 4 with ListWrapper

use of org.eclipse.persistence.sdo.helper.ListWrapper in project eclipselink by eclipse-ee4j.

the class SDODataObject method detach.

/**
 * INTERNAL:
 * Removes this DataObject from its container, if any.
 * Same as
 *  getContainer().getList(getContainmentProperty()).remove(this) or
 *  getContainer().unset(getContainmentProperty())
 *  depending on getContainmentProperty().isMany() respectively.
 *  @param fromDelete (true = delete action, false = detach/unset)
 *  @param updateSequence
 */
private void detach(boolean fromDelete, boolean updateSequence) {
    // Note: there is no case10 where fromDelete=true and updateSequence=false
    SDOProperty containmentProperty = getContainmentProperty();
    if ((containmentProperty != null) && containmentProperty.isReadOnly()) {
        throw new UnsupportedOperationException("Property is Readonly." + containmentProperty.getName() + "  " + getType().getName());
    }
    if (containmentProperty != null) {
        if (getContainmentProperty().isMany()) {
            List oldList = getContainer().getList(containmentProperty);
            // pass remove containment flag instead of calling remove(this) and detachOrDelete(fromDelete) separately
            // This will invoke creation of an intact list copy before removing its containment and clearing its changeSummary
            ((ListWrapper) oldList).remove(this, fromDelete, updateSequence);
        } else {
            getContainer().unset(containmentProperty, fromDelete, updateSequence);
        }
    } else {
        _setDeleted(true);
        detachOrDelete(fromDelete);
    }
}
Also used : ListWrapper(org.eclipse.persistence.sdo.helper.ListWrapper) ArrayList(java.util.ArrayList) List(java.util.List)

Example 5 with ListWrapper

use of org.eclipse.persistence.sdo.helper.ListWrapper in project eclipselink by eclipse-ee4j.

the class SDODataObject method updateContainment.

/**
 * INTERNAL:
 * Update containment on the dataObject with specified update sequence state
 * @param property
 * @param aDataObject
 * @param updateSequence
 */
public void updateContainment(Property property, SDODataObject aDataObject, boolean updateSequence) {
    if (property.isContainment() || isContainedByDataGraph(property)) {
        boolean wasInNewCS = // 
        (getChangeSummary() != null) && (aDataObject.getChangeSummary() != null) && getChangeSummary().equals(aDataObject.getChangeSummary());
        // Remove property or old changeSummary
        if (aDataObject.getContainer() != null) {
            aDataObject.detach(false, updateSequence);
        }
        // Need to know if the DO was deleted and being re-added later on in this method.
        // Since getChangeSummary().isDeleted() will be affected before the code in question
        // is hit, store the value now.
        boolean isDeleted = false;
        if (getChangeSummary() != null) {
            isDeleted = getChangeSummary().isDeleted(aDataObject);
        }
        /**
         * The following 2 update functions are kept separate for performance reasons in #6473342..
         * Alternate implementations could have used a Command pattern object or boolean states to enable a
         * single function to perform multiple operations.
         *
         * The DataGraph pointer on all subtrees are always updated regardless of the dataGraph value.
         * However, the ChangeSummary pointer is only updated if the dataObject(value) being updated is not
         * itself an internal changeSummary root.
         * For example: the following would not update the CS to null when we get to dataObject B - as it has its own changeSummary-B
         *  root
         *     -> B
         *             -> CS-B
         *             -> D (String)
         * But, the following would update the CS to CS-root when we get to dataObject B because the changeSummary root is above it
         *  root
         *     -> B
         *             -> D (String)
         *     -> CS-root
         */
        if (// 
        (getChangeSummary() != null) && (aDataObject.getType() != null) && (aDataObject.getType().getChangeSummaryProperty() == null)) {
            // Recursively set the current changeSummary and dataGraph - the CS root is above or absent
            aDataObject.updateChangeSummaryAndDataGraph(getChangeSummary(), getDataGraph());
        } else {
            // Recursively set the dataGraph when this level (value) is the CS root n the subtree
            if (aDataObject.getDataGraph() != getDataGraph()) {
                aDataObject.updateDataGraph(getDataGraph());
            }
        }
        // add value as a property of (this)
        aDataObject._setContainer(this);
        aDataObject._setContainmentPropertyName(property.getName());
        // We don't setCreated for objects that were previously deleted
        if (!wasInNewCS && (getChangeSummary() != null) && !getChangeSummary().isDeleted(aDataObject)) {
            aDataObject._setCreated(true);
        }
        // so we end up with all isDeleted, isModified == false
        if ((getChangeSummary() != null) && getChangeSummary().isDeleted(aDataObject)) {
            // explicitly clear the oldSetting and clear the key:value pair in the deleted map
            aDataObject._setDeleted(false);
        // remove oldSetting from map only when we return to original position
        // by comparing an undo() with the projected model after set() - for now keep oldSettings
        }
        // modify container object
        _setModified(true);
        // the change summary's OriginalValueStores list to ensure isModified correctness
        if (isDeleted) {
            // May need to remove the corresponding entry in the originalValueStore map.
            // Compare the value store to the corresponding entry in the originalValueStore map.
            // Check to see if we're adding into the old parent (undo delete) or into a new parent (move)
            Map originalValueStores = getChangeSummary().getOriginalValueStores();
            ValueStore originalVS = ((ValueStore) originalValueStores.get(aDataObject));
            if (originalVS.equals(aDataObject._getCurrentValueStore())) {
                // Remove the old value store from the change summary
                originalValueStores.remove(aDataObject);
            }
            DataObject oldParentDO = getChangeSummary().getOldContainer(aDataObject);
            if (oldParentDO == this) {
                // The data object was deleted and is now being re-added to same parent object.
                // May need to remove the corresponding entry in the oldValueStore map.
                // Compare the parent value store to the corresponding entry in the oldValueStore map.
                ValueStore originalParentVS = ((ValueStore) originalValueStores.get(oldParentDO));
                if (originalParentVS.equals(this._getCurrentValueStore())) {
                    // Value stores are equal, now make sure no ListWrappers have been modified
                    // For each typePropertyValue that is a ListWrapper in the currentValueStore, check
                    // the OriginalElements list in the CS to see if that wrapper exists in the list (indicating
                    // the wrapper's list was modified at some point) and if it does, compare the current list
                    // to that original list.  If they are equal, and the value stores are equal, the entries
                    // can be removed from the change summary so isModified will work correctly
                    Object prop;
                    Object oldList;
                    Map originalElements = getChangeSummary().getOriginalElements();
                    List oldParentProps = oldParentDO.getInstanceProperties();
                    for (int i = 0; i < oldParentProps.size(); i++) {
                        prop = originalParentVS.getDeclaredProperty(i);
                        oldList = originalElements.get(prop);
                        if (oldList != null) {
                            List oldElements = (List) oldList;
                            List currentElements = ((ListWrapper) prop).getCurrentElements();
                            if (oldElements.size() != currentElements.size()) {
                                // A ListWrapper has been modified - don't remove the old value store entry
                                return;
                            }
                            Iterator elementIt = currentElements.iterator();
                            Iterator oldelementIt = oldElements.iterator();
                            while (elementIt.hasNext()) {
                                if (elementIt.next() != oldelementIt.next()) {
                                    // A ListWrapper has been modified - don't remove the old value store entry
                                    return;
                                }
                            }
                        }
                    }
                    // Remove the old value store from the change summary
                    originalValueStores.remove(oldParentDO);
                }
            }
        }
    }
}
Also used : DataObject(commonj.sdo.DataObject) Iterator(java.util.Iterator) ListWrapper(org.eclipse.persistence.sdo.helper.ListWrapper) DataObject(commonj.sdo.DataObject) SequencedObject(org.eclipse.persistence.oxm.sequenced.SequencedObject) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ListWrapper (org.eclipse.persistence.sdo.helper.ListWrapper)164 SDODataObject (org.eclipse.persistence.sdo.SDODataObject)131 DataObject (commonj.sdo.DataObject)106 SDOSequence (org.eclipse.persistence.sdo.SDOSequence)73 ArrayList (java.util.ArrayList)72 Property (commonj.sdo.Property)47 SDOProperty (org.eclipse.persistence.sdo.SDOProperty)47 List (java.util.List)29 Iterator (java.util.Iterator)9 SDOChangeSummary (org.eclipse.persistence.sdo.SDOChangeSummary)9 ChangeSummary (commonj.sdo.ChangeSummary)8 Type (commonj.sdo.Type)8 QName (javax.xml.namespace.QName)7 SequencedObject (org.eclipse.persistence.oxm.sequenced.SequencedObject)7 DefaultSchemaLocationResolver (org.eclipse.persistence.sdo.helper.DefaultSchemaLocationResolver)7 SDOXSDHelper (org.eclipse.persistence.sdo.helper.SDOXSDHelper)7 SDOException (org.eclipse.persistence.exceptions.SDOException)6 Map (java.util.Map)5 Setting (org.eclipse.persistence.oxm.sequenced.Setting)4 SDOSetting (org.eclipse.persistence.sdo.SDOSetting)4