org.eclipse.persistence.internal.oxm.XMLRelationshipMappingNodeValue 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, 2024 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 org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.core.queries.CoreAttributeItem;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreField;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
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.mappings.UnmarshalKeepAsElementPolicy;
import org.eclipse.persistence.internal.oxm.mappings.XMLConverterMapping;
import org.eclipse.persistence.internal.oxm.record.MarshalRecord;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.oxm.record.XMLReader;
import org.eclipse.persistence.internal.oxm.record.XMLRecord;
import org.eclipse.persistence.internal.oxm.record.deferred.DescriptorNotFoundContentHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import javax.xml.namespace.QName;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public abstract class XMLRelationshipMappingNodeValue extends MappingNodeValue {
// Protected to public
public void processChild(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts, Descriptor xmlDescriptor, Mapping mapping) throws SAXException {
if(xmlDescriptor == null){
//Use the DescriptorNotFoundContentHandler to "look ahead" and determine if this is a simple or complex element
//if it is complex the exception should be thrown
DescriptorNotFoundContentHandler handler = new DescriptorNotFoundContentHandler(unmarshalRecord, mapping);
String qnameString = xPathFragment.getLocalName();
if(xPathFragment.getPrefix() != null) {
qnameString = xPathFragment.getPrefix() +Constants.COLON + qnameString;
}
handler.startElement(xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), qnameString, atts);
XMLReader xmlReader = unmarshalRecord.getXMLReader();
xmlReader.setContentHandler(handler);
xmlReader.setLexicalHandler(handler);
return;
}
if (xmlDescriptor.hasInheritance()) {
unmarshalRecord.setAttributes(atts);
CoreAbstractSession session = unmarshalRecord.getSession();
Class> classValue = ((ObjectBuilder)xmlDescriptor.getObjectBuilder()).classFromRow(unmarshalRecord, session);
if (classValue == null) {
// no xsi:type attribute - look for type indicator on the default root element
XPathQName leafElementType = unmarshalRecord.getLeafElementType();
// if we have a user-set type, try to get the class from the inheritance policy
if (leafElementType != null) {
Object indicator = xmlDescriptor.getInheritancePolicy().getClassIndicatorMapping().get(leafElementType);
if(indicator != null) {
classValue = (Class)indicator;
}
}
// if xsi:type is overriden by JSON_TYPE_ATTRIBUTE_NAME unmarshall property
if (classValue == null && unmarshalRecord.getUnmarshaller().isApplicationJSON() &&
unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().getJsonTypeAttributeName() != null && atts.getValue(unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().getJsonTypeAttributeName()) != null) {
QName qname = new QName(xmlDescriptor.getSchemaReference().getSchemaContextAsQName().getNamespaceURI(), atts.getValue(unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().getJsonTypeAttributeName()));
classValue = (Class)xmlDescriptor.getInheritancePolicy().getClassIndicatorMapping().get(qname);
}
}
if (classValue != null) {
xmlDescriptor = (Descriptor)session.getDescriptor(classValue);
} else {
// since there is no xsi:type attribute, use the reference descriptor set
// on the mapping - make sure it is non-abstract
if (Modifier.isAbstract(xmlDescriptor.getJavaClass().getModifiers())) {
// need to throw an exception here
throw DescriptorException.missingClassIndicatorField(unmarshalRecord, (org.eclipse.persistence.oxm.XMLDescriptor)xmlDescriptor.getInheritancePolicy().getDescriptor());
}
}
}
ObjectBuilder targetObjectBuilder = (ObjectBuilder)xmlDescriptor.getObjectBuilder();
CoreAttributeGroup group = unmarshalRecord.getUnmarshalAttributeGroup();
CoreAttributeGroup nestedGroup = null;
if(group == XMLRecord.DEFAULT_ATTRIBUTE_GROUP) {
nestedGroup = group;
}
if(nestedGroup == null) {
CoreAttributeItem item = group.getItem(getMapping().getAttributeName());
nestedGroup = item.getGroup(xmlDescriptor.getJavaClass());
if(nestedGroup == null) {
if(item.getGroup() == null) {
nestedGroup = XMLRecord.DEFAULT_ATTRIBUTE_GROUP;
} else {
nestedGroup = item.getGroup();
}
}
}
UnmarshalRecord childRecord = unmarshalRecord.getChildUnmarshalRecord(targetObjectBuilder);
childRecord.setAttributes(atts);
childRecord.startDocument();
childRecord.initializeRecord(null);
childRecord.setUnmarshalAttributeGroup(nestedGroup);
childRecord.startElement(xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), xPathFragment.getShortName(), atts);
XMLReader xmlReader = unmarshalRecord.getXMLReader();
xmlReader.setContentHandler(childRecord);
xmlReader.setLexicalHandler(childRecord);
}
protected Descriptor findReferenceDescriptor(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts, Mapping mapping, UnmarshalKeepAsElementPolicy policy) {
Descriptor returnDescriptor = null;
//try xsi:type
if(atts != null){
Context xmlContext = unmarshalRecord.getUnmarshaller().getContext();
String schemaType = null;
if(unmarshalRecord.isNamespaceAware()){
schemaType = atts.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE);
}else{
schemaType = atts.getValue(Constants.EMPTY_STRING, Constants.SCHEMA_TYPE_ATTRIBUTE);
}
if(schemaType != null){
schemaType = schemaType.trim();
if(!schemaType.isEmpty()) {
XPathFragment frag = new XPathFragment(schemaType, unmarshalRecord.getNamespaceSeparator(), unmarshalRecord.isNamespaceAware());
QName qname = null;
if (frag.hasNamespace()) {
String prefix = frag.getPrefix();
String url = unmarshalRecord.resolveNamespacePrefix(prefix);
frag.setNamespaceURI(url);
qname = new QName(url, frag.getLocalName());
unmarshalRecord.setTypeQName(qname);
} else {
String url = unmarshalRecord.resolveNamespacePrefix(Constants.EMPTY_STRING);
if(null != url) {
frag.setNamespaceURI(url);
qname = new QName(url, frag.getLocalName());
unmarshalRecord.setTypeQName(qname);
}
if(!unmarshalRecord.isNamespaceAware() || !unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().useXsdTypesWithPrefix()){
qname = new QName(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI ,frag.getLocalName());
unmarshalRecord.setTypeQName(qname);
}
}
returnDescriptor = xmlContext.getDescriptorByGlobalType(frag);
if(returnDescriptor == null){
if(policy == null || (!policy.isKeepUnknownAsElement() && !policy.isKeepAllAsElement())){
Class