gt:                     if (reference.isEnumerationType()) {
context: /*******************************************************************************
   * Copyright (c) 1998, 2016 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 v1.0 and Eclipse Distribution License v. 1.0
   * which accompanies this distribution.
   * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
   * and the Eclipse Distribution License is available at
   * http://www.eclipse.org/org/documents/edl-v10.php.
   *
   * 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.security.AccessController;
  import java.security.PrivilegedActionException;
  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.bind.JAXBElement;
  import javax.xml.bind.annotation.XmlAttribute;
  import javax.xml.bind.annotation.XmlMixed;
  import javax.xml.bind.annotation.XmlTransient;
  import javax.xml.bind.annotation.XmlValue;
  import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
  import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
  import javax.xml.namespace.QName;
  import javax.xml.transform.Source;
  
  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.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.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.ClassWriter;
  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.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.queries.ContainerPolicy;
  import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
  import org.eclipse.persistence.internal.security.PrivilegedClassForName;
  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.mappings.DatabaseMapping;
  import org.eclipse.persistence.mappings.converters.Converter;
  import org.eclipse.persistence.oxm.XMLDescriptor;
  import org.eclipse.persistence.oxm.XMLField;
  import org.eclipse.persistence.oxm.mappings.FixedMimeTypePolicy;
  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.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.schema.XMLSchemaClassPathReference;
  import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
  import org.eclipse.persistence.queries.AttributeGroup;
  import org.eclipse.persistence.sessions.Project;
  
  /**
   * 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<QName, Class>();
          qNamesToDeclaredClasses = new HashMap<QName, Class>();
          classToGeneratedClasses = new HashMap<String, Class>();
          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 customizerClass = PrivilegedAccessHelper.getClassForName(customizerClassName, true, helper.getClassLoader());
                      DescriptorCustomizer descriptorCustomizer = (DescriptorCustomizer) PrivilegedAccessHelper.newInstanceFromClass(customizerClass);
                      descriptorCustomizer.customize((XMLDescriptor)tInfo.getDescriptor());
                  } catch (IllegalAccessException iae) {
                      throw JAXBException.couldNotCreateCustomizerInstance(iae, customizerClassName);
                  } catch (InstantiationException ie) {
                      throw JAXBException.couldNotCreateCustomizerInstance(ie, customizerClassName);
                  } catch (ClassCastException cce) {
                      throw JAXBException.invalidCustomizerClass(cce, customizerClassName);
                  } catch (ClassNotFoundException cnfe) {
                      throw JAXBException.couldNotCreateCustomizerInstance(cnfe, 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<String, List<CoreAttributeGroup>>();
          //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<CoreAttributeGroup>(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("javax.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.
       *
       * @param property
       * @param descriptor
       * @param namespaceInfo
       * @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("javax.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 {
  