/*
 * 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<String, SchemaTypeInfo>(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.
     *
     * @param javaClass
     * @return
     */
    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 = (QName) 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.
     *
     * @param field
     * @return
     */
    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.
     *
     * @param namespace
     * @return
     */
    private Schema getSchemaForNamespace(String namespace, String packageName) {
        if (schemaForNamespace == null) {
            schemaForNamespace = new HashMap<String, Schema>();
            allSchemas = new ArrayList<Schema>();
        }
        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 namespaces = namespaceInfo.getNamespaceResolver().getNamespaces();
                for (int i = 0; i < namespaces.size(); i++) {
                    Namespace nextNamespace = (Namespace) 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<Schema>();
        }
        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 keys = namespaceResolver.getPrefixes();
        while (keys.hasMoreElements()) {
            String next = (String) 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.
     *
     * @param URI
     * @param schema
     * @return
     */
    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 = (QName) 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.
     *
     * @return
     */
    public Map<String, SchemaTypeInfo> getSchemaTypeInfo() {
        return this.schemaTypeInfo;
    }

    private boolean importExists(Schema schema, String importNsURI, String schemaLocation) {
        java.util.List imports = schema.getImports();
        for (int i = 0; i < imports.size(); i++) {
            Import nextImport = (Import) 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.
     *
     * @param src
     * @param tgtCanonicalName
     * @return
     */
    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.
     *
     * @param src
     * @param tgt
     * @return
     */
    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.
     *
     * @param next
     * @param javaType
     * @param theSchema
     * @return
     */
    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.
     *
     * @param prop
     * @param schema
     * @return
     */
    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.
     *
     * @param frag
     * @param xpr
     * @param isChoice
     * @param next
     * @return
     */
    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 = (Attribute) 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 = (Element) 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
     * @return
     */
    protected Element elementExistsInParticle(String elementName, String refString, TypeDefParticle particle) {
        if (particle == null || particle.getElements() == null || particle.getElements().size() == 0) {
            return null;
        }
        java.util.List existingElements = particle.getElements();
        if (existingElements != null) {
            Iterator 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 = (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.
     *
     * @param frag
     * @param workingSchema
     * @param fragSchema
     * @param prop
     * @return
     */
    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
     * @return
     */
    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.
     *
     * @param elementRefName
     * @param particle
     * @return
     */
    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.
     *
     * @param attributeRefName
     * @param owningComplexType
     * @return
     */
    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
     * @return
     */
    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
     * @return
     */
    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
     * @return
     */
    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
     * @return
     */
    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<Void, Restriction>() {
            @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<Pattern, String>(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;
        }
    }
}
