/** Set the value on the underlying POJO, unwrapping values as necessary. */ public void setDeclaredProperty(int propertyIndex, Object value) { SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex); if (declaredProperty.getType().isChangeSummaryType()) { return; } Mapping mapping = this.getJAXBMappingForProperty(declaredProperty); Object newValue = value; Object oldValue = mapping.getAttributeAccessor().getAttributeValueFromObject(entity); if (declaredProperty.getType().isDataType()) { if (!declaredProperty.isMany()) { AbstractSession session = ((JAXBContext) jaxbHelperContext.getJAXBContext()).getXMLContext().getSession(entity); XMLDirectMapping directMapping = (XMLDirectMapping) mapping; if (directMapping.hasConverter()) { newValue = directMapping.getConverter().convertDataValueToObjectValue(newValue, session); } else { CoreField field = mapping.getField(); newValue = session .getDatasourcePlatform() .getConversionManager() .convertObject( newValue, descriptor.getObjectBuilder().getFieldClassification((XMLField) field)); } } mapping.setAttributeValueInObject(entity, newValue); } else if (declaredProperty.isMany()) { // Get a ListWrapper and set it's current elements ListWrapper listWrapper = (ListWrapper) getDeclaredProperty(propertyIndex); listWrapper.addAll((List) newValue); } else { // OLD VALUE if (mapping.isAbstractCompositeObjectMapping()) { XMLCompositeObjectMapping compositeMapping = (XMLCompositeObjectMapping) mapping; if (oldValue != null && compositeMapping.getContainerAccessor() != null) { compositeMapping.getContainerAccessor().setAttributeValueInObject(oldValue, null); } } // NEW VALUE newValue = jaxbHelperContext.unwrap((DataObject) value); mapping.getAttributeAccessor().setAttributeValueInObject(entity, newValue); if (mapping.isAbstractCompositeObjectMapping()) { XMLCompositeObjectMapping compositeMapping = (XMLCompositeObjectMapping) mapping; if (value != null && compositeMapping.getContainerAccessor() != null) { compositeMapping.getContainerAccessor().setAttributeValueInObject(newValue, entity); } } } }
/** * Return the JAXB mapping for the SDO property. They are matched on their XML schema * representation. */ Mapping getJAXBMappingForProperty(SDOProperty sdoProperty) { DatabaseMapping sdoMapping = sdoProperty.getXmlMapping(); XMLField field; if (sdoMapping instanceof XMLObjectReferenceMapping) { XMLObjectReferenceMapping referenceMapping = (XMLObjectReferenceMapping) sdoMapping; field = (XMLField) referenceMapping.getFields().get(0); } else { field = (XMLField) sdoMapping.getField(); } TreeObjectBuilder treeObjectBuilder = (TreeObjectBuilder) descriptor.getObjectBuilder(); XPathNode xPathNode = treeObjectBuilder.getRootXPathNode(); XPathFragment xPathFragment = field.getXPathFragment(); while (xPathNode != null && xPathFragment != null) { if (xPathFragment.isAttribute()) { if (sdoProperty.isMany() && !sdoProperty.isContainment() && !sdoProperty.getType().isDataType()) { xPathFragment = null; break; } Map attributeChildrenMap = xPathNode.getAttributeChildrenMap(); if (null == attributeChildrenMap) { xPathNode = null; } else { xPathNode = (XPathNode) attributeChildrenMap.get(xPathFragment); } } else if (xPathFragment.nameIsText()) { xPathNode = xPathNode.getTextNode(); } else { Map nonAttributeChildrenMap = xPathNode.getNonAttributeChildrenMap(); if (null == nonAttributeChildrenMap) { xPathNode = null; } else { xPathNode = (XPathNode) nonAttributeChildrenMap.get(xPathFragment); } } xPathFragment = xPathFragment.getNextFragment(); if (xPathFragment != null && xPathFragment.nameIsText()) { if (sdoProperty.isMany() && !sdoProperty.isContainment()) { xPathFragment = null; break; } } } if (null == xPathFragment && xPathNode != null) { if (xPathNode.getNodeValue().isMappingNodeValue()) { MappingNodeValue mappingNodeValue = (MappingNodeValue) xPathNode.getNodeValue(); return mappingNodeValue.getMapping(); } } throw SDOException.sdoJaxbNoMappingForProperty(sdoProperty.getName(), field.getXPath()); }
/** * INTERNAL: Recursive function deep copies all contained properties. Requirements: The value * object has isSet=true for all callers. * * @param copy * @param property * @param value * @param doMap (cache original -> copy DataObject instances to set non-containment properties * after tree construction) * @param propMap (cache original DO:non-containment property values to be set after tree * construction) */ private void copyContainmentPropertyValue( SDODataObject copy, SDOProperty property, Object value, // HashMap doMap, HashMap ncPropMap, SDOChangeSummary cs) { if (property.isMany()) { List copyValue = new ArrayList(); // set the copy to an empty list and add each items from the original in sequence // updateSequence flag is false - we will populate the sequence in order after subtree // creation copy.setInternal(property, copyValue, false); for (Iterator iterValues = ((List) value).iterator(); iterValues.hasNext(); ) { SDODataObject o = (SDODataObject) iterValues.next(); SDODataObject copyO = copyPrivate(o, doMap, ncPropMap, cs); ((ListWrapper) copy.getList(property)).add(copyO, false); // set changeSummary on all cs-root elements in the list after they are added to the // containment tree if ((copyO != null) && (copyO.getChangeSummary() != null) && (copyO.getType().getChangeSummaryProperty() != null)) { // re-reference copy objects in the copy changeSummary if (o.getChangeSummary().isLogging()) { (copyO.getChangeSummary()).setLogging(true); } copyChangeSummary( o.getChangeSummary(), // copyO.getChangeSummary(), doMap); } } } else { // handle non-many case // implementers of this function will always pass in a DataObject that may be null SDODataObject copyO = copyPrivate((SDODataObject) value, doMap, ncPropMap, cs); // #5852525 handle null properties with isSet=true - fixed 20070130 // we will set the isSet index in the ValueStore to true for all isSet=true objects, even NULL // ones. // updateSequence flag is false - we will populate the sequence in order after subtree // creation copy.setInternal(property, copyO, false); // set changeSummary on all cs-root elements in the list after they are added to the // containment tree using the original logging value if ((copyO != null) && (copyO.getChangeSummary() != null) && (copyO.getType().getChangeSummaryProperty() != null)) { // re-reference copy objects in the copy changeSummary if (((SDODataObject) value).getChangeSummary().isLogging()) { copyO.getChangeSummary().setLogging(true); } copyChangeSummary( ((SDODataObject) value).getChangeSummary(), // copyO.getChangeSummary(), doMap); } } }
/** Get the value from the wrapped POJO, wrapping in DataObjects as necessary. */ public Object getDeclaredProperty(int propertyIndex) { SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex); if (declaredProperty.getType().isChangeSummaryType()) { return dataObject.getChangeSummary(); } Mapping mapping = this.getJAXBMappingForProperty(declaredProperty); Object value = mapping.getAttributeAccessor().getAttributeValueFromObject(entity); if (declaredProperty.isMany()) { JAXBListWrapper listWrapper = listWrappers.get(declaredProperty); if (null != listWrapper) { return listWrapper; } listWrapper = new JAXBListWrapper(this, declaredProperty); listWrappers.put(declaredProperty, listWrapper); return listWrapper; } else if (null == value || declaredProperty.getType().isDataType()) { return value; } else { if (declaredProperty.isContainment()) { return jaxbHelperContext.wrap(value, declaredProperty, dataObject); } else { return jaxbHelperContext.wrap(value); } } }
/** * For isMany=false properties set the value to null. For isMany=true set the value to an empty * container of the appropriate type. */ public void unsetDeclaredProperty(int propertyIndex) { SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex); Mapping mapping = this.getJAXBMappingForProperty(declaredProperty); if (declaredProperty.isMany()) { ContainerMapping containerMapping = (ContainerMapping) mapping; ContainerPolicy containerPolicy = containerMapping.getContainerPolicy(); // OLD VALUE if (mapping.isAbstractCompositeCollectionMapping()) { XMLCompositeCollectionMapping compositeMapping = (XMLCompositeCollectionMapping) mapping; if (compositeMapping.getContainerAccessor() != null) { Object oldContainer = mapping.getAttributeValueFromObject(entity); if (oldContainer != null) { AbstractSession session = ((JAXBContext) jaxbHelperContext.getJAXBContext()) .getXMLContext() .getSession(entity); Object iterator = containerPolicy.iteratorFor(oldContainer); while (containerPolicy.hasNext(iterator)) { Object oldValue = containerPolicy.next(iterator, session); compositeMapping.getContainerAccessor().setAttributeValueInObject(oldValue, null); } } } } // NEW VALUE Object container = containerPolicy.containerInstance(); mapping.getAttributeAccessor().setAttributeValueInObject(entity, container); } else { // OLD VALUE Object oldValue = mapping.getAttributeAccessor().getAttributeValueFromObject(entity); if (mapping.isAbstractCompositeObjectMapping()) { XMLCompositeObjectMapping compositeMapping = (XMLCompositeObjectMapping) mapping; if (compositeMapping.getContainerAccessor() != null) { if (oldValue != null) { compositeMapping.getContainerAccessor().setAttributeValueInObject(oldValue, null); } } } // NEW VALUE mapping.getAttributeAccessor().setAttributeValueInObject(entity, null); } }
/** * Returns true if the property is declared as an element in the XSD. Returns false if not known * or for advanced cases. It is possible for both isAttribute and isElement to return false but * they will not both return true. * * @param property to identify if an element. * @return true if the property is declared as an element in the XSD. */ public boolean isElement(Property property) { if (property == null) { return false; } SDOProperty sdoProperty = (SDOProperty) property; Object value = sdoProperty.get(SDOConstants.XMLELEMENT_PROPERTY); if ((value != null) && value instanceof Boolean) { return ((Boolean) value).booleanValue(); } if ((sdoProperty.getOpposite() != null) && (sdoProperty.getOpposite().isContainment())) { return false; } else if (sdoProperty.isMany() || sdoProperty.isContainment() || sdoProperty.isNullable()) { return true; } return false; }
/** * For isMany=false properties return true if not null. For collection properties return true if * the collection is not empty. */ public boolean isSetDeclaredProperty(int propertyIndex) { SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex); if (declaredProperty.getType().isChangeSummaryType()) { return true; } Mapping mapping = this.getJAXBMappingForProperty(declaredProperty); if (declaredProperty.isMany()) { Collection collection = (Collection) mapping.getAttributeAccessor().getAttributeValueFromObject(entity); if (null == collection) { return false; } return !collection.isEmpty(); } else { return null != mapping.getAttributeAccessor().getAttributeValueFromObject(entity); } }
/** * INTERNAL: Implement ChangeSummary deep copy Note: a copy with a CS requires the * DefautlValueStore implementation because of changes outside the ValueStore interface for the * dataObject field DeepCopy the original changeSummary into the copy dataObject. All deleted keys * in originalValueStore, deletedMap, deepCopies are the same original object. We require the * following relationships in order to build copies of originals and copies of copies of * originals. origDOtoCopyDOMap original object (deleted + current) - in original DO : copy of * original object - in copy DO copyDOtoCopyOfDOMap * * <p>Assumptions: Property objects instances are copied only by reference - metadata is the same * in the copy. Deleted objects never exist in the currentValueStore (and are therefore not in the * doMap). Created and modified objects are always in the currentValueStore (and are in the * doMap). * * @param anOriginalCS * @param aCopyCS * @param doMap (map of original do's (CS1) to their copy do's in (CS2)) */ private void copyChangeSummary( ChangeSummary anOriginalCS, ChangeSummary aCopyCS, // Map origDOCS1toCopyDOCS2Map) { // cast interfaces to concrete classes in one place SDOChangeSummary originalCS = (SDOChangeSummary) anOriginalCS; SDOChangeSummary copyCS = (SDOChangeSummary) aCopyCS; // handled by copy constructor // map of copy of original ListWrapper (CS2) to its new copy of a copy (CS2) - link ValueStores // to Elements HashMap copyListWrapperCS2toCopyOfListCS2Map = new HashMap(); // in the absence of a ListWrapper.getProperty() we keep a map HashMap propertyToOriginalListMap = new HashMap(); /** In 3 parts we add deleted objects to the global doMap and copy modified, created nodes */ // fields that need re-referencing from original to copy DataObject anOriginalObject = null; DataObject aCopyOfOriginalObject = null; // iterate deleted objects for (Iterator anIterator = originalCS.getDeleted().iterator(); anIterator.hasNext(); ) { anOriginalObject = (DataObject) anIterator.next(); aCopyOfOriginalObject = copy(anOriginalObject, null); // fix deletedList copyCS.getDeleted().add(aCopyOfOriginalObject); // Assumption check do map before a possible re-add - reset() if (null == origDOCS1toCopyDOCS2Map.get(anOriginalObject)) { // add temp map of original : copy of original origDOCS1toCopyDOCS2Map.put(anOriginalObject, aCopyOfOriginalObject); } } // iterate created objects for (Iterator aIterator = originalCS.getCreated().iterator(); aIterator.hasNext(); ) { copyCS.getCreated().add(origDOCS1toCopyDOCS2Map.get(aIterator.next())); } // add modified objects for (Iterator anIterator = originalCS.getModified().iterator(); anIterator.hasNext(); ) { copyCS.getModified().add(origDOCS1toCopyDOCS2Map.get(anIterator.next())); } /** * Fix originalValueStores by deep copying the original dataObject:key and the original * valueStore:value key is original deleted object in [deepCopies] - value is copy of the * ValueStore */ ValueStore aVSCopy = null; ValueStore aVSOriginal = null; for (Iterator anIterator = originalCS.getOriginalValueStores().keySet().iterator(); anIterator.hasNext(); ) { anOriginalObject = (DataObject) anIterator.next(); // deep copy to get corresponding copy DataObject (deleted objects were added to doMap) aCopyOfOriginalObject = (DataObject) origDOCS1toCopyDOCS2Map.get(anOriginalObject); /** * Recursively shallow-copy elements (by iterating the ovs map and iterating the properties of * each item) Fix the dataObject pointer */ aVSCopy = createValueStore(); aVSOriginal = (ValueStore) originalCS.getOriginalValueStores().get(anOriginalObject); // changes made to the copy VS must not affect the original -hence the dataObject field must // be a copy of the original aVSCopy.initialize(aCopyOfOriginalObject); Object aVSPropertyItem = null; // get the # of non-opencontent properties for the object holding the CS - do not use // DVS.getTypePropertyValues() for (int size = ((SDOType) anOriginalObject.getType()).getDeclaredProperties().size(), i = 0; i < size; i++) { aVSPropertyItem = aVSOriginal.getDeclaredProperty(i); // only iterate set properties if (aVSOriginal.isSetDeclaredProperty(i)) { // shallow copy the object values // handle single case SDOProperty currentProperty = (SDOProperty) ((SDOType) anOriginalObject.getType()).getDeclaredProperties().get(i); if (currentProperty.isMany()) { propertyToOriginalListMap.put(aVSPropertyItem, currentProperty); // handle many case - handled by originalElements // container DO must be in our reference map SDODataObject copyContainer = (SDODataObject) origDOCS1toCopyDOCS2Map.get(anOriginalObject); ListWrapper aCopyOfListCopy = (ListWrapper) ((DataObject) copyContainer).getList(currentProperty); // add reference of new copy of original List keyed on original List copyListWrapperCS2toCopyOfListCS2Map.put( (anOriginalObject).getList(currentProperty), aCopyOfListCopy); aVSCopy.setDeclaredProperty(i, aCopyOfListCopy); } else { // COMPLEX SINGLE if (!currentProperty.getType().isDataType()) { // are we using the cast to DataObject as a sort of instance check that would throw a // CCE? aVSCopy.setDeclaredProperty(i, origDOCS1toCopyDOCS2Map.get(aVSPropertyItem)); } else { // SIMPLE SINGLE // skip changeSummary property if (!currentProperty.getType().isChangeSummaryType()) { // simple singles set aVSCopy.setDeclaredProperty(i, aVSPropertyItem); } } } } } // create list of unset and current open content properties List ocPropertiesList = new ArrayList(); ocPropertiesList.addAll(originalCS.getUnsetOCProperties(anOriginalObject)); // add existing properties ocPropertiesList.addAll(((SDODataObject) anOriginalObject)._getOpenContentProperties()); ocPropertiesList.addAll( ((SDODataObject) anOriginalObject)._getOpenContentPropertiesAttributes()); // iterate existing open content properties for (Iterator i = ocPropertiesList.iterator(); i.hasNext(); ) { SDOProperty ocProperty = (SDOProperty) i.next(); if (aVSOriginal.isSetOpenContentProperty(ocProperty)) { // get oc value Object anOCPropertyItem = aVSOriginal.getOpenContentProperty(ocProperty); // get oc copy - shallow copy the object values if (ocProperty.isMany()) { // handle many case - handled by originalElements // container DO must be in our reference map SDODataObject copyContainer = (SDODataObject) origDOCS1toCopyDOCS2Map.get(anOriginalObject); ListWrapper aCopyOfListCopy = (ListWrapper) ((DataObject) copyContainer).getList(ocProperty); // add reference of new copy of original List keyed on original List copyListWrapperCS2toCopyOfListCS2Map.put( (anOriginalObject).getList(ocProperty), aCopyOfListCopy); aVSCopy.setOpenContentProperty(ocProperty, aCopyOfListCopy); } else { // handle complex single case if (!ocProperty.getType().isDataType()) { aVSCopy.setOpenContentProperty( ocProperty, origDOCS1toCopyDOCS2Map.get(aVSPropertyItem)); } else { // simple singles set aVSCopy.setOpenContentProperty(ocProperty, anOCPropertyItem); } } } } // set the copy map entry keyed on copy with value a deep copy of the copy copyCS.getOriginalValueStores().put(aCopyOfOriginalObject, aVSCopy); } // end originalValueStore iteration /** * Fix originalElements by deep copying the original dataObject:key and the original List:value * key is original deleted object in [deepCopies] - value is copy of the elements The instances * of ListWrapper inside the valueStores must be the same ones used in the originalElements */ ListWrapper anOriginalListKey = null; ListWrapper aCopyListWrapper = null; List aCopyList = null; for (Iterator anIterator = originalCS.getOriginalElements().keySet().iterator(); anIterator.hasNext(); ) { anOriginalListKey = (ListWrapper) anIterator.next(); // create a new ListWrapper SDOProperty aProperty = (SDOProperty) propertyToOriginalListMap.get(anOriginalListKey); aCopyListWrapper = (ListWrapper) copyListWrapperCS2toCopyOfListCS2Map.get(anOriginalListKey); aCopyList = new ArrayList(); /** * For each key:ListWrapper - shallow copy all the items in the currentElements list - replace * the dataObject with its copy of the copy - leave the property as is For each * value:ArrayList - replace all values with their copy */ Object aListItem = null; Object aListItemCopy = null; for (Iterator anItemIterator = anOriginalListKey.iterator(); anItemIterator.hasNext(); ) { aListItem = anItemIterator.next(); // for simple many types we use the original in the copy if (!aProperty.getType().isDataType()) { // get the copy of the original (in the current valuestore) - we need do not make a copy // of this copy // we should have a copy of the copy for List items - ListWrapper.add(item) will remove // the item from its original wrapper aListItemCopy = origDOCS1toCopyDOCS2Map.get(aListItem); } else { aListItemCopy = aListItem; } aCopyList.add(aListItemCopy); } // add element list directly to the ListWrapper and bypass the cs element copy and containment // updates aCopyListWrapper.setCurrentElements(aCopyList); List listValueCopy = new ArrayList(); // fix ArrayList value List listValue = (List) originalCS.getOriginalElements().get(anOriginalListKey); aListItem = null; aListItemCopy = null; for (Iterator aListIterator = listValue.iterator(); aListIterator.hasNext(); ) { aListItem = aListIterator.next(); // for simple many types we use the original in the copy if (!aProperty.getType().isDataType()) { aListItemCopy = origDOCS1toCopyDOCS2Map.get(aListItem); } else { aListItemCopy = aListItem; } // don't add nulls to the listWrapper so an undoChanges will encounter an NPE later if (aListItemCopy != null) { listValueCopy.add(aListItemCopy); } } // set the copy map entry keyed on copy with value a deep copy of the copy copyCS.getOriginalElements().put(aCopyListWrapper, listValueCopy); } // end originalist Iteration /** * fields that are already set when logging is turned on but need to be fixed (deleted objects * need references) */ Map oldContainersMap = originalCS.getOldContainers(); Map copyContainersMap = copyCS.getOldContainers(); DataObject oldContainerKey = null; DataObject copyContainerKey = null; // convert any existing entries in the Map - should normally be 0 - unless any OC properties // were unset for (Iterator anIterator = oldContainersMap.keySet().iterator(); anIterator.hasNext(); ) { oldContainerKey = (DataObject) anIterator.next(); // get corresponding copy copyContainerKey = (SDODataObject) origDOCS1toCopyDOCS2Map.get(oldContainerKey); // check existing copyContainers for existing objects - should be 0 - add all objects when // pauseLogging() used DataObject oldContainerValue = null; if (null == copyContainersMap.get(copyContainerKey)) { oldContainerValue = (DataObject) oldContainersMap.get(oldContainerKey); // set copy key:value pair on copy map directly copyContainersMap.put(copyContainerKey, origDOCS1toCopyDOCS2Map.get(oldContainerValue)); } } Map oldContainmentPropertyMap = originalCS.getOldContainmentProperty(); Map copyContainmentPropertyMap = copyCS.getOldContainmentProperty(); DataObject oldContainmentPropertyKey = null; DataObject copyContainmentPropertyKey = null; // convert any existing entries in the Map - should normally be 0 - unless any OC properties // were unset for (Iterator iterContProp = oldContainmentPropertyMap.keySet().iterator(); iterContProp.hasNext(); ) { oldContainmentPropertyKey = (DataObject) iterContProp.next(); // get corresponding copy copyContainmentPropertyKey = (SDODataObject) origDOCS1toCopyDOCS2Map.get(oldContainmentPropertyKey); // check existing copyContainers for existing objects - should be 0 - add all objects when // pauseLogging() used if (null == copyContainmentPropertyMap.get(copyContainmentPropertyKey)) { // set copy key:value pair on copy map directly copyContainmentPropertyMap.put( copyContainmentPropertyKey, oldContainmentPropertyMap.get(oldContainmentPropertyKey)); } } Map oldUnsetOCPropertyMap = originalCS.getUnsetOCPropertiesMap(); SDODataObject oldOCPropertyContainer = null; // convert any existing entries in the Map - should normally be 0 for (Iterator iterContainer = oldUnsetOCPropertyMap.keySet().iterator(); iterContainer.hasNext(); ) { // DataObject will be non-Null oldOCPropertyContainer = (SDODataObject) iterContainer.next(); // check existing copyContainers for existing objects - should be 0 - add all objects when // pauseLogging() used for (Iterator iterUnset = ((List) oldUnsetOCPropertyMap.get(oldOCPropertyContainer)).iterator(); iterUnset.hasNext(); ) { // set/create new list on copy Map with corresponding copy of container copyCS.setUnsetOCProperty( (SDODataObject) origDOCS1toCopyDOCS2Map.get( // oldOCPropertyContainer), (Property) iterUnset.next()); } } // process sequences /** * Fix originalSequences by deep copying the original dataObject:key and the original * Sequence:value key is original deleted object in [deepCopies] - value is copy of the settings * in the sequence. The instances of Sequence inside the originalSequences must be the same ones * used in the originalElements */ // iterate the map of <DataObject, Sequence> for (Iterator aMapIterator = originalCS.getOriginalSequences().keySet().iterator(); aMapIterator.hasNext(); ) { SDODataObject sequenceDataObjectKey = (SDODataObject) aMapIterator.next(); SDOSequence originalSequence = (SDOSequence) originalCS.getOriginalSequences().get(sequenceDataObjectKey); // create a new Sequence with a pointer to the copy of the original DataObject backpointer // assume that all dataObject backpointers are containment objects. SDODataObject copyOriginalSequenceDataObject = (SDODataObject) origDOCS1toCopyDOCS2Map.get(originalSequence.getDataObject()); SDOSequence copySequence = new SDOSequence(copyOriginalSequenceDataObject); replicateAndRereferenceSequenceCopyPrivate( originalSequence, copySequence, originalSequence.getDataObject(), copyOriginalSequenceDataObject, origDOCS1toCopyDOCS2Map, originalCS); // set the copy map entry keyed on copy with value a deep copy of the copy copyCS.getOriginalSequences().put(copyOriginalSequenceDataObject, copySequence); } /** * fields to ignore // aHelperContext SDOHelperContext (id=42) // dataGraph null // logging true * // loggingMapping true // unsetPropsMap HashMap<K,V> (id=117) // createdXPaths null // * deletedXPaths null // modifiedDoms null */ /** * fields to ignore that are on-demand oldSettings HashMap<K,V> (id=110) reverseDeletedMap * HashMap<K,V> (id=116) oldSequences HashMap<K,V> (id=88) */ }
/** * INTERNAL: Iterate the non-containment nodes and copy all uni/bi-directional properties on the * copy. * * @param doMap * @param ncPropMap */ private void processNonContainmentNodesPrivate(HashMap doMap, HashMap ncPropMap) { // for the doMap and ncPropMap we can either deep copy them all now or each one during // rereferencing later // iterate nc property map and set bidirectional/unidirectional properties that are in scope for (Iterator ncIterator = ncPropMap.keySet().iterator(); ncIterator.hasNext(); ) { // p.142 limit scope of while by using for // get current source dataobject (the one we will set properties on) DataObject sourceDO = (DataObject) ncIterator.next(); // get the list of properties for the current do ArrayList aList = (ArrayList) ncPropMap.get(sourceDO); // iterate property list for (Iterator propIterator = aList.iterator(); propIterator.hasNext(); ) { // p.142 limit scope of while by using for // get current property SDOProperty aProperty = (SDOProperty) propIterator.next(); /* * Stored in the map we have * doMap: (a=key, a'=value) * ncPropMap (a=key, (list of props)=value * We get the copy from the doMap * We get the copy of the source by doing a get on the current source do */ // get original object that sourceDO points to via current property Object targetDO = sourceDO.get(aProperty); // flag whether the property is inside the copy tree boolean isPropertyInsideCopyTreeScope = false; // get sourceDO copy that we will be setting the property on DataObject sourceDOCopy = null; // lookup copy of targetDO in map Object targetDOCopy = null; /* * Handle 1-n many case * For containment=true * the DO's will be cached previously, and both bidirectional (one) and unidirectional * properties will set the copy on the copy object * For containment=false * the DO's will not be cached (outside the tree), only unidirectional properties * will be set using the original list */ if (aProperty.isMany()) { // create new list to hold copied list items ListWrapper targetList = (ListWrapper) targetDO; // get source\DO copy that we will be setting the property on sourceDOCopy = (DataObject) doMap.get(sourceDO); // lookup copy of targetDO in map targetDOCopy = new ArrayList(); for (int i = 0, size = targetList.size(); i < size; i++) { // get sourceDO key - used as a lookup in our doMap DataObject sourceDOCopyKey = (DataObject) targetList.get(i); DataObject sourceDOCopyValue = (DataObject) doMap.get(sourceDOCopyKey); // add copy to new list if (sourceDOCopyValue != null) { // bidirectional/unidirectional inside copy tree - use copy object ((List) targetDOCopy).add(sourceDOCopyValue); } else { // non-containment properties are not cached - store original for unidirectional // targetDOCopy.add(sourceDOCopyKey); } } // check if the target copies are in our map (inside copy tree scope) // when containment = false then targetDOCopy is empty // Assume: all items in the list share the same property isPropertyInsideCopyTreeScope = ((List) targetDOCopy).size() > 0; } else { // handle 1-1 DataObject // lookup copy of targetDO in map targetDOCopy = doMap.get(targetDO); // get sourceDO copy that we will be setting the property on sourceDOCopy = (DataObject) doMap.get(sourceDO); // check if the target copy is in our map (inside copy tree scope) isPropertyInsideCopyTreeScope = targetDOCopy != null; } // set nc property if we are in the copy tree // check if the target copy is in our map (inside copy tree scope) if (isPropertyInsideCopyTreeScope) { ((SDODataObject) sourceDOCopy).set(aProperty, targetDOCopy, false); } else { // only set unidirectional properties if (null == aProperty.getOpposite()) { // spec 3.9.4 set property to original object when unidirectional ((SDODataObject) sourceDOCopy).set(aProperty, targetDO, false); } } } } }