| /* |
| * 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: |
| // dmccann - June 17/2009 - 2.0 - Initial implementation |
| // Martin Vojtek - July 8/2014 - 2.6 - XmlNullPolicy and XmlElementNillable |
| package org.eclipse.persistence.jaxb.compiler; |
| |
| import static org.eclipse.persistence.jaxb.javamodel.Helper.getQualifiedJavaTypeName; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.StringTokenizer; |
| |
| import jakarta.xml.bind.JAXBElement; |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.persistence.exceptions.JAXBException; |
| import org.eclipse.persistence.internal.oxm.Constants; |
| import org.eclipse.persistence.internal.oxm.XMLConversionManager; |
| 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.JavaHasAnnotations; |
| import org.eclipse.persistence.jaxb.javamodel.JavaMethod; |
| import org.eclipse.persistence.jaxb.javamodel.JavaModelInput; |
| import org.eclipse.persistence.jaxb.javamodel.reflection.JavaClassImpl; |
| import org.eclipse.persistence.jaxb.xmlmodel.JavaAttribute; |
| import org.eclipse.persistence.jaxb.xmlmodel.JavaType; |
| import org.eclipse.persistence.jaxb.xmlmodel.JavaType.JavaAttributes; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlAbstractNullPolicy; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlAnyAttribute; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlAnyElement; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlAttribute; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.XmlEnums; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.XmlRegistries; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlElement; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlElementNillable; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlElementRefs; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlElements; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlEnum; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlEnumValue; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlInverseReference; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapters; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlMap; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlNamedObjectGraph; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlNsForm; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlNullPolicy; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlProperties.XmlProperty; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema.XmlNs; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaType; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaTypes; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlTransient; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlValue; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlVariableNode; |
| import org.eclipse.persistence.oxm.NamespaceResolver; |
| import org.eclipse.persistence.oxm.XMLNameTransformer; |
| |
| /** |
| * INTERNAL: |
| * <p> |
| * Purpose: XMLProcessor is used to process the meta data provided |
| * in external OXM XML files. This information is then used in conjunction with the |
| * information from AnnotationsProcess to generate schemas (via SchemaGenerator) |
| * and mappings (via MappingsGenerator). |
| * </p> |
| * |
| * <p> |
| * As a general rule meta data provided in external OXM XML files overrides meta data |
| * specified through annotations. |
| * </p> |
| * @see org.eclipse.persistence.jaxb.compiler.Generator |
| */ |
| public class XMLProcessor { |
| private Map<String, XmlBindings> xmlBindingMap; |
| private JavaModelInput jModelInput; |
| private AnnotationsProcessor aProcessor; |
| private JAXBMetadataLogger logger; |
| private static final char COLON = ':'; |
| private static final char SLASH = '/'; |
| private static final String SELF = "."; |
| private static final char OPEN_BRACKET = '['; |
| private static final String IS_STR = "is"; |
| private static final String GET_STR = "get"; |
| private static final String SET_STR = "set"; |
| private static final String JAVA_LANG_OBJECT = "java.lang.Object"; |
| public static final String DEFAULT = "##default"; |
| public static final String GENERATE = "##generate"; |
| |
| |
| /** |
| * This is the preferred constructor. |
| * |
| * @param bindings |
| */ |
| public XMLProcessor(Map<String, XmlBindings> bindings) { |
| this.xmlBindingMap = bindings; |
| } |
| |
| /** |
| * Process XmlBindings on a per package basis for a given |
| * AnnotationsProcessor instance. |
| * |
| * @param annotationsProcessor |
| */ |
| public void processXML(AnnotationsProcessor annotationsProcessor, JavaModelInput jModelInput, TypeMappingInfo[] typeMappingInfos, JavaClass[] originalJavaClasses) { |
| this.jModelInput = jModelInput; |
| this.aProcessor = annotationsProcessor; |
| this.aProcessor.setHasXmlBindings(true); |
| Map<String, XmlEnum> xmlEnumMap = new HashMap<String, XmlEnum>(); |
| aProcessor.init(originalJavaClasses, typeMappingInfos); |
| |
| // build a map of packages to JavaClass so we only process the |
| // JavaClasses for a given package additional classes - i.e. ones from |
| // packages not listed in XML - will be processed later |
| Map<String, ArrayList<JavaClass>> pkgToClassMap = buildPackageToJavaClassMap(); |
| |
| // process each XmlBindings in the map |
| XmlBindings xmlBindings; |
| for (String packageName : xmlBindingMap.keySet()) { |
| ArrayList classesToProcess = pkgToClassMap.get(packageName); |
| if (classesToProcess == null) { |
| getLogger().logWarning("jaxb_metadata_warning_no_classes_to_process", new Object[] { packageName }); |
| continue; |
| } |
| |
| xmlBindings = xmlBindingMap.get(packageName); |
| |
| // handle @XmlSchema override |
| NamespaceInfo nsInfo = processXmlSchema(xmlBindings, packageName); |
| if (nsInfo != null) { |
| aProcessor.addPackageToNamespaceMapping(packageName, nsInfo); |
| } |
| |
| // handle @XmlElementNillable override |
| if (null != xmlBindings.getXmlElementNillable()) { |
| aProcessor.addPackageToXmlElementNillable(packageName, xmlBindings.getXmlElementNillable()); |
| } |
| |
| // handle @XmlNullPolicy override |
| if (null != xmlBindings.getXmlNullPolicy()) { |
| aProcessor.addPackageToXmlNullPolicy(packageName, xmlBindings.getXmlNullPolicy()); |
| } |
| |
| // handle xml-registries |
| // add an entry to the map of registries keyed on factory class name for each |
| XmlRegistries xmlRegs = xmlBindings.getXmlRegistries(); |
| if (xmlRegs != null) { |
| for (XmlRegistry xmlReg : xmlRegs.getXmlRegistry()) { |
| aProcessor.addXmlRegistry(xmlReg.getName(), xmlReg); |
| } |
| } |
| |
| // build an array of JavaModel classes to process |
| JavaClass[] javaClasses = (JavaClass[]) classesToProcess.toArray(new JavaClass[classesToProcess.size()]); |
| |
| // handle xml-enums |
| // build a map of enum class names to XmlEnum objects |
| XmlEnums xmlEnums = xmlBindings.getXmlEnums(); |
| if (xmlEnums != null) { |
| for (XmlEnum xmlEnum : xmlEnums.getXmlEnum()) { |
| xmlEnumMap.put(getQualifiedJavaTypeName(xmlEnum.getJavaEnum(), packageName), xmlEnum); |
| } |
| } |
| |
| //handle superclass override |
| if(xmlBindings.getJavaTypes() != null) { |
| List<JavaType> types = xmlBindings.getJavaTypes().getJavaType(); |
| for(JavaType next:types) { |
| JavaClass typeClass = jModelInput.getJavaModel().getClass(getQualifiedJavaTypeName(next.getName(), packageName)); |
| if(typeClass != null && typeClass.getClass() == JavaClassImpl.class) { |
| if(next.getSuperType() != null && !(next.getSuperType().equals(DEFAULT))) { |
| JavaClass newSuperClass = jModelInput.getJavaModel().getClass(next.getSuperType()); |
| ((JavaClassImpl)typeClass).setSuperClassOverride(newSuperClass); |
| } |
| } |
| } |
| } |
| // pre-build the TypeInfo objects |
| Map<String, TypeInfo> typeInfoMap = aProcessor.preBuildTypeInfo(javaClasses); |
| |
| // handle package-level xml-schema-types |
| List<XmlSchemaType> xmlSchemaTypes = null; |
| XmlSchemaTypes sTypes = xmlBindings.getXmlSchemaTypes(); |
| if (sTypes != null) { |
| xmlSchemaTypes = sTypes.getXmlSchemaType(); |
| } else { |
| xmlSchemaTypes = new ArrayList<XmlSchemaType>(); |
| } |
| // handle package-level xml-schema-type |
| if (xmlBindings.getXmlSchemaType() != null) { |
| xmlSchemaTypes.add(xmlBindings.getXmlSchemaType()); |
| } |
| // process each xml-schema-type entry |
| for (XmlSchemaType sType : xmlSchemaTypes) { |
| JavaClass jClass = aProcessor.getHelper().getJavaClass(sType.getType()); |
| if (jClass != null) { |
| aProcessor.processSchemaType(sType.getName(), sType.getNamespace(), jClass.getQualifiedName()); |
| } |
| } |
| |
| PackageInfo packageInfo = aProcessor.getPackageToPackageInfoMappings().get(packageName); |
| if (packageInfo == null) { |
| packageInfo = new PackageInfo(); |
| } |
| if(xmlBindings.isSetXmlAccessorType()) { |
| packageInfo.setAccessType(xmlBindings.getXmlAccessorType()); |
| } |
| JavaTypes jTypes = xmlBindings.getJavaTypes(); |
| if (jTypes != null) { |
| for (JavaType javaType : jTypes.getJavaType()) { |
| TypeInfo info = typeInfoMap.get(getQualifiedJavaTypeName(javaType.getName(), packageName)); |
| |
| // package/class override order: |
| // 1 - xml class-level |
| // 2 - java object class-level |
| // 3 - xml package-level |
| // 4 - package-info.java |
| |
| // handle class-level @XmlJavaTypeAdapter override |
| if (javaType.getXmlJavaTypeAdapter() != null) { |
| info.setXmlJavaTypeAdapter(javaType.getXmlJavaTypeAdapter()); |
| } |
| |
| // handle class-level @XmlNullPolicy override |
| XmlNullPolicy xmlNullPolicy = javaType.getXmlNullPolicy(); |
| if (null != xmlNullPolicy) { |
| info.setXmlNullPolicy(xmlNullPolicy); |
| } |
| |
| // handle class-level @XmlElementNillable override |
| XmlElementNillable xmlElementNillable = javaType.getXmlElementNillable(); |
| if (null != xmlElementNillable) { |
| info.setXmlElementNillable(xmlElementNillable.isNillable()); |
| } |
| |
| // handle class-level @XmlNameTransformer |
| String transformerClassName = javaType.getXmlNameTransformer(); |
| |
| XMLNameTransformer transformer = getXMLNameTransformerClassFromString(transformerClassName); |
| if(transformer != null){ |
| info.setXmlNameTransformer(transformer); |
| } |
| // handle class-level @XmlExtensible override |
| if (javaType.getXmlVirtualAccessMethods() != null) { |
| info.setXmlVirtualAccessMethods(javaType.getXmlVirtualAccessMethods()); |
| } |
| |
| // handle class-level @XmlAccessorOrder override |
| if (javaType.isSetXmlAccessorOrder()) { |
| info.setXmlAccessOrder(javaType.getXmlAccessorOrder()); |
| } else if (!info.isSetXmlAccessOrder()) { |
| // handle package-level @XmlAccessorOrder override |
| if (xmlBindings.isSetXmlAccessorOrder()) { |
| info.setXmlAccessOrder(xmlBindings.getXmlAccessorOrder()); |
| } else { |
| // finally, check the NamespaceInfo |
| info.setXmlAccessOrder(packageInfo.getAccessOrder()); |
| } |
| } |
| |
| // handle class-level @XmlAccessorType override |
| if (javaType.isSetXmlAccessorType()) { |
| info.setXmlAccessType(javaType.getXmlAccessorType()); |
| } |
| // handle @XmlInlineBinaryData override |
| if (javaType.isSetXmlInlineBinaryData()) { |
| info.setInlineBinaryData(javaType.isXmlInlineBinaryData()); |
| } |
| // handle @XmlTransient override |
| if (javaType.isSetXmlTransient()) { |
| info.setXmlTransient(javaType.isXmlTransient()); |
| } |
| // handle @XmlRootElement |
| if (javaType.getXmlRootElement() != null) { |
| info.setXmlRootElement(javaType.getXmlRootElement()); |
| } |
| // handle @XmlSeeAlso override |
| if (javaType.getXmlSeeAlso() != null && javaType.getXmlSeeAlso().size() > 0) { |
| info.setXmlSeeAlso(javaType.getXmlSeeAlso()); |
| } |
| // handle @XmlType override |
| if (javaType.getXmlType() != null) { |
| info.setXmlType(javaType.getXmlType()); |
| } |
| // handle @XmlCustomizer override |
| if (javaType.getXmlCustomizer() != null) { |
| info.setXmlCustomizer(javaType.getXmlCustomizer()); |
| } |
| // handle @XmlClassExtractor override |
| if (javaType.getXmlClassExtractor() != null) { |
| info.setClassExtractorName(javaType.getXmlClassExtractor().getClazz()); |
| } |
| // handle @XmlProperties override |
| if (javaType.getXmlProperties() != null && javaType.getXmlProperties().getXmlProperty().size() > 0) { |
| // may need to merge with @XmlProperties (xml wins in the case of a conflict) |
| if (info.getUserProperties() != null) { |
| info.setUserProperties(mergeUserPropertyMap(javaType.getXmlProperties().getXmlProperty(), info.getUserProperties())); |
| } else { |
| info.setUserProperties(createUserPropertyMap(javaType.getXmlProperties().getXmlProperty())); |
| } |
| } |
| // handle @XmlDiscriminatorNode override |
| if (javaType.getXmlDiscriminatorNode() != null) { |
| info.setXmlDiscriminatorNode(javaType.getXmlDiscriminatorNode()); |
| } |
| // handle @NamedObjectGraph/@NamedObjectGraphs override |
| if (javaType.getXmlNamedObjectGraphs() != null) { |
| List<XmlNamedObjectGraph> currentGraphs = info.getObjectGraphs(); |
| for(XmlNamedObjectGraph nextGraph:javaType.getXmlNamedObjectGraphs().getXmlNamedObjectGraph()) { |
| //check to see if a graph with the same name already exists |
| //if so, remove it and replace it with the one from xml. |
| //if not, add the new one |
| for(XmlNamedObjectGraph nextExistingGraph: currentGraphs) { |
| if(nextGraph.getName().equals(nextExistingGraph.getName())) { |
| currentGraphs.remove(nextExistingGraph); |
| break; |
| } |
| } |
| } |
| currentGraphs.addAll(javaType.getXmlNamedObjectGraphs().getXmlNamedObjectGraph()); |
| } |
| // handle @XmlDiscriminatorValue override |
| if (javaType.getXmlDiscriminatorValue() != null) { |
| info.setXmlDiscriminatorValue(javaType.getXmlDiscriminatorValue()); |
| } |
| } |
| } |
| //apply package-level @XmlNameTransformer |
| Map<String, TypeInfo> typeInfos = aProcessor.getTypeInfosForPackage(packageName); |
| String transformerClassName = xmlBindings.getXmlNameTransformer(); |
| |
| XMLNameTransformer transformer = getXMLNameTransformerClassFromString(transformerClassName); |
| if(transformer != null){ |
| packageInfo.setXmlNameTransformer(transformer); |
| } |
| // apply package-level @XmlJavaTypeAdapters |
| for (TypeInfo tInfo : typeInfos.values()) { |
| if(xmlBindings.getXmlJavaTypeAdapters() != null){ |
| List<XmlJavaTypeAdapter> adapters = xmlBindings.getXmlJavaTypeAdapters().getXmlJavaTypeAdapter(); |
| for (XmlJavaTypeAdapter xja : adapters) { |
| try { |
| JavaClass adapterClass = jModelInput.getJavaModel().getClass(xja.getValue()); |
| JavaClass boundType = jModelInput.getJavaModel().getClass(xja.getType()); |
| if (boundType != null) { |
| tInfo.addPackageLevelAdapterClass(adapterClass, boundType); |
| packageInfo.getPackageLevelAdaptersByClass().put(boundType.getQualifiedName(), adapterClass); |
| } |
| } catch(JAXBException e) { |
| throw JAXBException.invalidPackageAdapterClass(xja.getValue(), packageName); |
| } |
| } |
| } |
| } |
| |
| } |
| for (String packageName : xmlBindingMap.keySet()) { |
| ArrayList classesToProcess = pkgToClassMap.get(packageName); |
| if (classesToProcess == null) { |
| getLogger().logWarning("jaxb_metadata_warning_no_classes_to_process", new Object[] { packageName }); |
| continue; |
| } |
| |
| xmlBindings = xmlBindingMap.get(packageName); |
| JavaClass[] javaClasses = (JavaClass[]) classesToProcess.toArray(new JavaClass[classesToProcess.size()]); |
| // post-build the TypeInfo objects |
| javaClasses = aProcessor.postBuildTypeInfo(javaClasses); |
| |
| |
| |
| // get the generated TypeInfo |
| Map<String, TypeInfo> typeInfosForPackage = aProcessor.getTypeInfosForPackage(packageName); |
| |
| // update xml-enum info if necessary |
| for (Entry<String, TypeInfo> entry : typeInfosForPackage.entrySet()) { |
| TypeInfo tInfo = entry.getValue(); |
| if (tInfo.isEnumerationType()) { |
| EnumTypeInfo etInfo = (EnumTypeInfo) tInfo; |
| XmlEnum xmlEnum = xmlEnumMap.get(etInfo.getClassName()); |
| if (xmlEnum != null) { |
| JavaClass restrictionClass = aProcessor.getHelper().getJavaClass(xmlEnum.getValue()); |
| // default to String if necessary |
| if (restrictionClass == null) { |
| restrictionClass = jModelInput.getJavaModel().getClass(String.class); |
| } |
| etInfo.setRestrictionBase(aProcessor.getSchemaTypeFor(restrictionClass)); |
| for (XmlEnumValue xmlEnumValue : xmlEnum.getXmlEnumValue()) { |
| // overwrite any existing entries (from annotations) |
| etInfo.addJavaFieldToXmlEnumValuePair(true, xmlEnumValue.getJavaEnumValue(), xmlEnumValue.getValue()); |
| } |
| } |
| } |
| } |
| |
| // update TypeInfo objects based on the JavaTypes |
| JavaTypes jTypes = xmlBindings.getJavaTypes(); |
| if (jTypes != null) { |
| PackageInfo packageInfo = aProcessor.getPackageToPackageInfoMappings().get(packageName); |
| NamespaceInfo nsInfo = null; |
| if(null != packageInfo) { |
| nsInfo = packageInfo.getNamespaceInfo(); |
| } |
| for (JavaType javaType : jTypes.getJavaType()) { |
| processJavaType(javaType, typeInfosForPackage.get(getQualifiedJavaTypeName(javaType.getName(), packageName)), nsInfo); |
| } |
| } |
| // remove the entry for this package from the map |
| pkgToClassMap.remove(packageName); |
| } |
| |
| // now process remaining classes |
| Iterator<ArrayList<JavaClass>> classIt = pkgToClassMap.values().iterator(); |
| while (classIt.hasNext()) { |
| ArrayList<JavaClass> jClassList = classIt.next(); |
| JavaClass[] jClassArray = jClassList.toArray(new JavaClass[jClassList.size()]); |
| aProcessor.buildNewTypeInfo(jClassArray); |
| aProcessor.checkForCallbackMethods(); |
| } |
| |
| // need to ensure that any bound types (from XmlJavaTypeAdapter) have TypeInfo |
| // objects built for them - SchemaGenerator will require a descriptor for each |
| Map<String, TypeInfo> typeInfos = (Map<String, TypeInfo>) ((HashMap)aProcessor.getTypeInfos()).clone(); |
| for (Entry<String, TypeInfo> entry : typeInfos.entrySet()) { |
| JavaClass[] jClassArray; |
| for (Property prop : entry.getValue().getPropertyList()) { |
| if (prop.isSetXmlJavaTypeAdapter()) { |
| jClassArray = new JavaClass[] { prop.getActualType() }; |
| aProcessor.buildNewTypeInfo(jClassArray); |
| } |
| } |
| } |
| |
| // now trigger the annotations processor to process the classes |
| List<JavaClass> jClasses = aProcessor.getTypeInfoClasses(); |
| |
| // If multiple bindings (packages) are supplied, re-process super classes |
| // (in case super and sub classes were in different packages) |
| if (xmlBindingMap.size() > 1) { |
| for (JavaClass c : jClasses) { |
| TypeInfo ti = aProcessor.getTypeInfos().get(c.getQualifiedName()); |
| aProcessor.processPropertiesSuperClass(c, ti); |
| } |
| } |
| |
| aProcessor.processPropertyTypes(jClasses.toArray(new JavaClass[jClasses.size()])); |
| aProcessor.finalizeProperties(); |
| aProcessor.createElementsForTypeMappingInfo(); |
| aProcessor.checkForCallbackMethods(); |
| } |
| |
| private XMLNameTransformer getXMLNameTransformerClassFromString(String transformerClassName){ |
| XMLNameTransformer transformer = null; |
| if(transformerClassName != null){ |
| Class nameTransformerClass; |
| |
| try { |
| nameTransformerClass = Class.forName(transformerClassName); |
| } catch (ClassNotFoundException ex) { |
| throw JAXBException.exceptionWithNameTransformerClass(transformerClassName, ex); |
| } |
| try { |
| transformer = (XMLNameTransformer) nameTransformerClass.getConstructor().newInstance(); |
| } catch (ReflectiveOperationException ex) { |
| throw JAXBException.exceptionWithNameTransformerClass(transformerClassName, ex); |
| } |
| } |
| return transformer; |
| |
| } |
| |
| /** |
| * Process a given JavaType's attributes. |
| * |
| * @param javaType |
| * @param typeInfo |
| * @param nsInfo |
| */ |
| private void processJavaType(JavaType javaType, TypeInfo typeInfo, NamespaceInfo nsInfo) { |
| // process field/property overrides |
| if (null != javaType.getJavaAttributes()) { |
| List<String> processedPropertyNames = new ArrayList<String>(); |
| for (JAXBElement jaxbElement : javaType.getJavaAttributes().getJavaAttribute()) { |
| JavaAttribute javaAttribute = (JavaAttribute) jaxbElement.getValue(); |
| |
| Property originalProperty = typeInfo.getOriginalProperties().get(javaAttribute.getJavaAttribute()); |
| if(javaAttribute.getXmlAccessorType() != null) { |
| originalProperty = processPropertyForAccessorType(typeInfo, javaAttribute, originalProperty); |
| } |
| if (originalProperty == null) { |
| if (typeInfo.getXmlVirtualAccessMethods() != null) { |
| Property newProperty = new Property(this.aProcessor.getHelper()); |
| newProperty.setPropertyName(javaAttribute.getJavaAttribute()); |
| newProperty.setExtension(true); |
| |
| String attributeType = null; |
| |
| if (javaAttribute instanceof XmlElement) { |
| attributeType = ((XmlElement) javaAttribute).getType(); |
| } else if (javaAttribute instanceof XmlAttribute) { |
| attributeType = ((XmlAttribute) javaAttribute).getType(); |
| } |
| |
| if (attributeType != null && attributeType.equals("DEFAULT")) { |
| newProperty.setType(jModelInput.getJavaModel().getClass(attributeType)); |
| } else { |
| newProperty.setType(jModelInput.getJavaModel().getClass(Helper.STRING)); |
| } |
| |
| originalProperty = newProperty; |
| typeInfo.addProperty(javaAttribute.getJavaAttribute(), newProperty); |
| } else { |
| getLogger().logWarning(JAXBMetadataLogger.NO_PROPERTY_FOR_JAVA_ATTRIBUTE, new Object[] { javaAttribute.getJavaAttribute(), javaType.getName() }); |
| continue; |
| } |
| } |
| |
| boolean alreadyProcessed = processedPropertyNames.contains(javaAttribute.getJavaAttribute()); |
| Property propToProcess; |
| |
| // In the case where there is more than one javaAttribute for the same Property |
| // (multiple mappings to same attribute) clone the original and put it in a |
| // separate Map; otherwise, update the property as per usual |
| if (alreadyProcessed) { |
| propToProcess = (Property) originalProperty.clone(); |
| } else { |
| propToProcess = typeInfo.getProperties().get(javaAttribute.getJavaAttribute()); |
| } |
| |
| processJavaAttribute(typeInfo, javaAttribute, propToProcess, nsInfo, javaType); |
| |
| // (Bug 346081) if discover a transient attribute apply same behavior as transient annotation and remove |
| if(propToProcess.isTransient()){ |
| typeInfo.getPropertyList().remove(propToProcess); |
| } |
| |
| // if we are dealing with multiple mappings for the same attribute, leave the existing |
| // property as-is and update the additionalProperties list on the owning TypeInfo |
| if (alreadyProcessed) { |
| List<Property> additionalProps = null; |
| if(typeInfo.hasAdditionalProperties()) { |
| additionalProps = typeInfo.getAdditionalProperties().get(javaAttribute.getJavaAttribute()); |
| } |
| if (additionalProps == null) { |
| additionalProps = new ArrayList<Property>(); |
| } |
| additionalProps.add(propToProcess); |
| typeInfo.getAdditionalProperties().put(javaAttribute.getJavaAttribute(), additionalProps); |
| } else { |
| // single mapping case; update the TypeInfo as per usual |
| typeInfo.getProperties().put(javaAttribute.getJavaAttribute(), propToProcess); |
| // keep track of processed property names |
| processedPropertyNames.add(javaAttribute.getJavaAttribute()); |
| } |
| } |
| } |
| } |
| |
| private Property processPropertyForAccessorType(TypeInfo typeInfo, JavaAttribute javaAttribute, Property originalProperty) { |
| if(originalProperty == null) { |
| Property prop = createProperty(typeInfo, javaAttribute); |
| if(prop != null) { |
| typeInfo.addProperty(prop.getPropertyName(), prop); |
| } |
| return prop; |
| } |
| |
| if((javaAttribute.getXmlAccessorType() == XmlAccessType.FIELD && !(originalProperty.isMethodProperty())) || |
| javaAttribute.getXmlAccessorType() == XmlAccessType.PROPERTY && originalProperty.isMethodProperty()) { |
| return originalProperty; |
| } |
| |
| originalProperty.setMethodProperty(!(originalProperty.isMethodProperty())); |
| if(originalProperty.isMethodProperty()) { |
| //figure out get and set method names. See if they exist. |
| JavaClass jClass = this.jModelInput.getJavaModel().getClass(typeInfo.getJavaClassName()); |
| |
| String propName = originalProperty.getPropertyName(); |
| propName = Character.toUpperCase(propName.charAt(0)) + propName.substring(1); |
| String getMethodName = GET_STR + propName; |
| String setMethodName = SET_STR + propName; |
| |
| JavaMethod getMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{}); |
| if(getMethod == null) { |
| getMethodName = IS_STR + propName; |
| getMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{}); |
| } |
| JavaMethod setMethod = jClass.getDeclaredMethod(setMethodName, new JavaClass[]{originalProperty.getType()}); |
| if(getMethod != null) { |
| originalProperty.setGetMethodName(getMethodName); |
| } |
| if(setMethod != null) { |
| originalProperty.setSetMethodName(setMethodName); |
| } |
| } else { |
| originalProperty.setGetMethodName(null); |
| originalProperty.setSetMethodName(null); |
| originalProperty.setMethodProperty(false); |
| } |
| |
| return originalProperty; |
| } |
| |
| private Property createProperty(TypeInfo info, JavaAttribute javaAttribute) { |
| XmlAccessType xmlAccessorType = javaAttribute.getXmlAccessorType(); |
| //Property prop = new Property(); |
| //prop.setPropertyName(javaAttribute.getJavaAttribute()); |
| String propName = javaAttribute.getJavaAttribute(); |
| JavaHasAnnotations element = null; |
| JavaClass pType = null; |
| JavaClass jClass = this.jModelInput.getJavaModel().getClass(info.getJavaClassName()); |
| if(xmlAccessorType == XmlAccessType.PROPERTY) { |
| //set up accessor method names |
| String name = Character.toUpperCase(propName.charAt(0)) + propName.substring(1); |
| String getMethodName = GET_STR + name; |
| String setMethodName = SET_STR + name; |
| |
| JavaMethod jMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{}); |
| if(jMethod == null) { |
| getMethodName = IS_STR + name; |
| jMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{}); |
| } |
| if(jMethod != null) { |
| pType = jMethod.getReturnType(); |
| element = jMethod; |
| } else { |
| //look for a set method if type is set on javaAttribute |
| for (Object next:jClass.getDeclaredMethods()) { |
| JavaMethod nextMethod = (JavaMethod)next; |
| if(nextMethod.getName().equals(setMethodName) && nextMethod.getParameterTypes().length == 1) { |
| pType = nextMethod.getParameterTypes()[0]; |
| element = nextMethod; |
| } |
| |
| } |
| if(element == null) { |
| return null; |
| } |
| } |
| } else { |
| JavaField jField = jClass.getDeclaredField(propName); |
| if(jField == null) { |
| return null; |
| } |
| pType = jField.getResolvedType(); |
| element = jField; |
| } |
| |
| return this.aProcessor.buildNewProperty(info, jClass, element, propName, pType); |
| } |
| |
| /** |
| * Process a given JavaAtribute. |
| * |
| * @param javaAttribute |
| * @param oldProperty |
| * @param nsInfo |
| * @return |
| */ |
| private Property processJavaAttribute(TypeInfo typeInfo, JavaAttribute javaAttribute, Property oldProperty, NamespaceInfo nsInfo, JavaType javaType) { |
| if (javaAttribute instanceof XmlVariableNode) { |
| return processXmlVariableNodeAttribute((XmlVariableNode) javaAttribute, oldProperty, typeInfo, javaType); |
| } |
| if (javaAttribute instanceof XmlAnyAttribute) { |
| return processXmlAnyAttribute((XmlAnyAttribute) javaAttribute, oldProperty, typeInfo, javaType); |
| } |
| if (javaAttribute instanceof XmlAnyElement) { |
| return processXmlAnyElement((XmlAnyElement) javaAttribute, oldProperty, typeInfo, javaType); |
| } |
| if (javaAttribute instanceof XmlAttribute) { |
| return processXmlAttribute((XmlAttribute) javaAttribute, oldProperty, typeInfo, nsInfo, javaType); |
| } |
| if (javaAttribute instanceof XmlElement) { |
| return processXmlElement((XmlElement) javaAttribute, oldProperty, typeInfo, nsInfo, javaType); |
| } |
| if (javaAttribute instanceof XmlElements) { |
| return processXmlElements((XmlElements) javaAttribute, oldProperty, typeInfo); |
| } |
| if (javaAttribute instanceof XmlElementRef) { |
| return processXmlElementRef((XmlElementRef) javaAttribute, oldProperty, typeInfo); |
| } |
| if (javaAttribute instanceof XmlElementRefs) { |
| return processXmlElementRefs((XmlElementRefs) javaAttribute, oldProperty, typeInfo); |
| } |
| if (javaAttribute instanceof XmlTransient) { |
| return processXmlTransient((XmlTransient) javaAttribute, oldProperty); |
| } |
| if (javaAttribute instanceof XmlValue) { |
| return processXmlValue((XmlValue) javaAttribute, oldProperty, typeInfo, javaType); |
| } |
| if (javaAttribute instanceof XmlJavaTypeAdapter) { |
| return processXmlJavaTypeAdapter((XmlJavaTypeAdapter) javaAttribute, oldProperty); |
| } |
| if (javaAttribute instanceof XmlInverseReference) { |
| return processXmlInverseReference((XmlInverseReference)javaAttribute, oldProperty, typeInfo); |
| } |
| if (javaAttribute instanceof XmlTransformation) { |
| return processXmlTransformation((XmlTransformation)javaAttribute, oldProperty, typeInfo); |
| } |
| if (javaAttribute instanceof XmlJoinNodes) { |
| return processXmlJoinNodes((XmlJoinNodes) javaAttribute, oldProperty, typeInfo); |
| } |
| getLogger().logWarning("jaxb_metadata_warning_invalid_java_attribute", new Object[] { javaAttribute.getClass() }); |
| return null; |
| } |
| |
| /** |
| * Handle property-level XmlJavaTypeAdapter |
| * |
| * @param xmlAdapter |
| * @param oldProperty |
| * @return |
| */ |
| private Property processXmlJavaTypeAdapter(XmlJavaTypeAdapter xmlAdapter, Property oldProperty) { |
| oldProperty.setXmlJavaTypeAdapter(xmlAdapter); |
| return oldProperty; |
| } |
| |
| /** |
| * Handle xml-inverse-reference. |
| * |
| * @param xmlInverseReference |
| * @param oldProperty |
| * @return |
| */ |
| private Property processXmlInverseReference(XmlInverseReference xmlInverseReference, Property oldProperty, TypeInfo info) { |
| resetProperty(oldProperty, info); |
| oldProperty.setInverseReference(true, false); |
| oldProperty.setInverseReferencePropertyName(xmlInverseReference.getMappedBy()); |
| if (xmlInverseReference.getXmlAccessMethods() != null) { |
| oldProperty.setInverseReferencePropertyGetMethodName(xmlInverseReference.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setInverseReferencePropertySetMethodName(xmlInverseReference.getXmlAccessMethods().getSetMethod()); |
| } |
| // set user-defined properties |
| if (xmlInverseReference.getXmlProperties() != null && xmlInverseReference.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlInverseReference.getXmlProperties().getXmlProperty())); |
| } |
| // check for container type |
| if (!xmlInverseReference.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlInverseReference.getContainerType()); |
| } |
| // set type |
| if (!xmlInverseReference.getType().equals(DEFAULT)) { |
| JavaClass pType = jModelInput.getJavaModel().getClass(xmlInverseReference.getType()); |
| if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) { |
| oldProperty.setGenericType(pType); |
| } else { |
| oldProperty.setType(pType); |
| } |
| oldProperty.setHasXmlElementType(true); |
| // may need to generate a type info for the type |
| if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) { |
| aProcessor.buildNewTypeInfo(new JavaClass[] { pType }); |
| } |
| } |
| return oldProperty; |
| } |
| |
| /** |
| * Handle xml-any-attribute. |
| * |
| * @param xmlAnyAttribute |
| * @param oldProperty |
| * @param tInfo |
| * @param javaType |
| * @return |
| */ |
| private Property processXmlAnyAttribute(XmlAnyAttribute xmlAnyAttribute, Property oldProperty, TypeInfo tInfo, JavaType javaType) { |
| // if oldProperty is already an Any (via @XmlAnyAttribute annotation) |
| // there's nothing to do |
| if (oldProperty.isAnyAttribute()) { |
| return oldProperty; |
| } |
| |
| // type has to be a java.util.Map |
| if (!aProcessor.getHelper().isMapType(oldProperty.getType())) { |
| if (oldProperty.getType().getClass().getName().contains("OXMJavaClassImpl")) { |
| JavaClass pType = jModelInput.getJavaModel().getClass("java.util.Map"); |
| oldProperty.setType(pType); |
| } else { |
| throw org.eclipse.persistence.exceptions.JAXBException.anyAttributeOnNonMap(oldProperty.getPropertyName()); |
| } |
| } |
| |
| // reset any existing values |
| resetProperty(oldProperty, tInfo); |
| |
| oldProperty.setIsAnyAttribute(true); |
| tInfo.setAnyAttributePropertyName(oldProperty.getPropertyName()); |
| |
| // handle XmlPath |
| if (xmlAnyAttribute.getXmlPath() != null) { |
| oldProperty.setXmlPath(xmlAnyAttribute.getXmlPath()); |
| } |
| // handle get/set methods |
| if (xmlAnyAttribute.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlAnyAttribute.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlAnyAttribute.getXmlAccessMethods().getSetMethod()); |
| } |
| // handle read-only |
| if (xmlAnyAttribute.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlAnyAttribute.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlAnyAttribute.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlAnyAttribute.isWriteOnly()); |
| } |
| // set user-defined properties |
| if (xmlAnyAttribute.getXmlProperties() != null && xmlAnyAttribute.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlAnyAttribute.getXmlProperties().getXmlProperty())); |
| } |
| // check for container type |
| if (!xmlAnyAttribute.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlAnyAttribute.getContainerType()); |
| } |
| return oldProperty; |
| } |
| |
| |
| |
| private Property processXmlVariableNodeAttribute(XmlVariableNode xmlVariableNode, Property oldProperty, TypeInfo tInfo, JavaType javaType) { |
| processObjectFactory(tInfo); |
| |
| // reset any existing values |
| resetProperty(oldProperty, tInfo); |
| |
| oldProperty.setVariableAttributeName(xmlVariableNode.getJavaVariableAttribute()); |
| String type = xmlVariableNode.getType(); |
| if(!type.equals(DEFAULT)){ |
| oldProperty.setVariableClassName(type); |
| } |
| |
| if (xmlVariableNode.getXmlPath() != null) { |
| oldProperty.setXmlPath(xmlVariableNode.getXmlPath()); |
| } else { |
| // no xml-path, so use name/namespace from xml-element, and process wrapper |
| XmlElementWrapper xmlElementWrapper = xmlVariableNode.getXmlElementWrapper(); |
| if (xmlElementWrapper != null) { |
| if (DEFAULT.equals(xmlElementWrapper.getName())) { |
| xmlElementWrapper.setName(tInfo.getXmlNameTransformer().transformElementName(oldProperty.getPropertyName())); |
| } |
| oldProperty.setXmlElementWrapper(xmlVariableNode.getXmlElementWrapper()); |
| } |
| } |
| |
| |
| return oldProperty; |
| } |
| |
| |
| /** |
| * Handle xml-any-element. If the property was annotated with @XmlAnyElement |
| * in code all values will be overridden. |
| * |
| * @param xmlAnyElement |
| * @param oldProperty |
| * @param tInfo |
| * @param javaType |
| * @return |
| */ |
| private Property processXmlAnyElement(XmlAnyElement xmlAnyElement, Property oldProperty, TypeInfo tInfo, JavaType javaType) { |
| |
| processObjectFactory(tInfo); |
| |
| // reset any existing values |
| resetProperty(oldProperty, tInfo); |
| |
| // set xml-any-element specific properties |
| oldProperty.setIsAny(true); |
| oldProperty.setDomHandlerClassName(xmlAnyElement.getDomHandler()); |
| oldProperty.setLax(xmlAnyElement.isLax()); |
| oldProperty.setMixedContent(xmlAnyElement.isXmlMixed()); |
| oldProperty.setXmlJavaTypeAdapter(xmlAnyElement.getXmlJavaTypeAdapter()); |
| |
| // update TypeInfo |
| tInfo.setMixed(xmlAnyElement.isXmlMixed()); |
| tInfo.setAnyElementPropertyName(oldProperty.getPropertyName()); |
| |
| // handle XmlPath |
| if (xmlAnyElement.getXmlPath() != null) { |
| oldProperty.setXmlPath(xmlAnyElement.getXmlPath()); |
| } |
| // handle get/set methods |
| if (xmlAnyElement.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlAnyElement.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlAnyElement.getXmlAccessMethods().getSetMethod()); |
| } |
| // handle read-only |
| if (xmlAnyElement.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlAnyElement.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlAnyElement.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlAnyElement.isWriteOnly()); |
| } |
| // set user-defined properties |
| if (xmlAnyElement.getXmlProperties() != null && xmlAnyElement.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlAnyElement.getXmlProperties().getXmlProperty())); |
| } |
| // check for container type |
| if (!xmlAnyElement.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlAnyElement.getContainerType()); |
| } |
| // check for xml-element-refs |
| if (xmlAnyElement.getXmlElementRefs() != null) { |
| oldProperty.setXmlElementRefs(xmlAnyElement.getXmlElementRefs().getXmlElementRef()); |
| oldProperty.setIsReference(true); |
| |
| boolean required = true; |
| for (XmlElementRef eltRef : xmlAnyElement.getXmlElementRefs().getXmlElementRef()) { |
| required = required && eltRef.isRequired(); |
| } |
| oldProperty.setIsRequired(required); |
| if (xmlAnyElement.getXmlElementRefs().isSetXmlMixed()) { |
| oldProperty.setMixedContent(xmlAnyElement.getXmlElementRefs().isXmlMixed()); |
| } |
| } |
| |
| return oldProperty; |
| } |
| |
| /** |
| * XmlAttribute override will completely replace the existing values. |
| * |
| * @param xmlAttribute |
| * @param oldProperty |
| * @param nsInfo |
| * @return |
| */ |
| private Property processXmlAttribute(XmlAttribute xmlAttribute, Property oldProperty, TypeInfo typeInfo, NamespaceInfo nsInfo, JavaType javaType) { |
| // reset any existing values |
| resetProperty(oldProperty, typeInfo); |
| |
| // handle xml-id |
| if (xmlAttribute.isXmlId()) { |
| oldProperty.setIsXmlId(true); |
| oldProperty.setIsXmlIdExtension(true); |
| typeInfo.setIDProperty(oldProperty); |
| } else { |
| // account for XmlID un-set via XML |
| if (typeInfo.getIDProperty() != null && typeInfo.getIDProperty().getPropertyName().equals(oldProperty.getPropertyName())) { |
| typeInfo.setIDProperty(null); |
| } |
| } |
| |
| // handle xml-idref |
| oldProperty.setIsXmlIdRef(xmlAttribute.isXmlIdref()); |
| |
| // handle xml-key |
| if (xmlAttribute.isXmlKey()) { |
| typeInfo.addXmlKeyProperty(oldProperty); |
| } |
| |
| // set isAttribute |
| oldProperty.setIsAttribute(true); |
| |
| // set xml-inline-binary-data |
| oldProperty.setisInlineBinaryData(xmlAttribute.isXmlInlineBinaryData()); |
| |
| String name; |
| String namespace; |
| |
| // handle XmlPath |
| // if xml-path is set, we ignore name/namespace |
| if (xmlAttribute.getXmlPath() != null) { |
| oldProperty.setXmlPath(xmlAttribute.getXmlPath()); |
| name = getNameFromXPath(xmlAttribute.getXmlPath(), oldProperty.getPropertyName(), true); |
| namespace = DEFAULT; |
| } else { |
| // no xml-path, so use name/namespace from xml-attribute |
| name = xmlAttribute.getName(); |
| namespace = xmlAttribute.getNamespace(); |
| } |
| |
| if (javaType.getXmlType() != null && javaType.getXmlType().getNamespace() != null && |
| (xmlAttribute.getNamespace() != null && xmlAttribute.getNamespace().equals(DEFAULT))) { |
| // Inherit type-level namespace if there is one |
| namespace = javaType.getXmlType().getNamespace(); |
| } |
| |
| // set schema name |
| QName qName; |
| if (name.equals(DEFAULT)) { |
| name = typeInfo.getXmlNameTransformer().transformAttributeName(oldProperty.getPropertyName()); |
| } |
| if (namespace.equals(DEFAULT)) { |
| if (nsInfo.isAttributeFormQualified()) { |
| qName = new QName(nsInfo.getNamespace(), name); |
| } else { |
| qName = new QName(name); |
| } |
| } else { |
| qName = new QName(namespace, name); |
| } |
| oldProperty.setSchemaName(qName); |
| |
| // check for container type |
| if (!xmlAttribute.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlAttribute.getContainerType()); |
| } |
| // set type |
| if (!xmlAttribute.getType().equals(DEFAULT)) { |
| JavaClass pType = jModelInput.getJavaModel().getClass(xmlAttribute.getType()); |
| if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) { |
| oldProperty.setGenericType(pType); |
| } else { |
| oldProperty.setType(pType); |
| } |
| oldProperty.setHasXmlElementType(true); |
| // may need to generate a type info for the type |
| if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) { |
| aProcessor.buildNewTypeInfo(new JavaClass[] { pType }); |
| } |
| } |
| |
| reapplyPackageAndClassAdapters(oldProperty, typeInfo); |
| // handle XmlJavaTypeAdapter |
| if (xmlAttribute.getXmlJavaTypeAdapter() != null) { |
| oldProperty.setXmlJavaTypeAdapter(xmlAttribute.getXmlJavaTypeAdapter()); |
| } |
| |
| // handle required - for required, if set by user than true/false; |
| // if not set by user, true if property type == primitive |
| if (xmlAttribute.isSetRequired()) { |
| oldProperty.setIsRequired(xmlAttribute.isRequired()); |
| } else if (oldProperty.getActualType().isPrimitive()) { |
| oldProperty.setIsRequired(true); |
| } |
| |
| // handle xml-mime-type |
| if (xmlAttribute.getXmlMimeType() != null) { |
| oldProperty.setMimeType(xmlAttribute.getXmlMimeType()); |
| } |
| |
| // handle xml-attachment-ref |
| if (xmlAttribute.isXmlAttachmentRef()) { |
| oldProperty.setIsSwaAttachmentRef(true); |
| oldProperty.setSchemaType(Constants.SWA_REF_QNAME); |
| } else if (aProcessor.isMtomAttachment(oldProperty)) { |
| oldProperty.setIsMtomAttachment(true); |
| oldProperty.setSchemaType(Constants.BASE_64_BINARY_QNAME); |
| } |
| |
| // handle xml-schema-type |
| if (xmlAttribute.getXmlSchemaType() != null) { |
| oldProperty.setSchemaType(new QName(xmlAttribute.getXmlSchemaType().getNamespace(), xmlAttribute.getXmlSchemaType().getName())); |
| } |
| // handle get/set methods |
| if (xmlAttribute.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlAttribute.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlAttribute.getXmlAccessMethods().getSetMethod()); |
| } |
| // handle read-only |
| if (xmlAttribute.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlAttribute.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlAttribute.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlAttribute.isWriteOnly()); |
| } |
| // handle null policy |
| if (xmlAttribute.getXmlAbstractNullPolicy() != null) { |
| JAXBElement jaxbElt = xmlAttribute.getXmlAbstractNullPolicy(); |
| oldProperty.setNullPolicy((XmlAbstractNullPolicy) jaxbElt.getValue()); |
| } |
| // set user-defined properties |
| if (xmlAttribute.getXmlProperties() != null && xmlAttribute.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlAttribute.getXmlProperties().getXmlProperty())); |
| } |
| return oldProperty; |
| } |
| |
| /** |
| * XmlElement override will completely replace the existing values. |
| * |
| * @param xmlElement |
| * @param oldProperty |
| * @param typeInfo |
| * @param nsInfo |
| * @return |
| */ |
| private Property processXmlElement(XmlElement xmlElement, Property oldProperty, TypeInfo typeInfo, NamespaceInfo nsInfo, JavaType javaType) { |
| // reset any existing values |
| resetProperty(oldProperty, typeInfo); |
| |
| if (xmlElement.getXmlMap() != null) { |
| processXmlMap(xmlElement.getXmlMap(), oldProperty); |
| } |
| |
| if (xmlElement.isXmlLocation()) { |
| if (!aProcessor.getHelper().getJavaClass(Constants.LOCATOR_CLASS).isAssignableFrom(oldProperty.getType())) { |
| throw JAXBException.invalidXmlLocation(oldProperty.getPropertyName(), oldProperty.getType().getName()); |
| } |
| oldProperty.setXmlLocation(true); |
| } |
| |
| // handle xml-id |
| if (xmlElement.isXmlId()) { |
| oldProperty.setIsXmlId(true); |
| oldProperty.setIsXmlIdExtension(true); |
| typeInfo.setIDProperty(oldProperty); |
| } else { |
| // account for XmlID un-set via XML |
| if (typeInfo.getIDProperty() != null && typeInfo.getIDProperty().getPropertyName().equals(oldProperty.getPropertyName())) { |
| typeInfo.setIDProperty(null); |
| } |
| } |
| |
| if(xmlElement.getXmlInverseReference() != null){ |
| String mappedBy = xmlElement.getXmlInverseReference().getMappedBy(); |
| oldProperty.setInverseReference(true, true); |
| oldProperty.setInverseReferencePropertyName(mappedBy); |
| } |
| |
| // handle xml-idref |
| oldProperty.setIsXmlIdRef(xmlElement.isXmlIdref()); |
| |
| // handle xml-key |
| if (xmlElement.isXmlKey()) { |
| typeInfo.addXmlKeyProperty(oldProperty); |
| } |
| |
| // set required |
| oldProperty.setIsRequired(xmlElement.isRequired()); |
| |
| // set xml-inline-binary-data |
| oldProperty.setisInlineBinaryData(xmlElement.isXmlInlineBinaryData()); |
| |
| // set nillable |
| oldProperty.setNillable(xmlElement.isNillable()); |
| |
| // set defaultValue |
| if (xmlElement.getDefaultValue().equals("\u0000")) { |
| oldProperty.setDefaultValue(null); |
| } else { |
| oldProperty.setDefaultValue(xmlElement.getDefaultValue()); |
| } |
| |
| String name; |
| String namespace; |
| |
| // handle XmlPath / XmlElementWrapper |
| // if xml-path is set, we ignore xml-element-wrapper, as well as name/namespace on xml-element |
| if (xmlElement.getXmlPath() != null) { |
| oldProperty.setXmlPath(xmlElement.getXmlPath()); |
| name = getNameFromXPath(xmlElement.getXmlPath(), oldProperty.getPropertyName(), false); |
| namespace = DEFAULT; |
| } else { |
| // no xml-path, so use name/namespace from xml-element, and process wrapper |
| name = xmlElement.getName(); |
| namespace = xmlElement.getNamespace(); |
| XmlElementWrapper xmlElementWrapper = xmlElement.getXmlElementWrapper(); |
| if (xmlElementWrapper != null) { |
| if (DEFAULT.equals(xmlElementWrapper.getName())) { |
| xmlElementWrapper.setName(typeInfo.getXmlNameTransformer().transformElementName(oldProperty.getPropertyName())); |
| } |
| oldProperty.setXmlElementWrapper(xmlElement.getXmlElementWrapper()); |
| if(oldProperty.isMap()){ |
| name = xmlElement.getXmlElementWrapper().getName(); |
| namespace = xmlElement.getXmlElementWrapper().getNamespace(); |
| } |
| } |
| } |
| |
| if (javaType.getXmlType() != null && javaType.getXmlType().getNamespace() != null && |
| (xmlElement.getNamespace() != null && xmlElement.getNamespace().equals(DEFAULT))) { |
| // Inherit type-level namespace if there is one |
| namespace = javaType.getXmlType().getNamespace(); |
| } |
| |
| // set schema name |
| QName qName; |
| if (name.equals(DEFAULT)) { |
| name = typeInfo.getXmlNameTransformer().transformElementName(oldProperty.getPropertyName()); |
| } |
| if (namespace.equals(DEFAULT)) { |
| if (nsInfo.isElementFormQualified()) { |
| qName = new QName(nsInfo.getNamespace(), name); |
| } else { |
| qName = new QName(name); |
| } |
| } else { |
| qName = new QName(namespace, name); |
| } |
| oldProperty.setSchemaName(qName); |
| |
| // check for container type |
| if (!xmlElement.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlElement.getContainerType()); |
| } |
| // set type |
| if (xmlElement.getType().equals("jakarta.xml.bind.annotation.XmlElement.DEFAULT")) { |
| // if xmlElement has no type, and the property type was set via |
| // @XmlElement, reset it to the original value |
| if (oldProperty.isXmlElementType()) { |
| oldProperty.setType(oldProperty.getOriginalType()); |
| } |
| } else if (xmlElement.getXmlMap() != null) { |
| getLogger().logWarning(JAXBMetadataLogger.INVALID_TYPE_ON_MAP, new Object[] { xmlElement.getName() }); |
| } else { |
| JavaClass pType = jModelInput.getJavaModel().getClass(xmlElement.getType()); |
| if(aProcessor.getHelper().isCollectionType(oldProperty.getType())) { |
| oldProperty.setGenericType(pType); |
| } else { |
| oldProperty.setType(pType); |
| } |
| oldProperty.setHasXmlElementType(true); |
| // may need to generate a type info for the type |
| if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) { |
| aProcessor.buildNewTypeInfo(new JavaClass[] { pType }); |
| } |
| } |
| |
| reapplyPackageAndClassAdapters(oldProperty, typeInfo); |
| // handle XmlJavaTypeAdapter |
| if (xmlElement.getXmlJavaTypeAdapter() != null) { |
| try { |
| oldProperty.setXmlJavaTypeAdapter(xmlElement.getXmlJavaTypeAdapter()); |
| } catch(JAXBException e) { |
| throw JAXBException.invalidPropertyAdapterClass(xmlElement.getXmlJavaTypeAdapter().getValue(), xmlElement.getJavaAttribute(), javaType.getName()); |
| } |
| } |
| |
| // for primitives we always set required, a.k.a. minOccurs="1" |
| if (!oldProperty.isRequired()) { |
| JavaClass ptype = oldProperty.getActualType(); |
| oldProperty.setIsRequired(ptype.isPrimitive() || ptype.isArray() && ptype.getComponentType().isPrimitive()); |
| } |
| |
| // handle xml-list |
| if (xmlElement.isSetXmlList()) { |
| // Make sure XmlList annotation is on a collection or array |
| if (!aProcessor.getHelper().isCollectionType(oldProperty.getType()) && !oldProperty.getType().isArray()) { |
| throw JAXBException.invalidList(oldProperty.getPropertyName()); |
| } |
| oldProperty.setIsXmlList(xmlElement.isXmlList()); |
| } |
| |
| // handle xml-mime-type |
| if (xmlElement.getXmlMimeType() != null) { |
| oldProperty.setMimeType(xmlElement.getXmlMimeType()); |
| } |
| |
| // handle xml-attachment-ref |
| if (xmlElement.isXmlAttachmentRef()) { |
| oldProperty.setIsSwaAttachmentRef(true); |
| oldProperty.setSchemaType(Constants.SWA_REF_QNAME); |
| } else if (aProcessor.isMtomAttachment(oldProperty)) { |
| oldProperty.setIsMtomAttachment(true); |
| oldProperty.setSchemaType(Constants.BASE_64_BINARY_QNAME); |
| } |
| |
| // handle xml-schema-type |
| if (xmlElement.getXmlSchemaType() != null) { |
| oldProperty.setSchemaType(new QName(xmlElement.getXmlSchemaType().getNamespace(), xmlElement.getXmlSchemaType().getName())); |
| } |
| // handle get/set methods |
| if (xmlElement.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlElement.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlElement.getXmlAccessMethods().getSetMethod()); |
| } |
| // handle read-only |
| if (xmlElement.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlElement.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlElement.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlElement.isWriteOnly()); |
| } |
| // handle cdata |
| if (xmlElement.isSetCdata()) { |
| oldProperty.setCdata(xmlElement.isCdata()); |
| } |
| // handle null policy |
| if (xmlElement.getXmlAbstractNullPolicy() != null) { |
| JAXBElement jaxbElt = xmlElement.getXmlAbstractNullPolicy(); |
| oldProperty.setNullPolicy((XmlAbstractNullPolicy) jaxbElt.getValue()); |
| } |
| // set user-defined properties |
| if (xmlElement.getXmlProperties() != null && xmlElement.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlElement.getXmlProperties().getXmlProperty())); |
| } |
| return oldProperty; |
| } |
| |
| private Property processXmlMap(XmlMap xmlMap, Property oldProperty) { |
| XmlMap.Key mapKey = xmlMap.getKey(); |
| XmlMap.Value mapValue = xmlMap.getValue(); |
| |
| if (mapKey != null && mapKey.getType() != null) { |
| oldProperty.setKeyType(jModelInput.getJavaModel().getClass(mapKey.getType())); |
| } else { |
| oldProperty.setKeyType(jModelInput.getJavaModel().getClass(JAVA_LANG_OBJECT)); |
| } |
| |
| if (mapValue != null && mapValue.getType() != null) { |
| oldProperty.setValueType(jModelInput.getJavaModel().getClass(mapValue.getType())); |
| } else { |
| oldProperty.setValueType(jModelInput.getJavaModel().getClass(JAVA_LANG_OBJECT)); |
| } |
| |
| return oldProperty; |
| } |
| |
| /** |
| * Process XmlElements. |
| * |
| * The XmlElements object will be set on the property, and it will be |
| * flagged as a 'choice'. |
| * |
| * @param xmlElements |
| * @param oldProperty |
| * @param tInfo |
| * @return |
| */ |
| private Property processXmlElements(XmlElements xmlElements, Property oldProperty, TypeInfo tInfo) { |
| resetProperty(oldProperty, tInfo); |
| oldProperty.setChoice(true); |
| oldProperty.setXmlElements(xmlElements); |
| // handle idref |
| oldProperty.setIsXmlIdRef(xmlElements.isXmlIdref()); |
| // handle XmlElementWrapper |
| if (xmlElements.getXmlElementWrapper() != null) { |
| oldProperty.setXmlElementWrapper(xmlElements.getXmlElementWrapper()); |
| } |
| // handle get/set methods |
| if (xmlElements.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlElements.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlElements.getXmlAccessMethods().getSetMethod()); |
| } |
| // handle read-only |
| if (xmlElements.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlElements.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlElements.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlElements.isWriteOnly()); |
| } |
| // set user-defined properties |
| if (xmlElements.getXmlProperties() != null && xmlElements.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlElements.getXmlProperties().getXmlProperty())); |
| } |
| // check for container type |
| if (!xmlElements.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlElements.getContainerType()); |
| } |
| // check for xml-join-nodes |
| if (xmlElements.hasXmlJoinNodes()) { |
| // store the List of XmlJoinNodes so we can access them when |
| // we process the choice elements in AnnotationsProcessor |
| oldProperty.setXmlJoinNodesList(xmlElements.getXmlJoinNodes()); |
| } |
| // handle XmlJavaTypeAdapter |
| if (xmlElements.getXmlJavaTypeAdapter() != null) { |
| try { |
| oldProperty.setXmlJavaTypeAdapter(xmlElements.getXmlJavaTypeAdapter()); |
| } catch(JAXBException e) { |
| throw JAXBException.invalidPropertyAdapterClass(xmlElements.getXmlJavaTypeAdapter().getValue(), xmlElements.getJavaAttribute(), tInfo.getJavaClassName()); |
| } |
| } |
| return oldProperty; |
| } |
| |
| /** |
| * Process an xml-element-ref. |
| * |
| * @param xmlElementRef |
| * @param oldProperty |
| * @param info |
| * @return |
| */ |
| private Property processXmlElementRef(XmlElementRef xmlElementRef, Property oldProperty, TypeInfo info) { |
| processObjectFactory(info); |
| |
| resetProperty(oldProperty, info); |
| |
| List<XmlElementRef> eltRefs = new ArrayList<XmlElementRef>(); |
| eltRefs.add(xmlElementRef); |
| oldProperty.setXmlElementRefs(eltRefs); |
| oldProperty.setIsReference(true); |
| oldProperty.setIsRequired(xmlElementRef.isRequired()); |
| |
| // handle XmlAdapter |
| if (xmlElementRef.getXmlJavaTypeAdapter() != null) { |
| oldProperty.setXmlJavaTypeAdapter(xmlElementRef.getXmlJavaTypeAdapter()); |
| } |
| // check for container type |
| if (!xmlElementRef.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlElementRef.getContainerType()); |
| } |
| // handle XmlElementWrapper |
| if (xmlElementRef.getXmlElementWrapper() != null) { |
| oldProperty.setXmlElementWrapper(xmlElementRef.getXmlElementWrapper()); |
| } |
| // set user-defined properties |
| if (xmlElementRef.getXmlProperties() != null && xmlElementRef.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlElementRef.getXmlProperties().getXmlProperty())); |
| } |
| if (xmlElementRef.isSetXmlMixed()) { |
| oldProperty.setMixedContent(xmlElementRef.isXmlMixed()); |
| } |
| // handle get/set methods |
| if (xmlElementRef.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlElementRef.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlElementRef.getXmlAccessMethods().getSetMethod()); |
| } |
| // handle read-only |
| if (xmlElementRef.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlElementRef.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlElementRef.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlElementRef.isWriteOnly()); |
| } |
| return oldProperty; |
| } |
| |
| /** |
| * Process an xml-element-refs. |
| * |
| * @param xmlElementRefs |
| * @param oldProperty |
| * @param info |
| * @return |
| */ |
| private Property processXmlElementRefs(XmlElementRefs xmlElementRefs, Property oldProperty, TypeInfo info) { |
| processObjectFactory(info); |
| |
| resetProperty(oldProperty, info); |
| |
| List<XmlElementRef> eltRefs = new ArrayList<XmlElementRef>(); |
| boolean required = true; |
| for (XmlElementRef eltRef : xmlElementRefs.getXmlElementRef()) { |
| eltRefs.add(eltRef); |
| required = required && eltRef.isRequired(); |
| } |
| |
| oldProperty.setXmlElementRefs(eltRefs); |
| oldProperty.setIsReference(true); |
| oldProperty.setIsRequired(required); |
| |
| // handle XmlAdapter |
| if (xmlElementRefs.getXmlJavaTypeAdapter() != null) { |
| oldProperty.setXmlJavaTypeAdapter(xmlElementRefs.getXmlJavaTypeAdapter()); |
| } |
| // handle XmlElementWrapper |
| if (xmlElementRefs.getXmlElementWrapper() != null) { |
| oldProperty.setXmlElementWrapper(xmlElementRefs.getXmlElementWrapper()); |
| } |
| // set user-defined properties |
| if (xmlElementRefs.getXmlProperties() != null && xmlElementRefs.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlElementRefs.getXmlProperties().getXmlProperty())); |
| } |
| if (xmlElementRefs.isSetXmlMixed()) { |
| oldProperty.setMixedContent(xmlElementRefs.isXmlMixed()); |
| } |
| // handle get/set methods |
| if (xmlElementRefs.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlElementRefs.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlElementRefs.getXmlAccessMethods().getSetMethod()); |
| } |
| // handle read-only |
| if (xmlElementRefs.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlElementRefs.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlElementRefs.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlElementRefs.isWriteOnly()); |
| } |
| return oldProperty; |
| } |
| |
| private Property processXmlTransient(XmlTransient xmlTransient, Property oldProperty) { |
| if (xmlTransient.isXmlLocation()) { |
| if (!aProcessor.getHelper().getJavaClass(Constants.LOCATOR_CLASS).isAssignableFrom(oldProperty.getType())) { |
| throw JAXBException.invalidXmlLocation(oldProperty.getPropertyName(), oldProperty.getType().getName()); |
| } |
| oldProperty.setXmlLocation(true); |
| } |
| oldProperty.setTransient(true); |
| return oldProperty; |
| } |
| |
| private Property processXmlValue(XmlValue xmlValue, Property oldProperty, TypeInfo info, JavaType javaType) { |
| // reset any existing values |
| resetProperty(oldProperty, info); |
| |
| oldProperty.setIsXmlValue(true); |
| oldProperty.setIsXmlValueExtension(true); |
| info.setXmlValueProperty(oldProperty); |
| |
| // handle get/set methods |
| if (xmlValue.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlValue.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlValue.getXmlAccessMethods().getSetMethod()); |
| } |
| // check for container type |
| if (!xmlValue.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlValue.getContainerType()); |
| } |
| // set type |
| if (!xmlValue.getType().equals(DEFAULT)) { |
| JavaClass pType = jModelInput.getJavaModel().getClass(xmlValue.getType()); |
| if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) { |
| oldProperty.setGenericType(pType); |
| } else { |
| oldProperty.setType(pType); |
| } |
| oldProperty.setHasXmlElementType(true); |
| // may need to generate a type info for the type |
| if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) { |
| aProcessor.buildNewTypeInfo(new JavaClass[] { pType }); |
| } |
| } |
| |
| reapplyPackageAndClassAdapters(oldProperty, info); |
| // handle XmlJavaTypeAdapter |
| if (xmlValue.getXmlJavaTypeAdapter() != null) { |
| try { |
| oldProperty.setXmlJavaTypeAdapter(xmlValue.getXmlJavaTypeAdapter()); |
| } catch(JAXBException e) { |
| throw JAXBException.invalidPropertyAdapterClass(xmlValue.getXmlJavaTypeAdapter().getValue(), xmlValue.getJavaAttribute(), javaType.getName()); |
| } |
| } |
| // handle read-only |
| if (xmlValue.isSetReadOnly()) { |
| oldProperty.setReadOnly(xmlValue.isReadOnly()); |
| } |
| // handle write-only |
| if (xmlValue.isSetWriteOnly()) { |
| oldProperty.setWriteOnly(xmlValue.isWriteOnly()); |
| } |
| // handle cdata |
| if (xmlValue.isSetCdata()) { |
| oldProperty.setCdata(xmlValue.isCdata()); |
| } |
| // handle null policy |
| if (xmlValue.getXmlAbstractNullPolicy() != null) { |
| JAXBElement jaxbElt = xmlValue.getXmlAbstractNullPolicy(); |
| oldProperty.setNullPolicy((XmlAbstractNullPolicy) jaxbElt.getValue()); |
| } |
| // set user-defined properties |
| if (xmlValue.getXmlProperties() != null && xmlValue.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlValue.getXmlProperties().getXmlProperty())); |
| } |
| return oldProperty; |
| } |
| |
| /** |
| * Process an XmlSchema. This involves creating a NamespaceInfo instance and |
| * populating it based on the given XmlSchema. |
| * |
| * @param xmlBindings |
| * @param packageName |
| * @see NamespaceInfo |
| * @see AnnotationsProcessor |
| * @return newly created namespace info, or null if schema is null |
| */ |
| private NamespaceInfo processXmlSchema(XmlBindings xmlBindings, String packageName) { |
| XmlSchema schema = xmlBindings.getXmlSchema(); |
| if (schema == null) { |
| return null; |
| } |
| // create NamespaceInfo |
| NamespaceInfo nsInfo = this.aProcessor.findInfoForNamespace(schema.getNamespace()); |
| if(nsInfo == null) { |
| nsInfo = new NamespaceInfo(); |
| } |
| // process XmlSchema |
| XmlNsForm form = schema.getAttributeFormDefault(); |
| nsInfo.setAttributeFormQualified(form.equals(XmlNsForm.QUALIFIED)); |
| form = schema.getElementFormDefault(); |
| nsInfo.setElementFormQualified(form.equals(XmlNsForm.QUALIFIED)); |
| |
| |
| if (!nsInfo.isElementFormQualified() || nsInfo.isAttributeFormQualified()) { |
| aProcessor.setDefaultNamespaceAllowed(false); |
| } |
| |
| // make sure defaults are set, not null |
| nsInfo.setLocation(schema.getLocation() == null ? GENERATE : schema.getLocation()); |
| String namespace = schema.getNamespace(); |
| if(namespace == null) { |
| namespace = this.aProcessor.getDefaultTargetNamespace(); |
| } |
| nsInfo.setNamespace(namespace == null ? "" : schema.getNamespace()); |
| NamespaceResolver nsr = new NamespaceResolver(); |
| // process XmlNs |
| for (XmlNs xmlns : schema.getXmlNs()) { |
| nsr.put(xmlns.getPrefix(), xmlns.getNamespaceUri()); |
| } |
| nsInfo.setNamespaceResolver(nsr); |
| return nsInfo; |
| } |
| |
| /** |
| * Process an XmlTransformation. The info in the XmlTransformation will be |
| * used to generate an XmlTransformationMapping in MappingsGenerator. |
| * |
| * @param xmlTransformation |
| * @param oldProperty |
| * @param tInfo |
| */ |
| private Property processXmlTransformation(XmlTransformation xmlTransformation, Property oldProperty, TypeInfo tInfo) { |
| // reset any existing values |
| resetProperty(oldProperty, tInfo); |
| |
| oldProperty.setIsXmlTransformation(true); |
| oldProperty.setXmlTransformation(xmlTransformation); |
| |
| // handle get/set methods |
| if (xmlTransformation.getXmlAccessMethods() != null) { |
| oldProperty.setMethodProperty(true); |
| oldProperty.setGetMethodName(xmlTransformation.getXmlAccessMethods().getGetMethod()); |
| oldProperty.setSetMethodName(xmlTransformation.getXmlAccessMethods().getSetMethod()); |
| } |
| // set user-defined properties |
| if (xmlTransformation.getXmlProperties() != null && xmlTransformation.getXmlProperties().getXmlProperty().size() > 0) { |
| oldProperty.setUserProperties(createUserPropertyMap(xmlTransformation.getXmlProperties().getXmlProperty())); |
| } |
| aProcessor.getReferencedByTransformer().add(oldProperty.getType().getName()); |
| return oldProperty; |
| } |
| |
| /** |
| * Process XmlJoinNodes. This method sets the XmlJoinNodes instance on the Property |
| * for use in MappingsGen and SchemaGen. |
| * |
| * @param xmlJoinNodes |
| * @param oldProperty |
| * @return |
| */ |
| private Property processXmlJoinNodes(XmlJoinNodes xmlJoinNodes, Property oldProperty, TypeInfo typeInfo) { |
| // reset any existing values |
| resetProperty(oldProperty, typeInfo); |
| |
| oldProperty.setXmlJoinNodes(xmlJoinNodes); |
| |
| // check for container type |
| if (!xmlJoinNodes.getContainerType().equals(DEFAULT)) { |
| setContainerType(oldProperty, xmlJoinNodes.getContainerType()); |
| } |
| // set type |
| if (!xmlJoinNodes.getType().equals(DEFAULT)) { |
| JavaClass pType = jModelInput.getJavaModel().getClass(xmlJoinNodes.getType()); |
| if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) { |
| oldProperty.setGenericType(pType); |
| } else { |
| oldProperty.setType(pType); |
| } |
| oldProperty.setHasXmlElementType(true); |
| // may need to generate a type info for the type |
| if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) { |
| aProcessor.buildNewTypeInfo(new JavaClass[] { pType }); |
| } |
| } |
| return oldProperty; |
| } |
| |
| /** |
| * Convenience method for building a Map of package to classes. |
| * |
| * @return |
| */ |
| private Map<String, ArrayList<JavaClass>> buildPackageToJavaClassMap() { |
| Map<String, ArrayList<JavaClass>> theMap = new HashMap<String, ArrayList<JavaClass>>(); |
| Map<String, ArrayList<JavaClass>> xmlBindingsMap = new HashMap<String, ArrayList<JavaClass>>(); |
| |
| XmlBindings xmlBindings; |
| for (String packageName : xmlBindingMap.keySet()) { |
| xmlBindings = xmlBindingMap.get(packageName); |
| ArrayList classes = new ArrayList<JavaClass>(); |
| // add binding classes - the Java Model will be used to get a |
| // JavaClass via class name |
| JavaTypes jTypes = xmlBindings.getJavaTypes(); |
| if (jTypes != null) { |
| for (JavaType javaType : jTypes.getJavaType()) { |
| addClassToList(classes, javaType.getName(), packageName); |
| } |
| } |
| |
| // add any enum types to the class list |
| XmlEnums xmlEnums = xmlBindings.getXmlEnums(); |
| if (xmlEnums != null) { |
| for (XmlEnum xmlEnum : xmlEnums.getXmlEnum()) { |
| addClassToList(classes, xmlEnum.getJavaEnum(), packageName); |
| } |
| } |
| |
| theMap.put(packageName, classes); |
| xmlBindingsMap.put(packageName, new ArrayList(classes)); |
| } |
| |
| // add any other classes that aren't declared via external metadata |
| for (JavaClass jClass : jModelInput.getJavaClasses()) { |
| // need to verify that the class isn't already in the bindings file |
| // list |
| String pkg = jClass.getPackageName(); |
| ArrayList<JavaClass> existingXmlBindingsClasses = xmlBindingsMap.get(pkg); |
| ArrayList<JavaClass> allExistingClasses = theMap.get(pkg); |
| if (existingXmlBindingsClasses != null) { |
| if (!classExistsInArray(jClass, existingXmlBindingsClasses)) { |
| allExistingClasses.add(jClass); |
| } |
| } else { |
| if (allExistingClasses != null) { |
| allExistingClasses.add(jClass); |
| } else { |
| ArrayList classes = new ArrayList<JavaClass>(); |
| classes.add(jClass); |
| theMap.put(pkg, classes); |
| } |
| } |
| } |
| |
| return theMap; |
| } |
| |
| |
| private void addClassToList(List classes, String name, String packageName){ |
| JavaClass nextClass = jModelInput.getJavaModel().getClass(getQualifiedJavaTypeName(name, packageName)); |
| String nextPackageName = nextClass.getPackageName(); |
| if(nextPackageName == null || !nextPackageName.equals(packageName)){ |
| throw JAXBException.javaTypeNotAllowedInBindingsFile(nextPackageName, packageName); |
| } |
| classes.add(nextClass); |
| } |
| /** |
| * Lazy load the metadata logger. |
| * |
| * @return |
| */ |
| private JAXBMetadataLogger getLogger() { |
| if (logger == null) { |
| logger = new JAXBMetadataLogger(); |
| } |
| return logger; |
| } |
| |
| /** |
| * Convenience method to determine if a class exists in a given ArrayList. |
| * The classes are compared via equals() method. |
| */ |
| public boolean classExistsInArray(JavaClass theClass, ArrayList<JavaClass> existingClasses) { |
| return aProcessor.getHelper().classExistsInArray(theClass, existingClasses); |
| } |
| |
| /** |
| * Convenience method for resetting a number of properties on a given |
| * property. |
| * |
| * @param oldProperty |
| * @return |
| */ |
| private Property resetProperty(Property oldProperty, TypeInfo tInfo) { |
| oldProperty.setIsAttribute(false); |
| oldProperty.setHasXmlElementType(false); |
| oldProperty.setIsRequired(false); |
| oldProperty.setIsXmlList(false); |
| oldProperty.setXmlJavaTypeAdapter(null); |
| oldProperty.setInverseReferencePropertyName(null); |
| oldProperty.setDefaultValue(null); |
| oldProperty.setDomHandlerClassName(null); |
| oldProperty.setIsSwaAttachmentRef(false); |
| oldProperty.setIsXmlIdRef(false); |
| oldProperty.setIsXmlTransformation(false); |
| oldProperty.setXmlElementWrapper(null); |
| oldProperty.setLax(false); |
| oldProperty.setNillable(false); |
| oldProperty.setMixedContent(false); |
| oldProperty.setMimeType(null); |
| oldProperty.setTransient(false); |
| oldProperty.setChoice(false); |
| oldProperty.setIsReference(false); |
| oldProperty.setXmlPath(null); |
| oldProperty.setReadOnly(false); |
| oldProperty.setWriteOnly(false); |
| oldProperty.setCdata(false); |
| oldProperty.setNullPolicy(null); |
| oldProperty.setUserProperties(null); |
| oldProperty.setGetMethodName(oldProperty.getOriginalGetMethodName()); |
| oldProperty.setSetMethodName(oldProperty.getOriginalSetMethodName()); |
| oldProperty.setXmlTransformation(null); |
| oldProperty.setXmlJoinNodes(null); |
| if (oldProperty.getGetMethodName() == null && oldProperty.getSetMethodName() == null) { |
| oldProperty.setMethodProperty(false); |
| } |
| |
| oldProperty.setIsSwaAttachmentRef(false); |
| oldProperty.setIsMtomAttachment(false); |
| oldProperty.setSchemaType(null); |
| |
| unsetXmlElementRefs(oldProperty, tInfo); |
| unsetXmlElements(oldProperty); |
| unsetXmlAnyAttribute(oldProperty, tInfo); |
| unsetXmlAnyElement(oldProperty, tInfo); |
| unsetXmlValue(oldProperty, tInfo); |
| unsetXmlID(oldProperty, tInfo); |
| unsetXmlKey(oldProperty, tInfo); |
| return oldProperty; |
| } |
| |
| /** |
| * Ensure that a given property is not set as an xml-id. |
| * |
| * @param oldProperty |
| * @param tInfo |
| */ |
| private void unsetXmlID(Property oldProperty, TypeInfo tInfo) { |
| oldProperty.setIsXmlId(false); |
| oldProperty.setIsXmlIdExtension(false); |
| if (tInfo.isIDSet() && tInfo.getIDProperty().getPropertyName().equals(oldProperty.getPropertyName())) { |
| tInfo.setIDProperty(null); |
| } |
| } |
| |
| /** |
| * Ensure that a given property is not set as an xml-key. |
| * |
| * @param oldProperty |
| * @param tInfo |
| */ |
| private void unsetXmlKey(Property oldProperty, TypeInfo tInfo) { |
| if (tInfo.hasXmlKeyProperties()) { |
| Property propToRemove = null; |
| for (Property prop : tInfo.getXmlKeyProperties()) { |
| if (prop.getPropertyName().equals(oldProperty.getPropertyName())) { |
| propToRemove = prop; |
| } |
| } |
| if (propToRemove != null) { |
| tInfo.getXmlKeyProperties().remove(propToRemove); |
| } |
| } |
| } |
| |
| /** |
| * Ensure that a given property is not set as an xml-element-refs. |
| * |
| * @param oldProperty |
| * @param tInfo |
| */ |
| private void unsetXmlElementRefs(Property oldProperty, TypeInfo tInfo) { |
| if (tInfo.hasElementRefs() && tInfo.getElementRefsPropName().equals(oldProperty.getPropertyName())) { |
| tInfo.setElementRefsPropertyName(null); |
| } |
| } |
| |
| /** |
| * Ensure that a given property is not set as an xml-elements. |
| * |
| * @param oldProperty |
| */ |
| private void unsetXmlElements(Property oldProperty) { |
| oldProperty.setXmlElements(null); |
| oldProperty.setChoiceProperties(null); |
| } |
| |
| /** |
| * Ensure that a given property is not set as an xml-any-attribute. |
| * |
| * @param oldProperty |
| * @param tInfo |
| */ |
| private void unsetXmlAnyAttribute(Property oldProperty, TypeInfo tInfo) { |
| oldProperty.setIsAnyAttribute(false); |
| if (tInfo.isSetAnyAttributePropertyName() && tInfo.getAnyAttributePropertyName().equals(oldProperty.getPropertyName())) { |
| tInfo.setAnyAttributePropertyName(null); |
| } |
| } |
| |
| /** |
| * Ensure that a given property is not set as an xml-any-element. |
| * |
| * @param oldProperty |
| * @param tInfo |
| */ |
| private void unsetXmlAnyElement(Property oldProperty, TypeInfo tInfo) { |
| oldProperty.setIsAny(false); |
| if (tInfo.isSetAnyElementPropertyName() && tInfo.getAnyElementPropertyName().equals(oldProperty.getPropertyName())) { |
| tInfo.setAnyElementPropertyName(null); |
| } |
| } |
| |
| /** |
| * Ensure that a given property is not set as an xml-value. |
| * |
| * @param oldProperty |
| * @param tInfo |
| */ |
| private void unsetXmlValue(Property oldProperty, TypeInfo tInfo) { |
| oldProperty.setIsXmlValue(false); |
| oldProperty.setIsXmlValueExtension(false); |
| if (tInfo.isSetXmlValueProperty() && tInfo.getXmlValueProperty().getPropertyName().equals(oldProperty.getPropertyName())) { |
| tInfo.setXmlValueProperty(null); |
| } |
| } |
| |
| /** |
| * Convenience method that returns the field name for a given xml-path. This method |
| * would typically be called when building a QName to set as the 'SchemaName' on |
| * a Property. |
| * |
| * Examples: |
| * - returns 'id' for xml-path '@id' |
| * - returns 'managerId' for xml-path 'projects/prj:project/@prj:managerId' |
| * - returns 'first-name' for xml-path 'info/personal-info/first-name/text()' |
| * - returns 'project' for xml-path 'projects/prj:project/text()' |
| * - returns 'data' for xml-path 'pieces-of-data/data[1]/text()' |
| * |
| * @param xpath |
| * @param propertyName |
| * @param isAttribute |
| * @return |
| */ |
| public static String getNameFromXPath(String xpath, String propertyName, boolean isAttribute) { |
| // handle self mapping |
| if (xpath.equals(SELF)) { |
| return propertyName; |
| } |
| |
| String name; |
| String path; |
| |
| // may need to strip off '/text()' |
| int idx = xpath.indexOf(SLASH + Constants.TEXT); |
| if (idx >= 0) { |
| path = xpath.substring(0, idx); |
| } else { |
| path = xpath; |
| } |
| |
| idx = path.lastIndexOf(SLASH); |
| if (idx >= 0 && path.length() > 1) { |
| name = path.substring(idx+1); |
| // may have a prefix |
| StringTokenizer stok = new StringTokenizer(name, Character.toString(COLON)); |
| if (stok.countTokens() == 2) { |
| // first token is prefix |
| stok.nextToken(); |
| // second token is the field name |
| name = stok.nextToken(); |
| } |
| } else { |
| name = path; |
| } |
| // may need to strip off '@' |
| if (isAttribute) { |
| idx = name.indexOf(Constants.ATTRIBUTE); |
| if (idx >= 0 && name.length() > 1) { |
| name = name.substring(idx+1); |
| } |
| } else { |
| // may need to strip of positional info |
| idx = name.indexOf(OPEN_BRACKET); |
| if (idx != -1) { |
| name = name.substring(0, idx); |
| } |
| } |
| return name; |
| } |
| |
| private void processObjectFactory(TypeInfo tInfo){ |
| int index = tInfo.getJavaClassName().lastIndexOf('.'); |
| if(index > -1){ |
| String objectFactoryClassName = tInfo.getJavaClassName().substring(0, index) + ".ObjectFactory"; |
| aProcessor.findAndProcessObjectFactory(objectFactoryClassName); |
| }else{ |
| aProcessor.findAndProcessObjectFactory("ObjectFactory"); |
| } |
| } |
| |
| |
| /** |
| * Return a Map of user-defined properties. Typically the key will |
| * be a String (property name) and the value a String or some |
| * other simple type that was converted by ConversionManager, |
| * i.e. numerical, boolean, temporal. |
| * |
| * @param propList |
| * @return |
| */ |
| private Map createUserPropertyMap(List<XmlProperty> propList) { |
| return mergeUserPropertyMap(propList, new HashMap()); |
| } |
| |
| /** |
| * Return a Map of user-defined properties. The List of properties (from |
| * xml) will be merged with the given Map (from annotations). In the |
| * case of a conflict, xml will win. |
| * |
| * Note that this intended to be used when processing type-level user |
| * properties, as at the property-level, xml completely replaces any |
| * properties set via annotation. |
| * |
| * Typically the key will be a String (property name) and the value a |
| * String or some other simple type that was converted by |
| * ConversionManager, i.e. numerical, boolean, temporal. |
| * |
| * @param propList |
| * @return |
| */ |
| private Map mergeUserPropertyMap(List<XmlProperty> propList, Map existingMap) { |
| Map propMap = existingMap; |
| for (XmlProperty prop : propList) { |
| Object pvalue = prop.getValue(); |
| if (prop.isSetValueType()) { |
| pvalue = XMLConversionManager.getDefaultXMLManager().convertObject( |
| prop.getValue(), XMLConversionManager.getDefaultXMLManager().convertClassNameToClass(prop.getValueType())); |
| } |
| propMap.put(prop.getName(), pvalue); |
| } |
| return propMap; |
| } |
| |
| /** |
| * Convenience method for setting the container class on a given property. |
| * The generic type will be overwritten, and could be incorrect after |
| * doing so, so the original generic type will be retrieved and set after |
| * the call to set the container type. |
| * |
| * @param property |
| * @param containerClassName |
| */ |
| private void setContainerType(Property property, String containerClassName) { |
| // store the original generic type as the call to setType will overwrite it |
| JavaClass genericType = property.getGenericType(); |
| // set the type to the container-type value |
| property.setType(jModelInput.getJavaModel().getClass(containerClassName)); |
| // set the original generic type |
| property.setGenericType(genericType); |
| } |
| |
| /** |
| * This method checks for class and package level adapters after the type of a property has been set. |
| * @param prop the property that needs to be updated |
| * @param owningInfo the typeInfo that represents the owner of this property. |
| */ |
| public void reapplyPackageAndClassAdapters(Property prop, TypeInfo owningInfo) { |
| if(prop.getXmlJavaTypeAdapter() != null) { |
| //if there's already a property level adapter, don't apply package/class level |
| return; |
| } |
| JavaClass type = prop.getActualType(); |
| //if a class level adapter is present on the target class, set it |
| TypeInfo targetInfo = aProcessor.getTypeInfos().get(type.getQualifiedName()); |
| if(targetInfo != null) { |
| if(targetInfo.getXmlJavaTypeAdapter() != null) { |
| prop.setXmlJavaTypeAdapter(targetInfo.getXmlJavaTypeAdapter()); |
| } |
| } |
| |
| //check for package level adapter. Don't overwrite class level |
| if(owningInfo.hasPackageLevelAdaptersByClass()) { |
| JavaClass packageLevelAdapter = owningInfo.getPackageLevelAdaptersByClass().get(type.getQualifiedName()); |
| if(packageLevelAdapter != null && prop.getXmlJavaTypeAdapter() == null) { |
| org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xja = new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter(); |
| xja.setValue(packageLevelAdapter.getQualifiedName()); |
| xja.setType(type.getQualifiedName()); |
| prop.setXmlJavaTypeAdapter(xja); |
| } |
| } |
| } |
| |
| /** |
| * This method is used to merge several bindings files into one XMLBindings object. |
| * @param bindings the list of XmlBindings objects to merge. |
| * @return XmlBindings object representing the merged files. |
| */ |
| public static XmlBindings mergeXmlBindings(List<XmlBindings> bindings) { |
| if(bindings.size() == 0) { |
| return null; |
| } |
| XmlBindings rootBindings = bindings.get(0); |
| for(int i = 1; i < bindings.size(); i++) { |
| XmlBindings nextBindings = bindings.get(i); |
| if(nextBindings.isSetXmlAccessorOrder()) { |
| rootBindings.setXmlAccessorOrder(nextBindings.getXmlAccessorOrder()); |
| } |
| if(nextBindings.isSetXmlAccessorType()) { |
| rootBindings.setXmlAccessorType(nextBindings.getXmlAccessorType()); |
| } |
| if(nextBindings.isSetXmlMappingMetadataComplete()) { |
| rootBindings.setXmlMappingMetadataComplete(nextBindings.isXmlMappingMetadataComplete()); |
| } |
| mergeJavaTypes(rootBindings.getJavaTypes(), nextBindings.getJavaTypes()); |
| |
| if(rootBindings.getXmlEnums() == null) { |
| rootBindings.setXmlEnums(nextBindings.getXmlEnums()); |
| } else { |
| mergeXmlEnums(rootBindings.getXmlEnums(), nextBindings.getXmlEnums()); |
| } |
| |
| if(rootBindings.getXmlSchema() == null) { |
| rootBindings.setXmlSchema(nextBindings.getXmlSchema()); |
| } else if(nextBindings.getXmlSchema() != null){ |
| mergeXmlSchema(rootBindings.getXmlSchema(), nextBindings.getXmlSchema()); |
| } |
| |
| if(rootBindings.getXmlSchemaType() == null) { |
| rootBindings.setXmlSchemaTypes(nextBindings.getXmlSchemaTypes()); |
| } else if(nextBindings.getXmlSchemaTypes() != null){ |
| mergeXmlSchemaTypes(rootBindings.getXmlSchemaTypes(), nextBindings.getXmlSchemaTypes()); |
| } |
| |
| if(rootBindings.getXmlJavaTypeAdapters() == null) { |
| rootBindings.setXmlJavaTypeAdapters(nextBindings.getXmlJavaTypeAdapters()); |
| } else if(nextBindings.getXmlJavaTypeAdapters() != null){ |
| mergeXmlJavaTypeAdapters(rootBindings.getXmlJavaTypeAdapters(), nextBindings.getXmlJavaTypeAdapters()); |
| } |
| |
| if (rootBindings.getXmlNullPolicy() == null) { |
| rootBindings.setXmlNullPolicy(nextBindings.getXmlNullPolicy()); |
| } else if (nextBindings.getXmlNullPolicy() != null) { |
| mergeXmlNullPolicy(rootBindings.getXmlNullPolicy(), nextBindings.getXmlNullPolicy()); |
| } |
| |
| if (rootBindings.getXmlElementNillable() == null) { |
| rootBindings.setXmlElementNillable(nextBindings.getXmlElementNillable()); |
| } else if (nextBindings.getXmlElementNillable() != null) { |
| mergeXmlElementNillable(rootBindings.getXmlElementNillable(), nextBindings.getXmlElementNillable()); |
| } |
| } |
| return rootBindings; |
| } |
| |
| private static void mergeXmlElementNillable(XmlElementNillable xmlElementNillable, XmlElementNillable overrideXmlElementNillable) { |
| xmlElementNillable.setNillable(overrideXmlElementNillable.isNillable()); |
| } |
| |
| private static void mergeXmlNullPolicy(XmlNullPolicy xmlNullPolicy, XmlNullPolicy overrideXmlNullPolicy) { |
| xmlNullPolicy.setEmptyNodeRepresentsNull(overrideXmlNullPolicy.isEmptyNodeRepresentsNull()); |
| xmlNullPolicy.setIsSetPerformedForAbsentNode(overrideXmlNullPolicy.isIsSetPerformedForAbsentNode()); |
| xmlNullPolicy.setNullRepresentationForXml(overrideXmlNullPolicy.getNullRepresentationForXml()); |
| xmlNullPolicy.setXsiNilRepresentsNull(overrideXmlNullPolicy.isXsiNilRepresentsNull()); |
| } |
| |
| private static void mergeXmlJavaTypeAdapters(XmlJavaTypeAdapters xmlJavaTypeAdapters, XmlJavaTypeAdapters overrideAdapters) { |
| List<XmlJavaTypeAdapter> adapterList = xmlJavaTypeAdapters.getXmlJavaTypeAdapter(); |
| HashMap<String, XmlJavaTypeAdapter> adapterMap = new HashMap<String, XmlJavaTypeAdapter>(adapterList.size()); |
| for(XmlJavaTypeAdapter next:adapterList) { |
| adapterMap.put(next.getType(), next); |
| } |
| |
| for(XmlJavaTypeAdapter next:overrideAdapters.getXmlJavaTypeAdapter()) { |
| //If there's already an adapter for this type, replace it's value |
| XmlJavaTypeAdapter existingAdapter = adapterMap.get(next.getType()); |
| if(existingAdapter != null) { |
| existingAdapter.setValue(next.getValue()); |
| } else { |
| xmlJavaTypeAdapters.getXmlJavaTypeAdapter().add(next); |
| } |
| } |
| } |
| |
| private static void mergeXmlSchemaTypes(XmlSchemaTypes xmlSchemaTypes, XmlSchemaTypes overrideSchemaTypes) { |
| List<XmlSchemaType> schemaTypeList = xmlSchemaTypes.getXmlSchemaType(); |
| HashMap<String, XmlSchemaType> schemaTypeMap = new HashMap<String, XmlSchemaType>(schemaTypeList.size()); |
| for(XmlSchemaType next:schemaTypeList) { |
| schemaTypeMap.put(next.getType(), next); |
| } |
| |
| for(XmlSchemaType next:overrideSchemaTypes.getXmlSchemaType()) { |
| //if there's already a schemaType for this type, override it's value |
| XmlSchemaType existingType = schemaTypeMap.get(next.getType()); |
| if(existingType != null) { |
| existingType.setName(next.getName()); |
| existingType.setNamespace(next.getNamespace()); |
| } else { |
| xmlSchemaTypes.getXmlSchemaType().add(next); |
| } |
| } |
| } |
| |
| private static void mergeXmlSchema(XmlSchema xmlSchema, XmlSchema overrideSchema) { |
| |
| xmlSchema.setAttributeFormDefault(overrideSchema.getAttributeFormDefault()); |
| xmlSchema.setElementFormDefault(overrideSchema.getElementFormDefault()); |
| xmlSchema.setLocation(overrideSchema.getLocation()); |
| xmlSchema.setNamespace(overrideSchema.getNamespace()); |
| List<XmlNs> xmlNsList = xmlSchema.getXmlNs(); |
| xmlNsList.addAll(overrideSchema.getXmlNs()); |
| } |
| |
| private static void mergeXmlEnums(XmlEnums xmlEnums, XmlEnums overrideEnum) { |
| if(overrideEnum == null) { |
| return; |
| } |
| List<XmlEnum> enumList = xmlEnums.getXmlEnum(); |
| Map<String, XmlEnum> enumMap = new HashMap<String, XmlEnum>(enumList.size()); |
| for(XmlEnum next:enumList) { |
| enumMap.put(next.getJavaEnum(), next); |
| } |
| for(XmlEnum next:overrideEnum.getXmlEnum()) { |
| XmlEnum existingEnum = enumMap.get(next.getJavaEnum()); |
| if(existingEnum != null) { |
| mergeXmlEnumValues(existingEnum.getXmlEnumValue(), next.getXmlEnumValue()); |
| } else { |
| xmlEnums.getXmlEnum().add(next); |
| } |
| } |
| } |
| |
| private static void mergeXmlEnumValues(List<XmlEnumValue> xmlEnumValue, List<XmlEnumValue> overrideXmlEnumValue) { |
| |
| Map<String, XmlEnumValue> values = new HashMap<String, XmlEnumValue>(); |
| List<XmlEnumValue> extraValues = new ArrayList<XmlEnumValue>(); |
| for(XmlEnumValue next:xmlEnumValue){ |
| values.put(next.getJavaEnumValue(), next); |
| } |
| |
| for(XmlEnumValue next:overrideXmlEnumValue) { |
| XmlEnumValue existingValue = values.get(next.getJavaEnumValue()); |
| if(existingValue == null) { |
| extraValues.add(next); |
| } else { |
| existingValue.setValue(next.getValue()); |
| } |
| } |
| xmlEnumValue.addAll(extraValues); |
| } |
| |
| private static void mergeJavaTypes(JavaTypes javaTypes, JavaTypes overrideJavaTypes) { |
| List<JavaType> javaTypeList = javaTypes.getJavaType(); |
| Map<String, JavaType> javaTypeMap = new HashMap<String, JavaType>(javaTypeList.size()); |
| for(JavaType next:javaTypeList) { |
| javaTypeMap.put(next.getName(), next); |
| } |
| for(JavaType next:overrideJavaTypes.getJavaType()) { |
| JavaType existingType = javaTypeMap.get(next.getName()); |
| if(existingType == null) { |
| javaTypes.getJavaType().add(next); |
| } else { |
| mergeJavaType(existingType, next); |
| } |
| } |
| } |
| |
| private static void mergeJavaType(JavaType existingType, JavaType next) { |
| if(next.isSetXmlAccessorOrder()) { |
| existingType.setXmlAccessorOrder(next.getXmlAccessorOrder()); |
| } |
| |
| if(next.isSetXmlAccessorType()) { |
| existingType.setXmlAccessorType(next.getXmlAccessorType()); |
| } |
| |
| if(next.isSetXmlInlineBinaryData()) { |
| existingType.setXmlInlineBinaryData(next.isXmlInlineBinaryData()); |
| } |
| |
| if(next.isSetXmlTransient()) { |
| existingType.setXmlTransient(next.isXmlInlineBinaryData()); |
| } |
| |
| if(next.getXmlRootElement() != null) { |
| existingType.setXmlRootElement(next.getXmlRootElement()); |
| } |
| |
| if(existingType.getXmlProperties() == null) { |
| existingType.setXmlProperties(next.getXmlProperties()); |
| } else if(next.getXmlProperties() != null) { |
| existingType.getXmlProperties().getXmlProperty().addAll(next.getXmlProperties().getXmlProperty()); |
| } |
| |
| if(next.getXmlType() != null) { |
| existingType.setXmlType(next.getXmlType()); |
| } |
| |
| existingType.getXmlSeeAlso().addAll(next.getXmlSeeAlso()); |
| |
| |
| JavaAttributes attributes = existingType.getJavaAttributes(); |
| JavaAttributes overrideAttributes = next.getJavaAttributes(); |
| if(attributes == null) { |
| existingType.setJavaAttributes(overrideAttributes); |
| } else if(overrideAttributes != null) { |
| mergeJavaAttributes(attributes, overrideAttributes, existingType); |
| } |
| |
| } |
| |
| private static void mergeJavaAttributes(JavaAttributes attributes, JavaAttributes overrideAttributes, JavaType javaType) { |
| List<JAXBElement<? extends JavaAttribute>> attributeList = attributes.getJavaAttribute(); |
| Map<String, JAXBElement> attributeMap = new HashMap<String, JAXBElement>(attributeList.size()); |
| |
| for(JAXBElement next:attributeList) { |
| attributeMap.put(((JavaAttribute)next.getValue()).getJavaAttribute(), next); |
| } |
| for(JAXBElement next:overrideAttributes.getJavaAttribute()) { |
| JAXBElement existingAttribute = attributeMap.get(((JavaAttribute)next.getValue()).getJavaAttribute()); |
| if(existingAttribute != null) { |
| attributes.getJavaAttribute().remove(existingAttribute); |
| } |
| attributes.getJavaAttribute().add(next); |
| } |
| } |
| } |