/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.jaxb.compiler;

import java.awt.Image;
import java.beans.Introspector;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jakarta.xml.bind.SchemaOutputResolver;
import jakarta.xml.bind.annotation.XmlElementDecl.GLOBAL;
import jakarta.xml.bind.annotation.XmlSchemaType;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.Source;

import org.eclipse.persistence.exceptions.BeanValidationException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.jaxb.many.MapValue;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.schema.model.All;
import org.eclipse.persistence.internal.oxm.schema.model.Any;
import org.eclipse.persistence.internal.oxm.schema.model.AnyAttribute;
import org.eclipse.persistence.internal.oxm.schema.model.Attribute;
import org.eclipse.persistence.internal.oxm.schema.model.Choice;
import org.eclipse.persistence.internal.oxm.schema.model.ComplexContent;
import org.eclipse.persistence.internal.oxm.schema.model.ComplexType;
import org.eclipse.persistence.internal.oxm.schema.model.Element;
import org.eclipse.persistence.internal.oxm.schema.model.Extension;
import org.eclipse.persistence.internal.oxm.schema.model.Import;
import org.eclipse.persistence.internal.oxm.schema.model.Occurs;
import org.eclipse.persistence.internal.oxm.schema.model.Restriction;
import org.eclipse.persistence.internal.oxm.schema.model.Schema;
import org.eclipse.persistence.internal.oxm.schema.model.Sequence;
import org.eclipse.persistence.internal.oxm.schema.model.SimpleComponent;
import org.eclipse.persistence.internal.oxm.schema.model.SimpleContent;
import org.eclipse.persistence.internal.oxm.schema.model.SimpleType;
import org.eclipse.persistence.internal.oxm.schema.model.TypeDefParticle;
import org.eclipse.persistence.internal.oxm.schema.model.TypeDefParticleOwner;
import org.eclipse.persistence.jaxb.compiler.builder.TransformerPropertyBuilder;
import org.eclipse.persistence.jaxb.compiler.facets.DecimalMaxFacet;
import org.eclipse.persistence.jaxb.compiler.facets.DecimalMinFacet;
import org.eclipse.persistence.jaxb.compiler.facets.DigitsFacet;
import org.eclipse.persistence.jaxb.compiler.facets.Facet;
import org.eclipse.persistence.jaxb.compiler.facets.FacetVisitor;
import org.eclipse.persistence.jaxb.compiler.facets.MaxFacet;
import org.eclipse.persistence.jaxb.compiler.facets.MinFacet;
import org.eclipse.persistence.jaxb.compiler.facets.PatternFacet;
import org.eclipse.persistence.jaxb.compiler.facets.PatternListFacet;
import org.eclipse.persistence.jaxb.compiler.facets.SizeFacet;
import org.eclipse.persistence.jaxb.javamodel.Helper;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaClassCompareByNamespace;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper;
import org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode;
import org.eclipse.persistence.jaxb.xmlmodel.XmlVirtualAccessMethodsSchema;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLField;

/**
 * INTERNAL:
 * <p><b>Purpose:</b>To generate Schema objects based on a map of TypeInfo objects, and some
 * additional information gathered by the AnnotationsProcessing phase.
 * <p><b>Responsibilities:</b><ul>
 * <li>Create and maintain a collection of Schema objects based on the provided TypeInfo objects</li>
 * <li>Add additional global elements to the schema based on an optional map (for WS integration)</li>
 * <li>Should create a schema for each namespace encountered during generation.</li>
 * </ul>
 * <p>This class is used by the Generator to handle the generation of Schemas. The
 * Generator passes in a map of TypeInfo objects, generated by the Annotations processor.
 * The generated Schemas are stored in a map of keyed on Target Namespace.
 * @see org.eclipse.persistence.jaxb.compiler.TypeInfo
 * @see org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor
 * @see org.eclipse.persistence.jaxb.compiler.Generator
 * @since Oracle TopLink 11.1.1.0.0
 * @author mmacivor
 */
public class SchemaGenerator {
    private Map<String, Schema> schemaForNamespace;
    private List<Schema> allSchemas;
    private int schemaCount;
    private Helper helper;
    private Map<String, TypeInfo> typeInfo;
    private Map<String, PackageInfo> packageToPackageInfoMappings;
    private Map<String, SchemaTypeInfo> schemaTypeInfo;
    private Map<String, QName> userDefinedSchemaTypes;
    private Map<String, Class> arrayClassesToGeneratedClasses;

    private static final String JAVAX_ACTIVATION_DATAHANDLER = "jakarta.activation.DataHandler";
    private static final String JAVAX_MAIL_INTERNET_MIMEMULTIPART = "jakarta.mail.internet.MimeMultipart";
    private static final String SWA_REF_IMPORT = "http://ws-i.org/profiles/basic/1.1/swaref.xsd";

    private static final String COLON = ":";
    private static final String ATT = "@";
    private static final String EMPTY_STRING = "";
    private static final String DOT = ".";
    private static final String SKIP = "skip";
    private static final String ENTRY = "entry";
    private static final String GENERATE = "##generate";
    private static final String SCHEMA = "schema";
    private static final String SCHEMA_EXT = ".xsd";
    private static final String OBJECT_CLASSNAME = "java.lang.Object";
    private static final String ID = "ID";
    private static final String IDREF = "IDREF";
    private static final Character DOT_CHAR = '.';
    private static final Character SLASH = '/';
    private static final Character SLASHES = '\\';

    private SchemaOutputResolver outputResolver;
    private boolean facets;

    public SchemaGenerator(Helper helper) {
        this.helper = helper;
        this.facets = helper.isFacets();
    }

    public void generateSchema(List<JavaClass> typeInfoClasses, Map<String, TypeInfo> typeInfo, Map<String, QName> userDefinedSchemaTypes, Map<String, PackageInfo> packageToPackageInfoMappings, Map<QName, ElementDeclaration> additionalGlobalElements, Map<String, Class> arrayClassesToGeneratedClasses, SchemaOutputResolver outputResolver) {
        this.outputResolver = outputResolver;
        generateSchema(typeInfoClasses, typeInfo, userDefinedSchemaTypes, packageToPackageInfoMappings, additionalGlobalElements, arrayClassesToGeneratedClasses);
    }

    public void generateSchema(List<JavaClass> typeInfoClasses, Map<String, TypeInfo> typeInfo, Map<String, QName> userDefinedSchemaTypes, Map<String, PackageInfo> packageToPackageInfoMappings, Map<QName, ElementDeclaration> additionalGlobalElements, Map<String, Class> arrayClassesToGeneratedClasses) {
        this.typeInfo = typeInfo;
        this.userDefinedSchemaTypes = userDefinedSchemaTypes;
        this.packageToPackageInfoMappings = packageToPackageInfoMappings;
        this.schemaCount = 1;
        this.schemaTypeInfo = new HashMap<>(typeInfo.size());
        this.arrayClassesToGeneratedClasses = arrayClassesToGeneratedClasses;

        //sort input classes before schema name (like schema1.xsd, schema2.xsd....) is generated and assigned
        typeInfoClasses.sort(new JavaClassCompareByNamespace(typeInfo));
        for (JavaClass javaClass : typeInfoClasses) {
            addSchemaComponents(javaClass);
        }
        populateSchemaTypes();
        if (additionalGlobalElements != null) {
            addGlobalElements(additionalGlobalElements);
        }
    }

    public void addSchemaComponents(JavaClass myClass) {
        // first check for type
        String myClassName = myClass.getQualifiedName();
        Element rootElement = null;
        TypeInfo info = typeInfo.get(myClassName);
        if (info.isTransient() || info.getClassNamespace().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
            return;
        }
        SchemaTypeInfo schemaTypeInfo = new SchemaTypeInfo();
        schemaTypeInfo.setSchemaTypeName(new QName(info.getClassNamespace(), info.getSchemaTypeName()));
        this.schemaTypeInfo.put(myClass.getQualifiedName(), schemaTypeInfo);
        NamespaceInfo namespaceInfo = this.packageToPackageInfoMappings.get(myClass.getPackageName()).getNamespaceInfo();
        if (namespaceInfo.getLocation() != null && !namespaceInfo.getLocation().equals(GENERATE)) {
            return;
        }
        Schema schema = getSchemaForNamespace(info.getClassNamespace(), myClass.getPackageName());
        info.setSchema(schema);

        String typeName = info.getSchemaTypeName();
        String pfx = EMPTY_STRING;

        Property valueField = null;
        if (info.isSetXmlRootElement()) {
            //Create the root element and add it to the schema
            org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement xmlRE = info.getXmlRootElement();
            rootElement = new Element();
            String elementName = xmlRE.getName();
            if (elementName.equals(XMLProcessor.DEFAULT) || elementName.equals(EMPTY_STRING)) {
                try{
                    elementName = info.getXmlNameTransformer().transformRootElementName(myClassName);
                }catch (Exception ex){
                    throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(myClassName, info.getXmlNameTransformer().getClass().getName(), ex);
                }
            }
            rootElement.setName(elementName);
            String rootNamespace = xmlRE.getNamespace();
            if (rootNamespace.equals(XMLProcessor.DEFAULT)) {
                Schema rootElementSchema = getSchemaForNamespace(namespaceInfo.getNamespace());
                if (rootElementSchema != null) {
                    rootElementSchema.addTopLevelElement(rootElement);
                }
                schemaTypeInfo.getGlobalElementDeclarations().add(new QName(namespaceInfo.getNamespace(), rootNamespace));
                rootNamespace = namespaceInfo.getNamespace();
            } else {
                Schema rootElementSchema = getSchemaForNamespace(rootNamespace);
                if (rootElementSchema != null) {
                    rootElementSchema.addTopLevelElement(rootElement);
                }
                schemaTypeInfo.getGlobalElementDeclarations().add(new QName(rootNamespace, elementName));
            }

            // handle root-level imports/includes [schema = the type's schema]
            Schema rootSchema = getSchemaForNamespace(rootNamespace);
            addImportIfRequired(rootSchema, schema, schema.getTargetNamespace());

            // setup a prefix, if necessary
            if (rootSchema != null && !info.getClassNamespace().equals(EMPTY_STRING)) {
                pfx = getOrGeneratePrefixForNamespace(info.getClassNamespace(), rootSchema);
                pfx += COLON;
            }
        }



        if (CompilerHelper.isSimpleType(info)){

            SimpleType type = new SimpleType();
            //simple type case, we just need the name and namespace info
            if (typeName.equals(EMPTY_STRING)) {
                //In this case, it should be a type under
                //A root elem or locally defined whenever used
                if (rootElement != null) {
                    rootElement.setSimpleType(type);
                }
            } else {
                type.setName(typeName);
                schema.addTopLevelSimpleTypes(type);
                if (rootElement != null) {
                    rootElement.setType(pfx + type.getName());
                }
            }
            //Figure out schema type and set it as Restriction
            QName restrictionType = null;
            Restriction restriction = new Restriction();
            if (info.isEnumerationType()) {
                restrictionType = ((EnumTypeInfo) info).getRestrictionBase();
                restriction.setEnumerationFacets(this.getEnumerationFacetsFor((EnumTypeInfo) info));

                String prefix = null;
                if (restrictionType.getNamespaceURI() != null && !EMPTY_STRING.equals(restrictionType.getNamespaceURI())) {
                    if (javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(restrictionType.getNamespaceURI())) {
                        prefix = Constants.SCHEMA_PREFIX;
                    } else {
                        prefix = getPrefixForNamespace(schema, restrictionType.getNamespaceURI());
                    }
                }
                String extensionTypeName = restrictionType.getLocalPart();
                if (prefix != null) {
                    extensionTypeName = prefix + COLON + extensionTypeName;
                }
                restriction.setBaseType(extensionTypeName);

                type.setRestriction(restriction);
            } else {
                valueField= info.getXmlValueProperty();
                JavaClass javaType = valueField.getActualType();
                QName baseType = getSchemaTypeFor(javaType);
                String prefix = null;
                if (baseType.getNamespaceURI() != null && !baseType.getNamespaceURI().equals(EMPTY_STRING)) {
                    if (baseType.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                        prefix = Constants.SCHEMA_PREFIX;
                    } else {
                        prefix = getPrefixForNamespace(schema, baseType.getNamespaceURI());
                    }
                }
                String baseTypeName = baseType.getLocalPart();
                if (prefix != null) {
                    baseTypeName = prefix + COLON + baseTypeName;
                }
                if (valueField.isXmlList() || (valueField.getGenericType() != null)) {
                    //generate a list instead of a restriction
                    org.eclipse.persistence.internal.oxm.schema.model.List list = new org.eclipse.persistence.internal.oxm.schema.model.List();
                    list.setItemType(baseTypeName);
                    type.setList(list);
                } else {
                    if (helper.isAnnotationPresent(valueField.getElement(), XmlSchemaType.class)) {
                        XmlSchemaType schemaType = (XmlSchemaType) helper.getAnnotation(valueField.getElement(), XmlSchemaType.class);
                        baseType = new QName(schemaType.namespace(), schemaType.name()); // TODO: This assignment seems like a bug, probably this should be "baseTypeName" ?
                    }
                    restriction.setBaseType(baseTypeName);
                    type.setRestriction(restriction);
                }
            }
            info.setSimpleType(type);
        } else if ((valueField = this.getXmlValueFieldForSimpleContent(info)) != null) {
            ComplexType type = new ComplexType();
            SimpleContent content = new SimpleContent();
            if (EMPTY_STRING.equals(typeName)) {
                if (rootElement != null) {
                    rootElement.setComplexType(type);
                }
                info.setComplexType(type);
            } else {
                type.setName(typeName);
                schema.addTopLevelComplexTypes(type);
                if (rootElement != null) {
                    rootElement.setType(pfx + type.getName());
                }
            }
            QName extensionType = getSchemaTypeFor(valueField.getType());
            if (helper.isAnnotationPresent(valueField.getElement(), XmlSchemaType.class)) {
                XmlSchemaType schemaType = (XmlSchemaType) helper.getAnnotation(valueField.getElement(), XmlSchemaType.class);
                extensionType = new QName(schemaType.namespace(), schemaType.name());
            }
            String prefix = null;
            if (extensionType.getNamespaceURI() != null && !extensionType.getNamespaceURI().equals(EMPTY_STRING)) {
                if (extensionType.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                    prefix = Constants.SCHEMA_PREFIX;
                } else {
                    prefix = getPrefixForNamespace(schema, extensionType.getNamespaceURI());
                }
            }
            String extensionTypeName = extensionType.getLocalPart();
            if (prefix != null) {
                extensionTypeName = prefix + COLON + extensionTypeName;
            }
            Extension extension = new Extension();
            extension.setBaseType(extensionTypeName);
            content.setExtension(extension);
            type.setSimpleContent(content);
            info.setComplexType(type);
        } else {
            ComplexType type = createComplexTypeForClass(myClass, info);
            TypeDefParticle compositor = null;
            if(type.getComplexContent() != null && type.getComplexContent().getExtension() != null) {
                compositor = type.getComplexContent().getExtension().getTypeDefParticle();
            } else {
                compositor = type.getTypeDefParticle();
            }
            if (EMPTY_STRING.equals(typeName)) {
                if (rootElement != null) {
                    rootElement.setComplexType(type);
                }
                info.setComplexType(type);
                info.setCompositor(compositor);
            } else {
                type.setName(typeName);
                if (rootElement != null) {
                    rootElement.setType(pfx + type.getName());
                }
                schema.addTopLevelComplexTypes(type);
                info.setComplexType(type);
                info.setCompositor(compositor);
            }
        }
    }

