| /* |
| * Copyright (c) 1998, 2021 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.internal.oxm; |
| |
| import java.lang.reflect.Modifier; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.List; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.descriptors.InheritancePolicy; |
| import org.eclipse.persistence.exceptions.DatabaseException; |
| import org.eclipse.persistence.exceptions.DescriptorException; |
| import org.eclipse.persistence.exceptions.QueryException; |
| import org.eclipse.persistence.expressions.Expression; |
| import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession; |
| import org.eclipse.persistence.internal.descriptors.ObjectBuilder; |
| import org.eclipse.persistence.internal.helper.DatabaseField; |
| import org.eclipse.persistence.internal.identitymaps.CacheId; |
| import org.eclipse.persistence.internal.identitymaps.CacheKey; |
| import org.eclipse.persistence.internal.oxm.mappings.Descriptor; |
| import org.eclipse.persistence.internal.oxm.mappings.Field; |
| import org.eclipse.persistence.internal.oxm.mappings.Mapping; |
| import org.eclipse.persistence.internal.oxm.record.AbstractMarshalRecord; |
| import org.eclipse.persistence.internal.queries.JoinedAttributeManager; |
| import org.eclipse.persistence.internal.sessions.AbstractRecord; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| import org.eclipse.persistence.mappings.DatabaseMapping.WriteType; |
| import org.eclipse.persistence.mappings.ForeignReferenceMapping; |
| import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping; |
| import org.eclipse.persistence.oxm.NamespaceResolver; |
| import org.eclipse.persistence.oxm.XMLDescriptor; |
| import org.eclipse.persistence.oxm.XMLMarshaller; |
| import org.eclipse.persistence.oxm.XMLUnmarshaller; |
| import org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy; |
| import org.eclipse.persistence.oxm.record.DOMRecord; |
| import org.eclipse.persistence.oxm.record.XMLRecord; |
| import org.eclipse.persistence.queries.FetchGroup; |
| import org.eclipse.persistence.queries.ObjectBuildingQuery; |
| import org.eclipse.persistence.sessions.SessionProfiler; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| |
| /** |
| * INTERNAL: |
| * <p><b>Purpose</b>: Object-to-XML specific ObjectBuilder.</p> |
| * @author Rick Barkhouse - rick.barkhouse@oracle.com |
| * @since TopLink 10<i>i</i>, 03/31/2003 16:29:40 |
| */ |
| public class XMLObjectBuilder extends ObjectBuilder { |
| private Boolean isXMLDescriptor; |
| private boolean xsiTypeIndicatorField; |
| |
| /** |
| * Create an XML object builder for the descriptor. |
| */ |
| public XMLObjectBuilder(ClassDescriptor descriptor) { |
| super(descriptor); |
| } |
| |
| /** |
| * Build the nested row into the parent dom. |
| */ |
| public AbstractRecord buildRow(Object object, AbstractSession session, DatabaseField xmlField, XMLRecord parentRecord) { |
| if (isXmlDescriptor() && ((Descriptor)getDescriptor()).shouldPreserveDocument()) { |
| Object pk = extractPrimaryKeyFromObject(object, session); |
| if ((pk == null) || (pk instanceof CacheId) && (((CacheId)pk).getPrimaryKey().length == 0)) { |
| pk = new CacheId(new Object[]{ new WeakObjectWrapper(object) }); |
| } |
| CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(pk, getDescriptor().getJavaClass(), getDescriptor(), false); |
| if ((cacheKey != null) && (cacheKey.getRecord() != null)) { |
| XMLRecord nestedRecord = (XMLRecord)cacheKey.getRecord(); |
| nestedRecord.setMarshaller(parentRecord.getMarshaller()); |
| nestedRecord.setLeafElementType(parentRecord.getLeafElementType()); |
| parentRecord.setLeafElementType((XPathQName)null); |
| return buildIntoNestedRow(nestedRecord, object, session); |
| } |
| } |
| Element newNode = XPathEngine.getInstance().createUnownedElement(parentRecord.getDOM(), (Field)xmlField); |
| XMLRecord nestedRecord = new DOMRecord(newNode); |
| nestedRecord.setNamespaceResolver(parentRecord.getNamespaceResolver()); |
| nestedRecord.setMarshaller(parentRecord.getMarshaller()); |
| nestedRecord.setLeafElementType(parentRecord.getLeafElementType()); |
| parentRecord.setLeafElementType((XPathQName)null); |
| return buildIntoNestedRow(nestedRecord, object, session); |
| |
| } |
| |
| /** |
| * Create a new row/record for the object builder. |
| * This allows subclasses to define different record types. |
| */ |
| @Override |
| public AbstractRecord createRecord(AbstractSession session) { |
| return (AbstractRecord) createRecord(getDescriptor().getTableName(), session); |
| } |
| |
| /** |
| * Create a new row/record for the object builder. |
| * This allows subclasses to define different record types. |
| */ |
| @Override |
| public AbstractRecord createRecord(int size, AbstractSession session) { |
| return (AbstractRecord) createRecord(getDescriptor().getTableName(), session); |
| } |
| |
| /** |
| * Create a new row/record for the object builder with the given name. This |
| * allows subclasses to define different record types. |
| */ |
| public AbstractMarshalRecord createRecord(String rootName, AbstractSession session) { |
| NamespaceResolver namespaceResolver = getNamespaceResolver(); |
| XMLRecord xmlRec = new DOMRecord(rootName, namespaceResolver); |
| xmlRec.setSession(session); |
| return xmlRec; |
| } |
| |
| /** |
| * Create a new row/record for the object builder with the given name and |
| * namespace resolver instead of the namespace resolver from the descriptor. |
| * This allows subclasses to define different record types. |
| */ |
| public AbstractRecord createRecord(String rootName, String rootUri, AbstractSession session) { |
| XMLRecord xmlRec = new DOMRecord(rootName, rootUri); |
| xmlRec.setSession(session); |
| return xmlRec; |
| } |
| |
| /** |
| * Create a new row/record for the object builder with the given name. This |
| * allows subclasses to define different record types. |
| */ |
| public AbstractMarshalRecord createRecord(String rootName, Node parent, AbstractSession session) { |
| NamespaceResolver namespaceResolver = getNamespaceResolver(); |
| XMLRecord xmlRec = new DOMRecord(rootName, namespaceResolver, parent); |
| xmlRec.setSession(session); |
| return xmlRec; |
| } |
| |
| public AbstractRecord createRecordFor(Object attributeValue, Field xmlField, XMLRecord parentRecord, Mapping mapping) { |
| DocumentPreservationPolicy policy = parentRecord.getDocPresPolicy(); |
| Element newNode = null; |
| if(policy != null) { |
| newNode = (Element)policy.getNodeForObject(attributeValue); |
| } |
| if(newNode == null) { |
| newNode = XPathEngine.getInstance().createUnownedElement(parentRecord.getDOM(), xmlField); |
| if(policy !=null ){ |
| if(xmlField.isSelfField()) { |
| policy.addObjectToCache(attributeValue, newNode, mapping); |
| } else { |
| policy.addObjectToCache(attributeValue, newNode); |
| } |
| } |
| } |
| |
| DOMRecord nestedRecord = new DOMRecord(newNode); |
| nestedRecord.setMarshaller(parentRecord.getMarshaller()); |
| nestedRecord.setLeafElementType(parentRecord.getLeafElementType()); |
| parentRecord.setLeafElementType((XPathQName)null); |
| nestedRecord.setDocPresPolicy(policy); |
| nestedRecord.setXOPPackage(parentRecord.isXOPPackage()); |
| nestedRecord.setReferenceResolver(((DOMRecord) parentRecord).getReferenceResolver()); |
| return nestedRecord; |
| } |
| |
| public AbstractRecord createRecordFor(Object object, DocumentPreservationPolicy docPresPolicy) { |
| Element cachedNode = null; |
| XMLRecord record = null; |
| if(docPresPolicy != null) { |
| cachedNode = (Element)docPresPolicy.getNodeForObject(object); |
| } |
| if(cachedNode == null) { |
| record = new DOMRecord(getDescriptor().getTableName(), getNamespaceResolver()); |
| docPresPolicy.addObjectToCache(object, record.getDOM()); |
| } else { |
| record = new DOMRecord(cachedNode); |
| } |
| record.setDocPresPolicy(docPresPolicy); |
| return record; |
| } |
| |
| public AbstractRecord createRecordFor(Object object, DocumentPreservationPolicy docPresPolicy, String rootName, String rootUri) { |
| Element cachedNode = null; |
| XMLRecord record = null; |
| if(docPresPolicy != null) { |
| cachedNode = (Element)docPresPolicy.getNodeForObject(object); |
| } |
| if(cachedNode == null) { |
| record = new DOMRecord(rootName, rootUri); |
| docPresPolicy.addObjectToCache(object, record.getDOM()); |
| } else { |
| record = new DOMRecord(cachedNode); |
| } |
| record.setDocPresPolicy(docPresPolicy); |
| return record; |
| } |
| |
| /** |
| * Create a new row/record for the object builder. This allows subclasses to |
| * define different record types. This will typically be called when a |
| * record will be used for temporarily holding on to primary key fields. |
| */ |
| @Override |
| protected AbstractRecord createRecordForPKExtraction(int size, AbstractSession session) { |
| NamespaceResolver namespaceResolver = getNamespaceResolver(); |
| XMLRecord xmlRec = new DOMRecord(getDescriptor().getTableName(), namespaceResolver); |
| xmlRec.setSession(session); |
| return xmlRec; |
| } |
| |
| /** |
| * INTERNAL: Override the parent's buildObject to allow for the caching of |
| * aggregate objects in OX. By caching aggregates along with XML Nodes that |
| * they were created from, we are able to preserve the structure and |
| * unmapped content of the document that was used to create these objects. |
| */ |
| @Override |
| public Object buildObject(ObjectBuildingQuery query, AbstractRecord databaseRow, JoinedAttributeManager joinManager) throws DatabaseException, QueryException { |
| XMLRecord row = (XMLRecord) databaseRow; |
| row.setSession(query.getSession()); |
| |
| XMLUnmarshaller unmarshaller = row.getUnmarshaller(); |
| Object parent = row.getOwningObject(); |
| |
| if (!(isXmlDescriptor() || getDescriptor().isDescriptorTypeAggregate())) { |
| return super.buildObject(query, databaseRow, joinManager); |
| } |
| query.getSession().startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL); |
| ClassDescriptor concreteDescriptor = getDescriptor(); |
| Object domainObject = null; |
| |
| // only need to check in the root case since the nested case is handled |
| // in the mapping |
| if (concreteDescriptor.hasInheritance() && (parent == null)) { |
| // look for an xsi:type attribute in the xml document |
| InheritancePolicy inheritancePolicy = concreteDescriptor.getInheritancePolicy(); |
| Class<?> classValue = inheritancePolicy.classFromRow(databaseRow, query.getSession()); |
| if ((classValue == null) && isXmlDescriptor()) { |
| // no xsi:type attribute - look for type indicator on the |
| // default root element |
| QName leafElementType = ((Descriptor) concreteDescriptor).getDefaultRootElementType(); |
| |
| // if we have a user-set type, try to get the class from the |
| // inheritance policy |
| if (leafElementType != null) { |
| XPathQName xpathQName = new XPathQName(leafElementType, row.isNamespaceAware()); |
| Object indicator = inheritancePolicy.getClassIndicatorMapping().get(xpathQName); |
| if (indicator != null) { |
| classValue = (Class) indicator; |
| } |
| } |
| } |
| |
| // if we found the class, use it - otherwise, use the descriptor |
| // class, if non-abstract |
| if (classValue != null) { |
| concreteDescriptor = query.getSession().getDescriptor(classValue); |
| if ((concreteDescriptor == null) && query.hasPartialAttributeExpressions()) { |
| concreteDescriptor = getDescriptor(); |
| } |
| if (concreteDescriptor == null) { |
| throw QueryException.noDescriptorForClassFromInheritancePolicy(query, classValue); |
| } |
| } else { |
| // make sure the class is non-abstract |
| if (Modifier.isAbstract(concreteDescriptor.getJavaClass().getModifiers())) { |
| // throw an exception |
| throw DescriptorException.missingClassIndicatorField(databaseRow, inheritancePolicy.getDescriptor()); |
| } |
| } |
| } |
| domainObject = concreteDescriptor.getObjectBuilder().buildNewInstance(); |
| row.setCurrentObject(domainObject); |
| if ((unmarshaller != null) && (unmarshaller.getUnmarshalListener() != null)) { |
| unmarshaller.getUnmarshalListener().beforeUnmarshal(domainObject, parent); |
| } |
| concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, null, databaseRow, query, joinManager, null, false, query.getSession()); |
| if (isXmlDescriptor() && ((Descriptor) concreteDescriptor).getPrimaryKeyFieldNames().size() > 0) { |
| Object pk = extractPrimaryKeyFromRow(databaseRow, query.getSession()); |
| if ((pk != null) && (((CacheId) pk).getPrimaryKey().length > 0)) { |
| DOMRecord domRecord = (DOMRecord) databaseRow; |
| domRecord.getReferenceResolver().putValue(concreteDescriptor.getJavaClass(), pk, domainObject); |
| } |
| } |
| DocumentPreservationPolicy docPresPolicy = row.getDocPresPolicy(); |
| if (docPresPolicy != null) { |
| // EIS XML Cases won't have a doc pres policy set |
| row.getDocPresPolicy().addObjectToCache(domainObject, row.getDOM()); |
| } |
| query.getSession().endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL); |
| if ((unmarshaller != null) && (unmarshaller.getUnmarshalListener() != null)) { |
| unmarshaller.getUnmarshalListener().afterUnmarshal(domainObject, parent); |
| } |
| return domainObject; |
| } |
| |
| public AbstractRecord buildRow(AbstractRecord databaseRow, Object object, AbstractSession session) { |
| return buildRow(databaseRow, object, session, false); |
| } |
| |
| public AbstractRecord buildRow(AbstractRecord databaseRow, Object object, AbstractSession session, boolean wasXMLRoot) { |
| XMLRecord row = (XMLRecord)databaseRow; |
| row.setSession(session); |
| |
| XMLMarshaller marshaller = row.getMarshaller(); |
| if ((marshaller != null) && (marshaller.getMarshalListener() != null)) { |
| marshaller.getMarshalListener().beforeMarshal(object); |
| } |
| addNamespaceDeclarations((row).getDocument()); |
| writeOutMappings(row, object, session); |
| |
| |
| // If this descriptor has multiple tables then we need to append the |
| // primary keys for |
| // the non default tables. |
| if (!getDescriptor().isAggregateDescriptor()) { |
| addPrimaryKeyForNonDefaultTable(row); |
| } |
| |
| |
| |
| if ((marshaller != null) && (marshaller.getMarshalListener() != null)) { |
| marshaller.getMarshalListener().afterMarshal(object); |
| } |
| return row; |
| } |
| |
| public void writeOutMappings(XMLRecord row, Object object, AbstractSession session) { |
| List<DatabaseMapping> mappings = getDescriptor().getMappings(); |
| for (int index = 0; index < mappings.size(); index++) { |
| DatabaseMapping mapping = mappings.get(index); |
| mapping.writeFromObjectIntoRow(object, row, session, WriteType.UNDEFINED); |
| } |
| } |
| public void addNamespaceDeclarations(Document document) { |
| NamespaceResolver namespaceResolver = getNamespaceResolver(); |
| |
| if (namespaceResolver == null) { |
| return; |
| } |
| |
| Element docElement = document.getDocumentElement(); |
| if(namespaceResolver.getDefaultNamespaceURI() != null) { |
| docElement.setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE, namespaceResolver.getDefaultNamespaceURI()); |
| } |
| |
| Enumeration prefixes = namespaceResolver.getPrefixes(); |
| String prefix; |
| String namespace; |
| while (prefixes.hasMoreElements()) { |
| prefix = (String)prefixes.nextElement(); |
| namespace = namespaceResolver.resolveNamespacePrefix(prefix); |
| docElement.setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON + prefix, namespace); |
| } |
| } |
| |
| /** |
| * Override method in superclass in order to set the session on the record. |
| * Each mapping is recursed to assign values from the Record to the attributes in the domain object. |
| */ |
| @Override |
| public void buildAttributesIntoObject(Object domainObject, CacheKey cacheKey, AbstractRecord databaseRow, ObjectBuildingQuery query, JoinedAttributeManager joinManager, FetchGroup executionFetchGroup, boolean forRefresh, AbstractSession targetSession) throws DatabaseException { |
| ((XMLRecord)databaseRow).setSession(query.getSession().getExecutionSession(query)); |
| super.buildAttributesIntoObject(domainObject, cacheKey, databaseRow, query, joinManager, executionFetchGroup, forRefresh, targetSession); |
| } |
| |
| /** |
| * Override method in superclass in order to set the session on the record. |
| * Return the row with primary keys and their values from the given expression. |
| */ |
| @Override |
| public AbstractRecord extractPrimaryKeyRowFromExpression(Expression expression, AbstractRecord translationRow, AbstractSession session) { |
| AbstractRecord primaryKeyRow = createRecord(getPrimaryKeyMappings().size(), session); |
| expression.getBuilder().setSession(session.getRootSession(null)); |
| // Get all the field & values from expression |
| boolean isValid = expression.extractPrimaryKeyValues(true, getDescriptor(), primaryKeyRow, translationRow); |
| if (!isValid) { |
| return null; |
| } |
| |
| // Check that the sizes match up |
| if (primaryKeyRow.size() != getDescriptor().getPrimaryKeyFields().size()) { |
| return null; |
| } |
| |
| return primaryKeyRow; |
| } |
| |
| /** |
| * Override method in superclass in order to set the session on the record. |
| * Return the row with primary keys and their values from the given expression. |
| */ |
| @Override |
| public Object extractPrimaryKeyFromExpression(boolean requiresExactMatch, Expression expression, AbstractRecord translationRow, AbstractSession session) { |
| AbstractRecord primaryKeyRow = createRecord(getPrimaryKeyMappings().size(), session); |
| expression.getBuilder().setSession(session.getRootSession(null)); |
| // Get all the field & values from expression. |
| boolean isValid = expression.extractPrimaryKeyValues(requiresExactMatch, getDescriptor(), primaryKeyRow, translationRow); |
| if (requiresExactMatch && (!isValid)) { |
| return null; |
| } |
| |
| // Check that the sizes match. |
| if (primaryKeyRow.size() != getDescriptor().getPrimaryKeyFields().size()) { |
| return null; |
| } |
| |
| return extractPrimaryKeyFromRow(primaryKeyRow, session); |
| } |
| |
| @Override |
| public Object extractPrimaryKeyFromObject(Object domainObject, AbstractSession session) { |
| if (getDescriptor().hasInheritance() && (domainObject.getClass() != getDescriptor().getJavaClass()) && (!domainObject.getClass().getSuperclass().equals(getDescriptor().getJavaClass()))) { |
| return session.getDescriptor(domainObject.getClass()).getObjectBuilder().extractPrimaryKeyFromObject(domainObject, session); |
| } |
| List<DatabaseField> descriptorPrimaryKeyFields = getDescriptor().getPrimaryKeyFields(); |
| if (null == descriptorPrimaryKeyFields || descriptorPrimaryKeyFields.size() == 0) { |
| return null; |
| } |
| return super.extractPrimaryKeyFromObject(domainObject, session); |
| } |
| |
| public AbstractRecord buildIntoNestedRow(AbstractRecord row, Object object, AbstractSession session) { |
| return buildIntoNestedRow(row, null, object, session, null, null, false); |
| } |
| |
| public AbstractRecord buildIntoNestedRow(AbstractRecord row, Object object, AbstractSession session, Descriptor refDesc, Field xmlField) { |
| return buildIntoNestedRow(row, null, object, session, refDesc, xmlField, false); |
| } |
| public AbstractRecord buildIntoNestedRow(AbstractRecord row, Object originalObject, Object object, AbstractSession session, Descriptor refDesc, Field xmlField, boolean wasXMLRoot) { |
| // PERF: Avoid synchronized enumerator as is concurrency bottleneck. |
| XMLRecord record = (XMLRecord)row; |
| record.setSession(session); |
| |
| XMLMarshaller marshaller = record.getMarshaller(); |
| |
| if ((marshaller != null) && (marshaller.getMarshalListener() != null)) { |
| marshaller.getMarshalListener().beforeMarshal(object); |
| } |
| List extraNamespaces = null; |
| if (isXmlDescriptor()) { |
| Descriptor xmlDescriptor = (Descriptor)getDescriptor(); |
| extraNamespaces = addExtraNamespacesToNamespaceResolver(xmlDescriptor, record, session, false, false); |
| writeExtraNamespaces(extraNamespaces, record); |
| record.addXsiTypeAndClassIndicatorIfRequired(xmlDescriptor, refDesc, xmlField, originalObject, object, wasXMLRoot, false); |
| } |
| |
| writeOutMappings(record, object, session); |
| // If this descriptor is involved in inheritance add the class type. |
| if (isXmlDescriptor()) { |
| record.removeExtraNamespacesFromNamespaceResolver(extraNamespaces, session); |
| } |
| |
| // If this descriptor has multiple tables then we need to append the |
| // primary keys for |
| // the non default tables. |
| if (!getDescriptor().isAggregateDescriptor()) { |
| addPrimaryKeyForNonDefaultTable(row); |
| } |
| if ((marshaller != null) && (marshaller.getMarshalListener() != null)) { |
| marshaller.getMarshalListener().afterMarshal(object); |
| } |
| return row; |
| } |
| |
| public NamespaceResolver getNamespaceResolver() { |
| NamespaceResolver namespaceResolver = null; |
| if (isXmlDescriptor()) { |
| namespaceResolver = ((XMLDescriptor)getDescriptor()).getNamespaceResolver(); |
| } else if (getDescriptor() instanceof org.eclipse.persistence.eis.EISDescriptor) { |
| namespaceResolver = ((org.eclipse.persistence.eis.EISDescriptor)getDescriptor()).getNamespaceResolver(); |
| } |
| return namespaceResolver; |
| } |
| /** |
| * Indicates if the object builder's descriptor is an XMLDescriptor. |
| * The value is lazily initialized. |
| * |
| */ |
| protected boolean isXmlDescriptor() { |
| if (isXMLDescriptor == null) { |
| isXMLDescriptor = getDescriptor() instanceof Descriptor; |
| } |
| return isXMLDescriptor; |
| } |
| |
| /** |
| * Set the descriptor. This method is overridden so the |
| * isXMLDescriptor Boolean can be reset. |
| */ |
| @Override |
| public void setDescriptor(ClassDescriptor aDescriptor) { |
| super.setDescriptor(aDescriptor); |
| isXMLDescriptor = null; |
| } |
| |
| protected List<Namespace> addExtraNamespacesToNamespaceResolver(Descriptor desc, AbstractMarshalRecord marshalRecord, CoreAbstractSession session, boolean allowOverride, boolean ignoreEqualResolvers) { |
| return marshalRecord.addExtraNamespacesToNamespaceResolver(desc, session, allowOverride, ignoreEqualResolvers); |
| } |
| |
| public void writeExtraNamespaces(List extraNamespaces, XMLRecord xmlRecord) { |
| if(extraNamespaces == null){ |
| return; |
| } |
| |
| if(xmlRecord.getDOM().getNodeType() != Node.ELEMENT_NODE) { |
| return; |
| } |
| |
| for (int i = 0; i < extraNamespaces.size(); i++) { |
| Namespace next = (Namespace)extraNamespaces.get(i); |
| ((Element)xmlRecord.getDOM()).setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON + next.getPrefix(), next.getNamespaceURI()); |
| } |
| } |
| |
| @Override |
| public void initialize(AbstractSession session) throws DescriptorException { |
| mappingsByField.clear(); |
| if(null != readOnlyMappingsByField) { |
| readOnlyMappingsByField.clear(); |
| } |
| if(null != mappingsByAttribute) { |
| mappingsByAttribute.clear(); |
| } |
| cloningMappings.clear(); |
| if(null != eagerMappings) { |
| eagerMappings.clear(); |
| } |
| if(null != relationshipMappings) { |
| relationshipMappings.clear(); |
| } |
| |
| for (Enumeration<DatabaseMapping> mappings = this.descriptor.getMappings().elements(); |
| mappings.hasMoreElements();) { |
| DatabaseMapping mapping = mappings.nextElement(); |
| |
| // Add attribute to mapping association |
| if (!mapping.isWriteOnly()) { |
| if(mappingsByAttribute != null) { |
| getMappingsByAttribute().put(mapping.getAttributeName(), mapping); |
| } |
| } |
| // Cache mappings that require cloning. |
| if (mapping.isCloningRequired()) { |
| getCloningMappings().add(mapping); |
| } |
| // Cache eager mappings. |
| if (mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).usesIndirection() && (!mapping.isLazy())) { |
| getEagerMappings().add(mapping); |
| } |
| // Cache relationship mappings. |
| if (!mapping.isDirectToFieldMapping()) { |
| if(null != relationshipMappings) { |
| relationshipMappings.add(mapping); |
| } |
| } |
| |
| // Add field to mapping association |
| for (DatabaseField field : mapping.getFields()) { |
| |
| if (mapping.isReadOnly()) { |
| if(null != readOnlyMappingsByField) { |
| List<DatabaseMapping> readOnlyMappings = getReadOnlyMappingsByField().get(field); |
| |
| if (readOnlyMappings == null) { |
| readOnlyMappings = new ArrayList(); |
| getReadOnlyMappingsByField().put(field, readOnlyMappings); |
| } |
| |
| readOnlyMappings.add(mapping); |
| } |
| } else { |
| if (mapping.isAggregateObjectMapping()) { |
| // For Embeddable class, we need to test read-only |
| // status of individual fields in the embeddable. |
| ObjectBuilder aggregateObjectBuilder = mapping.getReferenceDescriptor().getObjectBuilder(); |
| |
| // Look in the non-read-only fields mapping |
| DatabaseMapping aggregatedFieldMapping = aggregateObjectBuilder.getMappingForField(field); |
| |
| if (aggregatedFieldMapping == null) { // mapping must be read-only |
| List<DatabaseMapping> readOnlyMappings = getReadOnlyMappingsByField().get(field); |
| |
| if (readOnlyMappings == null) { |
| readOnlyMappings = new ArrayList(); |
| getReadOnlyMappingsByField().put(field, readOnlyMappings); |
| } |
| |
| readOnlyMappings.add(mapping); |
| } else { |
| getMappingsByField().put(field, mapping); |
| } |
| } else { // Not an embeddable mapping |
| if (!getMappingsByField().containsKey(field)) { |
| getMappingsByField().put(field, mapping); |
| } |
| } |
| } |
| } |
| } |
| this.isSimple = null == relationshipMappings || relationshipMappings.isEmpty(); |
| |
| initializePrimaryKey(session); |
| initializeJoinedAttributes(); |
| |
| if (this.descriptor.usesSequenceNumbers()) { |
| DatabaseMapping sequenceMapping = getMappingForField(this.descriptor.getSequenceNumberField()); |
| if ((sequenceMapping != null) && sequenceMapping.isDirectToFieldMapping()) { |
| setSequenceMapping((AbstractDirectMapping)sequenceMapping); |
| } |
| } |
| |
| |
| |
| if (descriptor.hasInheritance() ) { |
| Field indicatorField = (Field) descriptor.getInheritancePolicy().getClassIndicatorField(); |
| if(indicatorField != null){ |
| if (indicatorField.getLastXPathFragment().getNamespaceURI() != null && indicatorField.getLastXPathFragment().getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI) |
| && indicatorField.getLastXPathFragment().getLocalName().equals(Constants.SCHEMA_TYPE_ATTRIBUTE)){ |
| xsiTypeIndicatorField = true; |
| } |
| |
| } |
| } |
| } |
| |
| @Override |
| public boolean isXMLObjectBuilder() { |
| return true; |
| } |
| |
| public boolean isXsiTypeIndicatorField() { |
| return xsiTypeIndicatorField; |
| } |
| |
| } |