/** * 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()); }
/** 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); } } }
/** * 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; }
/** * INTERNAL: Build the copy tree and cache all reachable DataObjects with their copy<br> * Cache all non-containment properties - to be set after tree construction<br> * Recurse the tree in preorder traversal (root, child1-n) Scope: We do not have to check the * copyTree scope when iterating opposites since we will not enter any opposite property dataTree * that is outside of the copyTree scope * * @param doMap (cache original -> copy DataObject instances to set non-containment properties * after tree construction) * @param ncPropMap (cache original DO:non-containment property values to be set after tree * construction) */ private SDODataObject copyPrivate( SDODataObject dataObject, HashMap doMap, // HashMap ncPropMap, SDOChangeSummary cs) throws IllegalArgumentException { // check for null DataObject if (null == dataObject) { return null; // this is acceptable behavior } SDODataObject copy = (SDODataObject) getHelperContext() // .getDataFactory() .create(dataObject.getType().getURI(), dataObject.getType().getName()); // store current object for reference by the non-containment map doMap.put(dataObject, copy); List ocListOriginal = dataObject._getOpenContentProperties(); for (Iterator anOCIterator = ocListOriginal.iterator(); anOCIterator.hasNext(); ) { copy.addOpenContentProperty((Property) anOCIterator.next()); } List ocAttrsListOriginal = dataObject._getOpenContentPropertiesAttributes(); for (Iterator anOCAttrIterator = ocAttrsListOriginal.iterator(); anOCAttrIterator.hasNext(); ) { copy.addOpenContentProperty((Property) anOCAttrIterator.next()); } // start iterating all copy's properties for (Iterator iterInstanceProperties = copy.getInstanceProperties().iterator(); iterInstanceProperties.hasNext(); ) { SDOProperty eachProperty = (SDOProperty) iterInstanceProperties.next(); boolean isSet = isSet(dataObject, eachProperty, cs); if (isSet) { Object o = getValue(dataObject, eachProperty, cs); if (eachProperty.getType().isDataType()) { if (!eachProperty.getType().isChangeSummaryType()) { /** * ChangeSummaries must be cleared with logging set to the original state without * creating oldSettings. The logging flag from the original will be set on the copy * after this copy call completes and gets set on its container. The cs is off by * default in the copy object. updateSequence flag is false - we will populate the * sequence in order after subtree creation */ copy.setInternal(eachProperty, o, false); } } else { // case matrix for containment and opposite combinations // cont=false, opp=false -> unidirectional // cont=false, opp=true -> bidirectional // cont=true, opp=false -> normal containment // cont=true, opp=true -> bidirectional if (eachProperty.isContainment()) { // process containment properties (normal, half of bidirectionals) copyContainmentPropertyValue(copy, eachProperty, o, doMap, ncPropMap, cs); } else { // copy non-containment do (not properties (unidirectional, half of bidirectionals)) // copyPropertyValue(dataObject, copy, eachProperty, o, copyRoot, doMap); // cacheNContainmentPropertyValue(copy, eachProperty, o, doMap, ncPropMap); // store non-containment properties ArrayList anArray = (ArrayList) ncPropMap.get(dataObject); if (anArray == null) { anArray = new ArrayList(); anArray.add(eachProperty); // store property array into the map for the first time ncPropMap.put(dataObject, anArray); } else { // add to existing array of nc properties in the map anArray.add(eachProperty); } } } } } // sequences will not be processed until the entire tree is copied so we can resolve any // reference relationships return copy; }