/*
 * Copyright (c) 1998, 2020 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
package org.eclipse.persistence.sdo;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.sequenced.SequencedObject;
import org.eclipse.persistence.oxm.sequenced.Setting;
import org.eclipse.persistence.sdo.helper.ListWrapper;
import org.eclipse.persistence.sdo.helper.SDODataHelper;
import org.eclipse.persistence.sdo.helper.SDOTypeHelper;
import org.eclipse.persistence.sdo.helper.XPathEngine;

import commonj.sdo.ChangeSummary;
import commonj.sdo.DataGraph;
import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Sequence;
import commonj.sdo.Type;
import commonj.sdo.helper.DataHelper;
import commonj.sdo.helper.HelperContext;

public class SDODataObject implements DataObject, SequencedObject {

    /**
     * Development Guidelines:
     * (1) All no-argument get and single argument set functions that are outside the DataObject interface
     * must be proceeded with a _ underscore in the form _getValue()/_setValue(value).
     * The reason for this is to avoid naming collisions with generated classes that extend SDODataObject
     * where the generated get/set methods for POJO fields would collide with the same function here.
     */
    /** The Type that this DataObject represents */
    private SDOType type;

    // t20070714_bc4j: Add pluggable DO support for BC4J using currentValueStore
    private SDODataObject container;

    /**
     * The (currentValueStore) will maintain the current state of our model
     *   after logged changes - it is a shallow copy of the original, progressively becoming deeper with changes.
     */
    private ValueStore currentValueStore;
    private List openContentProperties;
    private List openContentPropertiesAttributes;
    private Map openContentAliasNames;
    private String containmentPropertyName;
    private SDOChangeSummary changeSummary;
    private List<SDOProperty> instanceProperties;
    private String sdoRef;
    private SDOSequence sequence;
    private DataGraph dataGraph;

    /** hold the current context containing all helpers so that we can preserve inter-helper relationships */
    private HelperContext aHelperContext;

    /**Unique hash ID of this Externalizable class - not required at this point because we serialize the xml representation */

    @SuppressWarnings("unused")
    private String text;

    //static final long serialVersionUID = 5930094058760264198L;

    /**
     * INTERNAL:
     * Private constructor.
     * Use {@link org.eclipse.persistence.sdo.helper.delegates.SDODataFactoryDelegate#create(commonj.sdo.Type) SDODataFactoryDelegate.create(Type)} instead
     */
    public SDODataObject() {
        // Implementors should not be calling this constructor directly - please use SDODataFactory
        // however if it is called we will initialize the default implementation of the currentValueStore Map
        // initialize Map Implementation
        // set currentValueStore Map implementation (replace any that was set in the constructor in newInstance() above)
        _setCurrentValueStore(new DefaultValueStore());
    }

    /**
     * INTERNAL:
     * Set the HelperContext that will be associated with this DataObject.
     * @param aContext
     */
    public void _setHelperContext(HelperContext aContext) {
        aHelperContext = aContext;
        // reset the HelperContext on ChangeSummary
        if (changeSummary != null) {
            changeSummary.setHelperContext(aHelperContext);
        }
    }

    @Override
    public Object get(String path) {// path like "a/b/c"
        try {
            return XPathEngine.getInstance().get(path, this);
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return null;
        }
    }

    @Override
    public void set(String path, Object value) throws ClassCastException, UnsupportedOperationException, IllegalArgumentException {
        XPathEngine.getInstance().set(path, value, this, false);
    }

    @Override
    public boolean isSet(String path) {
        return XPathEngine.getInstance().isSet(path, this);
    }

    @Override
    public void unset(String path) {
        XPathEngine.getInstance().unset(path, this);
    }

    @Override
    public boolean getBoolean(String path) throws ClassCastException {
        try {
            Boolean value = (Boolean)XPathEngine.getInstance().convertObjectToValueByPath(path, Boolean.class, this);

            if (value == null) {
                return false;
            }
            return value.booleanValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return false;
        }
    }

    @Override
    public byte getByte(String path) {
        try {
            Byte value = (Byte)XPathEngine.getInstance().convertObjectToValueByPath(path, Byte.class, this);
            if (value == null) {
                return 0;
            }
            return value.byteValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return 0;
        }
    }

    @Override
    public char getChar(String path) {
        try {
            Character value = (Character)XPathEngine.getInstance().convertObjectToValueByPath(path, Character.class, this);
            if (value == null) {
                return '\u0000';
            }
            return value.charValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return '\u0000';
        }
    }

    @Override
    public double getDouble(String path) {
        try {
            Double value = (Double)XPathEngine.getInstance().convertObjectToValueByPath(path, Double.class, this);
            if (value == null) {
                return 0.0d;
            }
            return value.doubleValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return 0.0d;
        }
    }

    @Override
    public float getFloat(String path) {
        try {
            Float value = (Float)XPathEngine.getInstance().convertObjectToValueByPath(path, Float.class, this);
            if (value == null) {
                return 0.0f;
            }
            return value.floatValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return 0.0f;
        }
    }

    @Override
    public int getInt(String path) {
        try {
            Integer value = (Integer)XPathEngine.getInstance().convertObjectToValueByPath(path, Integer.class, this);
            if (value == null) {
                return 0;
            }
            return value.intValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return 0;
        }
    }

    @Override
    public long getLong(String path) {
        try {
            Long value = (Long)XPathEngine.getInstance().convertObjectToValueByPath(path, Long.class, this);
            if (value == null) {
                return 0L;
            }
            return value.longValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return 0L;
        }
    }

    @Override
    public short getShort(String path) {
        try {
            Short value = (Short)XPathEngine.getInstance().convertObjectToValueByPath(path, Short.class, this);
            if (value == null) {
                return 0;
            }
            return value.shortValue();
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return 0;
        }
    }

    @Override
    public byte[] getBytes(String path) {
        try {
            byte[] value = (byte[])XPathEngine.getInstance().convertObjectToValueByPath(path, byte[].class, this);
            return value;
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return null;
        }
    }

    @Override
    public BigDecimal getBigDecimal(String path) {
        try {
            BigDecimal value = (BigDecimal)XPathEngine.getInstance().convertObjectToValueByPath(path, BigDecimal.class, this);
            return value;
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return null;
        }
    }

    @Override
    public BigInteger getBigInteger(String path) {
        try {
            BigInteger value = (BigInteger)XPathEngine.getInstance().convertObjectToValueByPath(path, BigInteger.class, this);
            return value;
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return null;
        }
    }

    @Override
    public SDODataObject getDataObject(String path) throws ClassCastException {
        Object value = get(path);
        if(value instanceof ListWrapper) {
            return (SDODataObject)((ListWrapper)value).get(0);
        }
        return (SDODataObject)value;
    }

    @Override
    public Date getDate(String path) {
        try {
            Date value = (Date)XPathEngine.getInstance().convertObjectToValueByPath(path, Date.class, this);
            return value;
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return null;
        }
    }

    @Override
    public String getString(String path) {
        try {
            String value = (String)XPathEngine.getInstance().convertObjectToValueByPath(path, String.class, this);
            return value;
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return null;
        }
    }

    @Override
    public List getList(String path) {
        try {
            return (List)XPathEngine.getInstance().convertObjectToValueByPath(path, List.class, this);
        } catch (Exception e) {
            // Swallow exception and return null, as per SDO 2.1 spec
            return null;
        }
    }

    @Override
    public void setBoolean(String path, boolean value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setByte(String path, byte value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setChar(String path, char value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setDouble(String path, double value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setFloat(String path, float value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setInt(String path, int value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setLong(String path, long value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setShort(String path, short value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setBytes(String path, byte[] value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setBigDecimal(String path, BigDecimal value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setBigInteger(String path, BigInteger value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setDataObject(String path, DataObject value) {
        set(path, value);
    }

    @Override
    public void setDate(String path, Date value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setString(String path, String value) {
        convertValueAndSet(path, value);
    }

    @Override
    public void setList(String path, List value) {
        convertValueAndSet(path, value);
    }

    @Override
    public Object get(int propertyIndex) throws IllegalArgumentException {
        Property p = getInstanceProperty(propertyIndex);
        return get(p);
    }

    @Override
    public void set(int propertyIndex, Object value) {
        try {
            Property p = getInstanceProperty(propertyIndex);
            set(p, value);
        } catch (IndexOutOfBoundsException e) {
            throw new IllegalArgumentException("PropertyIndex invalid.");
        }
    }

    @Override
    public boolean isSet(int propertyIndex) {
        Property p = getInstanceProperty(propertyIndex);
        return isSet(p);
    }

    @Override
    public void unset(int propertyIndex) {
        Property p = getInstanceProperty(propertyIndex);
        unset(p);
    }

    @Override
    public boolean getBoolean(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getBoolean(property);
    }

    @Override
    public byte getByte(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getByte(property);
    }

    @Override
    public char getChar(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getChar(property);
    }

    @Override
    public double getDouble(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getDouble(property);
    }

    @Override
    public float getFloat(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getFloat(property);
    }

    @Override
    public int getInt(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getInt(property);
    }

    @Override
    public long getLong(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getLong(property);
    }

    @Override
    public short getShort(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getShort(property);
    }

    @Override
    public byte[] getBytes(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getBytes(property);
    }

    @Override
    public BigDecimal getBigDecimal(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getBigDecimal(property);
    }

    @Override
    public BigInteger getBigInteger(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getBigInteger(property);
    }

    @Override
    public SDODataObject getDataObject(int propertyIndex) {
        Property property = getInstanceProperty(propertyIndex);
        return getDataObject(property);
    }

    @Override
    public Date getDate(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getDate(property);
    }

    @Override
    public String getString(int propertyIndex) throws IllegalArgumentException, ClassCastException {
        Property property = getInstanceProperty(propertyIndex);
        return getString(property);
    }

    @Override
    public List getList(int propertyIndex) {
        Property property = getInstanceProperty(propertyIndex);
        return getList(property);
    }

    /**
     * @deprecated in SDO 2.1.0.
     */
    @Deprecated
    @Override
    public Sequence getSequence(String path) {
        // get property from path
        Object anObject = get(path);

        if ((null == anObject) || !(anObject instanceof DataObject)) {
            // throw exception because there is no way to get the property from a null object in this context
            throw SDOException.sequenceNotFoundForPath(path);
        } else {
            // we cannot use containmentProperty in the many case as the index is missing - use the DO
            return ((DataObject)anObject).getSequence();
        }
    }

    /**
     * @deprecated in SDO 2.1.0.
     */
    @Deprecated
    @Override
    public Sequence getSequence(int propertyIndex) {
        // get property
        Property aProperty = getInstanceProperty(propertyIndex);
        return getSequencePrivate(aProperty);
    }

    /**
     * @deprecated in SDO 2.1.0.
     */
    @Deprecated
    @Override
    public Sequence getSequence(Property property) {
        return getSequencePrivate(property);
    }

    /**
     * INTERNAL:
     * Return a Sequence object when the conditions of many=false and dataType=false are met.
     * Throw an UnsupportedOperationException in all other cases.
     */
    private Sequence getSequencePrivate(Property aProperty) {
        // we process only complex types that are non-many
        if ((aProperty != null) && ((SDOProperty)aProperty).getType().isSequenced() && isSet(aProperty) &&//
                !((SDOProperty)aProperty).getType().isDataType() && !aProperty.isMany()) {
            return ((DataObject)get(aProperty)).getSequence();
        } else {
            throw SDOException.sequenceNotSupportedForProperty(aProperty.getName());
        }
    }

    @Override
    public SDOSequence getSequence() {
        // sequence object should be null if !sequenced
        return sequence;
    }

    @Override
    public void setBoolean(int propertyIndex, boolean value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setByte(int propertyIndex, byte value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setChar(int propertyIndex, char value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setDouble(int propertyIndex, double value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setFloat(int propertyIndex, float value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setInt(int propertyIndex, int value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setLong(int propertyIndex, long value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setShort(int propertyIndex, short value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setBytes(int propertyIndex, byte[] value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setBigDecimal(int propertyIndex, BigDecimal value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setBigInteger(int propertyIndex, BigInteger value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setDataObject(int propertyIndex, DataObject value) {
        set(propertyIndex, value);
    }

    @Override
    public void setDate(int propertyIndex, Date value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setString(int propertyIndex, String value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public void setList(int propertyIndex, List value) {
        convertValueAndSet(propertyIndex, value);
    }

    @Override
    public Object get(Property property) throws IllegalArgumentException {
        if (null == property) {// check null property before null type
            throw new IllegalArgumentException("Argument not Supported.");
        }

        if ((null != type) && !type.isOpen() && property.isOpenContent()) {
            throw new IllegalArgumentException("Argument not Supported.");
        }
        if (property.isMany()) {
            return getList(property);
        }

        if (isSet(property)) {
            return getPropertyInternal(property);
        }

        // return the default or a cached pseudo default Object for an unset property
        // JIRA-253: We are wrapping primitive numerics with a wrapper Object
        return property.getDefault();
    }

    /**
     * INTERNAL:
     * Create a dynamic open content property if no property exists for (name).
     * @param name
     * @param value
     * @return Property
     * @throws UnsupportedOperationException
     * @throws IllegalArgumentException
     */
    public Property defineOpenContentProperty(String name, Object value) throws UnsupportedOperationException, IllegalArgumentException {
        if (value == null) {
            return null;
        }
        DataObject propertyDO = aHelperContext.getDataFactory().create(SDOConstants.SDO_URL, SDOConstants.PROPERTY);

        propertyDO.set("name", name);
        Type sdotype = null;
        boolean isMany = false;
        boolean isContainment = false;
        Class valueClass = value.getClass();

        if (value instanceof Collection) {
            if (((Collection)value).size() > 0) {
                Object firstObject = ((Collection)value).iterator().next();
                if (firstObject != null) {
                    valueClass = firstObject.getClass();
                    if (firstObject instanceof DataObject) {
                        if (((DataObject)firstObject).getContainer() == null) {
                            isContainment = true;
                        }
                        sdotype = ((DataObject)firstObject).getType();
                    } else {
                        sdotype = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getTypeForSimpleJavaType(valueClass);
                    }
                } else {
                    return null;
                }
            } else {
                return null;
            }
            isMany = true;
        } else if (value instanceof DataObject) {
            if (((DataObject)value).getContainer() == null) {
                isContainment = true;
            }
            sdotype = ((DataObject)value).getType();
        } else {
            Property xmlElementProperty = aHelperContext.getTypeHelper().getOpenContentProperty(SDOConstants.SDOXML_URL, SDOConstants.XMLELEMENT_PROPERTY_NAME);
            propertyDO.set(xmlElementProperty, Boolean.TRUE);
            sdotype = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getTypeForSimpleJavaType(valueClass);
        }
        propertyDO.set("type", sdotype);

        propertyDO.set("many", isMany);

        propertyDO.set("containment", isContainment);
        return aHelperContext.getTypeHelper().defineOpenContentProperty(null, propertyDO);
    }

    public Property defineOpenContentProperty(String name, Object value, Type sdotype) throws UnsupportedOperationException, IllegalArgumentException {
        if (value == null) {
            return null;
        }
        if(sdotype == null){
          return defineOpenContentProperty(name, value);
        }
        DataObject propertyDO = aHelperContext.getDataFactory().create(SDOConstants.SDO_URL, SDOConstants.PROPERTY);

        propertyDO.set("name", name);
        boolean isMany = false;
        boolean isContainment = false;
        Class valueClass = value.getClass();

        if (value instanceof Collection) {
            if (((Collection)value).size() > 0) {
                Object firstObject = ((Collection)value).iterator().next();
                if (firstObject != null) {
                    valueClass = firstObject.getClass();
                    if (firstObject instanceof DataObject) {
                        if (((DataObject)firstObject).getContainer() == null) {
                            isContainment = true;
                        }
                        sdotype = ((DataObject)firstObject).getType();
                    } else {
                        sdotype = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getTypeForSimpleJavaType(valueClass);
                    }
                }
            }
            isMany = true;
        } else if (value instanceof DataObject) {
            if (((DataObject)value).getContainer() == null) {
                isContainment = true;
            }
            sdotype = ((DataObject)value).getType();
        } else {
            sdotype = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getTypeForSimpleJavaType(valueClass);
        }
        propertyDO.set("type", sdotype);

        propertyDO.set("many", isMany);

        propertyDO.set("containment", isContainment);
        return aHelperContext.getTypeHelper().defineOpenContentProperty(null, propertyDO);
    }

    @Override
    public void set(Property property, Object value) throws UnsupportedOperationException, IllegalArgumentException {
        set((SDOProperty) property, value, true);
    }

    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()
            oldValueListWrapper.addAll((Collection)value, updateSequence);// for non-default Pluggable impl this function is not required
        } 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);
        }
    }

    /**
     * INTERNAL:
     * Sets the value of the given property of the object to the new value.
     * <p>
     * The use of a false updateSequence flag is internally implemented during an SDOSequence.add() call.
     * Refactor: we need to abstract this function using a type of Command pattern to handle the sequence context.
     * @param property
     * @param value
     * @param updateSequence
     * @throws UnsupportedOperationException
     * @throws IllegalArgumentException
     */
    public void set(SDOProperty property, Object value, boolean updateSequence) throws UnsupportedOperationException, IllegalArgumentException {
        if (null == property) {
            throw new IllegalArgumentException("Illegal Argument.");
        }

        if (property.isReadOnly()) {
            throw new UnsupportedOperationException("Property is Readonly." + property.getName() + "  " + getType().getName());
        }

        // Can't set null on a non-nullable property - implementation specific handling, one of:
        // 1) perform an unset operation
        // 2) throw new UnsupportedOperationException("Property ["+ property.getName() +"] is non-nullable");
        // We will perform an unset op...
        if (value == null && !property.isNullable()) {
            unset(property, false, updateSequence);
        } else {
            setInternal(property, value, updateSequence);
        }
    }

    @Override
    public boolean isSet(Property property) {
        if (null == property) {
            throw SDOException.cannotPerformOperationOnNullArgument("isSet");
        }

        if (property.isMany()) {
            List value = getList(property);
            return !value.isEmpty();
        } else {
            return isSetInternal(property);
        }
    }

    @Override
    public void unset(Property property) {
        if (null == property) {
            throw SDOException.cannotPerformOperationOnNullArgument("unset");
        }
        unset(property, false);
    }

    /**
     * INTERNAL:
     * This function is implemented internally to unset the specified property on this DataObject
     * @param property
     * @param fromDelete
     */
    private void unset(Property property, boolean fromDelete) {
        unset(property, fromDelete, true);
    }

    /**
     * INTERNAL:
     * Unset the specified property on this DataObject.
     * The fromDelete parameter specifies whether we are from a delete or unset/detach operation.
     * The updateSequence parameter is used internally to stop a bidirectional update in the SDOSequence
     * when originally called from this Sequence.
     * @param property
     * @param fromDelete
     * @param updateSequence
     */
    public void unset(Property property, boolean fromDelete, boolean updateSequence) {
        if (null == property) {
            throw SDOException.cannotPerformOperationOnNullArgument("unset");
        }

        if (((SDOProperty)property).isReadOnly()) {
            throw new UnsupportedOperationException("Property is Readonly." + property.getName() + "  " + getType().getName());
        }

        boolean wasSet = isSet(property);

        if (wasSet) {
            if(!fromDelete){
              _setModified(true);
            }
        } else {
            return;
        }

        if (property.isContainment() || isContainedByDataGraph(property)) {
            Object oldValue = get(property);
            if (oldValue != null) {
                if (property.isMany()) {
                    for (int itemIndex = 0, size = ((List)oldValue).size(); itemIndex < size;
                             itemIndex++) {
                        SDODataObject manyItem = (SDODataObject)((List)oldValue).get(itemIndex);
                        if (manyItem != null) {
                            manyItem.detachOrDelete(fromDelete);
                        }
                    }
                } else {
                    ((SDODataObject)oldValue).detachOrDelete(fromDelete);
                }
            }
        }

        if (wasSet) {
            unsetInternal(property, updateSequence);
        }
    }

    @Override
    public boolean getBoolean(Property property) throws IllegalArgumentException, ClassCastException {
        Boolean propertyBooleanValue = (Boolean)convertObjectToValue(property, Boolean.class);
        if (propertyBooleanValue == null) {
            return false;
        }
        return propertyBooleanValue.booleanValue();
    }

    @Override
    public byte getByte(Property property) throws IllegalArgumentException, ClassCastException {
        Byte propertyByteValue = (Byte)convertObjectToValue(property, Byte.class);
        if (propertyByteValue == null) {
            return 0;
        }
        return propertyByteValue.byteValue();
    }

    @Override
    public char getChar(Property property) throws IllegalArgumentException {
        Character propertyCharValue = (Character)convertObjectToValue(property, Character.class);
        if (propertyCharValue == null) {
            return '\u0000';
        }
        return propertyCharValue.charValue();
    }

    @Override
    public double getDouble(Property property) throws IllegalArgumentException {
        Double propertyDoubleValue = (Double)convertObjectToValue(property, Double.class);
        if (propertyDoubleValue == null) {
            return 0.0d;
        }
        return propertyDoubleValue.doubleValue();
    }

    @Override
    public float getFloat(Property property) throws IllegalArgumentException {
        Float propertyFloatValue = (Float)convertObjectToValue(property, Float.class);
        if (propertyFloatValue == null) {
            return 0.0f;
        }
        return propertyFloatValue.floatValue();
    }

    @Override
    public int getInt(Property property) throws IllegalArgumentException {
        Integer propertyIntegerValue = (Integer)convertObjectToValue(property, Integer.class);
        if (propertyIntegerValue == null) {
            return 0;
        }
        return propertyIntegerValue.intValue();
    }

    @Override
    public long getLong(Property property) throws IllegalArgumentException {
        Long propertyLongValue = (Long)convertObjectToValue(property, Long.class);
        if (propertyLongValue == null) {
            return 0L;
        }
        return propertyLongValue.longValue();
    }

    @Override
    public short getShort(Property property) throws IllegalArgumentException {
        Short propertyShortValue = (Short)convertObjectToValue(property, Short.class);
        if (propertyShortValue == null) {
            return 0;
        }
        return propertyShortValue.shortValue();
    }

    @Override
    public byte[] getBytes(Property property) throws IllegalArgumentException {
        byte[] propertyByteValue = (byte[])convertObjectToValue(property, byte[].class);
        return propertyByteValue;
    }

    @Override
    public BigDecimal getBigDecimal(Property property) throws IllegalArgumentException {
        BigDecimal propertyDecimalValue = (BigDecimal)convertObjectToValue(property, BigDecimal.class);
        return propertyDecimalValue;
    }

    @Override
    public BigInteger getBigInteger(Property property) throws IllegalArgumentException {
        BigInteger propertyBigIntegerValue = (BigInteger)convertObjectToValue(property, BigInteger.class);
        return propertyBigIntegerValue;
    }

    @Override
    public SDODataObject getDataObject(Property property) throws IllegalArgumentException, ClassCastException {
        if(property != null && property.isMany()) {
            List value = (List)get(property);
            if(value.size() > 0) {
                return (SDODataObject)value.get(0);
            } else {
                return null;
            }
        }
        return (SDODataObject)get(property);
    }

    @Override
    public Date getDate(Property property) {
        if (null == property) {
            throw SDOException.cannotPerformOperationOnNullArgument("getDate");
        }
        if (property.getType().equals(SDOConstants.SDO_STRING)) {
            DataHelper dHelper = aHelperContext.getDataHelper();
            String dateString = (String)get(property);
            return dHelper.toDate(dateString);
        }
        Date propertyDateValue = (Date)convertObjectToValue(property, Date.class);
        return propertyDateValue;
    }

    @Override
    public String getString(Property property) {
        String propertyStringValue = (String)convertObjectToValue(property, String.class);
        return propertyStringValue;
    }

    @Override
    public List getList(Property property) {
        if (null == property) {
            throw SDOException.cannotPerformOperationOnNullArgument("getList");
        }

        if (((type != null) && !type.isOpen() && property.isOpenContent())) {
            throw new IllegalArgumentException("Argument not Supported.");
        }
        if (!property.isMany()) {
            throw new ClassCastException("can not call getList for a property that has isMany false.");
        }

        /*
         * Check the currentValueStore map
         * (1) If the property is stored
         *     (1a) return the ListWrapper or
         *     (1b) return and store an empty default value ListWrapper
         * (2) if the property is not set
         *     (2a) return and store an empty default value ListWrapper
         */
        Object value = getPropertyInternal(property);
        if ((value != null) && value instanceof List) {
            return (List)value;
        }

        // get a default empty list
        List theList = new ListWrapper(this, property);
        if (getType().isOpen() && property.isOpenContent()) {
            addOpenContentProperty(property);
        }

        // set the property to a default empty list
        setPropertyInternal((SDOProperty) property, theList, false);
        return theList;
    }

    @Override
    public void setBoolean(Property property, boolean value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setByte(Property property, byte value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setChar(Property property, char value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setDouble(Property property, double value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setFloat(Property property, float value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setInt(Property property, int value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setLong(Property property, long value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setShort(Property property, short value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setBytes(Property property, byte[] value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setBigDecimal(Property property, BigDecimal value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setBigInteger(Property property, BigInteger value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setDataObject(Property property, DataObject value) {
        set(property, value);
    }

    @Override
    public void setDate(Property property, Date value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setString(Property property, String value) {
        convertValueAndSet(property, value);
    }

    @Override
    public void setList(Property property, List value) {
        convertValueAndSet(property, value);
    }

    @Override
    public DataObject createDataObject(String propertyName) {
        Property aProperty = getInstanceProperty(propertyName);
        return createDataObject(aProperty);
    }

    @Override
    public SDODataObject createDataObject(int propertyIndex) {
        Property aProperty = getInstanceProperty(propertyIndex);
        return createDataObject(aProperty);
    }

    @Override
    public SDODataObject createDataObject(Property aProperty) {
        if (aProperty.isContainment()) {
            Type aType = aProperty.getType();
            if (aType != null) {
                return createDataObject(aProperty, aType);
            }
        }
        return null;
    }

    @Override
    public SDODataObject createDataObject(String propertyName, String namespaceURI, String typeName) {
        Property aProperty = getInstanceProperty(propertyName);
        Type aType = aHelperContext.getTypeHelper().getType(namespaceURI, typeName);
        return createDataObject(aProperty, aType);
    }

    @Override
    public SDODataObject createDataObject(int propertyIndex, String namespaceURI, String typeName) {
        Property aProperty = getInstanceProperty(propertyIndex);
        Type aType = aHelperContext.getTypeHelper().getType(namespaceURI, typeName);
        return createDataObject(aProperty, aType);
    }

    @Override
    public SDODataObject createDataObject(Property property, Type aType) {
        SDODataObject created = (SDODataObject) aHelperContext.getDataFactory().create(aType);

        if (property.isMany()) {
            //getList.add will call updateContainment
            ((ListWrapper)getList(property)).add(created, true);
        } else {
            set(property, created);
        }

        _setModified(true);
        created._setCreated(true);

        return created;
    }

    /**
     * INTERNAL:
     * Perform a detach on a DataObject or List of DataObjects
     * @param property
     * @param oldValue (List or Object)
     */
    private void detach(Property property, Object oldValue) {
        // This function is called internally from set(property, object, boolean) when a detach of the existing object is required
        if (property.isMany()) {
            List oldListValue = (List) oldValue;
            for (int i = 0, size = oldListValue.size(); i < size; i++) {
                Object nextValue = oldListValue.get(i);
                if ((nextValue != null) && (nextValue instanceof SDODataObject)) {
                    ((SDODataObject)nextValue).detachOrDelete(false);
                }
            }
        } else {
            if ((oldValue != null) && (oldValue instanceof SDODataObject)) {
                ((SDODataObject)oldValue).detachOrDelete(false);
            }
        }
    }

    /**
     * INTERNAL:
     * Recursively walk the tree and set oldSettings for a detached/deleted object.
     * This function performs a single preOrder traversal of the tree.
     * An unset is done for each property if the action = delete
     * Implementors: detach() and delete() via detach
     * @param fromDelete (flag the action true = delete, false = detach)
     */
    public void detachOrDelete(boolean fromDelete) {
        // If we are detaching the root - perform a no-operation
        if ((null == container) && !fromDelete) {
            return;
        }
        boolean isCSRoot = (null != changeSummary) && (changeSummary.getRootObject() == this);

        // Detaching the dataObject that is the root of the CS doesn't need to do anything - truncate the recursive traversal
        if(!fromDelete && isCSRoot){
          return;
        }

        // This is the root of the recursive loop
        detachDeleteRecursivePrivate(fromDelete, !isCSRoot, true);
    }

    /**
     * INTERNAL:
     * Recursively walk the tree and set oldSettings for a detached/deleted object.
     * @param fromDelete
     * @param clearCS (true = clear the cs field) = !(is root of the detach/delete subtree the CS root?)
     * @param isRootOfRecursiveLoop (are we at the root of the detach/delete or inside the subtree)
     */
    private void detachDeleteRecursivePrivate(boolean fromDelete, boolean clearCS, boolean isRootOfRecursiveLoop) {
        // Store flag for (is root of the detach/delete subtree the CS root?) before we modify it when this object has no container
        boolean subTreeRootHasCStoClear = clearCS;
        if (null == getContainer()) {
            clearCS = false;
        }
        if (isRootOfRecursiveLoop || fromDelete) {
            if (null != getContainer()) {
                getContainer()._setModified(true);
                _setContainer(null);
                _setContainmentPropertyName(null);
            }
        }
        _setDeleted(true);

        /** Order here is important - the dataGraph pointer should be cleared preorder before we enter the recursive loop to clear child DO's */
        DataGraph previousDataGraph = getDataGraph();
        // Remove back pointer to containing DataGraph
        setDataGraph(null);

        List instancePropertiesList = getInstanceProperties();
        for (int i = 0, psize = instancePropertiesList.size(); i < psize; i++) {
            SDOProperty nextProperty = (SDOProperty)instancePropertiesList.get(i);
            Object oldValue = get(nextProperty);

            if (!nextProperty.getType().isChangeSummaryType()) {
                // Non-containment nodes have changeSummary and dataGraph pointers if they were in a dataGraph
                if (nextProperty.isContainment() || isContainedByDataGraph(previousDataGraph, nextProperty)) {
                    if (nextProperty.isMany()) {
                        Object manyItem;
                        for (int j = 0, lsize = ((List)oldValue).size(); j < lsize; j++) {
                            manyItem = ((List)oldValue).get(j);
                            detachDeleteRecursivePrivateHelper((SDODataObject)manyItem, fromDelete, clearCS);
                        }
                    } else {
                        detachDeleteRecursivePrivateHelper((SDODataObject)oldValue, fromDelete, clearCS);
                    }
                }
                if (fromDelete && !nextProperty.isReadOnly()) {
                    unset(nextProperty, fromDelete);
                }
            }
        }

        /**
         * Bug # 6202793
         * We delete the changeSummary field in the following use cases
         * in addition to when the clearCS field was passed in as or transformed to true.
         * Case 0: detach subtree root from root (with cs) = false
         * Case 1: detach subtree internal from root (with cs) = false
         * Case 2: delete subtree root from root (with cs) = false
         * Case 3: delete subtree internal from root (with cs) = true
         * Case 4: detach subtree root from root (without cs) = false
         * Case 5: detach subtree internal from root (without cs) = false
         * Case 6: delete subtree root from root (without cs) = true
         * Case 7: delete subtree internal from root (without cs) = true
         */
        if (clearCS || subTreeRootHasCStoClear) {
            _setChangeSummary(null);
        }
    }

    /**
     * INTERNAL:
     * Call detach or delete recursively on aDataObject after possibly changing the flag whether to clear the ChangeSummary pointer at this level
     * @param aDataObject
     * @param fromDelete
     * @param clearCS
     */
    private void detachDeleteRecursivePrivateHelper(SDODataObject aDataObject, boolean fromDelete, boolean clearCS) {
        if (aDataObject != null) {
            // Return whether (aDataObject) is the changeSummary root.
            boolean isCSRoot = (aDataObject.getChangeSummary() != null) &&//
            (aDataObject.getChangeSummary().getRootObject() == aDataObject);

            // If we are at the CS root - we do not clear the changeSummary
            if (isCSRoot) {
                clearCS = false;
            } else {
                if (aDataObject.getContainer() != null) {
                    ChangeSummary containerCS = aDataObject.getContainer().getChangeSummary();

                    // If there is no CS field set above this object then clear any ChangeSummary pointer at this level
                    if (containerCS == null) {
                        clearCS = true;
                    }
                }
            }
            aDataObject.detachDeleteRecursivePrivate(fromDelete, clearCS, false);
        }
    }

    @Override
    public void detach() {
        detachWithSequenceUpdate();
    }

    /**
     * INTERNAL:
     * Perform a detach action that originated from a detach and update the sequence.
     * Case 01
     */
    private void detachWithSequenceUpdate() {
        detach(false, true);
    }

    /**
     * INTERNAL:
     * Perform a detach action that originated from a delete and update the sequence.
     * Case 11
     */
    private void deleteWithSequenceUpdate() {
        detach(true, true);
    }

    /**
     * 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);
        }
    }

    @Override
    public void delete() {
        deleteWithSequenceUpdate();
    }

    @Override
    public SDODataObject getContainer() {
        return container;
    }

    @Override
    public SDOProperty getContainmentProperty() {
        if ((container != null) && (containmentPropertyName != null)) {
            return container.getInstanceProperty(containmentPropertyName);
        } else {
            return null;
        }
    }

    @Override
    public DataGraph getDataGraph() {
        return dataGraph;
    }

    public void setDataGraph(DataGraph dataGraph) {
        this.dataGraph = dataGraph;
    }

    @Override
    public SDOType getType() {
        return type;
    }

    @Override
    public List getInstanceProperties() {
        if (null == instanceProperties) {
            instanceProperties = new ArrayList();
        }
        return instanceProperties;
    }

    @Override
    public SDOProperty getProperty(String propertyName) {
        return getInstanceProperty(propertyName);
    }

    @Override
    public SDOProperty getInstanceProperty(String propertyName) {
        if (getType() == null) {
            throw new UnsupportedOperationException("Type is null");
        }
        SDOProperty property = getType().getProperty(propertyName);
        if (null == property) {
            property = (SDOProperty)_getOpenContentAliasNamesMap().get(propertyName);
            if (null == property) {
                for (int i = 0; i < _getOpenContentProperties().size(); i++) {
                    SDOProperty nextProp = (SDOProperty)_getOpenContentProperties().get(i);
                    if (nextProp.getName().equals(propertyName)) {
                        return nextProp;
                    }
                }
                if (null == property) {
                    for (int i = 0; i < _getOpenContentPropertiesAttributes().size(); i++) {
                        SDOProperty nextProp = (SDOProperty)_getOpenContentPropertiesAttributes().get(i);
                        if (nextProp.getName().equals(propertyName)) {
                           return nextProp;
                        }
                    }
                }
            }
        }
        return property;
    }

    SDOProperty getInstanceProperty(String propertyName, Object value) {
        SDOProperty sdoProperty = getInstanceProperty(propertyName);
        if(null == sdoProperty) {
            sdoProperty = (SDOProperty) defineOpenContentProperty(propertyName, value);
        }
        return sdoProperty;
    }

    /**
     * INTERNAL:
     * @param propertyIndex
     * @return
     * @throws SDOException
     */
    public SDOProperty getInstanceProperty(int propertyIndex) throws IllegalArgumentException {
        try {
            SDOProperty property = getInstancePropertiesArray()[propertyIndex];
            return property;
        } catch (IndexOutOfBoundsException e) {
            throw SDOException.propertyNotFoundAtIndex(e, propertyIndex);
        }
    }

    @Override
    public SDODataObject getRootObject() {
        if (getContainer() != null) {
            return getContainer().getRootObject();
        }
        return this;
    }

    @Override
    public SDOChangeSummary getChangeSummary() {
        return changeSummary;
    }

    /**
     * INTERNAL:
     * Set flag created value.
     * @param created   flag created's new value.
     */
    public void _setCreated(boolean created) {
        if (changeSummary != null) {
            changeSummary.setCreated(this, created);
        }
    }

    /**
     * INTERNAL:
     * Set flag modified value.
     * @param modified   flag modified's new value.
     */
    public void _setModified(boolean modified) {
        if (changeSummary != null) {
            if (isLogging()) {
                updateChangeSummaryWithOriginalValues();
            }
        }
    }

    /**
     * INTERNAL:
     * Set flag deleted value.
     * @param deleted   flag deleted's new value.
     */
    private void _setDeleted(boolean deleted) {
        // reduced scope from public to private 17 May 2007 - use the public deprecated public function until we remove it
        if (changeSummary != null) {
            boolean wasDeleted = changeSummary.setDeleted(this, deleted);
            if (wasDeleted && isLogging()) {
                updateChangeSummaryWithOriginalValues();
            }
        }
    }

    /**
     * INTERNAL:
     * @param csm
     */
    private void setChangeSummaryNonRecursive(ChangeSummary csm) {
        // set changeSummary instance using property
        changeSummary = (SDOChangeSummary) csm;
        if (getType() != null) {
            SDOProperty changeSummaryProperty = getType().getChangeSummaryProperty();
            if (changeSummaryProperty != null) {
                setChangeSummaryProperty(changeSummaryProperty, csm);
            }
        }
    }

    /**
     * INTERNAL:
      * Recursively Set this DataObject's ChangeSummary as passed in value.
     * @param aChangeSummary   the ChangeSummary taking this DataObject as root.
     */
    public void _setChangeSummary(SDOChangeSummary aChangeSummary) {
        updateChangeSummaryAndDataGraph(aChangeSummary, getDataGraph());
    }

    /**
     * INTERNAL:
     * Recursively set this DataObject's changeSummary and dataGraph.
     * The parent changeSummary and dataGraph may be null.
     * Preconditions: No changeSummary must exist on the child tree.
     * Callers: Typically updateContainment (during a set) or delete/detach
     *   of an object without its own changeSummary property.
     * @param aDataGraph
     */
    private void updateChangeSummaryAndDataGraph(ChangeSummary aChangeSummary, 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();

            // Note: Both opposite currentValueStore cannot be isContainment=true
            // special handling for bidirectional currentValueStore, do a shallow set
            // 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).updateChangeSummaryAndDataGraph(aChangeSummary, 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).updateChangeSummaryAndDataGraph(aChangeSummary, aDataGraph);
                        }
                    }
                }
            }
        }
        // Set/Clear changeSummary in postOrder sequence
        setChangeSummaryNonRecursive(aChangeSummary);
    }


    /**
     * 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();

            // Note: Both opposite currentValueStore cannot be isContainment=true
            // special handling for bidirectional currentValueStore, do a shallow set
            // 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);
                        }
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     *
     * @param property
     * @param value
     */
    private void setChangeSummaryProperty(SDOProperty property, ChangeSummary value) {
        if (property.isOpenContent()) {
            throw new IllegalArgumentException("ChangeSummary can not be on an open content property.");
        }
        if (property.isMany()) {
            throw new IllegalArgumentException("ChangeSummary can not be on a property with many set to true.");
        }

        if (isLogging()) {
            _setModified(true);
        }

        // process pluggable currentValueStore
        setPropertyInternal(property, value, true);
    }

    /**
     * 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;
        }

        /**
         * Logic: 4 steps - we defer undo responsibilty to each of DataObject, ListWrapper and Sequence.
         * 1) swap ValueStores (for DataObject)
         * 2) swap ListWrapper (if it exists)
         * 3) swap Sequence (if it exists)
         * 4) #5928954 restore openContent properties to the 3 data structures on SDODataObject -
         *     openContentPropertiesMap<String,Property>, openContentProperties(List<Property>). instanceProperties (List<Property>)
         *
         * Use Cases:
         *   UC1: no change
         *     doDirty=false seqDirty=false
         *   UC2: change non-sequenced do
         *     doDirty=false seqDirty=false
         *   UC3: change sequenced do
         *     doDirty=true. SeqDirty=true
         *   UC4: change unstructured text on sequence only
         *     [doDirty=false seqDirty=true] - special case - verify that we do not do it twice (here and in UC3)
         *   UC5: unset(oc property), undoChanges(), get("open property")
         *
         */

        // 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()) {// assume sequence is !null
            // 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()) {
                        // check for modified ListWrapper
                        // 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());
                        }
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Process ValueStore changes on any set/delete/detach/unset
     * when logging is on.
     */
    private void updateChangeSummaryWithOriginalValues() {

        /**
         * ValueStore processing:
         * We switch the current VS to original VS.
         * The current VS will be a shallow copy of the original for this dataobject at its first change
         * If the VS is already copied don't reswap them again
         *
         * Case: Move/Reset
         *  a detach of a child modifies its parent - trigering a copy of parent's ValueStore
         *  a set on the parent will trigger another copy - but we will skip this one as we already
         *  have a copy of the original.
         *  Issue: if we reset the child back the same place (in effect doing our own undo)
         *  do we optimize this and remove the copy - for now a real undoChanges() will do the same.
         *
         */

        // dont store an original sequence if there are already is one in the map
        if (isLogging() && (!getChangeSummary().isDirty(this)) && (!getChangeSummary().isCreated(this))) {
            // dont copy containers of many props
            // original valuestore becomes current one (from null)
            getChangeSummary().getOriginalValueStores().put(this, _getCurrentValueStore());
            // we make a shallow copy of the current valuestore arrays at this level in the tree
            currentValueStore = _getCurrentValueStore().copy();

            // handle Sequences only in UC2 where we have modified the container object - not when only the sequence is dirty
            if (getType().isSequenced()) {
                // deep copy the list of settings so a modification of the current sequence will not affect a setting in the originalSequences map
                SDOSequence copySequence = getSequence().copy();

                // store original sequence on ChangeSummary
                getChangeSummary().getOriginalSequences().put(this, copySequence);
            }
        }
    }

    /**
     * INTERNAL:
     * Initialize all old settings related to ChangeSummary and recursively go down
     * the tree to initialize all DataObjects rooted at this DataObject.
     */
    public void resetChanges() {
        // fill all oldSettings when logging is turned on
        if ((container != null) && (containmentPropertyName != null) && (changeSummary != null)) {
            changeSummary.setOldContainer(this, container);
            changeSummary.setOldContainmentProperty(this, container.getInstanceProperty(containmentPropertyName));
        }

        // Note: valueStores will not be switched and originalValueStore will continue to be null until the first modification
        // initialize empty list for current dataObject
        for(int x=0, instancePropertiesSize=instanceProperties.size(); x<instancePropertiesSize; x++) {
            SDOProperty property = instanceProperties.get(x);
            Object value = get(property);

            // #5878436 12-FEB-07 do not recurse into a non-containment relationship unless inside a dataGraph
            if ((property.isContainment() || isContainedByDataGraph(property)) && //
                !property.isMany() && (value != null) && !property.getType().isChangeSummaryType()) {

                ((SDODataObject)value).resetChanges();
            } else {
                // Handle isMany objects and store the oldCont* values for each item in the list
                if (property.isMany()) {
                    if (null != value) {// secondary NPE check
                        List listValue = (List) value;
                        for(int y=0, listValueSize=listValue.size(); y<listValueSize; y++) {
                            Object valueMany = listValue.get(y);

                            // do not recurse into a non-containment relationship unless inside a dataGraph
                            if ((property.isContainment() || isContainedByDataGraph(property)) && //
                                (valueMany != null) && !property.getType().isChangeSummaryType()) {
                                ((SDODataObject)valueMany).resetChanges();
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * @param aType
     */
    public void _setType(Type aType) {
        type = (SDOType) aType;

        if (getInstanceProperties().isEmpty()) {
            if (type != null) {
                getInstanceProperties().addAll(type.getProperties());
            }
            getInstanceProperties().addAll(_getOpenContentProperties());
        }

        if (type != null) {
            _getCurrentValueStore().initialize(this);
            // sequence is not initialized unless type.isSequenced=true, null otherwise
            if (type.isSequenced()) {
                sequence = new SDOSequence(this);
            }

            Property csmProperty = type.getChangeSummaryProperty();
            if (csmProperty != null) {
                SDOChangeSummary aChangeSummary = new SDOChangeSummary(this, aHelperContext);
                aChangeSummary.endLogging();
                _setChangeSummary(aChangeSummary);
            }
        }
    }

    /**
     * INTERNAL:
     * Pluggable Interface for substituting the default Map with a custom Map Class
     * @param aValueStore
     */
    public void _setCurrentValueStore(ValueStore aValueStore) {
        currentValueStore = aValueStore;
    }

    /**
     * INTERNAL:
     * Map interface into the currentValueStore of this DataObject.<br>
     * Note: Implementers of the {@link ValueStore ValueStore} interface require this accessor.
     * @return
     */
    public ValueStore _getCurrentValueStore() {
        // Note: do not remove this function as it is the accessor into the pluggable ValueStore
        // Notification of any change to this API is required
        return currentValueStore;
    }

    /**
     * INTERNAL:
     * Sets the DataObject which contains this DataObject.
     * @param aContainer the DataObject which is the container of this DataObject.
     */
    public void _setContainer(DataObject aContainer) {
        container = (SDODataObject) aContainer;
    }

    public Map _getOpenContentPropertiesAttributesMap() {
        Map openContentPropertiesAttrs = new HashMap();
        for (int i = 0, size = _getOpenContentPropertiesAttributes().size(); i < size; i++) {
            Property next = (Property)_getOpenContentPropertiesAttributes().get(i);
            //if uri is null then attributes won't be prefix qualified
            QName qname = new QName(((SDOProperty)next).getUri(), next.getName());
            openContentPropertiesAttrs.put(qname, get(next));
        }

        return openContentPropertiesAttrs;

    }

    public void _setOpenContentPropertiesAttributesMap(Map openAttributeProperties) {
        Iterator iter = openAttributeProperties.keySet().iterator();

        while (iter.hasNext()) {
            QName nextKey = (QName)iter.next();

            if ((!nextKey.getNamespaceURI().equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) && (!((nextKey.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)) && nextKey.getLocalPart().equals(XMLConstants.SCHEMA_TYPE_ATTRIBUTE)))) {
                Object value = openAttributeProperties.get(nextKey);
                SDOProperty prop = (SDOProperty)aHelperContext.getXSDHelper().getGlobalProperty(nextKey.getNamespaceURI(), nextKey.getLocalPart(), false);
                if (prop == null) {
                    DataObject propDo = aHelperContext.getDataFactory().create(SDOConstants.SDO_URL, SDOConstants.PROPERTY);
                    propDo.set("name", nextKey.getLocalPart());
                    propDo.set("type", SDOConstants.SDO_STRING);
                    propDo.set("many", false);
                    prop = (SDOProperty)aHelperContext.getTypeHelper().defineOpenContentProperty(null, propDo);
                    prop.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.FALSE);
                    prop.setUri(nextKey.getNamespaceURI());

                    set(prop, value);
                } else {
                    set(prop, value);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * This function is implemented by SDOType.setOpen() in a mapping setGet/SetMethodName call
     * @param openContentPropertiesWithXMLRoots
     */
    public void _setOpenContentPropertiesWithXMLRoots(List openContentPropertiesWithXMLRoots) {
        for (int i = 0, size = openContentPropertiesWithXMLRoots.size(); i < size; i++) {
            Object next = openContentPropertiesWithXMLRoots.get(i);
            String propertyName = null;
            String propertyUri = null;
            Object value = null;
            Type theType = null;
            if (next instanceof XMLRoot) {
                XMLRoot nextXMLRoot = (XMLRoot)next;
                value = nextXMLRoot.getObject();
                propertyName = nextXMLRoot.getLocalName();
                propertyUri = nextXMLRoot.getNamespaceURI();
                if (value instanceof DataObject) {
                    theType = ((DataObject)value).getType();
                } else {
                    theType = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getTypeForSimpleJavaType(value.getClass());
                }
            } else if (next instanceof DataObject) {
                value = next;
                String qualifiedName = ((SDOType)((DataObject)next).getType()).getXmlDescriptor().getDefaultRootElement();
                int colonIndex = qualifiedName.indexOf(':');
                if (colonIndex > -1) {
                    String prefix = qualifiedName.substring(0, colonIndex);
                    if ((prefix != null) && !prefix.equals("")) {
                        propertyUri = ((SDOType)((DataObject)next).getType()).getXmlDescriptor().getNonNullNamespaceResolver().resolveNamespacePrefix(prefix);
                    }
                    propertyName = qualifiedName.substring(colonIndex + 1, qualifiedName.length());
                } else {
                    propertyName = qualifiedName;
                }
                theType = ((DataObject)next).getType();
            }
            else{
              theType = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getTypeForSimpleJavaType(next.getClass());
            }
            if (propertyName != null) {
                SDOProperty prop = (SDOProperty)aHelperContext.getXSDHelper().getGlobalProperty(propertyUri, propertyName, true);
                if (prop == null) {
                    prop = getInstanceProperty(propertyName);
                    if(prop != null){
                      if(prop.getUri() == null && propertyUri != null){
                        prop = createNewProperty(propertyName,propertyUri, theType);
                      }else{
                        if(prop.getUri() != null){
                          if(propertyUri == null){
                            prop = createNewProperty(propertyName,propertyUri, theType);
                          }else if(!prop.getUri().equals(propertyUri)){
                             prop = createNewProperty(propertyName,propertyUri, theType);
                          }
                        }
                      }
                    }else{
                       prop = createNewProperty(propertyName,propertyUri, theType);
                    }
                }

                if (prop.isMany()) {
                    ((ListWrapper)getList(prop)).add(value, false);
                } else {
                    set(prop, value, false);
                }
            }
        }
    }

    private SDOProperty createNewProperty(String propertyName,String propertyUri, Type theType){
       DataObject propDo = aHelperContext.getDataFactory().create(SDOConstants.SDO_URL, SDOConstants.PROPERTY);
       propDo.set("name", propertyName);
       propDo.set("type", theType);
       propDo.set("many", true);
       SDOProperty prop = (SDOProperty)aHelperContext.getTypeHelper().defineOpenContentProperty(null, propDo);
       prop.setUri(propertyUri);
       return prop;
    }

    /**
     * INTERNAL:
     * This function is implemented by SDOType.setOpen() in a mapping setGet/SetMethodName call
     * @return
     */
    public List _getOpenContentPropertiesWithXMLRoots() {
        List returnList = new ArrayList();
        for (int i = 0, size = openContentProperties.size(); i < size; i++) {
            SDOProperty next = (SDOProperty) openContentProperties.get(i);

            XMLRoot root = new XMLRoot();
            String localName = next.getXPath();
            if (next.getType() != null) {
                if (!next.getType().isDataType()) {
                    String uri = next.getUri();
                    root.setNamespaceURI(uri);
                } else {
                    String uri = next.getUri();
                    root.setNamespaceURI(uri);
                }
            }

            root.setLocalName(localName);

            Object value = get(next);
            if (next.isMany()) {
                for (int j = 0, sizel = ((List)value).size(); j < sizel; j++) {
                    XMLRoot nextRoot = new XMLRoot();
                    nextRoot.setNamespaceURI(root.getNamespaceURI());
                    nextRoot.setLocalName(root.getLocalName());
                    Object nextItem = ((List)value).get(j);
                    if ((next.getType() != null) && (next.getType().getXmlDescriptor() == null)) {
                        nextItem = XMLConversionManager.getDefaultXMLManager().convertObject(nextItem, String.class);
                    }
                    nextRoot.setObject(nextItem);
                    returnList.add(nextRoot);
                }
            } else {
                if ((next.getType() != null) && (next.getType().getXmlDescriptor() == null)) {
                    value = XMLConversionManager.getDefaultXMLManager().convertObject(value, String.class);
                }
                root.setObject(value);
                returnList.add(root);
            }
        }
        return returnList;
    }

    /**
     * INTERNAL:
      * Returns a list of the Properties currently used in this DataObject which are not
      * included in getType().getProperties
      * @return the List of open content Properties currently used in this DataObject.
      */
    public List _getOpenContentProperties() {
        if (openContentProperties == null) {
            openContentProperties = new ArrayList();
        }
        return openContentProperties;
    }


    private Map<String, Property> _getOpenContentAliasNamesMap() {
        if (openContentAliasNames == null) {
            openContentAliasNames = new HashMap();
        }
        return openContentAliasNames;
    }

   /**
     * INTERNAL:
     */
    private void convertValueAndSet(Property property, Object originalValue) {
        Object convertedValue;
        if (property.isMany()) {
            if (originalValue == null) {
                convertedValue = new ArrayList();
            } else if (originalValue instanceof List) {
                convertedValue = aHelperContext.getDataHelper().convert(property, originalValue);
            } else {
                List l = new ArrayList();
                l.add(originalValue);
                convertedValue = aHelperContext.getDataHelper().convert(property, l);
            }
        } else {
            convertedValue = aHelperContext.getDataHelper().convert(property, originalValue);
        }
        set(property, convertedValue);
    }

    /**
    * INTERNAL:
    */
    private void convertValueAndSet(int propertyIndex, Object originalValue) {
        Property property = getInstanceProperty(propertyIndex);

        Object convertedValue = aHelperContext.getDataHelper().convert(property, originalValue);
        set(property, convertedValue);
    }

    /**
     * INTERNAL:
     */
    private void convertValueAndSet(String path, Object originalValue) {
        XPathEngine.getInstance().set(path, originalValue, this, true);
    }

    /**
     * INTERNAL:
     *
     * @param property
     * @param cls
     * @return
     * @throws ClassCastException
     * @throws IllegalArgumentException
     */
    public Object convertObjectToValue(Property property, Class cls) throws ClassCastException, IllegalArgumentException {
        //ie get String - convert(thisprop, String.class)
        if (null == property) {
            throw new IllegalArgumentException(SDOException.cannotPerformOperationOnNullArgument("convertObjectToValue"));
        }

        Object obj = unwrapListValue(property, get(property));

        try {
            return ((SDODataHelper)aHelperContext.getDataHelper()).convertValueToClass(property, obj, cls);
        } catch (Exception e) {
            throw new ClassCastException("An error occurred during converison or an unsupported conversion was attempted.");
        }
    }

    /**
     * INTERNAL:
     *
     * @param property
     * @param position
     * @param cls
     * @return
     * @throws ClassCastException
     * @throws IllegalArgumentException
     */
    public Object convertObjectToValue(Property property, int position, Class cls) throws ClassCastException, IllegalArgumentException {
        if (null == property) {
            throw new IllegalArgumentException(SDOException.cannotPerformOperationOnNullArgument("convertObjectToValue"));
        }

        if ((cls == ClassConstants.List_Class) && !property.isMany()) {
            throw new ClassCastException("can not call getList for a property that has isMany false.");
        }

        Object obj;
        if (position == -1) {
            if (cls == ClassConstants.List_Class) {
                obj = get(property);
            } else {
                obj = unwrapListValue(property, get(property));
            }
        } else {
            obj = getList(property).get(position);
        }

        try {
            return ((SDODataHelper)aHelperContext.getDataHelper()).convertValueToClass(property, obj, cls);
        } catch (Exception e) {
            throw new ClassCastException("An error occurred during conversion or an unsupported conversion was attempted.");
        }
    }

    /**
     * INTERNAL:
     * Sets the name of the property on the containing DataObject which contains this DataObject as a value.
     * @param aContainmentPropertyName the name of the property on the containing DataObject which has this DataObject as a value.
     */
    public void _setContainmentPropertyName(String aContainmentPropertyName) {
        containmentPropertyName = aContainmentPropertyName;
    }

    /**
     * INTERNAL:
     * Return the name of the Property of the DataObject containing this data object
     * or null if there is no container.
     * @return the property containing this data object.
     */
    public String _getContainmentPropertyName() {
        return containmentPropertyName;
    }

    /**
     * INTERNAL:
     *
     * @param value
     * @return
     */
    public boolean parentContains(Object value) {
        if ((value == null) || (!(value instanceof DataObject))) {
            return false;
        }
        if ((getContainer() != null) && (getContainmentProperty() != null)) {
            if (value.equals(getContainer())) {
                return true;
            }
            return getContainer().parentContains(value);
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return whether the current dataObject(this) is part of a dataGraph.
     * Typically this is used to determine whether to treat !isContainment dataObjects as containment while inside a dataGraph.
     * @param aProperty
     * @return
     */
    private boolean isContainedByDataGraph(Property aProperty) {
        // The property is of type DataObject that points to a DataGraph
        return isContainedByDataGraph(getDataGraph(),  (SDOProperty) aProperty);
    }

    /**
     * INTERNAL:
     * Return whether the current dataObject(this) is was part of the passed in dataGraph.
     * Typically this is used to determine whether to treat !isContainment dataObjects as containment while inside a dataGraph.
     * The dataGraph input is used when the current DataGraph pointer has already been cleared
     * @param aDataGraph
     * @param aProperty
     * @return
     */
    private boolean isContainedByDataGraph(DataGraph aDataGraph, SDOProperty aProperty) {
        // The property is of type DataObject that points to a DataGraph
        return (null != aDataGraph) && (null != aProperty.getType()) && !aProperty.getType().isDataType();
    }

    /**
     * INTERNAL:
     * Update containment with flagged update sequence state
     * @param property
     * @param values
     * @param updateSequence
     */
    public void updateContainment(Property property, Collection values, boolean updateSequence) {
        if (property.isContainment() || isContainedByDataGraph(property)) {//

            Object[] valuesArray = values.toArray();
            for(int i=0; i<valuesArray.length; i++){
               Object next = valuesArray[i];
                if (next instanceof SDODataObject) {
                    updateContainment(property, (SDODataObject)next, updateSequence);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Update containment on the specified collection of values and default to true = update the sequence
     * @param property
     * @param values
     */
    public void updateContainment(Property property, Collection values) {
        updateContainment(property, values, true);
    }

    /**
     * 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);
            }

            // Check that the target object is not a changeSummary root - an internal set of an internal changeSummary
            /**
             * 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);
            }

            // If we are adding a previously deleted object, we must cancel out the isDeleted with an isCreated
            // 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);

            // In the case of re-adding a previously deleted/detached data object, we may need to update
            // 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);
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * update containment and the update the sequence value by default.
     * @param property
     * @param value
     */
    public void updateContainment(Property property, SDODataObject value) {
        updateContainment(property, value, true);
    }

    /**
     * INTERNAL:
     * Return the changeSummary logging state
     * @return
     */
    private boolean isLogging() {
        return ((changeSummary != null) && changeSummary.isLogging());
    }

    /**
     * INTERNAL:
     * Defined in SDO 2.01 spec on page 65 Externalizable function is called by
     * ObjectStream.writeObject() A replacement object for serialization can be
     * called here.
     * <p>Security Note:
     *     This public function exposes a data replacement vulnerability where an outside client
     *     can gain access and modify their non-final constants.
     *     We may need to wrap the GZIP streams in some sort of encryption when we are not
     *     using HTTPS or SSL/TLS on the wire.
     *
     * @see org.eclipse.persistence.sdo.SDOResolvable
     */
    public Object writeReplace() {
        // JIRA129: pass the helperContext to the constructor to enable non-static contexts
        return new SDOExternalizableDelegator(this, aHelperContext);
    }

    /**
     * INTERNAL:
     * Return the SDO Path from the root to the current internal node
     *
     * Prereq: We know that the targetObject will always have a parent as called
     * from getPath()
     *
     * Matching conditions:
     *   Iterate up the tree
     *   return a non-null string for the XPath at when we reach the root node
     *
     * Function is partially based on SDOCopyHelper.copy(DataObject dataObject)
     *
     * Performance: This function is O(log n) where n=# of children in the tree
     *
     * @param currentPath
     * @param targetObject
     * @param aSeparator (XPath separator is written only between elements not for the first call)
     * @return String (representing the XPath)
     */
    private String getPathPrivate(String currentPath,//
                                  SDODataObject targetObject,//
                                  String aSeparator) {
        // Base Case: check we are at the root (get parent first)
        SDODataObject aParent = targetObject.getContainer();
        if (aParent == null) {
            // check for indexed property if root is a ListWrapper
            return currentPath;
        }

        // Recursive Case: O(log(n)) recursive calls, 1 for each tree level
        // get parent property based on parent property name in target, property will always be set
        String aContainmentPropertyName = targetObject._getContainmentPropertyName();
        SDOProperty aChild = aParent.getInstanceProperty(aContainmentPropertyName);

        // Handle ListWrapper contained DataObjects
        if (aChild.isMany()) {
            int index = (aParent.getList(aChild)).indexOf(targetObject);

            return getPathPrivate(aContainmentPropertyName +//
                                  SDOConstants.SDO_XPATH_LIST_INDEX_OPEN_BRACKET +//
                                  (1 + index) +// [indexes] start at 1
                                  SDOConstants.SDO_XPATH_LIST_INDEX_CLOSE_BRACKET +//
                                  aSeparator +//
                                  currentPath,//
                                  aParent,//
                                  SDOConstants.SDO_XPATH_SEPARATOR_FRAGMENT);
        }

        // recursive call to non ListWrappers
        return getPathPrivate(aContainmentPropertyName +//
                              aSeparator +//
                              currentPath,//
                              aParent,//
                              SDOConstants.SDO_XPATH_SEPARATOR_FRAGMENT);
    }

    /**
     * INTERNAL:
     * Return an SDO Path string from root of the caller to itself
     * @return String
     */
    public String _getPath() {
        // Base Case: The internal node is actually the root
        if (getContainer() == null) {
            return SDOConstants.SDO_XPATH_TO_ROOT;
        } else {
            // Recursive Case: call private recursive reverse O(logn) traversal
            // function on root object
            return getPathPrivate(SDOConstants.EMPTY_STRING,//
                                  this,//
                                  SDOConstants.EMPTY_STRING);
        }
    }

    /**
     * INTERNAL:
     *
     * @return
     */
    private SDOProperty[] getInstancePropertiesArray() {
        if ((openContentProperties == null) || openContentProperties.isEmpty()) {
            return getType().getPropertiesArray();
        }

        SDOProperty[] props = getType().getPropertiesArray();
        SDOProperty[] ret = new SDOProperty[openContentProperties.size() + props.length];
        for (int i = 0; i < props.length; i++) {
            ret[i] = props[i];
        }
        for (int i = props.length; i < ret.length; i++) {
            ret[i] = (SDOProperty)openContentProperties.get(i - props.length);
        }
        return ret;
    }

    /**
     * INTERNAL:
     * Get the value of the property (open-content or declared)..
     * @param property
     * @return
     */
    public Object getPropertyInternal(Property property) {
        int index = ((SDOProperty)property).getIndexInType();
        if (index == -1) {
            return _getCurrentValueStore().getOpenContentProperty(property);
        } else {
            return _getCurrentValueStore().getDeclaredProperty(index);
        }
    }

    /**
     * INTERNAL:
     * Update the ValueStore with the new property value and update any sequence if it exists.
     * @param property
     * @param value
     * @param updateSequence (truncate call back from sequence when this function was called from sequence)
     */
    public void setPropertyInternal(SDOProperty property, Object value, boolean updateSequence) {
        /*
         * Update sequence object if element and without invoking a back pointer from sequence.add() to this dataObject.
         * The sequence != null required in case where non-public type.setSequenced(true) called after type define.
         * Assume: aHelperContext is assumed not to be null.
         * ChangeSummaries are not part of sequences.
         *
         * See JIRA-242, bug#6031657: A modify operation will need logic to either
         * 1 - update the existing setting in place
         * 2 - add a new setting and remove the previous one - TBD
         *
         * The following code needs to check for !attribute instead of !element because
         * we have 3 states( !attribute, !element and (!attribute && !element))
         * - two of which are valid for sequence setting creation.
         */
        Object origValue = getPropertyInternal(property);

        if (type.isSequenced() && updateSequence//
                 &&!property.getType().isChangeSummaryType() && !aHelperContext.getXSDHelper().isAttribute(property)) {
            // As we do for ListWrappers and DataObjects we will need to remove the previous setting if this set is actually a modify
            // keep sequence code here for backdoor sets
            if(property.isMany()) {
                getSequence().addSettingWithoutModifyingDataObject(property, value);
            } else {
                if(isSet(property)) {
                    getSequence().updateSettingWithoutModifyingDataObject(property, get(property), value);
                } else {
                    getSequence().addSettingWithoutModifyingDataObject(property, value);
                }
            }
        }

        int index = property.getIndexInType();
        if (index == -1) {
            _getCurrentValueStore().setOpenContentProperty(property, value);
        } else {
            _getCurrentValueStore().setDeclaredProperty(index, value);
            SDOProperty oppositeProperty = property.getOpposite();
            if(null != oppositeProperty) {
                if(null != value) {
                    if(property.isMany()) {
                        List<SDODataObject> valueList = (List<SDODataObject>) value;
                        for(SDODataObject valueDO : valueList) {
                            if(this != valueDO.get(oppositeProperty)) {
                                valueDO.setInternal(oppositeProperty, this, true);
                            }
                        }
                    } else {
                        SDODataObject valueDO = (SDODataObject) value;
                        if(oppositeProperty.isMany()) {
                            List oppositeList = valueDO.getList(oppositeProperty);
                            if(!oppositeList.contains(this)) {
                                oppositeList.add(this);
                            }
                        } else {
                            if(this != valueDO.get(oppositeProperty)) {
                                valueDO.setInternal(oppositeProperty, this, true);
                            }
                        }
                    }
                }

                if(null != origValue) {
                    if(property.isMany()) {
                        List<SDODataObject> origValueList = (List<SDODataObject>) origValue;
                        for(SDODataObject origValueDO : origValueList) {
                            if(null != origValueDO.get(oppositeProperty)) {
                                origValueDO.set(oppositeProperty, null);
                            }
                        }
                    } else {
                        DataObject origValueDO = (DataObject) origValue;
                        if(oppositeProperty.isMany()) {
                            List oppositeList = origValueDO.getList(oppositeProperty);
                            if(oppositeList.contains(this)) {
                                oppositeList.remove(this);
                            }
                        } else {
                            if(null != origValueDO.get(oppositeProperty)) {
                                origValueDO.set(oppositeProperty, null);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Add the open content property into all 3 data structures.
     * Remove the property from the unset map.
     * @param property
     */
    public void addOpenContentProperty(Property property) {
        List theList = null;
        if (aHelperContext.getXSDHelper().isAttribute(property)) {
            theList = _getOpenContentPropertiesAttributes();
        }else {
            theList = _getOpenContentProperties();
        }

        if (!theList.contains(property)) {
            if (isLogging()) {
                getChangeSummary().removeUnsetOCProperty(this, property);
            }
            theList.add(property);
            getInstanceProperties().add(property);
            if (((SDOProperty)property).hasAliasNames()) {
                for (int i = 0, size = ((SDOProperty)property).getAliasNames().size(); i < size; i++) {
                    _getOpenContentAliasNamesMap().put((String)((SDOProperty)property).getAliasNames().get(i), property);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Remove the open content property (property) from all 3 data structures.
     * Add the property to the unset map.
     * We restore this OC property in undoChanges
     * @param property
     */
    public void removeOpenContentProperty(Property property) {
        // save OC property in changeSummary for use during cs.copy and undoChanges
        if (isLogging()) {
            getChangeSummary().setUnsetOCProperty(this, property);
        }

        // remove oc property
        _getOpenContentProperties().remove(property);
        _getOpenContentPropertiesAttributes().remove(property);
        getInstanceProperties().remove(property);
        if (((SDOProperty)property).hasAliasNames()) {
            for (int i = 0, size = ((SDOProperty)property).getAliasNames().size(); i < size; i++) {
               _getOpenContentAliasNamesMap().remove(((SDOProperty)property).getAliasNames().get(i));
            }
        }
    }

    /**
     * INTERNAL:
     * Return whether the property (open-content or declared) is set?
     * @param property
     * @return true if set, false otherwise
     */
    public boolean isSetInternal(Property property) {
        int index = ((SDOProperty)property).getIndexInType();
        if (index == -1) {
            return _getCurrentValueStore().isSetOpenContentProperty(property);
        } else {
            return _getCurrentValueStore().isSetDeclaredProperty(index);
        }
    }

    /**
     * INTERNAL:
     * Unset the property on the ValueStore interface and update the sequence if it exists.
     * Used by implementers that require
     * @param property
     * @param updateSequence
     */
    private void unsetInternal(Property property, boolean updateSequence) {
        if (property.isMany()) {
            getList(property).clear();
            if (property.isOpenContent()) {
                removeOpenContentProperty(property);
            } else {
                _getCurrentValueStore().unsetDeclaredProperty(((SDOProperty)property).getIndexInType());
            }
        } else {
            if (property.isOpenContent()) {
                _getCurrentValueStore().unsetOpenContentProperty(property);
                removeOpenContentProperty(property);
            } else {
                _getCurrentValueStore().unsetDeclaredProperty(((SDOProperty)property).getIndexInType());
            }
        }

        /*
         * Update sequence object if element and without invoking a back pointer from sequence.add() to this dataObject.
         * The sequence != null required in case where non-public type.setSequenced(true) called after type define
         */
        if (type.isSequenced() && (sequence != null) && updateSequence && aHelperContext.getXSDHelper().isElement(property)) {
            // remove all instances of the property from the sequence
            sequence.removeSettingWithoutModifyingDataObject(property);
        }
    }

    /**
     * INTERNAL:
     * Return the sdoref attribute value during unmarshaling
     * @return
     */
    public String _getSdoRef() {
        return sdoRef;
    }

    public void _setOpenContentPropertiesAttributes(List openContentPropertiesAttributes) {
        this.openContentPropertiesAttributes = openContentPropertiesAttributes;
    }

    public List _getOpenContentPropertiesAttributes() {
        if (openContentPropertiesAttributes == null) {
            openContentPropertiesAttributes = new ArrayList();
        }
        return openContentPropertiesAttributes;
    }

    @Override
    public List<Setting> getSettings() {
        if(null != sequence) {
            return getSequence().getSettings();
        } else {
            return null;
        }
    }

    public void _setSdoRef(String newRef) {
        sdoRef = newRef;
    }

    /**
     * Convenience method that unwraps a list and returns the first element,
     * if necessary.
     *
     * @param prop
     * @param val
     * @return
     */
    private Object unwrapListValue(Property prop, Object val) {
        if (prop == null || val == null) {
            return null;
        }
        if (! (prop.isMany() &&  val instanceof ListWrapper) ) {
            return val;
        }
        List l = (ListWrapper) val;
        if (l.size() == 0) {
            return null;
        }
        return l.get(0);
    }

}