    private ComplexType createComplexTypeForClass(JavaClass myClass, TypeInfo info) {

        Schema schema = getSchemaForNamespace(info.getClassNamespace());

        ComplexType type = new ComplexType();
        JavaClass superClass = CompilerHelper.getNextMappedSuperClass(myClass, this.typeInfo, this.helper);
        // Handle abstract class
        if (myClass.isAbstract()) {
            type.setAbstractValue(true);
        }

        Extension extension = null;
        if (superClass != null) {
            TypeInfo parentTypeInfo = this.typeInfo.get(superClass.getQualifiedName());
            if (parentTypeInfo != null) {
                extension = new Extension();
                // may need to qualify the type
                String parentPrefix = getPrefixForNamespace(schema, parentTypeInfo.getClassNamespace());
                if (parentPrefix != null) {
                    extension.setBaseType(parentPrefix + COLON + parentTypeInfo.getSchemaTypeName());
                } else {
                    extension.setBaseType(parentTypeInfo.getSchemaTypeName());
                }

                if(parentTypeInfo.getXmlValueProperty() != null){
                    SimpleContent content = new SimpleContent();
                    content.setExtension(extension);
                    type.setSimpleContent(content);
                    return type;
                }else{
                    ComplexContent content = new ComplexContent();
                    content.setExtension(extension);
                    type.setComplexContent(content);
                }

            }
        }

        TypeDefParticle compositor = null;
        String[] propOrder = null;
        if (info.isSetPropOrder()) {
            propOrder = info.getPropOrder();
        }

        if (propOrder != null && propOrder.length == 0) {
            // Note that the spec requires an 'all' to be generated
            // in cases where propOrder == 0, however, the TCK
            // requires the extension case to use sequences
            if (info.hasElementRefs()) {
                // generate a sequence to satisfy TCK
                compositor = new Sequence();
                if (extension != null) {
                    extension.setSequence((Sequence) compositor);
                } else {
                    type.setSequence((Sequence) compositor);
                }
            } else if (extension != null) {
                compositor = new All();
                extension.setAll((All) compositor);
            } else {
                compositor = new All();
                type.setAll((All) compositor);
            }
        } else {
            // generate a sequence to satisfy TCK
            compositor = new Sequence();
            if (extension != null) {
                extension.setSequence((Sequence) compositor);
            } else {
                type.setSequence((Sequence) compositor);
            }
        }
        return type;
    }
    public void addToSchemaType(TypeInfo ownerTypeInfo, java.util.List<Property> properties, TypeDefParticle compositor, ComplexType type, Schema workingSchema) {
        //If there are no properties we don't want a sequence/choice or all tag written out
        if (properties.size() == 0) {
            type.setAll(null);
            type.setSequence(null);
            type.setChoice(null);
            ownerTypeInfo.setCompositor(null);
            return;
        }

        boolean extAnyAdded = false;

        // generate schema components for each property
        for (Property next : properties) {
            if (next == null) { continue; }
            Schema currentSchema = workingSchema;
            TypeDefParticle parentCompositor = compositor;
            boolean isChoice = (parentCompositor instanceof Choice);
            ComplexType parentType = type;
            // ignore transient and inverse reference/non-writeable properties
            if(!next.isTransient() && !(next.isInverseReference() && !next.isWriteableInverseReference())){
                // handle xml extensions
                if (next.isVirtual()) {
                    boolean extSchemaAny = false;
                    if (ownerTypeInfo.getXmlVirtualAccessMethods().getSchema() != null) {
                        extSchemaAny = ownerTypeInfo.getXmlVirtualAccessMethods().getSchema().equals(XmlVirtualAccessMethodsSchema.ANY);
                    }
                    if (extSchemaAny && !next.isAttribute()) {
                        if (!extAnyAdded) {
                            addAnyToSchema(next, compositor, true, Constants.ANY_NAMESPACE_ANY);
                            extAnyAdded = true;
                            continue;
                        } else {
                            // any already added
                            continue;
                        }
                    } else {
                        // proceed, adding the schema element as usual
                    }
                }
                // handle transformers
                if (next.isSetXmlTransformation() && next.getXmlTransformation().isSetXmlWriteTransformers()) {
                    addTransformerToSchema(next, ownerTypeInfo, compositor, type, workingSchema);
                    continue;
                }
                // handle XmlJoinNodes
                if (next.isSetXmlJoinNodes()) {
                    addXmlJoinNodesToSchema(next, parentCompositor, currentSchema, parentType);
                    continue;
                }
                // deal with xml-path case
                if (next.getXmlPath() != null) {
                    // create schema components based on the XmlPath
                    AddToSchemaResult xpr = addXPathToSchema(next, parentCompositor, currentSchema, isChoice, type);
                    // if the returned object or schema component is null there is nothing to do
                    if (xpr == null || ((parentCompositor = xpr.particle) == null && xpr.simpleContentType == null)) {
                        continue;
                    }
                    // now process the property as per usual, adding to the created schema component
                    if(xpr.schema == null) {
                        //if there's no schema, this may be a ref to an attribute in an ungenerated schema
                        //no need to generate the attribute in the target schema
                        continue;
                    }
                    currentSchema = xpr.schema;
                    if(parentCompositor == null) {
                        parentType = xpr.simpleContentType;
                    } else if (parentCompositor.getOwner() instanceof ComplexType) {
                        parentType = ((ComplexType)parentCompositor.getOwner());
                    }
                    // deal with the XmlElementWrapper case
                } else if (!isChoice && !next.isMap() && next.isSetXmlElementWrapper()) {
                    AddToSchemaResult asr = addXmlElementWrapperToSchema(next, currentSchema, compositor);
                    // if returned object is null there is nothing to do
                    if (asr == null) {
                        continue;
                    }
                    // the returned object contains ComplexType and TypeDefParticles to use
                    parentType = asr.type;
                    parentCompositor = asr.particle;
                }
                // handle mixed content
                if (next.isMixedContent()) {
                    parentType.setMixed(true);
                }
                // handle attribute
                if (next.isAttribute() && !next.isAnyAttribute()) {
                    addAttributeToSchema(buildAttribute(next, currentSchema), next.getSchemaName(), currentSchema, parentType);
                    // handle any attribute
                } else if (next.isAnyAttribute()) {
                    addAnyAttributeToSchema(parentType);
                    // handle choice
                } else if (next.isChoice()) {
                    addChoiceToSchema(next, ownerTypeInfo, parentType, parentCompositor, currentSchema);
                    // handle reference
                } else if (next.isReference()) {
                    addReferenceToSchema(next, currentSchema, parentCompositor);
                    // handle any
                } else if (next.isAny() || next.getVariableAttributeName() !=null) {
                    addAnyToSchema(next, parentCompositor);
                    // add an element
                } else if (!(ownerTypeInfo.getXmlValueProperty() != null && ownerTypeInfo.getXmlValueProperty() == next)) {
                    Element element = buildElement(next, parentCompositor instanceof All, currentSchema, ownerTypeInfo);
                    addElementToSchema(element, next.getSchemaName().getNamespaceURI(), next.isPositional(), parentCompositor, currentSchema, ownerTypeInfo.getJavaClass().getPackageName());
                }
            }
        }
    }

    /**
     * Return the schema type (as QName) based on a given JavaClass.
     *
     */
    public QName getSchemaTypeFor(JavaClass javaClass) {
        String className;
        if (javaClass.isArray()) {
            Class wrapperClass = arrayClassesToGeneratedClasses.get(javaClass.getName());
            if (null == wrapperClass) {
                className = javaClass.getQualifiedName();
            } else {
                className = wrapperClass.getName();
            }
        } else {
            className = javaClass.getQualifiedName();
        }
        // check user defined types first
        QName schemaType = userDefinedSchemaTypes.get(className);
        if (schemaType == null) {
            schemaType = helper.getXMLToJavaTypeMap().get(javaClass.getRawName());
        }
        if (schemaType == null) {
            TypeInfo targetInfo = this.typeInfo.get(className);
            if (targetInfo != null) {
                schemaType = new QName(targetInfo.getClassNamespace(), targetInfo.getSchemaTypeName());
            }
        }
        if (schemaType == null) {
            if (javaClass.getQualifiedName().equals(OBJECT_CLASSNAME)) {
                return Constants.ANY_TYPE_QNAME;
            }
            return Constants.ANY_SIMPLE_TYPE_QNAME;
        }
        return schemaType;
    }

    public void populateSchemaTypes() {
        for (TypeInfo info : typeInfo.values()) {
            if (info.isComplexType()) {
                if (info.getSchema() != null) {
                    List<Property> props = info.getNonTransientPropertiesInPropOrder();
                    // handle class indicator field name
                    if (info.isSetXmlDiscriminatorNode()) {
                        String xpath = info.getXmlDiscriminatorNode();
                        String pname = XMLProcessor.getNameFromXPath(xpath, EMPTY_STRING, true);
                        if (!pname.equals(EMPTY_STRING)) {
                            // since there is no property for the indicator field name, we'll need to make one
                            Property prop = new Property(helper);
                            prop.setPropertyName(pname);
                            prop.setXmlPath(xpath);
                            prop.setSchemaName(new QName(pname));
                            prop.setType(helper.getJavaClass(String.class));
                            prop.setIsAttribute(true);
                            props.add(prop);
                        }
                    }
                    addToSchemaType(info, props, info.getCompositor(), info.getComplexType(), info.getSchema());
                    if (info.hasPredicateProperties()) {
                        addToSchemaType(info, info.getPredicateProperties(), info.getCompositor(), info.getComplexType(), info.getSchema());
                    }
                }
            }
        }
    }

    public String getSchemaTypeNameForClassName(String className) {
        return Introspector.decapitalize(className.substring(className.lastIndexOf(DOT_CHAR) + 1));
    }

    public ArrayList<Object> getEnumerationFacetsFor(EnumTypeInfo info) {
        return (ArrayList<Object>) info.getXmlEnumValues();
    }

