org.eclipse.persistence.internal.oxm.XMLRelationshipMappingNodeValue Maven / Gradle / Ivy
The newest version!
/*
* 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