blob: 248913d45f75826606da40b611d9dc0d1888be11 [file] [log] [blame]
/*
* 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.jaxb.compiler;
import java.awt.Image;
import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableSet;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeSet;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlMixed;
import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlValue;
import jakarta.xml.bind.annotation.adapters.CollapsedStringAdapter;
import jakarta.xml.bind.annotation.adapters.NormalizedStringAdapter;
import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.core.descriptors.CoreDescriptor;
import org.eclipse.persistence.core.mappings.CoreMapping;
import org.eclipse.persistence.core.mappings.converters.CoreConverter;
import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.core.sessions.CoreProject;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.InstantiationPolicy;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.VirtualAttributeAccessor;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.jaxb.AccessorFactoryWrapper;
import org.eclipse.persistence.internal.jaxb.CustomAccessorAttributeAccessor;
import org.eclipse.persistence.internal.jaxb.DefaultElementConverter;
import org.eclipse.persistence.internal.jaxb.DomHandlerConverter;
import org.eclipse.persistence.internal.jaxb.JAXBElementConverter;
import org.eclipse.persistence.internal.jaxb.JAXBElementRootConverter;
import org.eclipse.persistence.internal.jaxb.JAXBSetMethodAttributeAccessor;
import org.eclipse.persistence.internal.jaxb.JaxbClassLoader;
import org.eclipse.persistence.internal.jaxb.MultiArgInstantiationPolicy;
import org.eclipse.persistence.internal.jaxb.WrappedValue;
import org.eclipse.persistence.internal.jaxb.XMLJavaTypeConverter;
import org.eclipse.persistence.internal.jaxb.many.JAXBArrayAttributeAccessor;
import org.eclipse.persistence.internal.jaxb.many.ManyValue;
import org.eclipse.persistence.internal.jaxb.many.MapValue;
import org.eclipse.persistence.internal.jaxb.many.MapValueAttributeAccessor;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkASMClassWriter;
import org.eclipse.persistence.internal.libraries.asm.MethodVisitor;
import org.eclipse.persistence.internal.libraries.asm.Opcodes;
import org.eclipse.persistence.internal.libraries.asm.Type;
import org.eclipse.persistence.internal.localization.JAXBLocalization;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.mappings.AnyAttributeMapping;
import org.eclipse.persistence.internal.oxm.mappings.AnyCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.AnyObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.CollectionReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.DirectCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.InverseReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.TransformationMapping;
import org.eclipse.persistence.internal.oxm.mappings.VariableXPathCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.VariableXPathObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.XMLContainerMapping;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.oxm.record.XMLTransformationRecord;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jaxb.JAXBEnumTypeConverter;
import org.eclipse.persistence.jaxb.TypeMappingInfo;
import org.eclipse.persistence.jaxb.javamodel.Helper;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaField;
import org.eclipse.persistence.jaxb.javamodel.JavaMethod;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAbstractNullPolicy;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper;
import org.eclipse.persistence.jaxb.xmlmodel.XmlIsSetNullPolicy;
import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter;
import org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode;
import org.eclipse.persistence.jaxb.xmlmodel.XmlNamedAttributeNode;
import org.eclipse.persistence.jaxb.xmlmodel.XmlNamedObjectGraph;
import org.eclipse.persistence.jaxb.xmlmodel.XmlNamedSubgraph;
import org.eclipse.persistence.jaxb.xmlmodel.XmlNullPolicy;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlReadTransformer;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlWriteTransformer;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.mappings.FixedMimeTypePolicy;
import org.eclipse.persistence.oxm.mappings.MimeTypePolicy;
import org.eclipse.persistence.oxm.mappings.UnmarshalKeepAsElementPolicy;
import org.eclipse.persistence.oxm.mappings.XMLAnyAttributeMapping;
import org.eclipse.persistence.oxm.mappings.XMLAnyCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLAnyObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLBinaryDataCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLBinaryDataMapping;
import org.eclipse.persistence.oxm.mappings.XMLChoiceCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLChoiceObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLCollectionReferenceMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.oxm.mappings.XMLInverseReferenceMapping;
import org.eclipse.persistence.oxm.mappings.XMLMapping;
import org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping;
import org.eclipse.persistence.oxm.mappings.XMLTransformationMapping;
import org.eclipse.persistence.oxm.mappings.XMLVariableXPathCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLVariableXPathObjectMapping;
import org.eclipse.persistence.oxm.mappings.converters.XMLConverter;
import org.eclipse.persistence.oxm.mappings.converters.XMLListConverter;
import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.oxm.mappings.nullpolicy.IsSetNullPolicy;
import org.eclipse.persistence.oxm.mappings.nullpolicy.NullPolicy;
import org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.oxm.schema.XMLSchemaClassPathReference;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.Session;
/**
* INTERNAL:
* <p><b>Purpose:</b>To generate a TopLink OXM Project based on Java Class and TypeInfo information
* <p><b>Responsibilities:</b><ul>
* <li>Generate a XMLDescriptor for each TypeInfo object</li>
* <li>Generate a mapping for each TypeProperty object</li>
* <li>Determine the correct mapping type based on the type of each property</li>
* <li>Set up Converters on mappings for XmlAdapters or JDK 1.5 Enumeration types.</li>
* </ul>
* <p>This class is invoked by a Generator in order to create a TopLink Project.
* This is generally used by JAXBContextFactory to create the runtime project. A Descriptor will
* be generated for each TypeInfo and Mappings generated for each Property. In the case that a
* non-transient property's type is a user defined class, a Descriptor and Mappings will be generated
* for that class as well.
* @see org.eclipse.persistence.jaxb.compiler.Generator
* @see org.eclipse.persistence.jaxb.compiler.TypeInfo
* @see org.eclipse.persistence.jaxb.compiler.Property
* @author mmacivor
* @since Oracle TopLink 11.1.1.0.0
*
*/
public class MappingsGenerator {
private static final String ATT = "@";
private static final String TXT = "/text()";
private static String OBJECT_CLASS_NAME = "java.lang.Object";
public static final QName RESERVED_QNAME = new QName("urn:ECLIPSELINK_RESERVEDURI", "RESERVEDNAME");
String outputDir = ".";
private Map<String, QName> userDefinedSchemaTypes;
private Helper helper;
private JavaClass jotArrayList;
private JavaClass jotHashSet;
private JavaClass jotHashMap;
private JavaClass jotLinkedList;
private JavaClass jotTreeSet;
private Map<String, PackageInfo> packageToPackageInfoMappings;
private Map<String, TypeInfo> typeInfo;
private Map<QName, Class<?>> qNamesToGeneratedClasses;
private Map<String, Class<?>> classToGeneratedClasses;
private Map<QName, Class<?>> qNamesToDeclaredClasses;
private Map<QName, ElementDeclaration> globalElements;
private List<ElementDeclaration> localElements;
private Map<TypeMappingInfo, Class<?>> typeMappingInfoToGeneratedClasses;
private Map<MapEntryGeneratedKey, Class<?>> generatedMapEntryClasses;
private CoreProject project;
private org.eclipse.persistence.oxm.NamespaceResolver globalNamespaceResolver;
private boolean isDefaultNamespaceAllowed;
private Map<TypeMappingInfo, Class<?>>typeMappingInfoToAdapterClasses;
public MappingsGenerator(Helper helper) {
this.helper = helper;
jotArrayList = helper.getJavaClass(ArrayList.class);
jotHashSet = helper.getJavaClass(HashSet.class);
jotHashMap = helper.getJavaClass(HashMap.class);
jotLinkedList = helper.getJavaClass(LinkedList.class);
jotTreeSet = helper.getJavaClass(TreeSet.class);
qNamesToGeneratedClasses = new HashMap<>();
qNamesToDeclaredClasses = new HashMap<>();
classToGeneratedClasses = new HashMap<>();
globalNamespaceResolver = new org.eclipse.persistence.oxm.NamespaceResolver();
isDefaultNamespaceAllowed = true;
}
public CoreProject generateProject(List<JavaClass> typeInfoClasses, Map<String, TypeInfo> typeInfo, Map<String, QName> userDefinedSchemaTypes, Map<String, PackageInfo> packageToPackageInfoMappings, Map<QName, ElementDeclaration> globalElements, List<ElementDeclaration> localElements, Map<TypeMappingInfo, Class<?>> typeMappingInfoToGeneratedClass, Map<TypeMappingInfo, Class<?>> typeMappingInfoToAdapterClasses, boolean isDefaultNamespaceAllowed) throws Exception {
this.typeInfo = typeInfo;
this.userDefinedSchemaTypes = userDefinedSchemaTypes;
this.packageToPackageInfoMappings = packageToPackageInfoMappings;
this.isDefaultNamespaceAllowed = isDefaultNamespaceAllowed;
this.globalElements = globalElements;
this.localElements = localElements;
this.typeMappingInfoToGeneratedClasses = typeMappingInfoToGeneratedClass;
this.typeMappingInfoToAdapterClasses = typeMappingInfoToAdapterClasses;
project = new Project();
processDefaultNamespacePreferences(packageToPackageInfoMappings.values());
// Generate descriptors
for (JavaClass next : typeInfoClasses) {
if (!next.isEnum()) {
generateDescriptor(next, project);
}
}
// Setup inheritance
for (JavaClass next : typeInfoClasses) {
if (!next.isEnum()) {
setupInheritance(next);
}
}
// Now create mappings
generateMappings();
// Setup AttributeGroups
for(JavaClass next : typeInfoClasses) {
setupAttributeGroups(next);
}
// apply customizers if necessary
Set<Entry<String, TypeInfo>> entrySet = this.typeInfo.entrySet();
for (Entry<String, TypeInfo> entry : entrySet) {
TypeInfo tInfo = entry.getValue();
if (tInfo.getXmlCustomizer() != null) {
String customizerClassName = tInfo.getXmlCustomizer();
try {
Class<? extends DescriptorCustomizer> customizerClass = PrivilegedAccessHelper.getClassForName(customizerClassName, true, helper.getClassLoader());
DescriptorCustomizer descriptorCustomizer = PrivilegedAccessHelper.newInstanceFromClass(customizerClass);
descriptorCustomizer.customize((XMLDescriptor)tInfo.getDescriptor());
} catch (ClassCastException cce) {
throw JAXBException.invalidCustomizerClass(cce, customizerClassName);
} catch (ReflectiveOperationException roe) {
throw JAXBException.couldNotCreateCustomizerInstance(roe, customizerClassName);
}
}
}
processGlobalElements(project);
return project;
}
private void setupAttributeGroups(JavaClass javaClass) {
TypeInfo info = this.typeInfo.get(javaClass.getQualifiedName());
XMLDescriptor descriptor = (XMLDescriptor)info.getDescriptor();
if(!info.getObjectGraphs().isEmpty()) {
for(XmlNamedObjectGraph next:info.getObjectGraphs()) {
AttributeGroup group = descriptor.getAttributeGroup(next.getName());
Map<String, List<CoreAttributeGroup>> subgraphs = processSubgraphs(next.getXmlNamedSubgraph());
for(XmlNamedAttributeNode nextAttributeNode:next.getXmlNamedAttributeNode()) {
if(nextAttributeNode.getSubgraph() == null || nextAttributeNode.getSubgraph().length() == 0) {
group.addAttribute(nextAttributeNode.getName());
} else {
List<CoreAttributeGroup> nestedGroups = subgraphs.get(nextAttributeNode.getSubgraph());
if(nestedGroups == null || nestedGroups.isEmpty()) {
Property property = info.getProperties().get(nextAttributeNode.getName());
if(property == null) {
//if there's no property associated with the attributeNode, just ignore it
continue;
}
JavaClass cls = property.getActualType();
TypeInfo referenceType = typeInfo.get(cls.getQualifiedName());
if(referenceType != null) {
AttributeGroup targetGroup = (AttributeGroup)referenceType.getDescriptor().getAttributeGroup(nextAttributeNode.getSubgraph());
group.addAttribute(nextAttributeNode.getName(), targetGroup);
} else {
//TODO: Exception
}
} else {
if(nestedGroups.size() == 1) {
group.addAttribute(nextAttributeNode.getName(), nestedGroups.get(0));
} else {
group.addAttribute(nextAttributeNode.getName(), nestedGroups);
}
}
}
}
for(XmlNamedSubgraph nextSubclass:next.getXmlNamedSubclassGraph()) {
AttributeGroup subclassGroup = new AttributeGroup(next.getName(), nextSubclass.getType(), true);
group.getSubClassGroups().put(nextSubclass.getType(), subclassGroup);
for(XmlNamedAttributeNode nextAttributeNode:nextSubclass.getXmlNamedAttributeNode()) {
if(nextAttributeNode.getSubgraph() == null || nextAttributeNode.getSubgraph().length() == 0) {
subclassGroup.addAttribute(nextAttributeNode.getName());
} else {
List<CoreAttributeGroup> nestedGroups = subgraphs.get(nextAttributeNode.getSubgraph());
if(nestedGroups == null || nestedGroups.isEmpty()) {
Property property = info.getProperties().get(nextAttributeNode.getName());
JavaClass cls = property.getActualType();
TypeInfo referenceType = typeInfo.get(cls.getQualifiedName());
if(referenceType != null) {
AttributeGroup targetGroup = (AttributeGroup)referenceType.getDescriptor().getAttributeGroup(nextAttributeNode.getSubgraph());
subclassGroup.addAttribute(nextAttributeNode.getName(), targetGroup);
} else {
//TODO: Exception
}
} else {
if(nestedGroups.size() == 1) {
subclassGroup.addAttribute(nextAttributeNode.getName(), nestedGroups.get(0));
} else {
subclassGroup.addAttribute(nextAttributeNode.getName(), nestedGroups);
}
}
}
}
}
}
}
}
private Map<String, List<CoreAttributeGroup>> processSubgraphs(List<XmlNamedSubgraph> subgraphs) {
Map<String, List<CoreAttributeGroup>> subgroups = new HashMap<>();
//Iterate through once and create all the AttributeGroups
for(XmlNamedSubgraph next: subgraphs) {
String type = next.getType();
if(type == null) {
type = "java.lang.Object";
}
AttributeGroup group = new AttributeGroup(next.getName(), type, false);
if(subgroups.containsKey(group.getName())) {
List<CoreAttributeGroup> groups = subgroups.get(group.getName());
groups.add(group);
} else {
List<CoreAttributeGroup> groups = new ArrayList<>(1);
groups.add(group);
subgroups.put(group.getName(), groups);
}
}
//Iterate through a second time to populate the groups and set up links.
for(XmlNamedSubgraph next:subgraphs) {
List<XmlNamedAttributeNode> attributeNodes = next.getXmlNamedAttributeNode();
List<CoreAttributeGroup> attributeGroups = subgroups.get(next.getName());
if(attributeGroups != null) {
for(CoreAttributeGroup group:attributeGroups) {
String typeName = next.getType();
if(typeName == null) {
typeName = "java.lang.Object";
}
if(group.getTypeName().equals(typeName)) {
for(XmlNamedAttributeNode attributeNode:attributeNodes) {
if(attributeNode.getSubgraph() == null || attributeNode.getSubgraph().length() == 0) {
group.addAttribute(attributeNode.getName());
} else {
List<CoreAttributeGroup> nestedGroups = subgroups.get(attributeNode.getSubgraph());
if(nestedGroups == null || nestedGroups.size() == 0) {
//TODO: Exception or check for root level ones on target class
} else {
group.addAttribute(attributeNode.getName(), nestedGroups.get(0));
}
}
}
}
}
}
}
return subgroups;
}
public void generateDescriptor(JavaClass javaClass, CoreProject project) {
String jClassName = javaClass.getQualifiedName();
TypeInfo info = typeInfo.get(jClassName);
if (info.isTransient()){
return;
}
NamespaceInfo namespaceInfo = this.packageToPackageInfoMappings.get(javaClass.getPackageName()).getNamespaceInfo();
String packageNamespace = namespaceInfo.getNamespace();
String elementName;
String namespace;
if (javaClass.getSuperclass() != null && javaClass.getSuperclass().getName().equals("jakarta.xml.bind.JAXBElement")) {
generateDescriptorForJAXBElementSubclass(javaClass, project, getNamespaceResolverForDescriptor(namespaceInfo));
return;
}
Descriptor descriptor = new XMLDescriptor();
org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement rootElem = info.getXmlRootElement();
if (rootElem == null) {
try{
elementName = info.getXmlNameTransformer().transformRootElementName(javaClass.getName());
}catch (Exception ex){
throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(javaClass.getName(), info.getXmlNameTransformer().getClass().getName(), ex);
}
namespace = packageNamespace;
} else {
elementName = rootElem.getName();
if (elementName.equals(XMLProcessor.DEFAULT)) {
try{
elementName = info.getXmlNameTransformer().transformRootElementName(javaClass.getName());
}catch (Exception ex){
throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(javaClass.getName(), info.getXmlNameTransformer().getClass().getName(), ex);
}
}
namespace = rootElem.getNamespace();
}
descriptor.setJavaClassName(jClassName);
if (info.getFactoryMethodName() != null) {
descriptor.getInstantiationPolicy().useFactoryInstantiationPolicy(info.getObjectFactoryClassName(), info.getFactoryMethodName());
}
if (namespace.equals(XMLProcessor.DEFAULT)) {
namespace = namespaceInfo.getNamespace();
}
NamespaceResolver resolverForDescriptor = getNamespaceResolverForDescriptor(namespaceInfo);
JavaClass manyValueJavaClass = helper.getJavaClass(ManyValue.class);
if (!manyValueJavaClass.isAssignableFrom(javaClass)){
if(isDefaultNamespaceAllowed
&& namespace.length() != 0
&& globalNamespaceResolver.getDefaultNamespaceURI() == null
&& !resolverForDescriptor.getPrefixesToNamespaces().containsValue(namespace)) {
globalNamespaceResolver.setDefaultNamespaceURI(namespace);
resolverForDescriptor.setDefaultNamespaceURI(namespace);
}
if (rootElem == null) {
descriptor.setDefaultRootElement("");
} else {
if (namespace.length() == 0) {
descriptor.setDefaultRootElement(elementName);
} else {
descriptor.setDefaultRootElement(getQualifiedString(getPrefixForNamespace(namespace, resolverForDescriptor), elementName));
}
}
}
descriptor.setNamespaceResolver(resolverForDescriptor);
setSchemaContext(descriptor, info);
// set the ClassExtractor class name if necessary
if (info.isSetClassExtractorName()) {
descriptor.getInheritancePolicy().setClassExtractorName(info.getClassExtractorName());
}
// set any user-defined properties
if (info.getUserProperties() != null) {
descriptor.setProperties(info.getUserProperties());
}
if (info.isLocationAware()) {
Property locProp = null;
Iterator<Property> i = info.getPropertyList().iterator();
while (i.hasNext()) {
Property p = i.next();
if (p.getType().getName().equals(Constants.LOCATOR_CLASS_NAME)) {
locProp = p;
}
}
if (locProp != null && locProp.isTransient()) {
// build accessor
// don't make a mapping
if (locProp.isMethodProperty()) {
MethodAttributeAccessor aa = new MethodAttributeAccessor();
aa.setAttributeName(locProp.getPropertyName());
aa.setSetMethodName(locProp.getSetMethodName());
aa.setGetMethodName(locProp.getGetMethodName());
descriptor.setLocationAccessor(aa);
} else {
// instance variable property
InstanceVariableAttributeAccessor aa = new InstanceVariableAttributeAccessor();
aa.setAttributeName(locProp.getPropertyName());
descriptor.setLocationAccessor(aa);
}
}
}
if(!info.getObjectGraphs().isEmpty()) {
//create attribute groups for each object graph.
//these will be populated later to allow for linking
for(XmlNamedObjectGraph next:info.getObjectGraphs()) {
AttributeGroup attributeGroup = new AttributeGroup(next.getName(), info.getJavaClassName(), false);
((XMLDescriptor)descriptor).addAttributeGroup(attributeGroup);
//process subclass graphs for inheritance
//for(NamedSubgraph nextSubclass:next.getNamedSubclassGraph()) {
//attributeGroup.insertSubClass(new AttributeGroup(next.getName(), nextSubclass.getType()));
//}
}
}
project.addDescriptor((CoreDescriptor)descriptor);
info.setDescriptor(descriptor);
}
public void generateDescriptorForJAXBElementSubclass(JavaClass javaClass, CoreProject project, NamespaceResolver nsr) {
String jClassName = javaClass.getQualifiedName();
TypeInfo info = typeInfo.get(jClassName);
Descriptor xmlDescriptor = new XMLDescriptor();
xmlDescriptor.setJavaClassName(jClassName);
String[] factoryMethodParamTypes = info.getFactoryMethodParamTypes();
MultiArgInstantiationPolicy policy = new MultiArgInstantiationPolicy();
policy.useFactoryInstantiationPolicy(info.getObjectFactoryClassName(), info.getFactoryMethodName());
policy.setParameterTypeNames(factoryMethodParamTypes);
policy.setDefaultValues(new String[]{null});
xmlDescriptor.setInstantiationPolicy(policy);
JavaClass paramClass = helper.getJavaClass(factoryMethodParamTypes[0]);
boolean isObject = paramClass.getName().equals("java.lang.Object");
if(helper.isBuiltInJavaType(paramClass) && !isObject ){
if(isBinaryData(paramClass)){
BinaryDataMapping mapping = new XMLBinaryDataMapping();
mapping.setAttributeName("value");
mapping.setXPath(".");
((Field)mapping.getField()).setSchemaType(Constants.BASE_64_BINARY_QNAME);
mapping.setSetMethodName("setValue");
mapping.setGetMethodName("getValue");
Class<?> attributeClassification = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(factoryMethodParamTypes[0], helper.getClassLoader());
mapping.setAttributeClassification(attributeClassification);
mapping.getNullPolicy().setNullRepresentedByEmptyNode(false);
mapping.setShouldInlineBinaryData(false);
if(mapping.getMimeType() == null) {
if(areEquals(paramClass, javax.xml.transform.Source.class)) {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy("application/xml"));
} else {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy("application/octet-stream"));
}
}
xmlDescriptor.addMapping((CoreMapping)mapping);
} else {
DirectMapping mapping = new XMLDirectMapping();
mapping.setNullValueMarshalled(true);
mapping.setAttributeName("value");
mapping.setGetMethodName("getValue");
mapping.setSetMethodName("setValue");
mapping.setXPath("text()");
Class<?> attributeClassification = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(factoryMethodParamTypes[0], helper.getClassLoader());
mapping.setAttributeClassification(attributeClassification);
xmlDescriptor.addMapping((CoreMapping)mapping);
}
}else if(paramClass.isEnum()){
EnumTypeInfo enumInfo = (EnumTypeInfo)typeInfo.get(paramClass.getQualifiedName());
DirectMapping mapping = new XMLDirectMapping();
mapping.setConverter(buildJAXBEnumTypeConverter(mapping, enumInfo));
mapping.setNullValueMarshalled(true);
mapping.setAttributeName("value");
mapping.setGetMethodName("getValue");
mapping.setSetMethodName("setValue");
mapping.setXPath("text()");
Class<?> attributeClassification = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(factoryMethodParamTypes[0], helper.getClassLoader());
mapping.setAttributeClassification(attributeClassification);
xmlDescriptor.addMapping((CoreMapping)mapping);
}else{
CompositeObjectMapping mapping = new XMLCompositeObjectMapping();
mapping.setAttributeName("value");
mapping.setGetMethodName("getValue");
mapping.setSetMethodName("setValue");
mapping.setXPath(".");
if(isObject){
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
}else{
mapping.setReferenceClassName(factoryMethodParamTypes[0]);
}
xmlDescriptor.addMapping((CoreMapping)mapping);
}
xmlDescriptor.setNamespaceResolver(nsr);
setSchemaContext(xmlDescriptor, info);
project.addDescriptor((CoreDescriptor)xmlDescriptor);
info.setDescriptor(xmlDescriptor);
}
private void setSchemaContext(Descriptor desc, TypeInfo info) {
XMLSchemaClassPathReference schemaRef = new XMLSchemaClassPathReference();
if (info.getClassNamespace() == null || info.getClassNamespace().equals("")) {
schemaRef.setSchemaContext("/" + info.getSchemaTypeName());
schemaRef.setSchemaContextAsQName(new QName(info.getSchemaTypeName()));
} else {
String prefix = desc.getNonNullNamespaceResolver().resolveNamespaceURI(info.getClassNamespace());
if (prefix != null && !prefix.equals("")) {
schemaRef.setSchemaContext("/" + prefix + ":" + info.getSchemaTypeName());
schemaRef.setSchemaContextAsQName(new QName(info.getClassNamespace(), info.getSchemaTypeName(), prefix));
} else {
String generatedPrefix =getPrefixForNamespace(info.getClassNamespace(), desc.getNonNullNamespaceResolver(), false);
schemaRef.setSchemaContext("/" + getQualifiedString(generatedPrefix, info.getSchemaTypeName()));
if(generatedPrefix == null || generatedPrefix.equals(Constants.EMPTY_STRING)){
schemaRef.setSchemaContextAsQName(new QName(info.getClassNamespace(), info.getSchemaTypeName()));
}else{
schemaRef.setSchemaContextAsQName(new QName(info.getClassNamespace(), info.getSchemaTypeName(), generatedPrefix));
}
}
}
// the default type is complex; need to check for simple type case
if (info.isEnumerationType() || (info.getPropertyNames().size() == 1 && helper.isAnnotationPresent(info.getProperties().get(info.getPropertyNames().get(0)).getElement(), XmlValue.class))) {
schemaRef.setType(XMLSchemaReference.SIMPLE_TYPE);
}
desc.setSchemaReference(schemaRef);
}
/**
* Generate a mapping for a given Property.
*
* @return newly created mapping
*/
public Mapping generateMapping(Property property, Descriptor descriptor, JavaClass descriptorJavaClass, NamespaceInfo namespaceInfo) {
if (property.isSetXmlJavaTypeAdapter()) {
// if we are dealing with a reference, generate mapping and return
if (property.isReference()) {
return generateMappingForReferenceProperty(property, descriptor, namespaceInfo);
}
XmlJavaTypeAdapter xja = property.getXmlJavaTypeAdapter();
JavaClass adapterClass = helper.getJavaClass(xja.getValue());
JavaClass valueType = null;
String sValType = xja.getValueType();
if (sValType.equals("jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter.DEFAULT")) {
valueType = property.getActualType();
} else {
valueType = helper.getJavaClass(xja.getValueType());
}
Mapping mapping;
boolean isArray = property.getType().isArray() && !property.getType().getRawName().equals("byte[]");
// if the value type is something we have a descriptor for, create
// a composite mapping
if(property.isChoice()) {
if(helper.isCollectionType(property.getType()) || property.getType().isArray()) {
mapping = generateChoiceCollectionMapping(property, descriptor, namespaceInfo);
((ChoiceCollectionMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
} else {
mapping = generateChoiceMapping(property, descriptor, namespaceInfo);
((ChoiceObjectMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
} else if (typeInfo.containsKey(valueType.getQualifiedName())) {
TypeInfo reference = typeInfo.get(valueType.getQualifiedName());
if (helper.isCollectionType(property.getType())) {
if (reference.isEnumerationType()) {
mapping = generateEnumCollectionMapping(property, descriptor, namespaceInfo, (EnumTypeInfo) reference);
XMLJavaTypeConverter converter = new XMLJavaTypeConverter(adapterClass.getQualifiedName());
converter.setNestedConverter(((DirectCollectionMapping)mapping).getValueConverter());
((DirectCollectionMapping)mapping).setValueConverter(converter);
} else {
if(property.getVariableAttributeName() !=null){
mapping = generateVariableXPathCollectionMapping(property, descriptor, namespaceInfo, valueType);
((VariableXPathCollectionMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}else{
mapping = generateCompositeCollectionMapping(property, descriptor, descriptorJavaClass, namespaceInfo, valueType.getQualifiedName());
((CompositeCollectionMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
}
} else {
if (reference.isEnumerationType()) {
mapping = generateDirectEnumerationMapping(property, descriptor, namespaceInfo, (EnumTypeInfo) reference);
XMLJavaTypeConverter converter = new XMLJavaTypeConverter(adapterClass.getQualifiedName());
converter.setNestedConverter(((DirectMapping)mapping).getConverter());
((DirectMapping)mapping).setConverter(converter);
} else if (property.isInverseReference()) {
mapping = generateInverseReferenceMapping(property, descriptor, namespaceInfo);
} else {
if(property.getVariableAttributeName() !=null){
mapping = generateVariableXPathObjectMapping(property, descriptor, namespaceInfo, valueType);
((VariableXPathObjectMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}else{
mapping = generateCompositeObjectMapping(property, descriptor, namespaceInfo, valueType.getQualifiedName());
((CompositeObjectMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
}
}
} else {
// no descriptor for value type
if (property.isAny()) {
if (helper.isCollectionType(property.getType())){
mapping = generateAnyCollectionMapping(property, descriptor, namespaceInfo, property.isMixedContent());
((AnyCollectionMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
} else {
mapping = generateAnyObjectMapping(property, descriptor, namespaceInfo);
((AnyObjectMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
} else if (helper.isCollectionType(property.getType()) || isArray) {
if (property.isSwaAttachmentRef() || property.isMtomAttachment()) {
mapping = generateBinaryDataCollectionMapping(property, descriptor, namespaceInfo);
((BinaryDataCollectionMapping) mapping).setValueConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
} else{
mapping = generateDirectCollectionMapping(property, descriptor, namespaceInfo);
if(adapterClass.getQualifiedName().equals(CollapsedStringAdapter.class.getName())) {
((DirectCollectionMapping)mapping).setCollapsingStringValues(true);
} else if(adapterClass.getQualifiedName().equals(NormalizedStringAdapter.class.getName())) {
((DirectCollectionMapping)mapping).setNormalizingStringValues(true);
} else {
((DirectCollectionMapping) mapping).setValueConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
}
} else if (property.isSwaAttachmentRef() || property.isMtomAttachment()) {
mapping = generateBinaryMapping(property, descriptor, namespaceInfo);
((BinaryDataMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
} else {
if (!property.isAttribute() && areEquals(valueType, Object.class) || property.isTyped()){
mapping = generateCompositeObjectMapping(property, descriptor, namespaceInfo, null);
((CompositeObjectMapping)mapping).setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
((CompositeObjectMapping)mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
return mapping;
}
mapping = generateDirectMapping(property, descriptor, namespaceInfo);
if(adapterClass.getQualifiedName().equals(CollapsedStringAdapter.class.getName())) {
((DirectMapping)mapping).setCollapsingStringValues(true);
} else if(adapterClass.getQualifiedName().equals(NormalizedStringAdapter.class.getName())) {
((DirectMapping)mapping).setNormalizingStringValues(true);
} else {
((DirectMapping) mapping).setConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
}
}
return mapping;
}
if (property.getVariableAttributeName() != null){
if (helper.isCollectionType(property.getType()) || property.getType().isArray() || property.isMap()){
return generateVariableXPathCollectionMapping(property, descriptor, namespaceInfo, property.getActualType());
}else{
return generateVariableXPathObjectMapping(property, descriptor, namespaceInfo, property.getActualType());
}
}
if (property.isSetXmlJoinNodes()) {
if (helper.isCollectionType(property.getType())) {
return generateXMLCollectionReferenceMapping(property, descriptor, namespaceInfo, property.getActualType());
}
return generateXMLObjectReferenceMapping(property, descriptor, namespaceInfo, property.getType());
}
if (property.isXmlTransformation()) {
return generateTransformationMapping(property, descriptor, namespaceInfo);
}
if (property.isChoice()) {
if (helper.isCollectionType(property.getType()) || property.getType().isArray()) {
return generateChoiceCollectionMapping(property, descriptor, namespaceInfo);
}
return generateChoiceMapping(property, descriptor, namespaceInfo);
}
if (property.isInverseReference()) {
return generateInverseReferenceMapping(property, descriptor, namespaceInfo);
}
if (property.isReference()) {
return generateMappingForReferenceProperty(property, descriptor, namespaceInfo);
}
if (property.isAny()) {
if (helper.isCollectionType(property.getType()) || property.getType().isArray()){
return generateAnyCollectionMapping(property, descriptor, namespaceInfo, property.isMixedContent());
}
return generateAnyObjectMapping(property, descriptor, namespaceInfo);
}
if (property.isMap()){
if (property.isAnyAttribute()) {
return generateAnyAttributeMapping(property, descriptor, namespaceInfo);
}
return generateCompositeCollectionMapping(property, descriptor, descriptorJavaClass, namespaceInfo, null);
}
if (helper.isCollectionType(property.getType())) {
return generateCollectionMapping(property, descriptor, descriptorJavaClass, namespaceInfo);
}
JavaClass referenceClass = property.getType();
String referenceClassName = referenceClass.getRawName();
if (referenceClass.isArray() && !referenceClassName.equals("byte[]")){
JavaClass componentType = referenceClass.getComponentType();
TypeInfo reference = typeInfo.get(componentType.getName());
if (reference != null && reference.isEnumerationType()) {
return generateEnumCollectionMapping(property, descriptor, namespaceInfo,(EnumTypeInfo) reference);
}
if (areEquals(componentType, Object.class)){
CompositeCollectionMapping mapping = generateCompositeCollectionMapping(property, descriptor, descriptorJavaClass, namespaceInfo, null);
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
return mapping;
}
if (reference != null || componentType.isArray()){
if (property.isXmlIdRef() || property.isSetXmlJoinNodes()) {
return generateXMLCollectionReferenceMapping(property, descriptor, namespaceInfo, componentType);
}
return generateCompositeCollectionMapping(property, descriptor, descriptorJavaClass, namespaceInfo, componentType.getQualifiedName());
}
return generateDirectCollectionMapping(property, descriptor, namespaceInfo);
}
if (property.isXmlIdRef()) {
return generateXMLObjectReferenceMapping(property, descriptor, namespaceInfo, referenceClass);
}
TypeInfo reference = typeInfo.get(referenceClass.getQualifiedName());
if (reference != null) {
if (reference.isEnumerationType()) {
return generateDirectEnumerationMapping(property, descriptor, namespaceInfo, (EnumTypeInfo) reference);
}
if (property.isXmlLocation()) {
CompositeObjectMapping locationMapping = generateCompositeObjectMapping(property, descriptor, namespaceInfo, referenceClass.getQualifiedName());
reference.getDescriptor().setInstantiationPolicy(new NullInstantiationPolicy());
descriptor.setLocationAccessor(locationMapping.getAttributeAccessor());
return locationMapping;
} else {
return generateCompositeObjectMapping(property, descriptor, namespaceInfo, referenceClass.getQualifiedName());
}
}
if (property.isSwaAttachmentRef() || property.isMtomAttachment()) {
return generateBinaryMapping(property, descriptor, namespaceInfo);
}
if (referenceClass.getQualifiedName().equals(OBJECT_CLASS_NAME) && !property.isAttribute() || property.isTyped() ) {
CompositeObjectMapping coMapping = generateCompositeObjectMapping(property, descriptor, namespaceInfo, null);
coMapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
return coMapping;
}
if (property.isXmlLocation()) {
return null;
}
return generateDirectMapping(property, descriptor, namespaceInfo);
}
private Mapping generateVariableXPathCollectionMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, JavaClass actualType) {
XMLVariableXPathCollectionMapping mapping = new XMLVariableXPathCollectionMapping();
mapping.setAttributeName(property.getPropertyName());
if(property.isMap()){
actualType = property.getValueType();
}
initializeXMLContainerMapping(mapping, property.getType().isArray());
initializeXMLMapping(mapping, property);
initializeVariableXPathMapping(mapping, property, actualType);
if (property.getXmlPath() != null) {
mapping.setField(new XMLField(property.getXmlPath()));
} else {
if (property.isSetXmlElementWrapper()) {
mapping.setField((XMLField)getXPathForField(property, namespaceInfo, false, true));
}
}
if (property.isSetXmlElementWrapper()) {
mapping.setWrapperNullPolicy(getWrapperNullPolicyFromProperty(property));
}
JavaClass collectionType = property.getType();
if (collectionType.isArray()){
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), helper.getClassLoader());
JavaClass componentType = collectionType.getComponentType();
if(componentType.isArray()) {
JavaClass baseComponentType = getBaseComponentType(componentType);
if (baseComponentType.isPrimitive()){
Class<Object> primitiveClass = XMLConversionManager.getDefaultManager().convertClassNameToClass(baseComponentType.getRawName());
accessor.setComponentClass(primitiveClass);
} else {
accessor.setComponentClassName(baseComponentType.getQualifiedName());
}
} else {
accessor.setComponentClassName(componentType.getQualifiedName());
}
mapping.setAttributeAccessor(accessor);
}
if(property.isMap()){
JavaClass mapType = property.getType();
if(mapType.isInterface()){
mapping.useMapClass("java.util.HashMap");
}else{
mapping.useMapClass(property.getType().getName());
}
}else{
collectionType = containerClassImpl(collectionType);
mapping.useCollectionClass(helper.getClassForJavaClass(collectionType));
}
return mapping;
}
private Mapping generateVariableXPathObjectMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, JavaClass actualType) {
XMLVariableXPathObjectMapping mapping = new XMLVariableXPathObjectMapping();
initializeXMLMapping(mapping, property);
initializeVariableXPathMapping(mapping, property, actualType);
// handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else {
NullPolicy nullPolicy = (NullPolicy) mapping.getNullPolicy();
nullPolicy.setSetPerformedForAbsentNode(false);
if(property.isNillable()) {
nullPolicy.setNullRepresentedByXsiNil(true);
nullPolicy.setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
}
if (property.getXmlPath() != null) {
mapping.setField(new XMLField(property.getXmlPath()));
} else {
if (property.isSetXmlElementWrapper()) {
mapping.setField((XMLField)getXPathForField(property, namespaceInfo, false, true));
}
}
return mapping;
}
private void initializeVariableXPathMapping(VariableXPathObjectMapping mapping, Property property, JavaClass actualType){
String variableAttributeName = property.getVariableAttributeName();
TypeInfo refInfo = typeInfo.get(actualType.getName());
if(refInfo == null){
throw JAXBException.unknownTypeForVariableNode(actualType.getName());
}
Property refProperty = refInfo.getProperties().get(variableAttributeName);
while(refProperty == null){
JavaClass superClass = CompilerHelper.getNextMappedSuperClass(actualType, typeInfo, helper);
if (superClass != null){
refInfo = typeInfo.get(superClass.getName());
refProperty = refInfo.getProperties().get(variableAttributeName);
}else{
break;
}
}
if(refProperty == null){
throw JAXBException.unknownPropertyForVariableNode(variableAttributeName, actualType.getName());
}
String refPropertyType = refProperty.getActualType().getQualifiedName();
if(!(refPropertyType.equals("java.lang.String") || refPropertyType.equals("javax.xml.namespace.QName"))){
throw JAXBException.invalidTypeForVariableNode(variableAttributeName, refPropertyType, actualType.getName());
}
if (refProperty.isMethodProperty()) {
if (refProperty.getGetMethodName() == null) {
// handle case of set with no get method
String paramTypeAsString = refProperty.getType().getName();
JAXBSetMethodAttributeAccessor accessor = new JAXBSetMethodAttributeAccessor(paramTypeAsString, helper.getClassLoader());
accessor.setIsReadOnly(true);
accessor.setSetMethodName(refProperty.getSetMethodName());
mapping.setIsReadOnly(true);
accessor.setAttributeName("thingBLAH");
mapping.setVariableAttributeAccessor(accessor);
} else if (refProperty.getSetMethodName() == null) {
mapping.setVariableGetMethodName(refProperty.getGetMethodName());
} else {
mapping.setVariableGetMethodName(refProperty.getGetMethodName());
mapping.setVariableSetMethodName(refProperty.getSetMethodName());
}
}else{
mapping.setVariableAttributeName(property.getVariableAttributeName());
}
if(property.getVariableClassName() != null){
mapping.setReferenceClassName(property.getVariableClassName());
}else{
mapping.setReferenceClassName(actualType.getQualifiedName());
}
mapping.setAttribute(property.isVariableNodeAttribute());
}
private InverseReferenceMapping generateInverseReferenceMapping(Property property, Descriptor descriptor, NamespaceInfo namespace) {
InverseReferenceMapping<AbstractSession, AttributeAccessor, ContainerPolicy, ClassDescriptor, DatabaseField, DatabaseMapping, org.eclipse.persistence.internal.oxm.record.XMLRecord> invMapping = new XMLInverseReferenceMapping();
boolean isCollection = helper.isCollectionType(property.getType());
if (isCollection) {
invMapping.setReferenceClassName(property.getGenericType().getQualifiedName());
} else {
invMapping.setReferenceClassName(property.getType().getQualifiedName());
}
invMapping.setAttributeName(property.getPropertyName());
String setMethodName = property.getInverseReferencePropertySetMethodName();
String getMethodName = property.getInverseReferencePropertyGetMethodName();
if (setMethodName != null && !setMethodName.equals(Constants.EMPTY_STRING)) {
invMapping.setSetMethodName(setMethodName);
}
if (getMethodName != null && !getMethodName.equals(Constants.EMPTY_STRING)) {
invMapping.setGetMethodName(getMethodName);
}
invMapping.setMappedBy(property.getInverseReferencePropertyName());
if (isCollection) {
JavaClass collectionType = property.getType();
collectionType = containerClassImpl(collectionType);
invMapping.useCollectionClass(org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(collectionType.getQualifiedName(), helper.getClassLoader()));
}
if(property.isWriteableInverseReference()){
if(isCollection){
JavaClass descriptorClass = helper.getJavaClass(descriptor.getJavaClassName());
invMapping.setInlineMapping((XMLCompositeCollectionMapping)generateCompositeCollectionMapping(property, descriptor, descriptorClass, namespace, invMapping.getReferenceClassName()));
}else{
invMapping.setInlineMapping((XMLCompositeObjectMapping)generateCompositeObjectMapping(property, descriptor, namespace, invMapping.getReferenceClassName()));
}
}
return invMapping;
}
/**
* Generate an XMLTransformationMapping based on a given Property.
*
*/
public TransformationMapping generateTransformationMapping(Property property, Descriptor descriptor, NamespaceInfo namespace) {
TransformationMapping<AbstractSession, AttributeAccessor, ContainerPolicy, ClassDescriptor, DatabaseField, XMLTransformationRecord, XMLRecord> mapping = new XMLTransformationMapping();
if (property.isMethodProperty()) {
if (property.getGetMethodName() == null) {
// handle case of set with no get method
String paramTypeAsString = property.getType().getName();
mapping.setAttributeAccessor(new JAXBSetMethodAttributeAccessor(paramTypeAsString, helper.getClassLoader()));
mapping.setSetMethodName(property.getSetMethodName());
} else if (property.getSetMethodName() == null) {
mapping.setGetMethodName(property.getGetMethodName());
} else {
mapping.setSetMethodName(property.getSetMethodName());
mapping.setGetMethodName(property.getGetMethodName());
}
}
// handle transformation
if (property.isSetXmlTransformation()) {
XmlTransformation xmlTransformation = property.getXmlTransformation();
mapping.setIsOptional(xmlTransformation.isOptional());
// handle transformer(s)
if (xmlTransformation.isSetXmlReadTransformer()) {
// handle read transformer
mapping.setAttributeName(property.getPropertyName());
XmlReadTransformer readTransformer = xmlTransformation.getXmlReadTransformer();
if (readTransformer.isSetTransformerClass()) {
mapping.setAttributeTransformerClassName(xmlTransformation.getXmlReadTransformer().getTransformerClass());
} else {
mapping.setAttributeTransformation(xmlTransformation.getXmlReadTransformer().getMethod());
}
}
if (xmlTransformation.isSetXmlWriteTransformers()) {
// handle write transformer(s)
for (XmlWriteTransformer writeTransformer : xmlTransformation.getXmlWriteTransformer()) {
if (writeTransformer.isSetTransformerClass()) {
mapping.addFieldTransformerClassName(writeTransformer.getXmlPath(), writeTransformer.getTransformerClass());
} else {
mapping.addFieldTransformation(writeTransformer.getXmlPath(), writeTransformer.getMethod());
}
}
}
}
return mapping;
}
public ChoiceObjectMapping generateChoiceMapping(Property property, Descriptor descriptor, NamespaceInfo namespace) {
XMLChoiceObjectMapping mapping = new XMLChoiceObjectMapping();
initializeXMLMapping(mapping, property);
boolean isIdRef = property.isXmlIdRef();
Iterator<Property> choiceProperties = property.getChoiceProperties().iterator();
while (choiceProperties.hasNext()) {
Property next = choiceProperties.next();
JavaClass type = next.getType();
JavaClass originalType = next.getType();
Converter converter = null;
TypeInfo info = typeInfo.get(type.getName());
if(info != null){
XmlJavaTypeAdapter adapter = info.getXmlJavaTypeAdapter();
if(adapter != null){
String adapterValue = adapter.getValue();
JavaClass adapterClass = helper.getJavaClass(adapterValue);
JavaClass theClass = CompilerHelper.getTypeFromAdapterClass(adapterClass, helper);
type = theClass;
converter = new XMLJavaTypeConverter(adapterClass.getQualifiedName());
}
}
if (next.getXmlJoinNodes() != null) {
// handle XmlJoinNodes
List<XMLField> srcFlds = new ArrayList<>();
List<XMLField> tgtFlds = new ArrayList<>();
for (XmlJoinNode xmlJoinNode: next.getXmlJoinNodes().getXmlJoinNode()) {
srcFlds.add(new XMLField(xmlJoinNode.getXmlPath()));
tgtFlds.add(new XMLField(xmlJoinNode.getReferencedXmlPath()));
}
mapping.addChoiceElement(srcFlds, type.getQualifiedName(), tgtFlds);
} else if (isIdRef) {
// handle IDREF
String tgtXPath = null;
TypeInfo referenceType = typeInfo.get(type.getQualifiedName());
if (null != referenceType && referenceType.isIDSet()) {
Property prop = referenceType.getIDProperty();
tgtXPath = getXPathForField(prop, namespace, !prop.isAttribute(), false).getXPath();
}
// if the XPath is set (via xml-path) use it, otherwise figure it out
Field srcXPath;
if (next.getXmlPath() != null) {
srcXPath = new XMLField(next.getXmlPath());
} else {
srcXPath = getXPathForField(next, namespace, true, false);
}
mapping.addChoiceElement(srcXPath.getXPath(), type.getQualifiedName(), tgtXPath);
} else {
XMLField xpath;
if (next.getXmlPath() != null) {
xpath = new XMLField(next.getXmlPath());
} else {
xpath = (XMLField) getXPathForField(next, namespace, (!(this.typeInfo.containsKey(type.getQualifiedName()))) || next.isMtomAttachment() || type.isEnum(), false);
}
mapping.addChoiceElement(xpath, type.getQualifiedName());
if(!originalType.getQualifiedName().equals(type.getQualifiedName())) {
mapping.getClassNameToFieldMappings().putIfAbsent(originalType.getQualifiedName(), xpath);
mapping.addConverter(xpath, converter);
}
XMLMapping nestedMapping = mapping.getChoiceElementMappings().get(xpath);
if(nestedMapping instanceof BinaryDataMapping){
((BinaryDataMapping)nestedMapping).getNullPolicy().setNullRepresentedByEmptyNode(false);
}
if (type.isEnum()) {
if(nestedMapping.isAbstractDirectMapping()) {
((DirectMapping)nestedMapping).setConverter(buildJAXBEnumTypeConverter(nestedMapping, (EnumTypeInfo)info));
}
}
}
}
return mapping;
}
public ChoiceCollectionMapping generateChoiceCollectionMapping(Property property, Descriptor descriptor, NamespaceInfo namespace) {
ChoiceCollectionMapping mapping = new XMLChoiceCollectionMapping();
initializeXMLContainerMapping(mapping, property.getType().isArray());
initializeXMLMapping((XMLChoiceCollectionMapping)mapping, property);
JavaClass collectionType = property.getType();
if (collectionType.isArray()){
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), helper.getClassLoader());
JavaClass componentType = collectionType.getComponentType();
if(componentType.isArray()) {
JavaClass baseComponentType = getBaseComponentType(componentType);
if (baseComponentType.isPrimitive()){
Class<?> primitiveClass = XMLConversionManager.getDefaultManager().convertClassNameToClass(baseComponentType.getRawName());
accessor.setComponentClass(primitiveClass);
} else {
accessor.setComponentClassName(baseComponentType.getQualifiedName());
}
} else {
accessor.setComponentClassName(componentType.getQualifiedName());
}
mapping.setAttributeAccessor(accessor);
}
collectionType = containerClassImpl(collectionType);
mapping.useCollectionClassName(collectionType.getRawName());
if (property.isSetXmlElementWrapper()) {
mapping.setWrapperNullPolicy(getWrapperNullPolicyFromProperty(property));
}
boolean isIdRef = property.isXmlIdRef();
Iterator<Property> choiceProperties = property.getChoiceProperties().iterator();
while (choiceProperties.hasNext()) {
Property next = choiceProperties.next();
JavaClass type = next.getType();
JavaClass originalType = next.getType();
Converter converter = null;
Field xmlField = null;
TypeInfo info = typeInfo.get(type.getName());
if(info != null){
XmlJavaTypeAdapter adapter = info.getXmlJavaTypeAdapter();
if(adapter != null){
String adapterValue = adapter.getValue();
JavaClass adapterClass = helper.getJavaClass(adapterValue);
JavaClass theClass = CompilerHelper.getTypeFromAdapterClass(adapterClass, helper);
type = theClass;
converter = new XMLJavaTypeConverter(adapterClass.getQualifiedName());
}
}
if (next.getXmlJoinNodes() != null) {
// handle XmlJoinNodes
List<Field> srcFlds = new ArrayList<>();
List<Field> tgtFlds = new ArrayList<>();
for (XmlJoinNode xmlJoinNode: next.getXmlJoinNodes().getXmlJoinNode()) {
srcFlds.add(new XMLField(xmlJoinNode.getXmlPath()));
tgtFlds.add(new XMLField(xmlJoinNode.getReferencedXmlPath()));
}
mapping.addChoiceElement(srcFlds, type.getQualifiedName(), tgtFlds);
} else if (isIdRef) {
// handle IDREF
String tgtXPath = null;
TypeInfo referenceType = typeInfo.get(type.getQualifiedName());
if (null != referenceType && referenceType.isIDSet()) {
Property prop = referenceType.getIDProperty();
tgtXPath = getXPathForField(prop, namespace, !prop.isAttribute(), false).getXPath();
}
// if the XPath is set (via xml-path) use it, otherwise figure it out
Field srcXPath;
if (next.getXmlPath() != null) {
srcXPath = new XMLField(next.getXmlPath());
} else {
srcXPath = getXPathForField(next, namespace, true, false);
}
mapping.addChoiceElement(srcXPath.getXPath(), type.getQualifiedName(), tgtXPath);
} else {
Field xpath;
if (next.getXmlPath() != null) {
xpath = new XMLField(next.getXmlPath());
} else {
xpath = getXPathForField(next, namespace, (!(this.typeInfo.containsKey(type.getQualifiedName()))) || type.isEnum(), false);
}
xmlField = xpath;
mapping.addChoiceElement(xpath.getName(), type.getQualifiedName());
if(!originalType.getQualifiedName().equals(type.getQualifiedName())) {
mapping.getClassNameToFieldMappings().putIfAbsent(originalType.getQualifiedName(), xpath);
mapping.addConverter(xpath, converter);
}
}
if(xmlField !=null){
Mapping nestedMapping = (Mapping) mapping.getChoiceElementMappings().get(xmlField);
if(nestedMapping.isAbstractCompositeCollectionMapping()){
//handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
((CompositeCollectionMapping)nestedMapping).setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespace)));
} else if (next.isNillable() && property.isNillable()){
((CompositeCollectionMapping)nestedMapping).getNullPolicy().setNullRepresentedByXsiNil(true);
((CompositeCollectionMapping)nestedMapping).getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
} else if(nestedMapping.isAbstractCompositeDirectCollectionMapping()){
if (next.isSetNullPolicy()) {
((DirectCollectionMapping)nestedMapping).setNullPolicy(getNullPolicyFromProperty(next, getNamespaceResolverForDescriptor(namespace)));
} else if (next.isNillable() && property.isNillable()){
((DirectCollectionMapping)nestedMapping).getNullPolicy().setNullRepresentedByXsiNil(true);
((DirectCollectionMapping)nestedMapping).getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
((DirectCollectionMapping)nestedMapping).getNullPolicy().setNullRepresentedByEmptyNode(false);
if (type.isEnum()) {
((DirectCollectionMapping)nestedMapping).setValueConverter(buildJAXBEnumTypeConverter(nestedMapping, (EnumTypeInfo)info));
}
} else if(nestedMapping instanceof BinaryDataCollectionMapping){
if (next.isSetNullPolicy()) {
((BinaryDataCollectionMapping)nestedMapping).setNullPolicy(getNullPolicyFromProperty(next, getNamespaceResolverForDescriptor(namespace)));
} else if (next.isNillable() && property.isNillable()){
((BinaryDataCollectionMapping)nestedMapping).getNullPolicy().setNullRepresentedByXsiNil(true);
((BinaryDataCollectionMapping)nestedMapping).getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
}
}
}
return mapping;
}
public Mapping generateMappingForReferenceProperty(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo) {
boolean isCollection = helper.isCollectionType(property.getType()) || property.getType().isArray();
Mapping mapping;
if (isCollection) {
mapping = new XMLChoiceCollectionMapping();
initializeXMLContainerMapping((ChoiceCollectionMapping) mapping, property.getType().isArray());
JavaClass collectionType = property.getType();
collectionType = containerClassImpl(collectionType);
((ChoiceCollectionMapping) mapping).useCollectionClassName(collectionType.getRawName());
JAXBElementRootConverter jaxbERConverter = new JAXBElementRootConverter(Object.class);
if (property.isSetXmlJavaTypeAdapter()) {
JavaClass adapterClass = helper.getJavaClass(property.getXmlJavaTypeAdapter().getValue());
jaxbERConverter.setNestedConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
((ChoiceCollectionMapping) mapping).setConverter(jaxbERConverter);
if (property.isSetWriteOnly()) {
((ChoiceCollectionMapping) mapping).setIsWriteOnly(property.isWriteOnly());
}
if (property.isSetXmlElementWrapper()) {
((ChoiceCollectionMapping) mapping).setWrapperNullPolicy(getWrapperNullPolicyFromProperty(property));
}
} else {
mapping = new XMLChoiceObjectMapping();
JAXBElementRootConverter jaxbERConverter = new JAXBElementRootConverter(Object.class);
if (property.isSetXmlJavaTypeAdapter()) {
JavaClass adapterClass = helper.getJavaClass(property.getXmlJavaTypeAdapter().getValue());
jaxbERConverter.setNestedConverter(new XMLJavaTypeConverter(adapterClass.getQualifiedName()));
}
((ChoiceObjectMapping) mapping).setConverter(jaxbERConverter);
if (property.isSetWriteOnly()) {
((ChoiceObjectMapping) mapping).setIsWriteOnly(property.isWriteOnly());
}
}
initializeXMLMapping((XMLMapping)mapping, property);
List<ElementDeclaration> referencedElements = property.getReferencedElements();
JavaClass propertyType = property.getType();
if (propertyType.isArray()) {
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), helper.getClassLoader());
accessor.setComponentClassName(property.getType().getComponentType().getQualifiedName());
JavaClass componentType = propertyType.getComponentType();
if(componentType.isArray()) {
Class<?> adaptedClass = classToGeneratedClasses.get(componentType.getQualifiedName());
accessor.setAdaptedClassName(adaptedClass.getName());
}
mapping.setAttributeAccessor(accessor);
}
String wrapperXPath = "";
// handle XmlElementWrapper
if (property.isSetXmlElementWrapper()) {
XmlElementWrapper wrapper = property.getXmlElementWrapper();
String namespace = wrapper.getNamespace();
if (namespace.equals(XMLProcessor.DEFAULT)) {
if (namespaceInfo.isElementFormQualified()) {
namespace = namespaceInfo.getNamespace();
} else {
namespace = "";
}
}
if (namespace.equals("")) {
wrapperXPath += (wrapper.getName() + "/");
} else {
String prefix = getPrefixForNamespace(namespace, getNamespaceResolverForDescriptor(namespaceInfo));
wrapperXPath += getQualifiedString(prefix, wrapper.getName() + "/");
}
}
if(property.isMixedContent() && isCollection) {
if(wrapperXPath.length() == 0) {
((ChoiceCollectionMapping)mapping).setMixedContent(true);
} else {
((ChoiceCollectionMapping)mapping).setMixedContent(wrapperXPath.substring(0, wrapperXPath.length() - 1));
}
}
for (ElementDeclaration element:referencedElements) {
QName elementName = element.getElementName();
JavaClass pType = element.getJavaType();
String pTypeName = element.getJavaTypeName();
boolean isBinaryType = (areEquals(pType, AnnotationsProcessor.JAVAX_ACTIVATION_DATAHANDLER) || areEquals(pType, byte[].class) || areEquals(pType, Image.class) || areEquals(pType, Source.class) || areEquals(pType, AnnotationsProcessor.JAVAX_MAIL_INTERNET_MIMEMULTIPART));
boolean isText = pType.isEnum() || (!isBinaryType && !(this.typeInfo.containsKey(element.getJavaTypeName())) && !(element.getJavaTypeName().equals(OBJECT_CLASS_NAME)));
String xPath = wrapperXPath;
Field xmlField = this.getXPathForElement(xPath, elementName, namespaceInfo, isText);
//ensure byte[] goes to base64 instead of the default hex.
if(helper.getXMLToJavaTypeMap().get(pType.getRawName()) == Constants.BASE_64_BINARY_QNAME) {
xmlField.setSchemaType(Constants.BASE_64_BINARY_QNAME);
}
if(areEquals(pType, Object.class)) {
setTypedTextField(xmlField);
}
Mapping nestedMapping;
AbstractNullPolicy nullPolicy = null;
if(isCollection){
ChoiceCollectionMapping xmlChoiceCollectionMapping = (ChoiceCollectionMapping) mapping;
xmlChoiceCollectionMapping.addChoiceElement(xmlField, pTypeName);
nestedMapping = (Mapping) xmlChoiceCollectionMapping.getChoiceElementMappings().get(xmlField);
if(nestedMapping.isAbstractCompositeCollectionMapping()){
((CompositeCollectionMapping)nestedMapping).setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
nullPolicy = ((CompositeCollectionMapping)nestedMapping).getNullPolicy();
}
if (nestedMapping.isAbstractCompositeDirectCollectionMapping()) {
DirectCollectionMapping nestedCompositeDirectCollectionMapping = (DirectCollectionMapping) nestedMapping;
nullPolicy = nestedCompositeDirectCollectionMapping.getNullPolicy();
if(pType.isEnum()) {
TypeInfo enumTypeInfo = typeInfo.get(pType.getQualifiedName());
nestedCompositeDirectCollectionMapping.setValueConverter(buildJAXBEnumTypeConverter(nestedCompositeDirectCollectionMapping, (EnumTypeInfo) enumTypeInfo));
}
if(element.isList()){
XMLListConverter listConverter = new XMLListConverter();
listConverter.setObjectClassName(pType.getQualifiedName());
((DirectCollectionMapping)nestedMapping).setValueConverter(listConverter);
}
}else if(nestedMapping instanceof BinaryDataCollectionMapping){
nullPolicy = ((BinaryDataCollectionMapping)nestedMapping).getNullPolicy();
if(element.isList()){
((XMLField) nestedMapping.getField()).setUsesSingleNode(true);
}
}
} else {
ChoiceObjectMapping xmlChoiceObjectMapping = (ChoiceObjectMapping) mapping;
xmlChoiceObjectMapping.addChoiceElement(xmlField, pTypeName);
nestedMapping = (Mapping) xmlChoiceObjectMapping.getChoiceElementMappings().get(xmlField);
if(pType.isEnum()) {
TypeInfo enumTypeInfo = typeInfo.get(pType.getQualifiedName());
((DirectMapping)nestedMapping).setConverter(buildJAXBEnumTypeConverter(nestedMapping, (EnumTypeInfo) enumTypeInfo));
}
if(nestedMapping.isAbstractCompositeObjectMapping()){
((CompositeObjectMapping)nestedMapping).setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
nullPolicy = ((CompositeObjectMapping)nestedMapping).getNullPolicy();
}else if(nestedMapping instanceof BinaryDataMapping){
nullPolicy = ((BinaryDataMapping)nestedMapping).getNullPolicy();
}else if(nestedMapping instanceof DirectMapping){
nullPolicy = ((DirectMapping)nestedMapping).getNullPolicy();
}
}
if(nullPolicy != null){
nullPolicy.setNullRepresentedByEmptyNode(false);
nullPolicy.setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
nullPolicy.setNullRepresentedByXsiNil(true);
nullPolicy.setIgnoreAttributesForNil(false);
}
if (!element.isXmlRootElement()) {
Class<?> scopeClass = element.getScopeClass();
if (scopeClass == jakarta.xml.bind.annotation.XmlElementDecl.GLOBAL.class){
scopeClass = JAXBElement.GlobalScope.class;
}
Class<?> declaredType = null;
if(element.getAdaptedJavaType() != null){
declaredType = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(element.getAdaptedJavaType().getQualifiedName(), helper.getClassLoader());
}else{
declaredType = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(pType.getQualifiedName(), helper.getClassLoader());
}
JAXBElementConverter converter = new JAXBElementConverter(xmlField, declaredType, scopeClass);
if (isCollection){
ChoiceCollectionMapping xmlChoiceCollectionMapping = (ChoiceCollectionMapping) mapping;
if(element.getJavaTypeAdapterClass() != null){
converter.setNestedConverter(new XMLJavaTypeConverter(element.getJavaTypeAdapterClass().getName()));
}else{
CoreConverter originalConverter = xmlChoiceCollectionMapping.getConverter(xmlField);
converter.setNestedConverter(originalConverter);
}
xmlChoiceCollectionMapping.addConverter(xmlField, converter);
} else {
ChoiceObjectMapping xmlChoiceObjectMapping = (ChoiceObjectMapping) mapping;
if(element.getJavaTypeAdapterClass() != null){
converter.setNestedConverter(new XMLJavaTypeConverter(element.getJavaTypeAdapterClass().getName()));
}else{
CoreConverter originalConverter = xmlChoiceObjectMapping.getConverter(xmlField);
converter.setNestedConverter(originalConverter);
}
xmlChoiceObjectMapping.addConverter(xmlField, converter);
}
}
}
if(property.isAny()){
if(isCollection){
XMLChoiceCollectionMapping xmlChoiceCollectionMapping = (XMLChoiceCollectionMapping) mapping;
xmlChoiceCollectionMapping.setIsAny(true);
}
}
return mapping;
}
private void setTypedTextField(Field field){
field.setIsTypedTextField(true);
if(field.getSchemaType() == null){
field.setSchemaType(Constants.ANY_TYPE_QNAME);
}
((XMLField)field).addXMLConversion(Constants.DATE_TIME_QNAME, CoreClassConstants.XML_GREGORIAN_CALENDAR);
((XMLField)field).addXMLConversion(Constants.DATE_QNAME, CoreClassConstants.XML_GREGORIAN_CALENDAR);
((XMLField)field).addXMLConversion(Constants.TIME_QNAME, CoreClassConstants.XML_GREGORIAN_CALENDAR);
((XMLField)field).addJavaConversion(CoreClassConstants.APBYTE, Constants.BASE_64_BINARY_QNAME);
((XMLField)field).addJavaConversion(CoreClassConstants.ABYTE, Constants.BASE_64_BINARY_QNAME);
}
public AnyCollectionMapping generateAnyCollectionMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, boolean isMixed) {
AnyCollectionMapping mapping = new XMLAnyCollectionMapping();
initializeXMLContainerMapping(mapping, property.getType().isArray());
initializeXMLMapping((XMLMapping)mapping, property);
// if the XPath is set (via xml-path) use it
if (property.getXmlPath() != null) {
mapping.setField(new XMLField(property.getXmlPath()));
} else {
if (property.isSetXmlElementWrapper()) {
mapping.setField(getXPathForField(property, namespaceInfo, false, true));
}
}
if (property.isSetXmlElementWrapper()) {
mapping.setWrapperNullPolicy(getWrapperNullPolicyFromProperty(property));
}
Class<?> declaredType = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(property.getActualType().getQualifiedName(), helper.getClassLoader());
JAXBElementRootConverter jaxbElementRootConverter = new JAXBElementRootConverter(declaredType);
mapping.setConverter(jaxbElementRootConverter);
if (property.getDomHandlerClassName() != null) {
jaxbElementRootConverter.setNestedConverter(new DomHandlerConverter(property.getDomHandlerClassName()));
}
if (property.isLax() || property.isReference()) {
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
} else {
if (property.isAny()) {
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_ALL_AS_ELEMENT);
} else {
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_NONE_AS_ELEMENT);
}
}
mapping.setMixedContent(isMixed);
if (isMixed) {
mapping.setPreserveWhitespaceForMixedContent(true);
}
if (property.isAny()) {
mapping.setUseXMLRoot(true);
}
JavaClass collectionType = property.getType();
if (collectionType.isArray()){
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), helper.getClassLoader());
JavaClass componentType = collectionType.getComponentType();
if(componentType.isArray()) {
JavaClass baseComponentType = getBaseComponentType(componentType);
if (baseComponentType.isPrimitive()){
Class<Object> primitiveClass = XMLConversionManager.getDefaultManager().convertClassNameToClass(baseComponentType.getRawName());
accessor.setComponentClass(primitiveClass);
} else {
accessor.setComponentClassName(baseComponentType.getQualifiedName());
}
} else {
accessor.setComponentClassName(componentType.getQualifiedName());
}
mapping.setAttributeAccessor(accessor);
}
collectionType = containerClassImpl(collectionType);
mapping.useCollectionClass(helper.getClassForJavaClass(collectionType));
return mapping;
}
public CompositeObjectMapping generateCompositeObjectMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, String referenceClassName) {
CompositeObjectMapping mapping = new XMLCompositeObjectMapping();
initializeXMLMapping((XMLMapping)mapping, property);
// if the XPath is set (via xml-path) use it; otherwise figure it out
mapping.setField(getXPathForField(property, namespaceInfo, false, false));
// handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else {
NullPolicy nullPolicy = (NullPolicy) mapping.getNullPolicy();
nullPolicy.setSetPerformedForAbsentNode(false);
if(property.isNillable()) {
nullPolicy.setNullRepresentedByXsiNil(true);
nullPolicy.setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
}
if (referenceClassName == null){
setTypedTextField((Field)mapping.getField());
String defaultValue = property.getDefaultValue();
if (null != defaultValue) {
mapping.setConverter(new DefaultElementConverter(defaultValue));
}
} else {
mapping.setReferenceClassName(referenceClassName);
}
if(property.isTransientType()){
mapping.setReferenceClassName(Constants.UNKNOWN_OR_TRANSIENT_CLASS);
}
if (property.isRequired()) {
((Field) mapping.getField()).setRequired(true);
}
return mapping;
}
public DirectMapping generateDirectMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo) {
DirectMapping mapping = new XMLDirectMapping();
mapping.setNullValueMarshalled(true);
String fixedValue = property.getFixedValue();
if (fixedValue != null) {
mapping.setIsWriteOnly(true);
}
initializeXMLMapping((XMLMapping)mapping, property);
// if the XPath is set (via xml-path) use it; otherwise figure it out
Field xmlField = getXPathForField(property, namespaceInfo, true, false);
mapping.setField(xmlField);
if (property.getDefaultValue() != null) {
mapping.setNullValue(property.getDefaultValue());
}
if (property.isXmlId()) {
mapping.setCollapsingStringValues(true);
}
// handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else {
if (property.isNillable()){
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
mapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
mapping.getNullPolicy().setNullRepresentedByEmptyNode(false);
if (!mapping.getXPath().equals("text()")) {
((NullPolicy) mapping.getNullPolicy()).setSetPerformedForAbsentNode(false);
}
}
if (property.isRequired()) {
((Field) mapping.getField()).setRequired(true);
}
if (property.getType() != null) {
String theClass = null;
String targetClass = null;
if (property.isSetXmlJavaTypeAdapter()) {
theClass = property.getOriginalType().getQualifiedName();
targetClass = property.getType().getQualifiedName();
} else {
theClass = property.getType().getQualifiedName();
}
// Try to get the actual Class
try {
JavaClass actualJavaClass = helper.getJavaClass(theClass);
Class<?> actualClass = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(actualJavaClass.getQualifiedName(), helper.getClassLoader());
mapping.setAttributeClassification(actualClass);
if(targetClass != null) {
Class<?> fieldClass = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(targetClass, helper.getClassLoader());
mapping.getField().setType(fieldClass);
}
} catch (Exception e) {
// Couldn't find Class (Dynamic?), so set class name instead.
mapping.setAttributeClassificationName(theClass);
}
}
if (Constants.QNAME_QNAME.equals(property.getSchemaType())){
((Field) mapping.getField()).setSchemaType(Constants.QNAME_QNAME);
}
// handle cdata set via metadata
if (property.isSetCdata()) {
mapping.setIsCDATA(property.isCdata());
}
return mapping;
}
public BinaryDataMapping generateBinaryMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo) {
BinaryDataMapping mapping = new XMLBinaryDataMapping();
initializeXMLMapping((XMLMapping)mapping, property);
// if the XPath is set (via xml-path) use it
mapping.setField(getXPathForField(property, namespaceInfo, false, false));
if (property.isSwaAttachmentRef()) {
((Field) mapping.getField()).setSchemaType(Constants.SWA_REF_QNAME);
mapping.setSwaRef(true);
} else if (property.isMtomAttachment()) {
Field f = ((Field) mapping.getField());
if (!f.getSchemaType().equals(Constants.HEX_BINARY_QNAME)) {
f.setSchemaType(Constants.BASE_64_BINARY_QNAME);
}
}
if (property.isInlineBinaryData()) {
mapping.setShouldInlineBinaryData(true);
}
// use a non-dynamic implementation of MimeTypePolicy to wrap the MIME string
if (property.getMimeType() != null) {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy(property.getMimeType(),(DatabaseMapping) mapping));
} else {
if(areEquals(property.getType(), javax.xml.transform.Source.class)) {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy("application/xml", (DatabaseMapping)mapping));
} else if(areEquals(property.getType(), java.awt.Image.class)) {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy("image/png", (DatabaseMapping)mapping));
} else {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy("application/octet-stream", (DatabaseMapping)mapping));
}
}
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else {
if (property.isNillable()){
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
mapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
mapping.getNullPolicy().setNullRepresentedByEmptyNode(false);
if (!mapping.getXPath().equals("text()")) {
((NullPolicy) mapping.getNullPolicy()).setSetPerformedForAbsentNode(false);
}
}
mapping.setAttributeClassificationName(property.getActualType().getQualifiedName());
return mapping;
}
public BinaryDataCollectionMapping generateBinaryDataCollectionMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo) {
BinaryDataCollectionMapping mapping = new XMLBinaryDataCollectionMapping();
initializeXMLMapping((XMLMapping)mapping, property);
initializeXMLContainerMapping(mapping, property.getType().isArray());
if (property.isSetXmlElementWrapper()) {
mapping.setWrapperNullPolicy(getWrapperNullPolicyFromProperty(property));
}
// handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else if (property.isNillable()){
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
mapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
// if the XPath is set (via xml-path) use it
mapping.setField(getXPathForField(property, namespaceInfo, false, false));
if (property.isSwaAttachmentRef()) {
((Field) mapping.getField()).setSchemaType(Constants.SWA_REF_QNAME);
mapping.setSwaRef(true);
} else if (property.isMtomAttachment()) {
Field f = (Field) mapping.getField();
if (!f.getSchemaType().equals(Constants.HEX_BINARY_QNAME)) {
f.setSchemaType(Constants.BASE_64_BINARY_QNAME);
}
}
if (property.isInlineBinaryData()) {
mapping.setShouldInlineBinaryData(true);
}
// use a non-dynamic implementation of MimeTypePolicy to wrap the MIME string
if (property.getMimeType() != null) {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy(property.getMimeType()));
} else {
if(areEquals(property.getType(), javax.xml.transform.Source.class)) {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy("application/xml"));
} else {
mapping.setMimeTypePolicy(new FixedMimeTypePolicy("application/octet-stream"));
}
}
JavaClass collectionType = property.getType();
JavaClass itemType = property.getActualType();
if(collectionType != null && helper.isCollectionType(collectionType)){
try{
Class<Object> declaredClass = PrivilegedAccessHelper.getClassForName(itemType.getQualifiedName(), false, helper.getClassLoader());
mapping.setAttributeElementClass(declaredClass);
}catch (Exception e) {
}
}
collectionType = containerClassImpl(collectionType);
mapping.useCollectionClassName(collectionType.getRawName());
return mapping;
}
public DirectMapping generateDirectEnumerationMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, EnumTypeInfo enumInfo) {
DirectMapping mapping = new XMLDirectMapping();
initializeXMLMapping((XMLMapping)mapping, property);
mapping.setNullValueMarshalled(true);
mapping.setConverter(buildJAXBEnumTypeConverter(mapping, enumInfo));
// handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else if (property.isNillable()){
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
mapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
mapping.setField(getXPathForField(property, namespaceInfo, true, false));
if (!mapping.getXPath().equals("text()")) {
((NullPolicy) mapping.getNullPolicy()).setSetPerformedForAbsentNode(false);
}
return mapping;
}
private JAXBEnumTypeConverter buildJAXBEnumTypeConverter(Mapping mapping, EnumTypeInfo enumInfo){
JAXBEnumTypeConverter converter = new JAXBEnumTypeConverter(mapping, enumInfo.getClassName(), false);
List<String> fieldNames = enumInfo.getFieldNames();
List<Object> xmlEnumValues = enumInfo.getXmlEnumValues();
for (int i=0; i< fieldNames.size(); i++) {
converter.addConversionValue(xmlEnumValues.get(i), fieldNames.get(i));
}
return converter;
}
public Mapping generateCollectionMapping(Property property, Descriptor descriptor, JavaClass descriptorJavaClass, NamespaceInfo namespaceInfo) {
// check to see if this should be a composite or direct mapping
JavaClass javaClass = property.getActualType();
if (property.isMixedContent()) {
return generateAnyCollectionMapping(property, descriptor, namespaceInfo, true);
}
if (property.isXmlIdRef() || property.isSetXmlJoinNodes()) {
return generateXMLCollectionReferenceMapping(property, descriptor, namespaceInfo, javaClass);
}
if (javaClass != null && typeInfo.get(javaClass.getQualifiedName()) != null) {
TypeInfo referenceInfo = typeInfo.get(javaClass.getQualifiedName());
if (referenceInfo.isEnumerationType()) {
return generateEnumCollectionMapping(property, descriptor, namespaceInfo,(EnumTypeInfo) referenceInfo);
}
return generateCompositeCollectionMapping(property, descriptor, descriptorJavaClass, namespaceInfo, javaClass.getQualifiedName());
}
if (!property.isAttribute() && javaClass != null && javaClass.getQualifiedName().equals(OBJECT_CLASS_NAME)){
CompositeCollectionMapping ccMapping = generateCompositeCollectionMapping(property, descriptor, descriptorJavaClass, namespaceInfo, null);
ccMapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
return ccMapping;
}
if(isBinaryData(javaClass)){
return generateBinaryDataCollectionMapping(property, descriptor, namespaceInfo);
}
return generateDirectCollectionMapping(property, descriptor, namespaceInfo);
}
public DirectCollectionMapping generateEnumCollectionMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, EnumTypeInfo info) {
DirectCollectionMapping mapping = generateDirectCollectionMapping(property, descriptor, namespaceInfo);
mapping.setValueConverter(buildJAXBEnumTypeConverter(mapping, info));
return mapping;
}
public AnyAttributeMapping generateAnyAttributeMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo) {
XMLAnyAttributeMapping mapping = new XMLAnyAttributeMapping();
initializeXMLMapping(mapping, property);
initializeXMLContainerMapping(mapping, property.getType().isArray());
// if the XPath is set (via xml-path) use it
if (property.getXmlPath() != null) {
mapping.setField(new XMLField(property.getXmlPath()));
}
mapping.setSchemaInstanceIncluded(false);
mapping.setNamespaceDeclarationIncluded(false);
JavaClass mapType = property.getType();
if (areEquals(mapType, Map.class)) {
mapType = jotHashMap;
}
mapping.useMapClassName(mapType.getRawName());
return mapping;
}
public AnyObjectMapping generateAnyObjectMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo) {
AnyObjectMapping<AbstractSession, AttributeAccessor, ContainerPolicy, XMLConverter, ClassDescriptor, DatabaseField, XMLMarshaller, Session, UnmarshalKeepAsElementPolicy, XMLUnmarshaller, XMLRecord> mapping = new XMLAnyObjectMapping();
initializeXMLMapping((XMLMapping)mapping, property);
// if the XPath is set (via xml-path) use it
if (property.getXmlPath() != null) {
mapping.setField(new XMLField(property.getXmlPath()));
}
Class<?> declaredType = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(property.getActualType().getQualifiedName(), helper.getClassLoader());
JAXBElementRootConverter jaxbElementRootConverter = new JAXBElementRootConverter(declaredType);
mapping.setConverter(jaxbElementRootConverter);
if (property.getDomHandlerClassName() != null) {
jaxbElementRootConverter.setNestedConverter(new DomHandlerConverter(property.getDomHandlerClassName()));
}
if (property.isLax()) {
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
} else {
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_ALL_AS_ELEMENT);
}
if (property.isMixedContent()) {
mapping.setMixedContent(true);
} else {
mapping.setUseXMLRoot(true);
}
return mapping;
}
protected boolean areEquals(JavaClass src, Class<?> tgt) {
if (src == null || tgt == null) {
return false;
}
return src.getRawName().equals(tgt.getCanonicalName());
}
/**
* Compares a JavaModel JavaClass to a Class. Equality is based on
* the raw name of the JavaClass compared to the canonical
* name of the Class.
*
*/
protected boolean areEquals(JavaClass src, String tgtCanonicalName) {
if (src == null || tgtCanonicalName == null) {
return false;
}
return src.getRawName().equals(tgtCanonicalName);
}
private Class<?> generateMapEntryClassAndDescriptor(Property property, NamespaceResolver nr){
JavaClass keyType = property.getKeyType();
JavaClass valueType = property.getValueType();
if(keyType == null){
keyType = helper.getJavaClass("java.lang.Object");
}
if(valueType == null){
valueType = helper.getJavaClass("java.lang.Object");
}
String mapEntryClassName = getJaxbClassLoader().nextAvailableGeneratedClassName();
MapEntryGeneratedKey mapKey = new MapEntryGeneratedKey(keyType.getQualifiedName(),valueType.getQualifiedName());
Class<?> generatedClass = getGeneratedMapEntryClasses().get(mapKey);
if(generatedClass == null){
generatedClass = generateMapEntryClass(mapEntryClassName, keyType.getQualifiedName(), valueType.getQualifiedName());
getGeneratedMapEntryClasses().put(mapKey, generatedClass);
Descriptor desc = new XMLDescriptor();
desc.setJavaClass(generatedClass);
desc.addMapping((CoreMapping)generateMappingForType(keyType, Property.DEFAULT_KEY_NAME));
desc.addMapping((CoreMapping)generateMappingForType(valueType, Property.DEFAULT_VALUE_NAME));
desc.setNamespaceResolver(nr);
project.addDescriptor((CoreDescriptor)desc);
}
return generatedClass;
}
private Class<?> generateMapEntryClass(String className, String keyType, String valueType){
EclipseLinkASMClassWriter cw = new EclipseLinkASMClassWriter();
String qualifiedInternalClassName = className.replace('.', '/');
String qualifiedInternalKeyClassName = keyType.replace('.', '/');
String qualifiedInternalValueClassName = valueType.replace('.', '/');
String valuePrefix = "L"; // non-array type
if (qualifiedInternalValueClassName.startsWith("[L") && qualifiedInternalValueClassName.endsWith(";")) {
valuePrefix = "[L"; // array type
qualifiedInternalValueClassName = qualifiedInternalValueClassName.substring(2, qualifiedInternalValueClassName.length() - 1);
}
String sig = "Ljava/lang/Object;Lorg/eclipse/persistence/internal/jaxb/many/MapEntry<L"+qualifiedInternalKeyClassName+";" + valuePrefix + qualifiedInternalValueClassName+";>;";
cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, qualifiedInternalClassName, sig, "java/lang/Object", new String[] { "org/eclipse/persistence/internal/jaxb/many/MapEntry" });
cw.visitField(Opcodes.ACC_PRIVATE, "key", "L"+qualifiedInternalKeyClassName+";", null, null);
cw.visitField(Opcodes.ACC_PRIVATE, "value", valuePrefix + qualifiedInternalValueClassName+";", null, null);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getKey", "()L"+qualifiedInternalKeyClassName+";", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, qualifiedInternalClassName, "key", "L"+qualifiedInternalKeyClassName+";");
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "setKey", "(L"+qualifiedInternalKeyClassName+";)V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitFieldInsn(Opcodes.PUTFIELD, qualifiedInternalClassName, "key", "L"+qualifiedInternalKeyClassName+";");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getValue", "()" + valuePrefix + qualifiedInternalValueClassName+";", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, qualifiedInternalClassName, "value", valuePrefix + qualifiedInternalValueClassName+";");
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "setValue", "(" + valuePrefix + qualifiedInternalValueClassName+";)V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitFieldInsn(Opcodes.PUTFIELD, qualifiedInternalClassName, "value", valuePrefix + qualifiedInternalValueClassName+";");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
if(!qualifiedInternalValueClassName.equals("java/lang/Object")){
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, "getValue", "()Ljava/lang/Object;", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, qualifiedInternalClassName, "getValue", "()" + valuePrefix + qualifiedInternalValueClassName+";", false);
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, "setValue", "(Ljava/lang/Object;)V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 1);
// CHECKCAST is slightly different for array types
if (valuePrefix.equals("[L")) {
mv.visitTypeInsn(Opcodes.CHECKCAST, valuePrefix + qualifiedInternalValueClassName + ";");
} else {
mv.visitTypeInsn(Opcodes.CHECKCAST, qualifiedInternalValueClassName);
}
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, qualifiedInternalClassName, "setValue", "(" + valuePrefix + qualifiedInternalValueClassName+";)V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
if(!qualifiedInternalKeyClassName.equals("java/lang/Object")){
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, "getKey", "()Ljava/lang/Object;", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,qualifiedInternalClassName, "getKey", "()L"+qualifiedInternalKeyClassName+";", false);
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, "setKey", "(Ljava/lang/Object;)V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitTypeInsn(Opcodes.CHECKCAST, qualifiedInternalKeyClassName);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, qualifiedInternalClassName, "setKey", "(L"+qualifiedInternalKeyClassName+";)V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
cw.visitEnd();
byte[] classBytes =cw.toByteArray();
Class<?> generatedClass = getJaxbClassLoader().generateClass(className, classBytes);
return generatedClass;
}
private Mapping generateMappingForType(JavaClass theType, String attributeName){
Mapping mapping;
boolean typeIsObject = theType.getRawName().equals(OBJECT_CLASS_NAME);
TypeInfo info = typeInfo.get(theType.getQualifiedName());
if ((info != null && !(info.isEnumerationType())) || typeIsObject) {
mapping = new XMLCompositeObjectMapping();
mapping.setAttributeName(attributeName);
((CompositeObjectMapping)mapping).setXPath(attributeName);
if(typeIsObject){
((CompositeObjectMapping)mapping).setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
setTypedTextField((Field) mapping.getField());
}else{
((CompositeObjectMapping)mapping).setReferenceClassName(theType.getQualifiedName());
}
} else if (theType.isArray() || helper.isCollectionType(theType)) {
DirectCollectionMapping directCollectionMapping;
mapping = directCollectionMapping = new XMLCompositeDirectCollectionMapping();
initializeXMLContainerMapping(directCollectionMapping, theType.isArray());
directCollectionMapping.setAttributeName(attributeName);
if (theType.isArray()) {
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(directCollectionMapping.getAttributeAccessor(),
directCollectionMapping.getContainerPolicy(), helper.getClassLoader());
String componentClassName = theType.getComponentType().getQualifiedName();
if (theType.getComponentType().isPrimitive()){
Class<Object> primitiveClass = XMLConversionManager.getDefaultManager().convertClassNameToClass(componentClassName);
accessor.setComponentClass(primitiveClass);
directCollectionMapping.setAttributeAccessor(accessor);
Class<Object> declaredClass = XMLConversionManager.getObjectClass(primitiveClass);
directCollectionMapping.setAttributeElementClass(declaredClass);
} else {
accessor.setComponentClassName(componentClassName);
directCollectionMapping.setAttributeAccessor(accessor);
JavaClass componentType = theType.getComponentType();
Class<?> declaredClass = PrivilegedAccessHelper.callDoPrivilegedWithException(
() -> PrivilegedAccessHelper.getClassForName(componentType.getRawName(), false, helper.getClassLoader()),
(ex) -> JAXBException.classNotFoundException(componentType.getRawName())
);
directCollectionMapping.setAttributeElementClass(declaredClass);
}
} else if (helper.isCollectionType(theType)) {
Collection args = theType.getActualTypeArguments();
if (args.size() > 0) {
JavaClass itemType = (JavaClass) args.iterator().next();
Class<?> declaredClass = PrivilegedAccessHelper.callDoPrivilegedWithException(
() -> PrivilegedAccessHelper.getClassForName(itemType.getRawName(), false, helper.getClassLoader()),
(ex) -> JAXBException.classNotFoundException(itemType.getRawName())
);
if (declaredClass != String.class) {
directCollectionMapping.setAttributeElementClass(declaredClass);
}
}
}
theType = containerClassImpl(theType);
directCollectionMapping.useCollectionClassName(theType.getRawName());
directCollectionMapping.setXPath(attributeName + TXT);
} else {
mapping = new XMLDirectMapping();
mapping.setAttributeName(attributeName);
((DirectMapping)mapping).setNullValueMarshalled(true);
((DirectMapping)mapping).setXPath(attributeName + TXT);
QName schemaType = userDefinedSchemaTypes.get(theType.getQualifiedName());
if (schemaType == null) {
schemaType = helper.getXMLToJavaTypeMap().get(theType.getName());
}
((Field) mapping.getField()).setSchemaType(schemaType);
if(info != null && info.isEnumerationType()) {
((DirectMapping)mapping).setConverter(buildJAXBEnumTypeConverter(mapping, (EnumTypeInfo)info));
}
}
return mapping;
}
public CompositeCollectionMapping generateCompositeCollectionMapping(Property property, Descriptor descriptor, JavaClass javaClass, NamespaceInfo namespaceInfo, String referenceClassName) {
boolean nestedArray = false;
CompositeCollectionMapping<AbstractSession, AttributeAccessor, ContainerPolicy, Converter, ClassDescriptor, DatabaseField, XMLMarshaller, Session, UnmarshalKeepAsElementPolicy, XMLUnmarshaller, XMLRecord> mapping = new XMLCompositeCollectionMapping();
initializeXMLMapping((XMLMapping)mapping, property);
initializeXMLContainerMapping(mapping, property.getType().isArray());
JavaClass manyValueJavaClass = helper.getJavaClass(ManyValue.class);
if (manyValueJavaClass.isAssignableFrom(javaClass)){
mapping.setReuseContainer(false);
}
// handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else if (property.isNillable()){
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
mapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
if (property.isSetXmlElementWrapper()) {
mapping.setWrapperNullPolicy(getWrapperNullPolicyFromProperty(property));
}
JavaClass collectionType = property.getType();
if (collectionType.isArray()){
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), helper.getClassLoader());
JavaClass componentType = collectionType.getComponentType();
if(componentType.isArray()) {
Class<?> adaptedClass = classToGeneratedClasses.get(componentType.getName());
referenceClassName = adaptedClass.getName();
accessor.setAdaptedClassName(referenceClassName);
JavaClass baseComponentType = getBaseComponentType(componentType);
if (baseComponentType.isPrimitive()){
Class<Object> primitiveClass = XMLConversionManager.getDefaultManager().convertClassNameToClass(baseComponentType.getRawName());
accessor.setComponentClass(primitiveClass);
} else {
accessor.setComponentClassName(baseComponentType.getQualifiedName());
}
} else {
accessor.setComponentClassName(componentType.getQualifiedName());
}
mapping.setAttributeAccessor(accessor);
}else if (helper.isMapType(property.getType())){
Class<?> generatedClass = generateMapEntryClassAndDescriptor(property, descriptor.getNonNullNamespaceResolver());
referenceClassName = generatedClass.getName();
String mapClassName = property.getType().getRawName();
mapping.setAttributeAccessor(new MapValueAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), generatedClass, mapClassName, helper.getClassLoader()));
}
//Nested array check (used in JSON marshalling)
if (collectionType.getComponentType() == null) {
if ((collectionType.isArray() || helper.isCollectionType(collectionType)) && (referenceClassName != null && referenceClassName.contains(AnnotationsProcessor.ARRAY_PACKAGE_NAME))) {
nestedArray = true;
}
} else if ((collectionType.isArray() || helper.isCollectionType(collectionType)) && (collectionType.getComponentType().isArray() || helper.isCollectionType(collectionType.getComponentType()))) {
nestedArray = true;
}
collectionType = containerClassImpl(collectionType);
mapping.useCollectionClassName(collectionType.getRawName());
// if the XPath is set (via xml-path) use it; otherwise figure it out
Field xmlField = getXPathForField(property, namespaceInfo, false, false);
if(helper.isMapType(property.getType())){
JavaClass mapValueClass = helper.getJavaClass(MapValue.class);
if(mapValueClass.isAssignableFrom(javaClass)){
mapping.setXPath("entry");
}else{
mapping.setXPath(xmlField.getXPath() + "/entry");
}
}else{
mapping.setXPath(xmlField.getXPath());
}
if (referenceClassName == null){
setTypedTextField((Field)mapping.getField());
} else {
mapping.setReferenceClassName(referenceClassName);
}
if(property.isTransientType()){
mapping.setReferenceClassName(Constants.UNKNOWN_OR_TRANSIENT_CLASS);
}
if (property.isRequired()) {
((Field) mapping.getField()).setRequired(true);
}
((Field) mapping.getField()).setNestedArray(nestedArray);
return mapping;
}
public DirectCollectionMapping generateDirectCollectionMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo) {
DirectCollectionMapping mapping = new XMLCompositeDirectCollectionMapping();
initializeXMLMapping((XMLMapping)mapping, property);
initializeXMLContainerMapping(mapping, property.getType().isArray());
JavaClass collectionType = property.getType();
if (collectionType.isArray()){
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), helper.getClassLoader());
String componentClassName = collectionType.getComponentType().getQualifiedName();
if (collectionType.getComponentType().isPrimitive()){
Class<?> primitiveClass = XMLConversionManager.getDefaultManager().convertClassNameToClass(componentClassName);
accessor.setComponentClass(primitiveClass);
mapping.setAttributeAccessor(accessor);
Class<?> declaredClass = XMLConversionManager.getObjectClass(primitiveClass);
mapping.setAttributeElementClass(declaredClass);
} else {
accessor.setComponentClassName(componentClassName);
mapping.setAttributeAccessor(accessor);
JavaClass componentType = collectionType.getComponentType();
try{
Class<?> declaredClass = PrivilegedAccessHelper.getClassForName(componentType.getRawName(), false, helper.getClassLoader());
mapping.setAttributeElementClass(declaredClass);
}catch (Exception e) {}
}
} else if (helper.isCollectionType(collectionType)){
Collection args = collectionType.getActualTypeArguments();
if (args.size() >0){
JavaClass itemType = (JavaClass)args.iterator().next();
try {
Class<?> declaredClass = PrivilegedAccessHelper.getClassForName(itemType.getRawName(), false, helper.getClassLoader());
if(declaredClass != String.class){
mapping.setAttributeElementClass(declaredClass);
}
} catch (Exception e) {}
}
}
collectionType = containerClassImpl(collectionType);
mapping.useCollectionClassName(collectionType.getRawName());
if (property.getDefaultValue() != null) {
mapping.setNullValue(property.getDefaultValue());
}
// if the XPath is set (via xml-path) use it; otherwise figure it out
Field xmlField = getXPathForField(property, namespaceInfo, true, false);
mapping.setField(xmlField);
if (helper.isAnnotationPresent(property.getElement(), XmlMixed.class)) {
xmlField.setXPath("text()");
}
if (Constants.QNAME_QNAME.equals(property.getSchemaType())){
((Field) mapping.getField()).setSchemaType(Constants.QNAME_QNAME);
}
// handle null policy set via xml metadata
if (property.isSetNullPolicy()) {
mapping.setNullPolicy(getNullPolicyFromProperty(property, getNamespaceResolverForDescriptor(namespaceInfo)));
} else if (property.isNillable()){
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
mapping.getNullPolicy().setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
}
mapping.getNullPolicy().setNullRepresentedByEmptyNode(false);
if (property.isSetXmlElementWrapper()) {
mapping.setWrapperNullPolicy(getWrapperNullPolicyFromProperty(property));
}
if (property.isRequired()) {
((Field) mapping.getField()).setRequired(true);
}
if (property.isXmlElementType() && property.getGenericType()!=null ){
Class<?> theClass = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(property.getGenericType().getQualifiedName(), helper.getClassLoader());
mapping.setAttributeElementClass(theClass);
}
if (xmlField.getXPathFragment().isAttribute() || property.isXmlList() || xmlField.getXPathFragment().nameIsText()){
mapping.setUsesSingleNode(true);
}
// handle cdata set via metadata
if (property.isSetCdata()) {
mapping.setIsCDATA(property.isCdata());
}
return mapping;
}
public String getPrefixForNamespace(String URI, NamespaceResolver namespaceResolver) {
return getPrefixForNamespace(URI, namespaceResolver, true);
}
public String getPrefixForNamespace(String URI, NamespaceResolver namespaceResolver, boolean addPrefixToNR) {
String defaultNS = namespaceResolver.getDefaultNamespaceURI();
if(URI.equals(defaultNS)){
return null;
}
String prefix = namespaceResolver.resolveNamespaceURI(URI);
if (prefix != null) {
return prefix;
}
prefix = globalNamespaceResolver.resolveNamespaceURI(URI);
if(prefix == null){
if(URI.equals(globalNamespaceResolver.getDefaultNamespaceURI())) {
namespaceResolver.setDefaultNamespaceURI(URI);
return null;
} else {
//Bug 400536 before generating a new one check other resolvers
String suggestedPrefix = null;
NamespaceInfo refInfo = getNamespaceInfoForURI(URI);
if(refInfo != null && refInfo.getNamespaceResolver() !=null){
suggestedPrefix = refInfo.getNamespaceResolver().resolveNamespaceURI(URI);
}
if(suggestedPrefix != null){
prefix = globalNamespaceResolver.generatePrefix(suggestedPrefix);
} else{
prefix = globalNamespaceResolver.generatePrefix();
}
}
}
String nrUri = namespaceResolver.resolveNamespacePrefix(prefix);
while(null != nrUri && !URI.equals(nrUri)){
prefix = globalNamespaceResolver.generatePrefix();
nrUri = namespaceResolver.resolveNamespacePrefix(prefix);
}
if(addPrefixToNR){
namespaceResolver.put(prefix, URI);
}
globalNamespaceResolver.put(prefix, URI);
return prefix;
}
/**
* Setup inheritance for abstract superclass.
*
* NOTE: We currently only handle one level of inheritance in this case.
* For multiple levels the code will need to be modified. The logic in
* generateMappings() that determines when to copy down inherited
* methods from the parent class will need to be changed as well.
*
*/
private void setupInheritance(JavaClass jClass) {
TypeInfo tInfo = typeInfo.get(jClass.getName());
Descriptor descriptor = tInfo.getDescriptor();
if (descriptor == null) {
return;
}
JavaClass superClass = CompilerHelper.getNextMappedSuperClass(jClass, typeInfo, helper);
if (superClass == null){
return;
}
TypeInfo superTypeInfo = typeInfo.get(superClass.getName());
if (superTypeInfo == null){
return;
}
Descriptor superDescriptor = superTypeInfo.getDescriptor();
if (superDescriptor != null) {
XMLSchemaReference sRef = descriptor.getSchemaReference();
if (sRef == null || sRef.getSchemaContext() == null) {
return;
}
JavaClass rootMappedSuperClass = getRootMappedSuperClass(superClass);
TypeInfo rootTypeInfo = typeInfo.get(rootMappedSuperClass.getName());
Descriptor rootDescriptor = rootTypeInfo.getDescriptor();
if (rootDescriptor.getNamespaceResolver() == null) {
rootDescriptor.setNamespaceResolver(new org.eclipse.persistence.oxm.NamespaceResolver());
}
if (rootDescriptor.getInheritancePolicy().getClassIndicatorField() == null) {
Field classIndicatorField;
if (rootTypeInfo.isSetXmlDiscriminatorNode()) {
classIndicatorField = new XMLField(rootTypeInfo.getXmlDiscriminatorNode());
} else {
classIndicatorField = XMLConstants.DEFAULT_XML_TYPE_ATTRIBUTE;
classIndicatorField.getXPathFragment().setNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
}
rootDescriptor.getInheritancePolicy().setClassIndicatorField(classIndicatorField);
}
Object sCtx = null;
//TypeInfo tInfo = typeInfo.get(jClass.getName());
if (tInfo.isSetXmlDiscriminatorValue()) {
sCtx = tInfo.getXmlDiscriminatorValue();
} else if(!tInfo.isAnonymousComplexType()){
sCtx = sRef.getSchemaContextAsQName();
}
if(sCtx != null) {
descriptor.getInheritancePolicy().setParentClassName(superClass.getName());
rootDescriptor.getInheritancePolicy().addClassNameIndicator(jClass.getName(), sCtx);
}
Object value = rootDescriptor.getInheritancePolicy().getClassNameIndicatorMapping().get(rootDescriptor.getJavaClassName());
if (value == null){
if (rootTypeInfo.isSetXmlDiscriminatorValue()) {
rootDescriptor.getInheritancePolicy().addClassNameIndicator(rootDescriptor.getJavaClassName(), rootTypeInfo.getXmlDiscriminatorValue());
} else {
XMLSchemaReference rootSRef = rootDescriptor.getSchemaReference();
if (rootSRef != null && rootSRef.getSchemaContext() != null) {
QName rootSCtx = rootSRef.getSchemaContextAsQName();
rootDescriptor.getInheritancePolicy().addClassNameIndicator(rootDescriptor.getJavaClassName(), rootSCtx);
}
}
}
rootDescriptor.getInheritancePolicy().setShouldReadSubclasses(true);
//Check for attributeGroups
Map<String, AttributeGroup> childGroups = ((XMLDescriptor)descriptor).getAttributeGroups();
Map<String, AttributeGroup> parentGroups = ((XMLDescriptor)rootDescriptor).getAttributeGroups();
if(childGroups != null && !(childGroups.isEmpty()) && parentGroups != null && !(parentGroups.isEmpty())) {
for(String nextKey:childGroups.keySet()) {
AttributeGroup parentGroup = parentGroups.get(nextKey);
if(parentGroup != null) {
AttributeGroup childGroup = childGroups.get(nextKey);
parentGroup.getSubClassGroups().put(descriptor.getJavaClassName(), childGroup);
}
}
}
}
}
private JavaClass getRootMappedSuperClass(JavaClass javaClass){
JavaClass rootMappedSuperClass = javaClass;
JavaClass nextMappedSuperClass = rootMappedSuperClass;
while(nextMappedSuperClass != null){
nextMappedSuperClass = CompilerHelper.getNextMappedSuperClass(nextMappedSuperClass, this.typeInfo, helper);
if(nextMappedSuperClass == null){
return rootMappedSuperClass;
}
rootMappedSuperClass = nextMappedSuperClass;
}
return rootMappedSuperClass;
}
public void generateMappings() {
Iterator<String> javaClasses = this.typeInfo.keySet().iterator();
while (javaClasses.hasNext()) {
String next = javaClasses.next();
JavaClass javaClass = helper.getJavaClass(next);
TypeInfo info = this.typeInfo.get(next);
if (info.isEnumerationType()) {
continue;
}
NamespaceInfo namespaceInfo = this.packageToPackageInfoMappings.get(javaClass.getPackageName()).getNamespaceInfo();
Descriptor descriptor = info.getDescriptor();
if (descriptor != null) {
generateMappings(info, descriptor, javaClass, namespaceInfo);
// set primary key fields (if necessary)
CoreMapping mapping;
// handle XmlID
if (info.isIDSet()) {
mapping = descriptor.getMappingForAttributeName(info.getIDProperty().getPropertyName());
if (mapping != null) {
descriptor.addPrimaryKeyField(mapping.getField());
}
}
// handle XmlKey
if (info.hasXmlKeyProperties()) {
for (Property keyProp : info.getXmlKeyProperties()) {
mapping = descriptor.getMappingForAttributeName(keyProp.getPropertyName());
if (mapping != null) {
descriptor.addPrimaryKeyField(mapping.getField());
}
}
}
}
info.postInitialize();
if (descriptor != null) {
logMappingGeneration(descriptor);
}
}
}
/**
* Generate mappings for a given TypeInfo.
*
*/
public void generateMappings(TypeInfo info, Descriptor descriptor, JavaClass descriptorJavaClass, NamespaceInfo namespaceInfo) {
if(info.isAnonymousComplexType()) {
//may need to generate inherited mappings
generateInheritedMappingsForAnonymousType(info, descriptor, descriptorJavaClass, namespaceInfo);
}
List<Property> propertiesInOrder = info.getNonTransientPropertiesInPropOrder();
for (int i = 0; i < propertiesInOrder.size(); i++) {
Property next = propertiesInOrder.get(i);
if (next != null && (!next.isTransient() || (next.isTransient() && next.isXmlLocation()))) {
Mapping mapping = generateMapping(next, descriptor, descriptorJavaClass, namespaceInfo);
if (next.isVirtual()) {
VirtualAttributeAccessor accessor = new VirtualAttributeAccessor();
accessor.setAttributeName(mapping.getAttributeName());
String getMethod = info.getXmlVirtualAccessMethods().getGetMethod();
String setMethod = info.getXmlVirtualAccessMethods().getSetMethod();
// Check to see if get/set were overridden in the mapping
if (mapping.getAttributeAccessor().isMethodAttributeAccessor()) {
getMethod = ((MethodAttributeAccessor) mapping.getAttributeAccessor()).getGetMethodName();
setMethod = ((MethodAttributeAccessor) mapping.getAttributeAccessor()).getSetMethodName();
accessor.setValueType(mapping.getAttributeClassification());
}
accessor.setGetMethodName(getMethod);
accessor.setSetMethodName(setMethod);
if (mapping.getAttributeAccessor() instanceof JAXBArrayAttributeAccessor) {
JAXBArrayAttributeAccessor jaa = (JAXBArrayAttributeAccessor) mapping.getAttributeAccessor();
jaa.setNestedAccessor(accessor);
} else {
mapping.setAttributeAccessor(accessor);
}
}
if (mapping != null) {
descriptor.addMapping((CoreMapping)mapping);
}
// set user-defined properties if necessary
if (next.isSetUserProperties()) {
mapping.setProperties(next.getUserProperties());
}
//get package info
AccessorFactoryWrapper accessorFactory = info.getXmlAccessorFactory();
if(accessorFactory == null) {
accessorFactory = info.getPackageLevelXmlAccessorFactory();
}
if(accessorFactory != null) {
try {
Object accessor = CompilerHelper.createAccessorFor(descriptorJavaClass, next, helper, accessorFactory);
if(accessor != null) {
CustomAccessorAttributeAccessor attributeAccessor = new CustomAccessorAttributeAccessor(accessor);
mapping.setAttributeAccessor(attributeAccessor);
}
} catch(Exception ex) {}
}
}
next.postInitialize();
}
}
private void generateInheritedMappingsForAnonymousType(TypeInfo info, Descriptor descriptor, JavaClass descriptorJavaClass, NamespaceInfo namespaceInfo) {
List<TypeInfo> mappedParents = new ArrayList<>();
JavaClass next = CompilerHelper.getNextMappedSuperClass(descriptorJavaClass, typeInfo, helper);
while(next != null) {
TypeInfo nextInfo = this.typeInfo.get(next.getName());
mappedParents.add(0, nextInfo);
next = CompilerHelper.getNextMappedSuperClass(helper.getJavaClass(nextInfo.getJavaClassName()), typeInfo, helper);
}
for(TypeInfo nextInfo:mappedParents) {
List<Property> propertiesInOrder = nextInfo.getNonTransientPropertiesInPropOrder();
for (int i = 0; i < propertiesInOrder.size(); i++) {
Property nextProp = propertiesInOrder.get(i);
if (nextProp != null){
Mapping mapping = generateMapping(nextProp, descriptor, descriptorJavaClass, namespaceInfo);
descriptor.addMapping((CoreMapping)mapping);
// set user-defined properties if necessary
if (nextProp.isSetUserProperties()) {
mapping.setProperties(nextProp.getUserProperties());
}
}
}
}
}
/**
* Create an XMLCollectionReferenceMapping and add it to the descriptor.
*
*/
public CollectionReferenceMapping generateXMLCollectionReferenceMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, JavaClass referenceClass) {
CollectionReferenceMapping<AbstractSession, AttributeAccessor, ContainerPolicy, ClassDescriptor, DatabaseField, UnmarshalRecord, XMLField, XMLRecord> mapping = new XMLCollectionReferenceMapping();
initializeXMLMapping((XMLMapping)mapping, property);
initializeXMLContainerMapping(mapping, property.getType().isArray());
mapping.setUsesSingleNode(property.isXmlList() || (property.isAttribute() && (property.getXmlPath() == null || !property.getXmlPath().contains("/"))));
String referenceClassName = referenceClass.getQualifiedName();
JavaClass collectionType = property.getType();
if (collectionType.isArray()){
JAXBArrayAttributeAccessor accessor = new JAXBArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy(), helper.getClassLoader());
JavaClass componentType = collectionType.getComponentType();
if(componentType.isArray()) {
Class<?> adaptedClass = classToGeneratedClasses.get(componentType.getName());
referenceClassName = adaptedClass.getName();
accessor.setAdaptedClassName(referenceClassName);
JavaClass baseComponentType = getBaseComponentType(componentType);
if (baseComponentType.isPrimitive()){
Class<Object> primitiveClass = XMLConversionManager.getDefaultManager().convertClassNameToClass(baseComponentType.getRawName());
accessor.setComponentClass(primitiveClass);
} else {
accessor.setComponentClassName(baseComponentType.getQualifiedName());
}
} else {
accessor.setComponentClassName(componentType.getQualifiedName());
}
mapping.setAttributeAccessor(accessor);
}
collectionType = containerClassImpl(collectionType);
mapping.useCollectionClassName(collectionType.getRawName());
mapping.setReferenceClassName(referenceClassName);
// here we need to setup source/target key field associations
if (property.isSetXmlJoinNodes()) {
for (XmlJoinNode xmlJoinNode: property.getXmlJoinNodes().getXmlJoinNode()) {
validateJoinNode(descriptor.getJavaClassName(), property, xmlJoinNode.getReferencedXmlPath(), referenceClass);
mapping.addSourceToTargetKeyFieldAssociation(xmlJoinNode.getXmlPath(), xmlJoinNode.getReferencedXmlPath());
}
} else {
// here we need to setup source/target key field associations
TypeInfo referenceType = typeInfo.get(referenceClass.getQualifiedName());
String tgtXPath = null;
if (null != referenceType && referenceType.isIDSet()) {
Property prop = referenceType.getIDProperty();
tgtXPath = getXPathForField(prop, namespaceInfo, !prop.isAttribute(), false).getXPath();
}
// if the XPath is set (via xml-path) use it
Field srcXPath;
if (property.getXmlPath() != null) {
srcXPath = new XMLField(property.getXmlPath());
} else {
srcXPath = getXPathForField(property, namespaceInfo, true, false);
}
mapping.addSourceToTargetKeyFieldAssociation(srcXPath.getXPath(), tgtXPath);
}
if (property.getInverseReferencePropertyName() != null) {
mapping.getInverseReferenceMapping().setAttributeName(property.getInverseReferencePropertyName());
JavaClass backPointerPropertyType = null;
if (property.getInverseReferencePropertyGetMethodName() != null && property.getInverseReferencePropertySetMethodName() != null && !property.getInverseReferencePropertyGetMethodName().equals("") && !property.getInverseReferencePropertySetMethodName().equals("")) {
mapping.getInverseReferenceMapping().setGetMethodName(property.getInverseReferencePropertySetMethodName());
mapping.getInverseReferenceMapping().setSetMethodName(property.getInverseReferencePropertySetMethodName());
JavaMethod getMethod = referenceClass.getDeclaredMethod(mapping.getInverseReferenceMapping().getGetMethodName(), new JavaClass[]{});
if (getMethod != null) {
backPointerPropertyType = getMethod.getReturnType();
}
} else {
JavaField backpointerField = referenceClass.getDeclaredField(property.getInverseReferencePropertyName());
if (backpointerField != null) {
backPointerPropertyType = backpointerField.getResolvedType();
}
}
if (helper.isCollectionType(backPointerPropertyType)) {
mapping.getInverseReferenceMapping().setContainerPolicy(ContainerPolicy.buildDefaultPolicy());
}
}
return mapping;
}
/**
* Create an XMLObjectReferenceMapping and add it to the descriptor.
*
*/
public ObjectReferenceMapping generateXMLObjectReferenceMapping(Property property, Descriptor descriptor, NamespaceInfo namespaceInfo, JavaClass referenceClass) {
ObjectReferenceMapping<AbstractSession, AttributeAccessor, ContainerPolicy, ClassDescriptor, DatabaseField, UnmarshalRecord, XMLField, XMLRecord> mapping = new XMLObjectReferenceMapping();
initializeXMLMapping((XMLMapping)mapping, property);
mapping.setReferenceClassName(referenceClass.getQualifiedName());
// here we need to setup source/target key field associations
if (property.isSetXmlJoinNodes()) {
for (XmlJoinNode xmlJoinNode: property.getXmlJoinNodes().getXmlJoinNode()) {
validateJoinNode(descriptor.getJavaClassName(), property, xmlJoinNode.getReferencedXmlPath(), referenceClass);
mapping.addSourceToTargetKeyFieldAssociation(xmlJoinNode.getXmlPath(), xmlJoinNode.getReferencedXmlPath());
}
} else {
String tgtXPath = null;
TypeInfo referenceType = typeInfo.get(referenceClass.getQualifiedName());
if (null != referenceType && referenceType.isIDSet()) {
Property prop = referenceType.getIDProperty();
tgtXPath = getXPathForField(prop, namespaceInfo, !prop.isAttribute(), false).getXPath();
}
// if the XPath is set (via xml-path) use it, otherwise figure it out
Field srcXPath;
if (property.getXmlPath() != null) {
srcXPath = new XMLField(property.getXmlPath());
} else {
srcXPath = getXPathForField(property, namespaceInfo, true, false);
}
mapping.addSourceToTargetKeyFieldAssociation(srcXPath.getXPath(), tgtXPath);
}
if (property.getInverseReferencePropertyName() != null) {
mapping.getInverseReferenceMapping().setAttributeName(property.getInverseReferencePropertyName());
JavaClass backPointerPropertyType = null;
if (property.getInverseReferencePropertyGetMethodName() != null && property.getInverseReferencePropertySetMethodName() != null && !property.getInverseReferencePropertyGetMethodName().equals("") && !property.getInverseReferencePropertySetMethodName().equals("")) {
mapping.getInverseReferenceMapping().setGetMethodName(property.getInverseReferencePropertySetMethodName());
mapping.getInverseReferenceMapping().setSetMethodName(property.getInverseReferencePropertySetMethodName());
JavaMethod getMethod = referenceClass.getDeclaredMethod(mapping.getInverseReferenceMapping().getGetMethodName(), new JavaClass[]{});
if (getMethod != null) {
backPointerPropertyType = getMethod.getReturnType();
}
} else {
JavaField backpointerField = referenceClass.getDeclaredField(property.getInverseReferencePropertyName());
if (backpointerField != null) {
backPointerPropertyType = backpointerField.getResolvedType();
}
}
if (helper.isCollectionType(backPointerPropertyType)) {
mapping.getInverseReferenceMapping().setContainerPolicy(ContainerPolicy.buildDefaultPolicy());
}
}
return mapping;
}
private void validateJoinNode(String className, Property property, String referencedXmlPath, JavaClass referenceClass) {
TypeInfo targetInfo = this.typeInfo.get(referenceClass.getQualifiedName());
NamespaceInfo namespaceInfo = this.packageToPackageInfoMappings.get(referenceClass.getPackageName()).getNamespaceInfo();
Property idProp = targetInfo.getIDProperty();
if(idProp != null) {
String idXpath = idProp.getXmlPath();
if(idXpath == null) {
idXpath = this.getXPathForField(idProp, namespaceInfo, !idProp.isAttribute(), false).getXPath();
}
if (referencedXmlPath.equals(idXpath)) {
return;
}
}
boolean matched = false;
if (targetInfo.getXmlKeyProperties() != null) {
for (Property xmlkeyProperty : targetInfo.getXmlKeyProperties()) {
String keyXpath = xmlkeyProperty.getXmlPath();
if(keyXpath == null) {
keyXpath = this.getXPathForField(xmlkeyProperty, namespaceInfo, !xmlkeyProperty.isAttribute(), false).getXPath();
}
if (referencedXmlPath.equals(keyXpath)) {
matched = true;
break;
}
}
}
if (!matched) {
throw JAXBException.invalidReferencedXmlPathOnJoin(className, property.getPropertyName(), referenceClass.getQualifiedName(), referencedXmlPath);
}
}
private String prefixCustomXPath(String unprefixedXPath, Property property, NamespaceInfo nsInfo) {
StringBuilder newXPath = new StringBuilder(32);
QName schemaName = property.getSchemaName();
String namespace = schemaName.getNamespaceURI();
if (null == namespace || namespace.equals(Constants.EMPTY_STRING)) {
return unprefixedXPath;
}
String prefix = getPrefixForNamespace(namespace, getNamespaceResolverForDescriptor(nsInfo));
if (null == prefix) {
return unprefixedXPath;
}
StringTokenizer st = new StringTokenizer(unprefixedXPath, Constants.XPATH_SEPARATOR);
while (st.hasMoreTokens()) {
String nextToken = st.nextToken();
if (st.hasMoreTokens()) {
if (nextToken.lastIndexOf(Constants.COLON) != -1) {
// Token already has a user-supplied prefix
newXPath.append(nextToken);
} else {
newXPath.append(prefix).append(Constants.COLON).append(nextToken);
}
newXPath.append(Constants.XPATH_SEPARATOR);
} else {
// Last token is text()
newXPath.append(nextToken);
}
}
return newXPath.toString();
}
public Field getXPathForField(Property property, NamespaceInfo namespaceInfo, boolean isTextMapping, boolean isAny) {
Field xmlField = null;
String xPath = property.getXmlPath();
if (null != xPath) {
String newXPath = prefixCustomXPath(xPath, property, namespaceInfo);
xmlField = new XMLField(newXPath);
} else {
StringBuilder xPathBuilder = new StringBuilder();
if (property.isSetXmlElementWrapper()) {
XmlElementWrapper wrapper = property.getXmlElementWrapper();
String namespace = wrapper.getNamespace();
if (namespace.equals(XMLProcessor.DEFAULT)) {
if (namespaceInfo.isElementFormQualified()) {
namespace = namespaceInfo.getNamespace();
} else {
namespace = "";
}
}
if (namespace.equals("")) {
xPathBuilder.append(wrapper.getName()).append("/");
} else {
String prefix = getPrefixForNamespace(namespace, getNamespaceResolverForDescriptor(namespaceInfo));
xPathBuilder.append(getQualifiedString(prefix, wrapper.getName() + "/"));
}
if (isAny || property.isMap()) {
xmlField = new XMLField(xPathBuilder.toString());
return xmlField;
}
}
if (property.isAttribute()) {
if (property.isSetXmlPath()) {
xPathBuilder.append(property.getXmlPath());
} else {
QName name = property.getSchemaName();
String namespace = name.getNamespaceURI();
if (namespace.equals("")) {
xPathBuilder.append(ATT).append(name.getLocalPart());
} else {
String prefix = getPrefixForNamespace(namespace, getNamespaceResolverForDescriptor(namespaceInfo));
xPathBuilder.append(ATT).append(getQualifiedString(prefix, name.getLocalPart()));
}
}
xmlField = new XMLField(xPathBuilder.toString());
} else if (property.isXmlValue()) {
if(isBinaryData(property.getActualType())){
xmlField = new XMLField(".");
}else{
xmlField = new XMLField("text()");
}
} else {
QName elementName = property.getSchemaName();
xmlField = getXPathForElement(xPathBuilder.toString(), elementName, namespaceInfo, isTextMapping);
}
}
QName schemaType = userDefinedSchemaTypes.get(property.getActualType().getQualifiedName());
if (property.getSchemaType() != null) {
schemaType = property.getSchemaType();
}
if (schemaType == null) {
String propertyActualTypeRawName = property.getActualType().getRawName();
if(QName.class.getCanonicalName().equals(propertyActualTypeRawName)) {
schemaType = helper.getXMLToJavaTypeMap().get(propertyActualTypeRawName);
}
}
if(schemaType !=null && !schemaType.equals (Constants.NORMALIZEDSTRING_QNAME)){
xmlField.setSchemaType(schemaType);
}
return xmlField;
}
public Field getXPathForElement(String path, QName elementName, NamespaceInfo namespaceInfo, boolean isText) {
String namespace = "";
if (!elementName.getNamespaceURI().equals(Constants.EMPTY_STRING)) {
namespace = elementName.getNamespaceURI();
}
if (namespace.equals(Constants.EMPTY_STRING)) {
path += elementName.getLocalPart();
if (isText) {
path += TXT;
}
} else {
String prefix = getPrefixForNamespace(namespace, getNamespaceResolverForDescriptor(namespaceInfo));
path += getQualifiedString(prefix, elementName.getLocalPart());
if (isText) {
path += TXT;
}
}
return new XMLField(path);
}
public Property getXmlValueFieldForSimpleContent(ArrayList<Property> properties) {
boolean foundValue = false;
boolean foundNonAttribute = false;
Property valueField = null;
for (Property prop : properties) {
if (helper.isAnnotationPresent(prop.getElement(), XmlValue.class)) {
foundValue = true;
valueField = prop;
} else if (!helper.isAnnotationPresent(prop.getElement(), XmlAttribute.class) && !helper.isAnnotationPresent(prop.getElement(), XmlTransient.class) && !prop.isAnyAttribute()) {
foundNonAttribute = true;
}
}
if (foundValue && !foundNonAttribute) {
return valueField;
}
return null;
}
public String getSchemaTypeNameForClassName(String className) {
String typeName = Introspector.decapitalize(className.substring(className.lastIndexOf('.') + 1));
return typeName;
}
public void processGlobalElements(CoreProject project) {
//Find any global elements for classes we've generated descriptors for, and add them as possible
//root elements.
if(this.globalElements == null && this.localElements == null) {
return;
}
List<ElementDeclaration> elements = new ArrayList<>();
elements.addAll(this.localElements);
elements.addAll(this.globalElements.values());
for(ElementDeclaration nextElement:elements) {
QName next = nextElement.getElementName();
String nextClassName = nextElement.getJavaTypeName();
TypeInfo type = this.typeInfo.get(nextClassName);
if(helper.isBuiltInJavaType(nextElement.getJavaType()) || (type !=null && type.isEnumerationType())){
//generate a class/descriptor for this element
String attributeTypeName = nextClassName;
if(nextElement.getJavaType().isPrimitive()) {
attributeTypeName = helper.getClassForJavaClass(nextElement.getJavaType()).getName();
}
if (nextElement.getAdaptedJavaTypeName() != null) {
attributeTypeName = nextElement.getAdaptedJavaTypeName();
}
if(next == null){
if(isBinaryData(nextElement.getJavaType())){
Class<?> generatedClass = addByteArrayWrapperAndDescriptor(type, nextElement.getJavaType().getRawName(), nextElement,nextClassName, attributeTypeName);
this.qNamesToGeneratedClasses.put(next, generatedClass);
if(nextElement.getTypeMappingInfo() != null) {
typeMappingInfoToGeneratedClasses.put(nextElement.getTypeMappingInfo(), generatedClass);
}
try{
Class<Object> declaredClass = PrivilegedAccessHelper.getClassForName(nextClassName, false, helper.getClassLoader());
this.qNamesToDeclaredClasses.put(next, declaredClass);
}catch(Exception e){
}
}
if(nextElement.getJavaType().isEnum()) {
if(!(helper.getClassLoader() instanceof DynamicClassLoader)) {
// Only generate enum wrappers in non-dynamic case.
Class<?> generatedClass = addEnumerationWrapperAndDescriptor(type, nextElement.getJavaType().getRawName(), nextElement, nextClassName, attributeTypeName);
this.qNamesToGeneratedClasses.put(next, generatedClass);
if(nextElement.getTypeMappingInfo() != null) {
typeMappingInfoToGeneratedClasses.put(nextElement.getTypeMappingInfo(), generatedClass);
}
try{
Class<Object> declaredClass = PrivilegedAccessHelper.getClassForName(nextClassName, false, helper.getClassLoader());
this.qNamesToDeclaredClasses.put(next, declaredClass);
}catch(Exception ex) {
}
}
}
continue;
}
Class<?> generatedClass = generateWrapperClassAndDescriptor(type, next, nextElement, nextClassName, attributeTypeName);
this.qNamesToGeneratedClasses.put(next, generatedClass);
if(type != null && type.isEnumerationType() && nextElement.isXmlRootElement()) {
this.classToGeneratedClasses.put(type.getJavaClassName(), generatedClass);
}
try{
Class<Object> declaredClass = PrivilegedAccessHelper.getClassForName(nextClassName, false, helper.getClassLoader());
this.qNamesToDeclaredClasses.put(next, declaredClass);
}catch(Exception e){
}
}else if(type != null && !type.isTransient()){
if(next.getNamespaceURI() == null || next.getNamespaceURI().equals("")) {
type.getDescriptor().addRootElement(next.getLocalPart());
} else {
Descriptor descriptor = type.getDescriptor();
String uri = next.getNamespaceURI();
String prefix = getPrefixForNamespace(uri, descriptor.getNamespaceResolver());
descriptor.addRootElement(getQualifiedString(prefix, next.getLocalPart()));
}
}
}
}
private Class<?> addByteArrayWrapperAndDescriptor(TypeInfo type , String javaClassName, ElementDeclaration nextElement, String nextClassName, String attributeTypeName){
Class<?> generatedClass = classToGeneratedClasses.get(javaClassName);
if(generatedClass == null){
generatedClass = generateWrapperClassAndDescriptor(type, null, nextElement, nextClassName, attributeTypeName);
classToGeneratedClasses.put(javaClassName, generatedClass);
}
return generatedClass;
}
private Class<?> addEnumerationWrapperAndDescriptor(TypeInfo type, String javaClassName, ElementDeclaration nextElement, String nextClassName, String attributeTypeName) {
Class<?> generatedClass = classToGeneratedClasses.get(javaClassName);
if(generatedClass == null){
generatedClass = generateWrapperClassAndDescriptor(type, nextElement.getElementName(), nextElement, nextClassName, attributeTypeName);
classToGeneratedClasses.put(javaClassName, generatedClass);
}
return generatedClass;
}
private Class<?> generateWrapperClassAndDescriptor(TypeInfo type, QName next, ElementDeclaration nextElement, String nextClassName, String attributeTypeName){
String namespaceUri = null;
if(next!= null){
//generate a class/descriptor for this element
namespaceUri = next.getNamespaceURI();
if (namespaceUri == null || namespaceUri.equals(XMLProcessor.DEFAULT)) {
namespaceUri = "";
}
}
TypeMappingInfo tmi = nextElement.getTypeMappingInfo();
Class<?> generatedClass = null;
JaxbClassLoader loader = getJaxbClassLoader();
if(tmi != null){
generatedClass = CompilerHelper.getExisitingGeneratedClass(tmi, typeMappingInfoToGeneratedClasses, typeMappingInfoToAdapterClasses, helper.getClassLoader());
if(generatedClass == null){
generatedClass = this.generateWrapperClass(loader.nextAvailableGeneratedClassName(), attributeTypeName, nextElement.isList(), next);
}
typeMappingInfoToGeneratedClasses.put(tmi, generatedClass);
}else{
generatedClass = this.generateWrapperClass(loader.nextAvailableGeneratedClassName(), attributeTypeName, nextElement.isList(), next);
}
this.qNamesToGeneratedClasses.put(next, generatedClass);
try{
Class<Object> declaredClass = PrivilegedAccessHelper.getClassForName(nextClassName, false, helper.getClassLoader());
this.qNamesToDeclaredClasses.put(next, declaredClass);
}catch(Exception e){
}
Descriptor desc = (Descriptor)project.getDescriptor(generatedClass);
if(desc == null){
desc = new XMLDescriptor();
desc.setJavaClass(generatedClass);
if(nextElement.isList()){
DirectCollectionMapping<AbstractSession, AttributeAccessor, ContainerPolicy, Converter, ClassDescriptor, DatabaseField, XMLMarshaller, Session, XMLUnmarshaller, XMLRecord> mapping = new XMLCompositeDirectCollectionMapping();
mapping.setAttributeName("value");
mapping.setXPath("text()");
mapping.setUsesSingleNode(true);
mapping.setReuseContainer(true);
if(type != null && type.isEnumerationType()){
mapping.setValueConverter(buildJAXBEnumTypeConverter(mapping, (EnumTypeInfo)type));
}else{
try{
Class<Object> fieldElementClass = PrivilegedAccessHelper.getClassForName(nextClassName, false, helper.getClassLoader());
mapping.setFieldElementClass(fieldElementClass);
}catch(ClassNotFoundException e){
}
}
if(nextClassName.equals("[B") || nextClassName.equals("[Ljava.lang.Byte;")) {
((Field)mapping.getField()).setSchemaType(Constants.BASE_64_BINARY_QNAME);
}
else if(nextClassName.equals("javax.xml.namespace.QName")){
((Field)mapping.getField()).setSchemaType(Constants.QNAME_QNAME);
}
desc.addMapping((CoreMapping)mapping);
} else{
if(nextElement.getJavaTypeName().equals(OBJECT_CLASS_NAME)){
CompositeObjectMapping<AbstractSession, AttributeAccessor, ContainerPolicy, Converter, ClassDescriptor, DatabaseField, XMLMarshaller, Session, UnmarshalKeepAsElementPolicy, XMLUnmarshaller, XMLRecord> mapping = new XMLCompositeObjectMapping();
mapping.setAttributeName("value");
mapping.setSetMethodName("setValue");
mapping.setGetMethodName("getValue");
mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
mapping.setXPath(".");
setTypedTextField((Field)mapping.getField());
desc.addMapping((CoreMapping)mapping);
}else if(isBinaryData(nextElement.getJavaType())){
BinaryDataMapping<AbstractSession, AttributeAccessor, ContainerPolicy, Converter, ClassDescriptor, DatabaseField, XMLMarshaller, MimeTypePolicy, Session, XMLUnmarshaller, XMLRecord> mapping = new XMLBinaryDataMapping();
mapping.setAttributeName("value");
mapping.setXPath(".");
((Field)mapping.getField()).setSchemaType(Constants.BASE_64_BINARY_QNAME);
mapping.setSetMethodName("setValue");
mapping.setGetMethodName("getValue");
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
mapping.getNullPolicy().setNullRepresentedByEmptyNode(false);
Class<?> attributeClassification = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(attributeTypeName, helper.getClassLoader());
mapping.setAttributeClassification(attributeClassification);
mapping.setShouldInlineBinaryData(false);
//if(nextElement.getTypeMappingInfo() != null) {
mapping.setSwaRef(nextElement.isXmlAttachmentRef());
mapping.setMimeType(nextElement.getXmlMimeType());
//}
desc.addMapping((CoreMapping)mapping);
}else{
DirectMapping<AbstractSession, AttributeAccessor, ContainerPolicy, Converter, ClassDescriptor, DatabaseField, XMLMarshaller, Session, XMLUnmarshaller, XMLRecord> mapping = new XMLDirectMapping();
mapping.setNullValueMarshalled(true);
mapping.setAttributeName("value");
mapping.setXPath("text()");
mapping.setSetMethodName("setValue");
mapping.setGetMethodName("getValue");
if(nextElement.getDefaultValue() != null) {
mapping.setNullValue(nextElement.getDefaultValue());
mapping.getNullPolicy().setNullRepresentedByXsiNil(true);
}
if(helper.isBuiltInJavaType(nextElement.getJavaType())){
Class<?> attributeClassification = null;
if(nextElement.getJavaType().isPrimitive()) {
attributeClassification = XMLConversionManager.getDefaultManager().convertClassNameToClass(attributeTypeName);
} else {
attributeClassification = org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(attributeTypeName, helper.getClassLoader());
}
mapping.setAttributeClassification(attributeClassification);
}
IsSetNullPolicy nullPolicy = new IsSetNullPolicy("isSetValue", false, true, XMLNullRepresentationType.ABSENT_NODE);
//nullPolicy.setNullRepresentedByEmptyNode(true);
mapping.setNullPolicy(nullPolicy);
if(type != null && type.isEnumerationType()){
mapping.setConverter(buildJAXBEnumTypeConverter(mapping, (EnumTypeInfo)type));
}
if(nextClassName.equals("[B") || nextClassName.equals("[Ljava.lang.Byte;")) {
((Field)mapping.getField()).setSchemaType(Constants.BASE_64_BINARY_QNAME);
}
else if(nextClassName.equals("javax.xml.namespace.QName")){
((Field)mapping.getField()).setSchemaType(Constants.QNAME_QNAME);
}
if (nextElement.getJavaTypeAdapterClass() != null) {
mapping.setConverter(new XMLJavaTypeConverter(nextElement.getJavaTypeAdapterClass()));
}
desc.addMapping((CoreMapping)mapping);
}
}
if(next != null){
NamespaceInfo info = getNamespaceInfoForURI(namespaceUri);
if(info != null) {
NamespaceResolver resolver = getNamespaceResolverForDescriptor(info);
String prefix = null;
if(namespaceUri != Constants.EMPTY_STRING){
prefix = resolver.resolveNamespaceURI(namespaceUri);
if(prefix == null){
prefix = getPrefixForNamespace(namespaceUri, resolver);
}
}
desc.setNamespaceResolver(resolver);
if(nextElement.isXmlRootElement()) {
desc.setDefaultRootElement(getQualifiedString(prefix, next.getLocalPart()));
} else {
desc.setDefaultRootElement("");
desc.addRootElement(getQualifiedString(prefix, next.getLocalPart()));
desc.setResultAlwaysXMLRoot(true);
}
} else {
if(namespaceUri.equals("")) {
desc.setDefaultRootElement(next.getLocalPart());
} else {
NamespaceResolver resolver = new org.eclipse.persistence.oxm.NamespaceResolver();
String prefix = getPrefixForNamespace(namespaceUri, resolver);
desc.setNamespaceResolver(resolver);
if(nextElement.isXmlRootElement()) {
desc.setDefaultRootElement(getQualifiedString(prefix, next.getLocalPart()));
} else {
desc.setDefaultRootElement("");
desc.addRootElement(getQualifiedString(prefix, next.getLocalPart()));
desc.setResultAlwaysXMLRoot(true);
}
}
}
}
project.addDescriptor((CoreDescriptor)desc);
}
return generatedClass;
}
private String getQualifiedString(String prefix, String localPart){
if(prefix == null){
return localPart;
}
return prefix + Constants.COLON + localPart;
}
private NamespaceInfo getNamespaceInfoForURI(String namespaceUri) {
Iterator<PackageInfo> namespaces = this.packageToPackageInfoMappings.values().iterator();
while(namespaces.hasNext()) {
NamespaceInfo next = namespaces.next().getNamespaceInfo();
if(next.getNamespace().equals(namespaceUri)) {
return next;
}
}
return null;
}
@SuppressWarnings("unused")
private String getPackageNameForURI(String namespaceUri) {
for(String next:this.packageToPackageInfoMappings.keySet()) {
if(packageToPackageInfoMappings.get(next).getNamespace().equals(namespaceUri)) {
return next;
}
}
return null;
}
public Class<?> generateWrapperClass(String className, String attributeType, boolean isList, QName theQName) {
EclipseLinkASMClassWriter cw = new EclipseLinkASMClassWriter();
String sig = null;
cw.visit(Opcodes.ACC_PUBLIC, className.replace(".", "/"), sig, Type.getType(WrappedValue.class).getInternalName(), null);
String fieldType = null;
if(isList){
fieldType ="Ljava/util/List;";
}else{
fieldType = attributeType.replace(".", "/");
if(!(fieldType.startsWith("["))) {
fieldType = "L" + fieldType + ";";
}
}
if(theQName == null){
theQName = RESERVED_QNAME;
}
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitTypeInsn(Opcodes.NEW, "javax/xml/namespace/QName");
mv.visitInsn(Opcodes.DUP);
mv.visitLdcInsn(theQName.getNamespaceURI());
mv.visitLdcInsn(theQName.getLocalPart());
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "javax/xml/namespace/QName", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V", false);
mv.visitLdcInsn(Type.getType(fieldType));
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "org/eclipse/persistence/internal/jaxb/WrappedValue", "<init>", "(Ljavax/xml/namespace/QName;Ljava/lang/Class;Ljava/lang/Object;)V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(5, 1);
mv.visitEnd();
cw.visitEnd();
byte[] classBytes = cw.toByteArray();
//byte[] classBytes = new byte[]{};
Module moxyModule = MappingsGenerator.class.getModule();
if (moxyModule.isNamed() && !moxyModule.isExported(WrappedValue.class.getPackageName(), getJaxbClassLoader().getUnnamedModule())) {
// our generated classes live in unnamed module, therefore we need to export our private class
// to the unnamed module as we don't want to export internal package from eclipselink.jar
moxyModule.addExports(WrappedValue.class.getPackageName(), getJaxbClassLoader().getUnnamedModule());
}
Class<?> generatedClass = getJaxbClassLoader().generateClass(className, classBytes);
return generatedClass;
}
public Map<QName, Class<?>> getQNamesToGeneratedClasses() {
return qNamesToGeneratedClasses;
}
public Map<String, Class<?>> getClassToGeneratedClasses() {
return classToGeneratedClasses;
}
public Map<QName, Class<?>> getQNamesToDeclaredClasses() {
return qNamesToDeclaredClasses;
}
private Map<MapEntryGeneratedKey, Class<?>> getGeneratedMapEntryClasses() {
if(generatedMapEntryClasses == null){
generatedMapEntryClasses = new HashMap<>();
}
return generatedMapEntryClasses;
}
// Made static final for performance reasons.
private static final class MapEntryGeneratedKey {
@SuppressWarnings("unused")
String keyClassName;
@SuppressWarnings("unused")
String valueClassName;
public MapEntryGeneratedKey(String keyClass, String valueClass){
keyClassName = keyClass;
valueClassName = valueClass;
}
}
private AbstractNullPolicy getWrapperNullPolicyFromProperty(Property property) {
NullPolicy nullPolicy = null;
if (property.isSetXmlElementWrapper()) {
nullPolicy = new NullPolicy();
nullPolicy.setNullRepresentedByEmptyNode(false);
nullPolicy.setSetPerformedForAbsentNode(false);
if (property.getXmlElementWrapper().isNillable()) {
nullPolicy.setMarshalNullRepresentation(XMLNullRepresentationType.XSI_NIL);
nullPolicy.setNullRepresentedByXsiNil(true);
} else {
nullPolicy.setMarshalNullRepresentation(XMLNullRepresentationType.ABSENT_NODE);
nullPolicy.setNullRepresentedByXsiNil(false);
}
}
return nullPolicy;
}
/**
* Convenience method which returns an AbstractNullPolicy built from an XmlAbstractNullPolicy.
*
* @param nsr if 'NullRepresentedByXsiNil' is true, this is the resolver
* that we will add the schema instance prefix/uri pair to
* @see org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy
* @see org.eclipse.persistence.jaxb.xmlmodel.XmlAbstractNullPolicy
*/
private AbstractNullPolicy getNullPolicyFromProperty(Property property, NamespaceResolver nsr) {
AbstractNullPolicy absNullPolicy = null;
XmlAbstractNullPolicy xmlAbsNullPolicy = property.getNullPolicy();
// policy is assumed to be one of XmlNullPolicy or XmlIsSetNullPolicy
if (xmlAbsNullPolicy instanceof XmlNullPolicy) {
XmlNullPolicy xmlNullPolicy = (XmlNullPolicy) xmlAbsNullPolicy;
NullPolicy nullPolicy = new NullPolicy();
nullPolicy.setSetPerformedForAbsentNode(xmlNullPolicy.isIsSetPerformedForAbsentNode());
absNullPolicy = nullPolicy;
} else {
XmlIsSetNullPolicy xmlIsSetNullPolicy = (XmlIsSetNullPolicy) xmlAbsNullPolicy;
IsSetNullPolicy isSetNullPolicy = new IsSetNullPolicy();
isSetNullPolicy.setIsSetMethodName(xmlIsSetNullPolicy.getIsSetMethodName());
// handle isSetParams
ArrayList<Object> parameters = new ArrayList<>();
ArrayList<Class<?>> parameterTypes = new ArrayList<>();
List<XmlIsSetNullPolicy.IsSetParameter> params = xmlIsSetNullPolicy.getIsSetParameter();
for (XmlIsSetNullPolicy.IsSetParameter param : params) {
String valueStr = param.getValue();
String typeStr = param.getType();
// create a conversion manager instance with the helper's loader
XMLConversionManager mgr = new XMLConversionManager();
mgr.setLoader(helper.getClassLoader());
// handle parameter type
Class<Object> typeClass = mgr.convertClassNameToClass(typeStr);
// handle parameter value
Object parameterValue = mgr.convertObject(valueStr, typeClass);
parameters.add(parameterValue);
parameterTypes.add(typeClass);
}
isSetNullPolicy.setIsSetParameters(parameters.toArray());
isSetNullPolicy.setIsSetParameterTypes(parameterTypes.toArray(new Class<?>[parameterTypes.size()]));
absNullPolicy = isSetNullPolicy;
}
// handle commmon settings
absNullPolicy.setMarshalNullRepresentation(XMLNullRepresentationType.valueOf(xmlAbsNullPolicy.getNullRepresentationForXml().name()));
absNullPolicy.setNullRepresentedByEmptyNode(xmlAbsNullPolicy.isEmptyNodeRepresentsNull());
boolean xsiRepresentsNull = xmlAbsNullPolicy.isXsiNilRepresentsNull();
if (xsiRepresentsNull) {
absNullPolicy.setNullRepresentedByXsiNil(true);
}
return absNullPolicy;
}
/**
* Return the base component type for a class. For example, the base
* component type for Integer, Integer[], and Integer[][] are all Integer.
*/
private JavaClass getBaseComponentType(JavaClass javaClass) {
JavaClass componentType = javaClass.getComponentType();
if(null == componentType) {
return javaClass;
}
if(!componentType.isArray()) {
return componentType;
}
return getBaseComponentType(componentType);
}
public JaxbClassLoader getJaxbClassLoader() {
if (helper.getClassLoader() instanceof DynamicClassLoader) {
return (JaxbClassLoader) helper.getClassLoader().getParent();
} else {
return (JaxbClassLoader) helper.getClassLoader();
}
}
private boolean isBinaryData(JavaClass type){
return areEquals(type, CoreClassConstants.APBYTE) ||areEquals(type, "jakarta.activation.DataHandler") || areEquals(type, "java.awt.Image") || areEquals(type, "javax.xml.transform.Source") || areEquals(type, "jakarta.mail.internet.MimeMultipart");
}
// Made static final for performance reasons.
/**
* <p>An InstantiationPolicy that does not construct any objects (and therefore
* will not throw validation errors caused by a lack of a no-arg constructor).</p>
*
* <p>This is used by @XmlLocation, where we want to have a real mapping created
* (so we can later set its value through the mapping), but where we will never
* instantiate a Locator from XML (the Locator will be built internally during parsing).</p>
*
* @see org.eclipse.persistence.internal.descriptors.InstantiationPolicy
* @see org.xml.sax.Locator
*/
private static final class NullInstantiationPolicy extends InstantiationPolicy {
/**
* Returns a new instance of this InstantiationPolicy's Descriptor's class.
*
* In this case, do nothing and return null.
*/
@Override
public Object buildNewInstance() throws DescriptorException {
return null;
}
}
private void initializeXMLContainerMapping(XMLContainerMapping xmlContainerMapping, boolean isArray) {
xmlContainerMapping.setReuseContainer(!isArray);
xmlContainerMapping.setDefaultEmptyContainer(false);
}
private void initializeXMLMapping(XMLMapping mapping, Property property){
mapping.setAttributeName(property.getPropertyName());
// handle read-only set via metadata
if (property.isSetReadOnly()) {
mapping.setIsReadOnly(property.isReadOnly());
}
// handle write-only set via metadata
if (property.isSetWriteOnly()) {
mapping.setIsWriteOnly(property.isWriteOnly());
}
if (property.isMethodProperty()) {
if (property.getGetMethodName() == null) {
// handle case of set with no get method
String paramTypeAsString = property.getType().getName();
mapping.setAttributeAccessor(new JAXBSetMethodAttributeAccessor(paramTypeAsString, helper.getClassLoader()));
mapping.setIsReadOnly(true);
mapping.setSetMethodName(property.getSetMethodName());
} else if (property.getSetMethodName() == null) {
mapping.setGetMethodName(property.getGetMethodName());
mapping.setIsWriteOnly(true);
} else {
mapping.setSetMethodName(property.getSetMethodName());
mapping.setGetMethodName(property.getGetMethodName());
}
}
}
private JavaClass containerClassImpl(JavaClass collectionType) {
if (areEquals(collectionType, List.class) || areEquals(collectionType, Collection.class) || collectionType.isArray() || helper.isMapType(collectionType) ) {
return jotArrayList;
} else if (areEquals(collectionType, Set.class)) {
return jotHashSet;
} else if (areEquals(collectionType, Deque.class) || areEquals(collectionType, Queue.class)) {
return jotLinkedList;
} else if (areEquals(collectionType, NavigableSet.class) || areEquals(collectionType, SortedSet.class)) {
return jotTreeSet;
} else {
return collectionType;
}
}
private void processDefaultNamespacePreferences(Collection<PackageInfo> packageInfos) {
if (isDefaultNamespaceAllowed && globalNamespaceResolver.getDefaultNamespaceURI() == null) {
for (PackageInfo packageInfo : packageInfos) {
NamespaceResolver resolver = packageInfo.getNamespaceInfo().getNamespaceResolver();
String defaultNS = resolver.getDefaultNamespaceURI();
if (defaultNS != null) {
globalNamespaceResolver.setDefaultNamespaceURI(defaultNS);
break;
}
}
}
}
private NamespaceResolver getNamespaceResolverForDescriptor(NamespaceInfo info) {
return info.getNamespaceResolverForDescriptor(globalNamespaceResolver, isDefaultNamespaceAllowed);
}
private void logMappingGeneration(Descriptor xmlDescriptor) {
String i18nmsg = JAXBLocalization.buildMessage("create_mappings", new Object[] { xmlDescriptor.getJavaClassName() });
AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.MOXY, i18nmsg, new Object[0], false);
Iterator mappingIterator = xmlDescriptor.getMappings().iterator();
Mapping xmlMapping;
while (mappingIterator.hasNext()) {
xmlMapping = (Mapping) mappingIterator.next();
AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.MOXY, xmlMapping.toString(), new Object[0], false);
}
}
}