org.eclipse.persistence.internal.oxm.XMLObjectBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2019 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:
* Purpose: Object-to-XML specific ObjectBuilder.
* @author Rick Barkhouse - [email protected]
* @since TopLink 10i, 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 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 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.
*
* @return
*/
protected boolean isXmlDescriptor() {
if (isXMLDescriptor == null) {
isXMLDescriptor = getDescriptor() instanceof Descriptor;
}
return isXMLDescriptor.booleanValue();
}
/**
* 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 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 mappings = this.descriptor.getMappings().elements();
mappings.hasMoreElements();) {
DatabaseMapping mapping = (DatabaseMapping)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 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 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;
}
}