    public Property getXmlValueFieldForSimpleContent(TypeInfo info) {
        ArrayList<Property> properties = info.getPropertyList();
        Property xmlValueProperty = info.getXmlValueProperty();
        boolean foundValue = false;
        boolean foundNonAttribute = false;
        Property valueField = null;

        for (Property prop : properties) {
            if (xmlValueProperty != null && xmlValueProperty == prop) {
                foundValue = true;
                valueField = prop;
            } else if (!prop.isAttribute() && !prop.isTransient() && !prop.isAnyAttribute()) {
                foundNonAttribute = true;
            }
        }
        if (foundValue && !foundNonAttribute) {
            return valueField;
        }
        return null;
    }

    /**
     * Indicates if a given Property is a collection type.
     *
     */
    public boolean isCollectionType(Property field) {
        JavaClass type = field.getType();
        return (helper.getJavaClass(java.util.Collection.class).isAssignableFrom(type)
                || helper.getJavaClass(java.util.List.class).isAssignableFrom(type)
                || helper.getJavaClass(java.util.Set.class).isAssignableFrom(type));
    }

    private Schema getSchemaForNamespace(String namespace) {
        return getSchemaForNamespace(namespace, null);
    }

    /**
     * Return the Schema for a given namespace.  If no schema exists for the
     * given namespace, one will be created.
     *
     */
    private Schema getSchemaForNamespace(String namespace, String packageName) {
        if (schemaForNamespace == null) {
            schemaForNamespace = new HashMap<>();
            allSchemas = new ArrayList<>();
        }
        Schema schema = schemaForNamespace.get(namespace);
        if (schema == null && !javax.xml.XMLConstants.XML_NS_URI.equals(namespace)) {
            schema = new Schema();
            String schemaName = SCHEMA + schemaCount + SCHEMA_EXT;

            NamespaceInfo namespaceInfo = getNamespaceInfoForNamespace(namespace, packageName);
            if (namespaceInfo != null) {
                if (namespaceInfo.getLocation() != null && !namespaceInfo.getLocation().equals(GENERATE)) {
                    return null;
                }
                java.util.Vector<Namespace> namespaces = namespaceInfo.getNamespaceResolver().getNamespaces();
                for (int i = 0; i < namespaces.size(); i++) {
                    Namespace nextNamespace = namespaces.get(i);
                    schema.getNamespaceResolver().put(nextNamespace.getPrefix(), nextNamespace.getNamespaceURI());
                }
            }

            if (outputResolver != null) {
                try {
                    Result res = outputResolver.createOutput(namespace, schemaName);
                    // if the resolver returns null, schema generation for this namespace URI will be skipped
                    if (res == null) {
                        return null;
                    }
                    schema.setResult(res);
                    if (res.getSystemId() != null) {
                        schemaName = res.getSystemId();
                        // may use schema name to create a URI, which expects '/' as file separator
                        schemaName = schemaName.replace(SLASHES, SLASH);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            schema.setName(schemaName);
            schemaCount++;

            if (!namespace.equals(EMPTY_STRING)) {
                schema.setTargetNamespace(namespace);
                String prefix = null;
                if (namespaceInfo != null) {
                    prefix = namespaceInfo.getNamespaceResolver().resolveNamespaceURI(namespace);
                }
                if (prefix == null) {
                    prefix = schema.getNamespaceResolver().generatePrefix();
                }
                schema.getNamespaceResolver().put(prefix, namespace);
            }

            if (namespaceInfo != null) {
                schema.setAttributeFormDefault(namespaceInfo.isAttributeFormQualified());
                schema.setElementFormDefault(namespaceInfo.isElementFormQualified());
            }
            schemaForNamespace.put(namespace, schema);
            allSchemas.add(schema);
        }
        return schema;
    }

    public Collection<Schema> getAllSchemas() {
        if (allSchemas == null) {
            allSchemas = new ArrayList<>();
        }
        return allSchemas;
    }

    public NamespaceInfo getNamespaceInfoForNamespace(String namespace) {

        return getNamespaceInfoForNamespace(namespace, null);
    }

    public NamespaceInfo getNamespaceInfoForNamespace(String namespace, String packageName) {

        if (null != packageName) {
            if (packageToPackageInfoMappings.containsKey(packageName)) {
                PackageInfo packageInfo = packageToPackageInfoMappings.get(packageName);
                if (packageInfo.getNamespace().equals(namespace)) {
                    return packageInfo.getNamespaceInfo();
                }
            }
        }

        Collection<PackageInfo> packageInfo = packageToPackageInfoMappings.values();
        for (PackageInfo info : packageInfo) {
            if (info.getNamespace().equals(namespace)) {
                return info.getNamespaceInfo();
            }
        }
        return null;
    }

    public String getPrefixForNamespace(Schema schema, String URI) {
        //add Import if necessary
        Schema referencedSchema = this.getSchemaForNamespace(URI);
        addImportIfRequired(schema, referencedSchema, URI);

        NamespaceResolver namespaceResolver = schema.getNamespaceResolver();
        Enumeration<String> keys = namespaceResolver.getPrefixes();
        while (keys.hasMoreElements()) {
            String next = keys.nextElement();
            String nextUri = namespaceResolver.resolveNamespacePrefix(next);
            if (nextUri.equals(URI)) {
                return next;
            }
        }
        return null;
    }

    /**
     * Attempt to resolve the given URI to a prefix.  If this is unsuccessful, one
     * will be generated and added to the resolver.
     *
     */
    public String getOrGeneratePrefixForNamespace(String URI, Schema schema) {
        String prefix = schema.getNamespaceResolver().resolveNamespaceURI(URI);
        if (prefix == null) {
            if (URI.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                prefix = schema.getNamespaceResolver().generatePrefix(Constants.SCHEMA_PREFIX);
            } else if (URI.equals(Constants.REF_URL)) {
                prefix = schema.getNamespaceResolver().generatePrefix(Constants.REF_PREFIX);

                if(!importExists(schema, URI, SWA_REF_IMPORT)){
                    Import schemaImport = new Import();
                    schemaImport.setSchemaLocation(SWA_REF_IMPORT);
                    schemaImport.setNamespace(URI);
                    schema.getImports().add(schemaImport);
                }
            } else {
                prefix = schema.getNamespaceResolver().generatePrefix();
            }
            schema.getNamespaceResolver().put(prefix, URI);
        }
        return prefix;
    }

    public void addGlobalElements(Map<QName, ElementDeclaration> additionalElements) {
        for (Entry<QName, ElementDeclaration> entry : additionalElements.entrySet()) {
            QName next = entry.getKey();
            if(next != null) {
                ElementDeclaration nextElement = entry.getValue();
                if (nextElement.getScopeClass() == GLOBAL.class) {

                    String namespaceURI = next.getNamespaceURI();
                    Schema targetSchema = getSchemaForNamespace(namespaceURI);
                    if (targetSchema == null) {
                        continue;
                    }

                    if (targetSchema.getTopLevelElements().get(next.getLocalPart()) == null) {
                        Element element = new Element();
                        element.setName(next.getLocalPart());
                        element.setNillable(nextElement.isNillable());
                        JavaClass javaClass = nextElement.getJavaType();

                        //First check for built in type
                        QName schemaType = helper.getXMLToJavaTypeMap().get(javaClass.getRawName());
                        if (schemaType != null) {
                            element.setType(Constants.SCHEMA_PREFIX + COLON + schemaType.getLocalPart());
                        } else if (areEquals(javaClass, JAVAX_ACTIVATION_DATAHANDLER) || areEquals(javaClass, byte[].class) || areEquals(javaClass, Byte[].class) || areEquals(javaClass, Image.class) || areEquals(javaClass, Source.class) || areEquals(javaClass, JAVAX_MAIL_INTERNET_MIMEMULTIPART)) {
                            schemaType = Constants.BASE_64_BINARY_QNAME;
                            if(nextElement.getTypeMappingInfo() != null) {
                                if(nextElement.isXmlAttachmentRef()) {
                                    schemaType = Constants.SWA_REF_QNAME;
                                }
                                if (nextElement.getXmlMimeType() != null) {
                                    element.getAttributesMap().put(Constants.EXPECTED_CONTENT_TYPES_QNAME, nextElement.getXmlMimeType());
                                }
                            }
                            String prefix = getOrGeneratePrefixForNamespace(schemaType.getNamespaceURI(), targetSchema);
                            element.setType(prefix + COLON + schemaType.getLocalPart());
                        } else if (areEquals(javaClass, CoreClassConstants.XML_GREGORIAN_CALENDAR)) {
                            schemaType = Constants.ANY_SIMPLE_TYPE_QNAME;
                            element.setType(Constants.SCHEMA_PREFIX + COLON + schemaType.getLocalPart());
                        } else {

                            TypeInfo type = this.typeInfo.get(javaClass.getQualifiedName());
                            if (type != null) {
                                String typeName = null;
                                if (type.isComplexType()) {
                                    typeName = type.getComplexType().getName();
                                } else {
                                    typeName = type.getSimpleType().getName();
                                }
                                // may need an anonymous complex type
                                if (typeName == null) {
                                    Schema schema = getSchemaForNamespace(next.getNamespaceURI());
                                    ComplexType cType = createComplexTypeForClass(javaClass, type);
                                    TypeDefParticle particle = null;
                                    if(cType.getComplexContent() != null && cType.getComplexContent().getExtension() != null) {
                                        particle = cType.getComplexContent().getExtension().getTypeDefParticle();
                                    } else {
                                        particle = cType.getTypeDefParticle();
                                    }
                                    addToSchemaType(type, type.getPropertyList(), particle, cType, schema);
                                    targetSchema = schema;
                                    element.setComplexType(cType);
                                } else {
                                    //  check namespace of schemaType
                                    if (type.getClassNamespace().equals(namespaceURI)) {
                                        //no need to prefix here
                                        String prefix = targetSchema.getNamespaceResolver().resolveNamespaceURI(namespaceURI);
                                        if(prefix != null && !(prefix.equals(EMPTY_STRING))) {
                                            element.setType(prefix + COLON + typeName);
                                        } else {
                                            element.setType(typeName);
                                        }
                                    } else {
                                        Schema complexTypeSchema = getSchemaForNamespace(type.getClassNamespace());
                                        String complexTypeSchemaNS = type.getClassNamespace();
                                        if (complexTypeSchemaNS == null) {
                                            complexTypeSchemaNS = EMPTY_STRING;
                                        }
                                        addImportIfRequired(targetSchema, complexTypeSchema, type.getClassNamespace());

                                        String prefix = targetSchema.getNamespaceResolver().resolveNamespaceURI(complexTypeSchemaNS);
                                        if (prefix != null) {
                                            element.setType(prefix + COLON + typeName);
                                        } else {
                                            element.setType(typeName);
                                        }
                                    }
                                }
                            }
                        }
                        if (nextElement.getSubstitutionHead() != null) {
                            String subLocal = nextElement.getSubstitutionHead().getLocalPart();
                            String subNamespace = nextElement.getSubstitutionHead().getNamespaceURI();
                            String prefix = getPrefixForNamespace(targetSchema, subNamespace);
                            if (prefix == null || prefix.equals(EMPTY_STRING)) {
                                element.setSubstitutionGroup(subLocal);
                            } else {
                                element.setSubstitutionGroup(prefix + COLON + subLocal);
                            }
                        }
                        targetSchema.addTopLevelElement(element);
                        SchemaTypeInfo info = this.schemaTypeInfo.get(javaClass.getQualifiedName());
                        if (info == null) {
                            // probably for a simple type, not generated
                            info = new SchemaTypeInfo();
                            info.setSchemaTypeName(schemaType);
                            schemaTypeInfo.put(javaClass.getQualifiedName(), info);
                        }
                        info.getGlobalElementDeclarations().add(next);
                    }
                }
            }
        }
    }

    /**
     * Return the Map of SchemaTypeInfo instances.  The Map is keyed on JavaClass
     * qualified name.
     *
     */
    public Map<String, SchemaTypeInfo> getSchemaTypeInfo() {
        return this.schemaTypeInfo;
    }

    private boolean importExists(Schema schema, String importNsURI, String schemaLocation) {
        java.util.List<Import> imports = schema.getImports();
        for (int i = 0; i < imports.size(); i++) {
            Import nextImport = imports.get(i);
            if (nextImport.getSchemaLocation() != null && nextImport.getSchemaLocation().equals(schemaLocation)) {
                if ("".equals(importNsURI)) {
                    if (nextImport.getNamespace() == null) {
                        return true;
                    }
                } else {
                    if (importNsURI.equals(nextImport.getNamespace())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private boolean addImportIfRequired(Schema sourceSchema, Schema importSchema, String importNamespace) {
        if (importSchema != sourceSchema && !(importNamespace != null && importNamespace.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI))) {
            String schemaName = null;
            if(javax.xml.XMLConstants.XML_NS_URI.equals(importNamespace)){
                schemaName = Constants.XML_NAMESPACE_SCHEMA_LOCATION;
            }else{
                if (importSchema != null) {
                    schemaName = importSchema.getName();
                } else if (importNamespace != null) {
                    NamespaceInfo nInfo = getNamespaceInfoForNamespace(importNamespace);
                    schemaName = nInfo.getLocation();
                }
            }
            // may need to relativize the schema name
            if (schemaName != null && importSchema != null) {
                URI relativizedURI = null;
                try {
                    // need to strip off the last slash and the file name that follows
                    String schemaPath = sourceSchema.getName();
                    int idx;
                    if ((idx = schemaPath.lastIndexOf(SLASH)) != -1) {
                        schemaPath = schemaPath.substring(0, idx);
                    }
                    URI baseURI = new URI(schemaPath);
                    URI importURI = new URI(schemaName);
                    relativizedURI = baseURI.relativize(importURI);
                } catch (Exception e) {
                    // at this point we will leave schemaName as is
                    relativizedURI = null;
                }
                if (relativizedURI != null) {
                    schemaName = relativizedURI.getPath();
                }
            }

            if (schemaName != null && !importExists(sourceSchema, importNamespace, schemaName)) {
                Import schemaImport = new Import();
                schemaImport.setSchemaLocation(schemaName);
                if (importNamespace != null && !importNamespace.equals(EMPTY_STRING)) {
                    schemaImport.setNamespace(importNamespace);
                }
                sourceSchema.getImports().add(schemaImport);
                if (schemaImport.getNamespace() != null) {
                    if(schemaImport.getNamespace().equals(javax.xml.XMLConstants.XML_NS_URI)) {
                        //make sure xml namespace is in the resolver so it gets declared
                        sourceSchema.getNamespaceResolver().put(javax.xml.XMLConstants.XML_NS_PREFIX, javax.xml.XMLConstants.XML_NS_URI);
                    }
                    String prefix = sourceSchema.getNamespaceResolver().resolveNamespaceURI(importNamespace);
                    //Don't need to generate prefix for default namespace
                    if (prefix == null && !importNamespace.equals(EMPTY_STRING)) {
                        sourceSchema.getNamespaceResolver().put(sourceSchema.getNamespaceResolver().generatePrefix(), importNamespace);
                    }
                }
                return true;
            }
        }
        return false;
    }

    /**
     * Compares a JavaModel JavaClass to a Class.  Equality is based on
     * the raw name of the JavaClass compared to the canonical
     * name of the Class.
     *
     */
    protected boolean areEquals(JavaClass src, String tgtCanonicalName) {
        if (src == null || tgtCanonicalName == null) {
            return false;
        }
        return src.getRawName().equals(tgtCanonicalName);
    }

    /**
     * Compares a JavaModel JavaClass to a Class.  Equality is based on
     * the raw name of the JavaClass compared to the canonical
     * name of the Class.
     *
     */
    protected boolean areEquals(JavaClass src, Class tgt) {
        if (src == null || tgt == null) {
            return false;
        }
        return src.getRawName().equals(tgt.getCanonicalName());
    }

    /**
     * Return the type name for a given Property.
     *
     */
    private String getTypeName(Property next, JavaClass javaType, Schema theSchema){
        QName schemaType = next.getSchemaType();
        if (schemaType == null) {
            schemaType = getSchemaTypeFor(javaType);
        }
        if (schemaType != null) {
            if (schemaType.getNamespaceURI() == null) {
                return schemaType.getLocalPart();
            }
            return getOrGeneratePrefixForNamespace(schemaType.getNamespaceURI(), theSchema) + COLON + schemaType.getLocalPart();
        }
        return Constants.SCHEMA_PREFIX + Constants.COLON + Constants.ANY_SIMPLE_TYPE;
    }

    /**
     * Return the qualified (if necessary) type name for a given Property.
     *
     */
    private String getQualifiedTypeName(Property prop, Schema schema) {
        JavaClass javaType = prop.getActualType();
        String typeName = getTypeName(prop, javaType, schema);
        // may need to qualify the type
        if (typeName != null && !typeName.contains(COLON)) {
            String prefix = getPrefixForNamespace(schema, schema.getTargetNamespace());
            if (prefix != null) {
                typeName = prefix + COLON + typeName;
            }
        }
        return typeName;
    }

    /**
     * This method will build element/complexType/typedefparticle components for a given xml-path,
     * and return an XmlPathResult instance containg the sequence that the target should be added
     * to, as well as the current schema - which could be different than the working schema used
     * before calling this method in the case of a prefixed path element from a different namespace.
     * Regarding the path 'target', if the xml-path was "contact-info/address/street", "street"
     * would be the target.  In this case the sequence containing the "address" element would be
     * set in the XmlPathResult to be returned.
     *
     * The exception case is an 'any', where we want to process the last path element before
     * returning - this is necessary due to the fact that an Any will be added to the sequence
     * in place of the last path element by the calling method.
     *
     */
    private AddToSchemaResult buildSchemaComponentsForXPath(XPathFragment frag, AddToSchemaResult xpr, boolean isChoice, Property next) {
        boolean isAny = next.isAny() || next.isAnyAttribute();
        TypeDefParticle currentParticle = xpr.particle;
        Schema workingSchema = xpr.schema;

        // each nested choice on a collection will be unbounded
        boolean isUnbounded = false;
        if(currentParticle != null) {
            isUnbounded = (currentParticle.getMaxOccurs() != null && currentParticle.getMaxOccurs()==Occurs.UNBOUNDED);
        }

        // don't process the last frag; that will be handled by the calling method if necessary
        // note that we may need to process the last frag if it has a namespace or is an 'any'
        boolean lastFrag = (frag.getNextFragment() == null || frag.getNextFragment().nameIsText());
        //boolean isNextAttribute = (frag.getNextFragment() != null) && (frag.getNextFragment().isAttribute());
        // if the element is already in the sequence we don't want the calling method to add a second one
        if (lastFrag && (elementExistsInParticle(frag.getLocalName(), frag.getShortName(), currentParticle) != null)) {
            xpr.particle = null;
            return xpr;
        }


        // if the current element exists, use it; otherwise create a new one
        Element currentElement = elementExistsInParticle(frag.getLocalName(), frag.getShortName(), currentParticle);
        boolean currentElementExists = (currentElement != null);

        if (!currentElementExists) {
            currentElement = new Element();
            // don't set the element name yet, as it may end up being a ref
            ComplexType cType = new ComplexType();
            TypeDefParticle particle = null;
            if (isChoice) {
                particle = new Choice();
                if (isUnbounded) {
                    particle.setMaxOccurs(Occurs.UNBOUNDED);
                }
            } else {
                XPathFragment nextFragment = frag.getNextFragment();
                if (frag.containsIndex() || frag.getPredicate() != null || (!next.isXmlList() && null != nextFragment && nextFragment.isAttribute() && helper.isCollectionType(next.getType()))) {
                    currentElement.setMaxOccurs(Occurs.UNBOUNDED);
                }
                particle = new Sequence();
            }
            cType.setTypeDefParticle(particle);
            currentElement.setComplexType(cType);
        } else {
            //if the current element already exists, we may need to change it's type
            XPathFragment nextFrag = frag.getNextFragment();
            if(nextFrag != null && nextFrag.isAttribute()) {
                if(currentElement.getType() != null && currentElement.getComplexType() == null) {
                    //there's already a text mapping to this element, so
                    //attributes can be added by making it complex with
                    //simple content.
                    SimpleType type = currentElement.getSimpleType();
                    if(type != null) {
                        ComplexType cType = new ComplexType();
                        cType.setSimpleContent(new SimpleContent());
                        Extension extension = new Extension();
                        extension.setBaseType(type.getRestriction().getBaseType());
                        cType.getSimpleContent().setExtension(extension);
                        currentElement.setSimpleType(null);
                        currentElement.setComplexType(cType);
                    } else {
                        String eType = currentElement.getType();
                        ComplexType cType = new ComplexType();
                        SimpleContent sContent = new SimpleContent();
                        Extension extension = new Extension();
                        extension.setBaseType(eType);
                        sContent.setExtension(extension);
                        cType.setSimpleContent(sContent);
                        currentElement.setType(null);
                        currentElement.setComplexType(cType);
                    }
                }
            }
        }
        // may need to create a ref, depending on the namespace
        Element globalElement = null;

        String fragUri = frag.getNamespaceURI();
        if (fragUri != null) {
            Schema fragSchema = getSchemaForNamespace(fragUri);
            String targetNS = workingSchema.getTargetNamespace();

            // handle Attribute case
            if (frag.isAttribute()) {
                if (fragSchema == null || (fragSchema.isAttributeFormDefault() && !fragUri.equals(targetNS)) || (!fragSchema.isAttributeFormDefault() && fragUri.length() > 0)) {
                    // must generate a global attribute and create a reference to it
                    // if the global attribute exists, use it; otherwise create a new one
                    // if fragSchema is null, just generate the ref
                    if(fragSchema != null) {
                        Attribute globalAttribute = null;
                        globalAttribute = fragSchema.getTopLevelAttributes().get(frag.getLocalName());
                        if (globalAttribute == null) {
                            globalAttribute = createGlobalAttribute(frag, workingSchema, fragSchema, next);
                        }
                    } else {
                        //may need to add an import
                        addImportIfRequired(workingSchema, null, fragUri);
                    }
                    // add the attribute ref to the current element
                    String attributeRefName;
                    if (fragUri.equals(targetNS)) {
                        String prefix = fragSchema.getNamespaceResolver().resolveNamespaceURI(fragUri);
                        attributeRefName = prefix + COLON + frag.getLocalName();
                    } else {
                        attributeRefName = frag.getShortName();
                    }
                    TypeDefParticleOwner type;
                    if(currentParticle != null) {
                        type = currentParticle.getOwner();
                    } else {
                        type = xpr.simpleContentType;
                    }
                    if (type instanceof ComplexType) {
                        createRefAttribute(attributeRefName, (ComplexType)type);
                    }
                    // set the frag's schema as it may be different than the current schema
                    xpr.schema = fragSchema;
                    // ref case - indicate to the calling method that there's nothing to do
                    xpr.particle = null;
                }
                // since we are dealing with an attribute, we are on the last fragment; return
                return xpr;
            }

            // here we are dealing with an Element
            if ((fragSchema.isElementFormDefault() && !fragUri.equals(targetNS)) || (!fragSchema.isElementFormDefault() && fragUri.length() > 0)) {
                // must generate a global element and create a reference to it
                // if the global element exists, use it; otherwise create a new one
                globalElement = fragSchema.getTopLevelElements().get(frag.getLocalName());
                if (globalElement == null) {
                    globalElement = createGlobalElement(frag, workingSchema, fragSchema, isChoice, isUnbounded, next, (lastFrag && !isAny));
                }
                // if the current element doesn't exist set a ref and add it to the sequence
                if (!currentElementExists) {
                    // use prefix from the working schema's resolver - add prefix/uri pair if necessary
                    String fragPrefix = workingSchema.getNamespaceResolver().resolveNamespaceURI(fragUri);
                    if (fragPrefix == null) {
                        fragPrefix = workingSchema.getNamespaceResolver().generatePrefix(frag.getPrefix());
                        workingSchema.getNamespaceResolver().put(fragPrefix, fragUri);
                    }
                    currentElement = createRefElement(fragPrefix + COLON + frag.getLocalName(), currentParticle);
                    if (frag.containsIndex() || frag.getPredicate() != null || helper.isCollectionType(next.getType())) {
                        currentElement.setMaxOccurs(Occurs.UNBOUNDED);
                    }
                    currentElementExists = true;
                }
                // set the frag's schema as it may be different than the current schema
                xpr.schema = fragSchema;
                // at this point, if we are dealing with the last fragment we will need to return
                if (lastFrag) {
                    // since we processed the last frag, return null so the calling method doesn't
                    // add a second one...unless we're dealing with an 'any'
                    if (isAny) {
                        // set the particle that the 'any' will be added to by the calling method
                        xpr.particle = globalElement.getComplexType().getTypeDefParticle();
                        return xpr;
                    }
                    // ref case - indicate to the calling method that there's nothing to do
                    xpr.particle = null;
                    return xpr;
                }
                // make the global element current
                currentElement = globalElement;
            }
        }
        if (!lastFrag || (lastFrag && isAny)) {
            // if we didn't process a global element, and the current element isn't already in the sequence, add it
            if (!currentElementExists && globalElement == null) {
                currentElement.setName(frag.getLocalName());
                Integer minOccurs = next.getMinOccurs();
                if (minOccurs != null) currentElement.setMinOccurs(String.valueOf(minOccurs));
                else                   currentElement.setMinOccurs(Occurs.ZERO);
                currentParticle.addElement(currentElement);
            }
            // set the correct particle to use/return
            if(currentElement.getComplexType() != null) {
                if(currentElement.getComplexType().getTypeDefParticle() == null) {
                    //complexType with simple-content
                    xpr.simpleContentType = currentElement.getComplexType();
                    xpr.particle = null;
                } else {
                    xpr.particle = currentElement.getComplexType().getTypeDefParticle();
                }
            } else {
                //If there's no complex type, we're building the path through an element with
                //a simple type. In order to build the path through this
                //element, switch to a complex type with simple content.
                SimpleType type = currentElement.getSimpleType();
                if(type != null) {
                    ComplexType cType = new ComplexType();
                    cType.setSimpleContent(new SimpleContent());
                    Extension extension = new Extension();
                    extension.setBaseType(type.getRestriction().getBaseType());
                    cType.getSimpleContent().setExtension(extension);
                    currentElement.setSimpleType(null);
                    currentElement.setComplexType(cType);
                    xpr.particle = null;
                    xpr.simpleContentType = cType;
                } else {
                    String eType = currentElement.getType();
                    ComplexType cType = new ComplexType();
                    SimpleContent sContent = new SimpleContent();
                    Extension extension = new Extension();
                    extension.setBaseType(eType);
                    sContent.setExtension(extension);
                    cType.setSimpleContent(sContent);
                    currentElement.setType(null);
                    currentElement.setComplexType(cType);
                    xpr.particle = null;
                    xpr.simpleContentType = cType;
                }
            }
        }
        // if we're on the last fragment, we're done
        if (lastFrag) {
            return xpr;
        }
        // call back into this method to process the next path element
        return buildSchemaComponentsForXPath(frag.getNextFragment(), xpr, isChoice, next);
    }

    /**
     * Convenience method for determining if an element already exists in a given
     * typedefparticle.  If an element exists whose ref is equal to 'refString'
     * or its name is equal to 'elementName', it is returned.  Null otherwise.
     *
     * Note that ref takes precidence, so if either has a ref set name equality
     * will not be performed.
     *
     * @param elementName the non-null element name to look for
     * @param refString if the element is a ref, this will be the prefix qualified element name
     * @param particle the sequence/choice/all to search for an existing element
     */
    protected Element elementExistsInParticle(String elementName, String refString, TypeDefParticle particle) {
        if (particle == null || particle.getElements() == null || particle.getElements().size() == 0) {
            return null;
        }
        java.util.List<Element> existingElements = particle.getElements();
        if (existingElements != null) {
            Iterator<Element> elementIt = existingElements.iterator();
            while (elementIt.hasNext()) {
                Element element;
                // could be other components in the list, like Any, but we only care about Element
                try {
                    element = elementIt.next();
                } catch (ClassCastException cce) {
                    continue;
                }
                // case #1 - refString is null
                if (refString == null) {
                    // if element has a null ref value and the element names are equal, or element has a non-null
                    // ref that is not equal to its name, and the element names are equal, we found a match
                    if ((element.getRef() == null || (element.getRef() != null && element.getRef().equals(element.getName()))) && elementName.equals(element.getName())) {
                        return element;
                    }
                }
                // case #2 - refString equals elementName
                else if (refString.equals(elementName)) {
                    // if element has a ref equal to refString, or no ref but element names are equal, we found a match
                    if ((element.getRef() != null && element.getRef().equals(refString)) || (element.getRef() == null && elementName.equals(element.getName()))) {
                        return element;
                    }
                }
                // case #3 - refString is different than elementName
                else if (element.getRef() != null && element.getRef().equals(refString)) {
                    return element;
                }
            }
        }
        return null;
    }

    /**
     * Create a global attribute.  An import is added if necessary.  This method
     * will typically be called when processing an XPath and a prefixed path
     * element is encountered tha requires an attribute ref.
     *
     */
    public Attribute createGlobalAttribute(XPathFragment frag, Schema workingSchema, Schema fragSchema, Property prop) {
        Attribute gAttribute = new Attribute();
        gAttribute.setName(frag.getLocalName());
        gAttribute.setType(getQualifiedTypeName(prop, fragSchema));
        fragSchema.getTopLevelAttributes().put(gAttribute.getName(), gAttribute);
        addImportIfRequired(workingSchema, fragSchema, frag.getNamespaceURI());
        return gAttribute;
    }

    /**
     * Create a global element.  An import is added if necessary.  This method
     * will typically be called when processing an XPath and a prefixed path
     * element is encountered the requires an element ref.
     *
     * @param frag XPathFragment which wil lbe used to create the global element
     * @param workingSchema current schema
     * @param fragSchema frag's schema
     * @param isChoice indicates if we need to construct a choice
     * @param isUnbounded maxOccurs setting for choice
     * @param prop property which owns the xml-path
     * @param shouldSetType if this is the last fragment in the xml-path and not an 'any', we should set the type
     */
    public Element createGlobalElement(XPathFragment frag, Schema workingSchema, Schema fragSchema, boolean isChoice, boolean isUnbounded, Property prop, boolean shouldSetType) {
        Element gElement = new Element();
        gElement.setName(frag.getLocalName());
        if (shouldSetType) {
            gElement.setType(getQualifiedTypeName(prop, fragSchema));
        } else {
            ComplexType gCType = new ComplexType();
            TypeDefParticle particle;
            if (isChoice) {
                particle = new Choice();
                if (isUnbounded) {
                    particle.setMaxOccurs(Occurs.UNBOUNDED);
                }
            } else {
                particle = new Sequence();
            }
            gCType.setTypeDefParticle(particle);
            gElement.setComplexType(gCType);
        }
        fragSchema.addTopLevelElement(gElement);
        addImportIfRequired(workingSchema, fragSchema, frag.getNamespaceURI());
        return gElement;
    }

    /**
     * Create an element reference and add it to a given particle. This
     * method will typically be called when processing an XPath and a
     * prefixed path element is encountered that requires an element ref.
     *
     */
    public Element createRefElement(String elementRefName, TypeDefParticle particle) {
        Element refElement = new Element();
        // ref won't have a complex type
        refElement.setComplexType(null);
        refElement.setMinOccurs(Occurs.ZERO);
        refElement.setMaxOccurs(Occurs.ONE);
        refElement.setRef(elementRefName);
        particle.addElement(refElement);
        return refElement;
    }

    /**
     * Create an attribute reference and add it to a given complex type.
     * This method will typically be called when processing an XPath
     * and a prefixed path element is encountered that requires an
     * attribute ref.
     *
     */
    public Attribute createRefAttribute(String attributeRefName, ComplexType owningComplexType) {
        Attribute refAttribute = new Attribute();
        refAttribute.setRef(attributeRefName);
        if (owningComplexType.getSimpleContent() != null) {
            owningComplexType.getSimpleContent().getExtension().getOrderedAttributes().add(refAttribute);
        } else {
            owningComplexType.getOrderedAttributes().add(refAttribute);
        }
        return refAttribute;
    }

    /**
     * This class will typically be used when building schema components.  It will hold the
     * TypeDefParticle (all, sequence, choice), ComplexType, and/or Schema that are to be
     * used by the method that is processing the given property.
     *
     */
    private static final class AddToSchemaResult {
        ComplexType type;
        TypeDefParticle particle;
        Schema schema;
        ComplexType simpleContentType;

        AddToSchemaResult(TypeDefParticle particle, Schema schema) {
            this.particle = particle;
            this.schema = schema;
        }

        AddToSchemaResult(TypeDefParticle particle, ComplexType type) {
            this.particle = particle;
            this.type = type;
        }
    }

    /**
     * Convenience method for processing XmlWriteTransformer(s) for a given property.
     * Required schema components will be generated and set accordingly.
     *
     * @param property the property containing one or more XmlWriteTransformers.
     * @param typeInfo the TypeInfo that owns the property
     * @param compositor sequence/choice/all to modify
     * @param type ComplexType which compositor(s) should be added to
     * @param schema current schema which ComplextType will be added to
     */
    private void addTransformerToSchema(Property property, TypeInfo typeInfo, TypeDefParticle compositor, ComplexType type, Schema schema) {
        java.util.List<Property> props = getTransformerPropertyBuilder(property, typeInfo).buildProperties();
        addToSchemaType(typeInfo, props, compositor, type, schema);
    }

    /**
     * Returns TransformerPropertyBuilder which builds properties from xml transformers.
     *
     * @param property property holding xml transformers
     * @param typeInfo typeInfo with transformer class
     * @return  transformer property builder
     */
    protected TransformerPropertyBuilder getTransformerPropertyBuilder(Property property, TypeInfo typeInfo) {
        return new TransformerPropertyBuilder(property, typeInfo, helper, ATT);
    }

    /**
     * Process a given XmlPath, and create the required schema components.  The last
     * fragment may not be processed; in this case the returned XmlPathResult is
     * used to set the current schema and parent complex type, then the owning
     * property is processed as per usual. Note the last fragment may be processed
     * if it has a namespace or is an 'any'.
     *
     * @param property the property containing the XmlPath for which schema components are to be built
     * @param compositor the sequence/choice/all to modify
     * @param schema the schema being built when this method is called - this could
     *        if the XmlPath contains an entry that references a different namespace
     * @param isChoice indicates if the given property is a choice property
     * @param type the ComplexType which compositor(s) should be added to
     * @return AddToSchemaResult containing current schema and sequence/all/choice build
     *         based on the given XmlPath
     */
    private AddToSchemaResult addXPathToSchema(Property property, TypeDefParticle compositor, Schema schema, boolean isChoice, ComplexType type) {
        // '.' xml-path requires special handling
        if (property.getXmlPath().equals(DOT)) {
            TypeInfo info = typeInfo.get(property.getActualType().getQualifiedName());
            JavaClass infoClass = property.getActualType();
            addSelfProperties(infoClass, info, compositor, type);
            return null;
        }
        // create the XPathFragment(s) for the path
        Field<XMLConversionManager, NamespaceResolver> xfld = new XMLField(property.getXmlPath());
        xfld.setNamespaceResolver(schema.getNamespaceResolver());
        xfld.initialize();
        // build the schema components for the xml-path
        return buildSchemaComponentsForXPath(xfld.getXPathFragment(), new AddToSchemaResult(compositor, schema), isChoice, property);
    }

    private void addSelfProperties(JavaClass aJavaClass, TypeInfo info, TypeDefParticle compositor, ComplexType type) {
        // Recursively add all properties from aJavaClass and its superclasses, adding superclass properties first.
        if (aJavaClass.getSuperclass() != null) {
            TypeInfo superInfo = typeInfo.get(aJavaClass.getSuperclass().getQualifiedName());
            if (superInfo != null) {
                addSelfProperties(aJavaClass.getSuperclass(), superInfo, compositor, type);
            }
        }
        addToSchemaType(info, info.getPropertyList(), compositor, type, info.getSchema());
    }

    /**
     * Convenience method for processing an XmlElementWrapper for a given property. Required schema
     * components will be generated and set accordingly.
     *
     * @param property the property containing an XmlElementWrapper
     * @param schema the schema currently being generated
     * @param compositor sequence/choice/all that the generated wrapper Element will be added to
     * @return AddToSchemaResult containing current ComplexType and TypeDefParticle
     */
    private AddToSchemaResult addXmlElementWrapperToSchema(Property property, Schema schema, TypeDefParticle compositor) {
        XmlElementWrapper wrapper = property.getXmlElementWrapper();
        Element wrapperElement = new Element();
        String name = wrapper.getName();
        // handle nillable
        wrapperElement.setNillable(wrapper.isNillable());

        // namespace in not the target or ##default, create a ref with min/max = 1
        String wrapperNS = wrapper.getNamespace();
        if (!wrapperNS.equals(XMLProcessor.DEFAULT) && !wrapperNS.equals(schema.getTargetNamespace())) {
            wrapperElement.setMinOccurs(Occurs.ONE);
            wrapperElement.setMaxOccurs(Occurs.ONE);

            String prefix = getOrGeneratePrefixForNamespace(wrapperNS, schema);
            wrapperElement.setRef(prefix + COLON + name);
            compositor.addElement(wrapperElement);
            // assume that the element exists and does not need to be created
            return null;
        }
        wrapperElement.setName(name);
        if (wrapper.isRequired()) {
            wrapperElement.setMinOccurs(Occurs.ONE);
        } else {
            wrapperElement.setMinOccurs(Occurs.ZERO);
        }
        if (!wrapperNS.equals(XMLProcessor.DEFAULT)) {
            String lookupNamespace = schema.getTargetNamespace();
            if (lookupNamespace == null) {
                lookupNamespace = EMPTY_STRING;
            }
            NamespaceInfo namespaceInfo = getNamespaceInfoForNamespace(lookupNamespace);
            boolean isElementFormQualified = false;
            if (namespaceInfo != null) {
                isElementFormQualified = namespaceInfo.isElementFormQualified();
            }
            shouldAddRefAndSetForm(wrapperElement, wrapperNS, lookupNamespace,
                    isElementFormQualified, true);
        }
        compositor.addElement(wrapperElement);
        ComplexType wrapperType = new ComplexType();
        Sequence wrapperSequence = new Sequence();
        wrapperType.setSequence(wrapperSequence);
        wrapperElement.setComplexType(wrapperType);
        return new AddToSchemaResult(wrapperSequence, wrapperType);
    }

    /**
     * Build an Attribute with name and type set.  This method will typically be
     * called when processing an XPath that has no associated Property that can
     * be used to build an Attribute, such as in the case of XmlJoinNodes.
     *
     * @param attributeName name of the Attribute
     * @param typeName type of the Attribute
     */
    private Attribute buildAttribute(QName attributeName, String typeName) {
        Attribute attribute = new Attribute();
        attribute.setName(attributeName.getLocalPart());
        attribute.setType(typeName);
        return attribute;
    }

    /**
     * Build an Attribute based on a given Property.
     *
     * @param property the Property used to build the Attribute
     * @param schema the schema currently being generated
     */
    private Attribute buildAttribute(Property property, Schema schema) {
        Attribute attribute = new Attribute();

        QName attributeName = property.getSchemaName();
        attribute.setName(attributeName.getLocalPart());
        if (property.isRequired()) {
            attribute.setUse(Attribute.REQUIRED);
        }
        String fixedValue = property.getFixedValue();
        if (fixedValue != null){
            attribute.setFixed(fixedValue);
        }
        // Check to see if it's a collection
        TypeInfo info = typeInfo.get(property.getActualType().getQualifiedName());
        String typeName = getTypeNameForComponent(property, schema, property.getActualType(), attribute, false);
        if (isCollectionType(property)) {
            if(!property.isXmlList() && null != property.getXmlPath() && property.getXmlPath().contains("/")) {
                attribute.setType(typeName);
            } else {
                // assume XmlList for an attribute collection
                SimpleType localType = new SimpleType();
                org.eclipse.persistence.internal.oxm.schema.model.List list = new org.eclipse.persistence.internal.oxm.schema.model.List();
                list.setItemType(typeName);
                localType.setList(list);
                attribute.setSimpleType(localType);
            }
        } else {
            // may need to qualify the type
            if (typeName != null && !typeName.contains(COLON)) {
                if (info.getSchema() == schema) {
                    String uri = schema.getTargetNamespace();
                    if(uri == null) {
                        uri = EMPTY_STRING;
                    }
                    String prefix = getPrefixForNamespace(schema, uri);
                    if (prefix != null) {
                        typeName = prefix + COLON + typeName;
                    }
                }
            }
            attribute.setType(typeName);
        }
        return attribute;
    }

    /**
     * Convenience method for processing an attribute property. Required schema
     * components will be generated and set accordingly.
     *
     * @param attribute the attribute property to be processed
     * @param schema the schema currently being generated
     * @param type the ComplexType which compositor(s) should be added to
     */
    private void addAttributeToSchema(Attribute attribute, QName attributeName, Schema schema, ComplexType type) {
        String lookupNamespace = schema.getTargetNamespace();
        if (lookupNamespace == null) {
            lookupNamespace = EMPTY_STRING;
        }
        NamespaceInfo namespaceInfo = getNamespaceInfoForNamespace(lookupNamespace);
        boolean isAttributeFormQualified = false;
        if (namespaceInfo != null) {
            isAttributeFormQualified = namespaceInfo.isAttributeFormQualified();
        }

        boolean addRef = shouldAddRefAndSetForm(attribute, attributeName.getNamespaceURI(), lookupNamespace, isAttributeFormQualified, false);
        if(addRef){
            Schema attributeSchema = this.getSchemaForNamespace(attributeName.getNamespaceURI());
            if (attributeSchema != null && attributeSchema.getTopLevelAttributes().get(attribute.getName()) == null) {
                //don't overwrite existing global elements and attributes.
                attributeSchema.getTopLevelAttributes().put(attribute.getName(), attribute);
            }
            Attribute reference = new Attribute();
            String prefix = getPrefixForNamespace(schema, attributeName.getNamespaceURI());
            if (prefix == null) {
                reference.setRef(attribute.getName());
            } else {
                reference.setRef(prefix + COLON + attribute.getName());
            }
            if (type.getSimpleContent() != null) {
                type.getSimpleContent().getExtension().getOrderedAttributes().add(reference);
            } else {
                type.getOrderedAttributes().add(reference);
            }
        } else {
            if (type.getSimpleContent() != null) {
                type.getSimpleContent().getExtension().getOrderedAttributes().add(attribute);
            } else if (type.getComplexContent() != null) {
                type.getComplexContent().getExtension().getOrderedAttributes().add(attribute);
            } else {
                type.getOrderedAttributes().add(attribute);
            }
        }
    }

    private boolean shouldAddRefAndSetForm(SimpleComponent sc, String simpleComponentNamespace, String lookupNamespace, boolean formQualified, boolean isElement){
        if(sc.getRef() != null){
            return true;
        }
        boolean addRef = false;
        boolean sameNamespace = simpleComponentNamespace.equals(lookupNamespace);

        if (formQualified && !sameNamespace){
            if(simpleComponentNamespace.equals(EMPTY_STRING)){
                sc.setForm(Constants.UNQUALIFIED);
            }else{
                addRef = true;
            }
        } else if(!formQualified  && !simpleComponentNamespace.equals(EMPTY_STRING)){
            if(sameNamespace && isElement){
                sc.setForm(Constants.QUALIFIED);
            }else{
                addRef = true;
            }
        }
        return addRef;
    }

    /**
     * Convenience method for processing an any attribute property. Required
     * schema components will be generated and set accordingly.
     *
     * @param type the ComplexType which compositor(s) should be added to
     */
    private void addAnyAttributeToSchema(ComplexType type) {
        AnyAttribute anyAttribute = new AnyAttribute();
        anyAttribute.setProcessContents(SKIP);
        anyAttribute.setNamespace(Constants.ANY_NAMESPACE_OTHER);
        if (type.getSimpleContent() != null) {
            SimpleContent content = type.getSimpleContent();
            if(content.getExtension() != null){
                content.getExtension().setAnyAttribute(anyAttribute);
            }else if(content.getRestriction() != null){
                content.getRestriction().setAnyAttribute(anyAttribute);
            }
        } else {
            type.setAnyAttribute(anyAttribute);
        }
    }

    /**
     * Convenience method for processing an any property. Required
     * schema components will be generated and set accordingly.
     *
     * @param property the choice property to be processed
     * @param compositor the sequence/choice/all to modify
     */
    private void addAnyToSchema(Property property, TypeDefParticle compositor) {
        addAnyToSchema(property, compositor, isCollectionType(property)|| property.getType().isArray(), Constants.ANY_NAMESPACE_OTHER);
    }

    /**
     * Convenience method for processing an any property. Required
     * schema components will be generated and set accordingly.
     *
     * @param property the choice property to be processed
     * @param compositor the sequence/choice/all to modify
     * @param isCollection if true will be unbounded
     */
    private void addAnyToSchema(Property property, TypeDefParticle compositor, boolean isCollection) {
        addAnyToSchema(property, compositor, isCollection, Constants.ANY_NAMESPACE_OTHER);
    }

    /**
     * Convenience method for processing an any property. Required
     * schema components will be generated and set accordingly.
     *
     * @param property the choice property to be processed
     * @param compositor the sequence/choice/all to modify
     * @param isCollection if true will be unbounded
     * @param anyNamespace value for the Any's namespace attribute
     */
    private void addAnyToSchema(Property property, TypeDefParticle compositor, boolean isCollection, String anyNamespace) {
        Any any = new Any();
        any.setNamespace(anyNamespace);
        if (property.isLax()) {
            any.setProcessContents(Any.LAX);
        } else {
            any.setProcessContents(SKIP);
        }
        if (isCollection) {
            any.setMinOccurs(Occurs.ZERO);
            any.setMaxOccurs(Occurs.UNBOUNDED);
        }
        if (compositor instanceof Sequence) {
            ((Sequence) compositor).addAny(any);
        } else if (compositor instanceof Choice) {
            ((Choice) compositor).addAny(any);
        }
    }

    /**
     * Convenience method for processing a choice property. Required
     * schema components will be generated and set accordingly.
     *
     * @param property the choice property to be processed
     * @param typeInfo the TypeInfo that the given property belongs to
     * @param type the ComplexType which compositor(s) should be added to
     * @param compositor the sequence/choice/all to modify
     * @param schema the schema being built
     */
    private void addChoiceToSchema(Property property, TypeInfo typeInfo, ComplexType type, TypeDefParticle compositor, Schema schema) {
        Choice choice = new Choice();
        if (property.getGenericType() != null) {
            choice.setMaxOccurs(Occurs.UNBOUNDED);
        }
        ArrayList<Property> choiceProperties = (ArrayList<Property>) property.getChoiceProperties();
        addToSchemaType(typeInfo, choiceProperties, choice, type, schema);
        if (compositor instanceof Sequence) {
            ((Sequence) compositor).addChoice(choice);
        } else if (compositor instanceof Choice) {
            ((Choice) compositor).addChoice(choice);
        }
    }

    /**
     * Convenience method for processing a reference property. Required
     * schema components will be generated and set accordingly.
     *
     * @param property the choice property to be processed
     * @param compositor the sequence/choice/all to modify
     * @param schema the schema being built
     */
    private void addReferenceToSchema(Property property, Schema schema, TypeDefParticle compositor) {
        java.util.List<ElementDeclaration> referencedElements = property.getReferencedElements();
        if (referencedElements.size() == 1 && !property.isAny()) {
            // if only a single reference, just add the element.
            Element element = new Element();
            ElementDeclaration decl = referencedElements.get(0);
            String localName = decl.getElementName().getLocalPart();

            String prefix = getPrefixForNamespace(schema, decl.getElementName().getNamespaceURI());
            if (decl.getScopeClass() == GLOBAL.class){
                if (prefix == null || prefix.equals(EMPTY_STRING)) {
                    element.setRef(localName);
                } else {
                    element.setRef(prefix + COLON + localName);
                }
            } else {
                element.setType(getTypeName(property, decl.getJavaType(), schema));
                element.setName(localName);
            }
            if (property.getGenericType() != null) {
                element.setMinOccurs(Occurs.ZERO);
                element.setMaxOccurs(Occurs.UNBOUNDED);
            }else if(!property.isRequired()){
                element.setMinOccurs(Occurs.ZERO);
            }
            compositor.addElement(element);
        } else {
            // otherwise, add a choice of referenced elements.
            Choice choice = new Choice();
            if (property.getGenericType() != null) {
                choice.setMaxOccurs(Occurs.UNBOUNDED);
            }
            if (!property.isRequired()){
                choice.setMinOccurs(Occurs.ZERO);
            }
            for (ElementDeclaration elementDecl : referencedElements) {
                Element element = new Element();
                String localName = elementDecl.getElementName().getLocalPart();

                String prefix = getPrefixForNamespace(schema, elementDecl.getElementName().getNamespaceURI());
                if (elementDecl.getScopeClass() == GLOBAL.class){
                    if (prefix == null || prefix.equals(EMPTY_STRING)) {
                        element.setRef(localName);
                    } else {
                        element.setRef(prefix + COLON + localName);
                    }
                } else {
                    Schema referencedSchema = getSchemaForNamespace(elementDecl.getElementName().getNamespaceURI());
                    element.setType(getTypeName(property, elementDecl.getJavaType(), referencedSchema));
                    element.setName(localName);
                }
                choice.addElement(element);
            }
            // handle XmlAnyElement case
            if (property.isAny()) {
                addAnyToSchema(property, choice, false);
            }
            if (compositor instanceof Sequence) {
                ((Sequence) compositor).addChoice(choice);
            } else if (compositor instanceof Choice) {
                ((Choice) compositor).addChoice(choice);
            }
        }
    }

    /**
     * Convenience method for processing a reference property. Required
     * schema components will be generated and set accordingly.
     *
     * @param property the map property to be processed
     * @param element schema Element a new complex type will be added to
     * @param schema the schema being built
     * @param typeInfo the TypeInfo that the given property belongs to
     */
    private void addMapToSchema(Property property, Element element, Schema schema, TypeInfo typeInfo) {
        ComplexType entryComplexType = new ComplexType();
        Sequence entrySequence = new Sequence();

        Element keyElement = new Element();
        keyElement.setName(Property.DEFAULT_KEY_NAME);
        keyElement.setMinOccurs(Occurs.ZERO);

        JavaClass keyType = property.getKeyType();
        JavaClass valueType = property.getActualValueType();

        if (keyType == null) {
            keyType = helper.getJavaClass(Object.class);
        }

        if (valueType == null) {
            valueType = helper.getJavaClass(Object.class);
        }

        String typeName;
        QName keySchemaType = getSchemaTypeFor(keyType);
        if (keySchemaType != null) {
            TypeInfo targetInfo = this.typeInfo.get(keyType.getQualifiedName());
            if (targetInfo != null) {
                Schema keyElementSchema = this.getSchemaForNamespace(keySchemaType.getNamespaceURI());
                //add an import here
                addImportIfRequired(schema, keyElementSchema, keySchemaType.getNamespaceURI());
            }
            String prefix;
            if (keySchemaType.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                prefix = Constants.SCHEMA_PREFIX;
            } else {
                prefix = getPrefixForNamespace(schema, keySchemaType.getNamespaceURI());
            }
            if (prefix != null && !prefix.equals(EMPTY_STRING)) {
                typeName = prefix + COLON + keySchemaType.getLocalPart();
            } else {
                typeName = keySchemaType.getLocalPart();
            }
            keyElement.setType(typeName);
        }

        entrySequence.addElement(keyElement);

        Element valueElement = new Element();
        valueElement.setName(Property.DEFAULT_VALUE_NAME);
        valueElement.setMinOccurs(Occurs.ZERO);
        QName valueSchemaType = getSchemaTypeFor(valueType);
        if (valueSchemaType != null) {
            TypeInfo targetInfo = this.typeInfo.get(valueType.getQualifiedName());
            if (targetInfo != null) {
                Schema valueElementSchema = this.getSchemaForNamespace(valueSchemaType.getNamespaceURI());
                //add an import here
                addImportIfRequired(schema, valueElementSchema, valueSchemaType.getNamespaceURI());
            }
            String prefix;
            if (valueSchemaType.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                prefix = Constants.SCHEMA_PREFIX;
            } else {
                prefix = getPrefixForNamespace(schema, valueSchemaType.getNamespaceURI());
            }
            if (prefix != null && !prefix.equals(EMPTY_STRING)) {
                typeName = prefix + COLON + valueSchemaType.getLocalPart();
            } else {
                typeName = valueSchemaType.getLocalPart();
            }
            if (property.getValueGenericType() != null) {
                valueElement.setMaxOccurs(Occurs.UNBOUNDED);
            }
            valueElement.setType(typeName);
        }

        entrySequence.addElement(valueElement);
        entryComplexType.setSequence(entrySequence);

        JavaClass descriptorClass = null;
        if (null != typeInfo.getDescriptor()) {
            descriptorClass = helper.getJavaClass(typeInfo.getDescriptor().getJavaClassName());
        }

        JavaClass mapValueClass = helper.getJavaClass(MapValue.class);

        if (null != descriptorClass && mapValueClass.isAssignableFrom(descriptorClass)) {
            element.setComplexType(entryComplexType);
            element.setMaxOccurs(Occurs.UNBOUNDED);
        } else {
            ComplexType complexType = new ComplexType();
            Sequence sequence = new Sequence();
            complexType.setSequence(sequence);

            Element entryElement = new Element();
            entryElement.setName(ENTRY);
            entryElement.setMinOccurs(Occurs.ZERO);
            entryElement.setMaxOccurs(Occurs.UNBOUNDED);
            sequence.addElement(entryElement);
            entryElement.setComplexType(entryComplexType);
            element.setComplexType(complexType);
        }
    }

    /**
     * Convenience method that adds an element ref to a given schema.
     *
     * @param schema the schema being built
     * @param compositor the sequence/choice/all the new reference will be added to
     * @param referencedElement the element being referenced
     * @param referencedElementURI the URI of the element being referenced
     */
    private void addElementRefToSchema(Schema schema, TypeDefParticle compositor, Element referencedElement, String referencedElementURI) {
        Element reference = new Element();
        reference.setMinOccurs(referencedElement.getMinOccurs());
        reference.setMaxOccurs(referencedElement.getMaxOccurs());
        Schema attributeSchema = this.getSchemaForNamespace(referencedElementURI);
        if (attributeSchema != null && attributeSchema.getTopLevelElements().get(referencedElement.getName()) == null) {
            // reset min/max occurs as they aren't applicable for global elements
            referencedElement.setMinOccurs(null);
            referencedElement.setMaxOccurs(null);
            // don't overwrite global elements; may have been defined by a type
            attributeSchema.getTopLevelElements().put(referencedElement.getName(), referencedElement);
        }
        String prefix = getPrefixForNamespace(schema, referencedElementURI);
        if (prefix == null) {
            reference.setRef(referencedElement.getName());
        } else {
            reference.setRef(prefix + COLON + referencedElement.getName());
        }
        // make sure a ref doesn't already exist before adding this one
        if (elementExistsInParticle(reference.getName(), reference.getRef(), compositor) == null) {
            compositor.addElement(reference);
        }
    }

    /**
     * Build an Element with name, type and possibly minOccurs set.  This method will
     * typically be called when processing an XPath that has no associated Property
     * that can be used to build an Element, such as in the case of XmlJoinNodes.
     *
     * @param elementName name of the Element
     * @param elementType type of the Element
     * @param isAll indicates if the Element will be added to an All structure
     */
    private Element buildElement(String elementName, String elementType, boolean isAll) {
        Element element = new Element();
        // Set minOccurs based on the 'required' flag
        if (!(isAll)) {
            element.setMinOccurs(Occurs.ZERO);
        }
        element.setName(elementName);
        element.setType(elementType);
        return element;
    }

    /**
     * Build an Element based on a given Property.
     *
     * @param property the Property used to build the Element
     * @param isAll true if the Element will be added to an All structure
     * @param schema the schema currently being built
     * @param typeInfo the TypeInfo that owns the given Property
     */
    private Element buildElement(Property property, boolean isAll, Schema schema, TypeInfo typeInfo) {
        Element element = new Element();

        // handle nillable
        if (property.shouldSetNillable()) {
            if (property.isNotNullAnnotated()) throw BeanValidationException.notNullAndNillable(property.getPropertyName());
            element.setNillable(true);
        }
        // handle defaultValue
        if (property.isSetDefaultValue()) {
            element.setDefaultValue(property.getDefaultValue());
        }
        // handle mime-type
        if (property.getMimeType() != null) {
            element.getAttributesMap().put(Constants.EXPECTED_CONTENT_TYPES_QNAME, property.getMimeType());
        }

        QName elementName = property.getSchemaName();
        String elementNamespace = elementName.getNamespaceURI();
        String lookupNamespace = schema.getTargetNamespace();
        if (lookupNamespace == null) {
            lookupNamespace = EMPTY_STRING;
        }
        NamespaceInfo namespaceInfo = getNamespaceInfoForNamespace(lookupNamespace, getPackageName(typeInfo));
        boolean isElementFormQualified = false;
        if (namespaceInfo != null) {
            isElementFormQualified = namespaceInfo.isElementFormQualified();
        }
        // handle element reference

        boolean addRef = shouldAddRefAndSetForm(element, elementNamespace, lookupNamespace, isElementFormQualified, true);

        if(addRef){
            schema = this.getSchemaForNamespace(elementNamespace);
        }

        JavaClass javaType = property.getActualType();
        element.setName(elementName.getLocalPart());
        String typeName = getTypeNameForComponent(property, schema, javaType, element, true);

        if (property.getGenericType() != null) {
            if (property.isXmlList()) {
                SimpleType localSimpleType = new SimpleType();
                org.eclipse.persistence.internal.oxm.schema.model.List list = new org.eclipse.persistence.internal.oxm.schema.model.List();
                list.setItemType(typeName);
                localSimpleType.setList(list);
                element.setSimpleType(localSimpleType);
            } else {
                element.setMaxOccurs(Occurs.UNBOUNDED);
                element.setType(typeName);
            }
            // handle map property
        } else if (property.isMap()) {
            addMapToSchema(property, element, schema, typeInfo);
        } else {
            element.setType(typeName);
        }

        // Set minOccurs based on the 'required' flag
        Integer minOccurs = property.getMinOccurs();
        if (minOccurs != null) {
            element.setMinOccurs(String.valueOf(minOccurs));
        } else {
            element.setMinOccurs(property.isRequired() ? Occurs.ONE : Occurs.ZERO);
        }
        // Overwrite maxOccurs if it has been explicitly set on property.
        Integer maxOccurs = property.getMaxOccurs();
        if (maxOccurs != null) element.setMaxOccurs(String.valueOf(maxOccurs));

        if (facets) {
            for (Facet facet : property.getFacets()) {
                processFacet(element, facet);
            }
        }
        return element;
    }

    private String getPackageName(TypeInfo typeInfo) {
        if (null != typeInfo && null != typeInfo.getDescriptor() && null != typeInfo.getDescriptor().getJavaClass() && null != typeInfo.getDescriptor().getJavaClass().getPackage()) {
            return typeInfo.getDescriptor().getJavaClass().getPackage().getName();
        }
        return null;
    }

    private void processFacet(Element element, Facet facet) {
        if (element.getSimpleType() == null) element.setSimpleType(new SimpleType());
        Restriction restriction = element.getSimpleType().getRestriction();
        if (restriction == null) {
            restriction = new Restriction(element.getType());
            element.getSimpleType().setRestriction(restriction);
        }
        element.setType(null); // Prevent error: "Cannot have both a 'type' attribute and an 'anonymous type' child".
        facet.accept(FacetVisitorHolder.VISITOR, restriction);
    }


    /**
     * @since 2.6
     * @author Marcel Valovy
     */
    private static final class FacetVisitorHolder {
        private static final FacetVisitor<Void, Restriction> VISITOR = new FacetVisitor<>() {
            @Override
            public Void visit(DecimalMinFacet t, Restriction restriction) {
                if (t.isInclusive()) restriction.setMinInclusive(t.getValue());
                else restriction.setMinExclusive(t.getValue());
                return null;
            }

            @Override
            public Void visit(DecimalMaxFacet t, Restriction restriction) {
                if (t.isInclusive()) restriction.setMaxInclusive(t.getValue());
                else restriction.setMaxExclusive(t.getValue());
                return null;
            }

            @Override
            public Void visit(DigitsFacet t, Restriction restriction) {
                int fraction = t.getFraction();
                if (fraction > 0) {
                    restriction.setFractionDigits(fraction);
                    restriction.setTotalDigits(fraction + t.getInteger());
                } else if (fraction == 0) {
                    restriction.setTotalDigits(t.getInteger());
                }
                return null;
            }

            @Override
            public Void visit(MaxFacet t, Restriction restriction) {
                restriction.setMaxInclusive(String.valueOf(t.getValue()));
                return null;
            }

            @Override
            public Void visit(MinFacet t, Restriction restriction) {
                restriction.setMinInclusive(String.valueOf(t.getValue()));
                return null;
            }

            @Override
            public Void visit(PatternFacet t, Restriction restriction) {
                String regex = t.getRegexp();
                regex = introduceShorthands(regex);
                restriction.addPattern(regex);
                return null;
            }

            @Override
            public Void visit(PatternListFacet t, Restriction restriction) {
                for (PatternFacet pf : t.getPatterns()) {
                    String regex = pf.getRegexp();
                    regex = introduceShorthands(regex);
                    restriction.addPattern(regex);
                }
                return null;
            }

            @Override
            public Void visit(SizeFacet t, Restriction restriction) {
                int minLength = t.getMin();
                int maxLength = t.getMax();
                if (minLength == maxLength) {
                    restriction.setLength(minLength);
                } else {
                    // 0 is the default minBoundary.
                    if (minLength > 0) restriction.setMinLength(minLength);
                    // 2^31 is the default maxBoundary.
                    if (maxLength < Integer.MAX_VALUE) restriction.setMaxLength(maxLength);
                }
                return null;
            }
        };
    }

    /**
     * Convenience method that adds an element to a given schema.
     *
     * @param element the Property that the Element will be based on
     * @param compositor the sequence/choice/all that the Element will be added to
     * @param schema the schema currently being built
     */
    private void addElementToSchema(Element element, String elementURI, boolean isPositional, TypeDefParticle compositor, Schema schema, String packageName) {
        String lookupNamespace = schema.getTargetNamespace();
        if (lookupNamespace == null) {
            lookupNamespace = EMPTY_STRING;
        }
        NamespaceInfo namespaceInfo = getNamespaceInfoForNamespace(lookupNamespace, packageName);
        boolean isElementFormQualified = false;
        if (namespaceInfo != null) {
            isElementFormQualified = namespaceInfo.isElementFormQualified();
        }
        boolean addRef = shouldAddRefAndSetForm(element, elementURI, lookupNamespace, isElementFormQualified, true);
        if(addRef){
            addElementRefToSchema(schema, compositor, element, elementURI);
        } else {
            // for positional mappings we could have multiple elements with same name; check before adding
            if (elementExistsInParticle(element.getName(), element.getRef(), compositor) == null) {
                if (isPositional) {
                    element.setMaxOccurs(Occurs.UNBOUNDED);
                }
                compositor.addElement(element);
            }
        }
    }

    /**
     * Convenience method that processes the XmlJoinNodes for a given Property and adds the
     * appropriate components to the schema.
     *
     * @param property the Property contianing one or more XmlJoinNode entries
     * @param compositor the sequence/choice/all that will be added to
     * @param schema the schema currently being built
     * @param type the complex type currently being built
     */
    private void addXmlJoinNodesToSchema(Property property, TypeDefParticle compositor, Schema schema, ComplexType type) {
        for (XmlJoinNode xmlJoinNode : property.getXmlJoinNodes().getXmlJoinNode()) {
            // create the XPathFragment(s) for the path
            Field<XMLConversionManager, NamespaceResolver> xfld = new XMLField(xmlJoinNode.getXmlPath());
            xfld.setNamespaceResolver(schema.getNamespaceResolver());
            xfld.initialize();

            // build the schema components for the xml-path
            AddToSchemaResult asr = buildSchemaComponentsForXPath(xfld.getXPathFragment(), new AddToSchemaResult(compositor, schema), false, property);

            // process the last fragment
            TypeDefParticle currentParticle = asr.particle;
            Schema currentSchema = asr.schema;
            if (currentParticle.getOwner() instanceof ComplexType) {
                type = ((ComplexType) currentParticle.getOwner());
            }
            // get a QName for the last part of the xpath - this will be used as the
            // attribute/element name, and also to figure out if a ref is required
            QName schemaName;
            XPathFragment frag = xfld.getLastXPathFragment();
            boolean isAttribute = xmlJoinNode.getXmlPath().contains(ATT);
            // for non-attributes, the last fragment may be 'text()'
            if (!isAttribute) {
                if (frag.nameIsText()) {
                    frag = xfld.getXPathFragment();
                    while (frag.getNextFragment() != null && !frag.getNextFragment().nameIsText()) {
                        frag = frag.getNextFragment();
                    }
                }
            }
            schemaName = new QName(frag.getNamespaceURI(), frag.getLocalName());

            // handle Element/Attribute
            if (isAttribute) {
                addAttributeToSchema(buildAttribute(schemaName, Constants.SCHEMA_PREFIX + COLON + Constants.ANY_SIMPLE_TYPE), schemaName, currentSchema, type);
            } else {
                addElementToSchema(buildElement(schemaName.getLocalPart(), Constants.SCHEMA_PREFIX + COLON + Constants.ANY_SIMPLE_TYPE, currentParticle instanceof All), schemaName.getNamespaceURI(), false, currentParticle, currentSchema, null);
            }
        }
    }

    /**
     * Return the type name for an Element based on a given property.
     *
     * @param property the Property that the type name will be based on
     * @param schema the schema currently being built
     * @param javaClass the given Property's 'actual' type
     * @param sc the element being generated for the given Property
     * @return a type name based on the given Property, or null if not obtainable
     */
    private String getTypeNameForComponent(Property property, Schema schema, JavaClass javaClass, SimpleComponent sc, boolean isElement) {
        String typeName = null;
        if (property.isXmlId()) {
            // handle user-set schema-type
            if (property.getSchemaType() != null) {
                typeName = getTypeName(property, property.getActualType(), schema);
            } else {
                // default to xsd:ID
                typeName = Constants.SCHEMA_PREFIX + COLON + ID;
            }
        } else if (property.isXmlIdRef()) {
            typeName = Constants.SCHEMA_PREFIX + COLON + IDREF;
        } else {
            TypeInfo info = typeInfo.get(javaClass.getQualifiedName());
            if (info != null) {
                if (info.isComplexType()) {
                    typeName = info.getComplexType().getName();
                } else if (info.getSimpleType() != null) {
                    typeName = info.getSimpleType().getName();
                } else {
                    typeName = info.getSchemaTypeName();
                }
                if (typeName == null) {
                    // need to add complex-type locally, or reference global element
                    if(isElement && info.hasRootElement() && info.getXmlRootElement().getName().equals(sc.getName())){
                        String refName = info.getXmlRootElement().getName();
                        (sc).setRef(refName);
                    }else{
                        if (isElement && info.isComplexType()) {
                            ((Element)sc).setComplexType(info.getComplexType());
                        } else {
                            sc.setSimpleType(info.getSimpleType());
                        }
                    }
                } else {
                    // check to see if we need to add an import
                    if (addImportIfRequired(schema, info.getSchema(), info.getClassNamespace())) {
                        String prefix = schema.getNamespaceResolver().resolveNamespaceURI(info.getClassNamespace());
                        if (prefix != null && (!typeName.equals(EMPTY_STRING))) {
                            typeName = prefix + COLON + typeName;
                        }
                    }
                }
            } else if (!property.isMap()) {
                typeName = getTypeName(property, javaClass, schema);
            }
            // may need to qualify the type
            if (typeName != null && !typeName.contains(COLON)) {
                String prefix;
                if (info.getClassNamespace().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                    prefix = Constants.SCHEMA_PREFIX;
                } else {
                    prefix = getPrefixForNamespace(schema, info.getClassNamespace());
                }
                if (prefix != null) {
                    typeName = prefix + COLON + typeName;
                }
            }
        }
        return typeName;
    }
    private static String introduceShorthands(String regex) {
        return RegexMutator.mutate(regex);
    }

    /**
     * Maintains compatibility between Java Pattern Regex and XML Schema regex.
     * Replaces Java regexes with their respective XML Regex Shorthands, where applicable.
     * <p>
     * Recognized are Java regexes for the following XML Shorthands, and their negations:
     * <blockquote><pre>{@code
     * \i - Matches any character that may be the first character of an XML name.
     *      "[_:A-Za-z]"
     * \c - Matches any character that may occur after the first character in an XML name.
     *      "[-.0-9:A-Z_a-z]"
     * \d - All digits.
     *      "\\p{Nd}"
     * \w - Word character.
     *      "[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]]"
     * \s - Whitespace character.
     *      "[\\u0009-\\u000D\\u0020\\u0085\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]"
     * \b, \B - Boundary definitions.
     *      "(?:(?<=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])
     *      (?![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])|
     *      (?<![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])
     *      (?=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]]))"
     *      "(?:(?<=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])
     *      (?=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])|
     *      (?<![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])
     *      (?![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]]))"
     * \h - Horizontal whitespace character - Java does not support, changed in Java 8 though.
     *      "[\\u0009\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u202F\\u205F\\u3000]"
     * \v - Vertical whitespace character - Java translates the shorthand to \cK only, meaning changed in Java 8 though.
     *      "[\\u000A-\\u000D\\u0085\\u2028\\u2029]"
     * \X - Extended grapheme cluster.
     *      "(?:(?:\\u000D\\u000A)|(?:[\\u0E40\\u0E41\\u0E42\\u0E43\\u0E44\\u0EC0\\u0EC1\\u0EC2\\u0EC3\\u0EC4\\uAAB5
     *      \\uAAB6\\uAAB9\\uAABB\\uAABC]*(?:[\\u1100-\\u115F\\uA960-\\uA97C]+|([\\u1100-\\u115F\\uA960-\\uA97C]*(
     *      (?:[[\\u1160-\\u11A2\\uD7B0-\\uD7C6][\\uAC00\\uAC1C\\uAC38]][\\u1160-\\u11A2\\uD7B0-\\uD7C6]*|[\\uAC01
     *      \\uAC02\\uAC03\\uAC04])[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]*))|[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]+|[^[\\p{Zl}
     *      \\p{Zp}\\p{Cc}\\p{Cf}&&[^\\u000D\\u000A\\u200C\\u200D]]\\u000D\\u000A])[[\\p{Mn}\\p{Me}\\u200C\\u200D\\
     *      u0488\\u0489\\u20DD\\u20DE\\u20DF\\u20E0\\u20E2\\u20E3\\u20E4\\uA670\\uA671\\uA672\\uFF9E\\uFF9F][\\p{Mc
     *      }\\u0E30\\u0E32\\u0E33\\u0E45\\u0EB0\\u0EB2\\u0EB3]]*)|(?s:.))"
     * \R - Carriage return.
     *      "(?:(?>\\u000D\\u000A)|[\\u000A\\u000B\\u000C\\u000D\\u0085\\u2028\\u2029])"
     * }</pre></blockquote>
     *
     * CAUTION - ORDER SENSITIVE: Longer patterns should come first, because they may contain one of the shorter pattern.
     * <p>
     * Changes to this class should also be reflected in the opposite {@link org.eclipse.persistence.jaxb.plugins.BeanValidationPlugin.RegexMutator RegexMutator} class within XJC BeanValidation Plugin.
     *
     * @see <a href="http://stackoverflow.com/questions/4304928/unicode-equivalents-for-w-and-b-in-java-regular-expressions">tchrist's work</a>
     * @see <a href="http://www.regular-expressions.info/shorthand.html#xml">Special shorthands in XML Schema.</a>
     */
    private static final class RegexMutator {
        private static final Map<Pattern, String> shorthandReplacements = new LinkedHashMap<>(32) {{
            put(Pattern.compile("[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", Pattern.LITERAL), "\\\\i");
            put(Pattern.compile("[^:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", Pattern.LITERAL), "\\\\I");
            put(Pattern.compile("[-.0-9:A-Z_a-z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", Pattern.LITERAL), "\\\\c");
            put(Pattern.compile("[^-.0-9:A-Z_a-z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", Pattern.LITERAL), "\\\\C");
            put(Pattern.compile("[\\u0009-\\u000D\\u0020\\u0085\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]", Pattern.LITERAL), "\\\\s");
            put(Pattern.compile("[^\\u0009-\\u000D\\u0020\\u0085\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]", Pattern.LITERAL), "\\\\S");
            put(Pattern.compile("[\\u000A-\\u000D\\u0085\\u2028\\u2029]", Pattern.LITERAL), "\\\\v");
            put(Pattern.compile("[^\\u000A-\\u000D\\u0085\\u2028\\u2029]", Pattern.LITERAL), "\\\\V");
            put(Pattern.compile("[\\u0009\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u202F\\u205F\\u3000]", Pattern.LITERAL), "\\\\h");
            put(Pattern.compile("[^\\u0009\\u0020\\u00A0\\u1680\\u180E\\u2000\\u2001-\\u200A\\u202F\\u205F\\u3000]", Pattern.LITERAL), "\\\\H");
            put(Pattern.compile("[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]]", Pattern.LITERAL), "\\\\w");
            put(Pattern.compile("[^\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]]", Pattern.LITERAL), "\\\\W");
            put(Pattern.compile("(?:(?<=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])(?![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])|(?<![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])(?=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]]))", Pattern.LITERAL), "\\\\b");
            put(Pattern.compile("(?:(?<=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])(?=[\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])|(?<![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]])(?![\\pL\\pM\\p{Nd}\\p{Nl}\\p{Pc}[\\p{InEnclosedAlphanumerics}&&\\p{So}]]))", Pattern.LITERAL), "\\\\B");
            put(Pattern.compile("\\p{Nd}", Pattern.LITERAL), "\\\\d");
            put(Pattern.compile("\\P{Nd}", Pattern.LITERAL), "\\\\D");
            put(Pattern.compile("(?:(?>\\u000D\\u000A)|[\\u000A\\u000B\\u000C\\u000D\\u0085\\u2028\\u2029])", Pattern.LITERAL), "\\\\R");
            put(Pattern.compile("(?:(?:\\u000D\\u000A)|(?:[\\u0E40\\u0E41\\u0E42\\u0E43\\u0E44\\u0EC0\\u0EC1\\u0EC2\\u0EC3\\u0EC4\\uAAB5\\uAAB6\\uAAB9\\uAABB\\uAABC]*(?:[\\u1100-\\u115F\\uA960-\\uA97C]+|([\\u1100-\\u115F\\uA960-\\uA97C]*((?:[[\\u1160-\\u11A2\\uD7B0-\\uD7C6][\\uAC00\\uAC1C\\uAC38]][\\u1160-\\u11A2\\uD7B0-\\uD7C6]*|[\\uAC01\\uAC02\\uAC03\\uAC04])[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]*))|[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]+|[^[\\p{Zl}\\p{Zp}\\p{Cc}\\p{Cf}&&[^\\u000D\\u000A\\u200C\\u200D]]\\u000D\\u000A])[[\\p{Mn}\\p{Me}\\u200C\\u200D\\u0488\\u0489\\u20DD\\u20DE\\u20DF\\u20E0\\u20E2\\u20E3\\u20E4\\uA670\\uA671\\uA672\\uFF9E\\uFF9F][\\p{Mc}\\u0E30\\u0E32\\u0E33\\u0E45\\u0EB0\\u0EB2\\u0EB3]]*)|(?s:.))", Pattern.LITERAL), "\\\\X");
            put(Pattern.compile("[_:A-Za-z]", Pattern.LITERAL), "\\\\i"); // ascii only
            put(Pattern.compile("[^:A-Z_a-z]", Pattern.LITERAL), "\\\\I"); // ascii only
            put(Pattern.compile("[-.0-9:A-Z_a-z]", Pattern.LITERAL), "\\\\c"); // ascii only
            put(Pattern.compile("[^-.0-9:A-Z_a-z]", Pattern.LITERAL), "\\\\C"); // ascii only
        }};

        private RegexMutator() {
        }

        /**
         * @param input Java regex
         * @return XML regex
         */
        private static String mutate(String input){
            for (Map.Entry<Pattern, String> entry : shorthandReplacements.entrySet()) {
                Matcher m = entry.getKey().matcher(input);
                input = m.replaceAll(entry.getValue());
            }
            return input;
        }
    }
}
