/*
 * 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.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 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 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>
     * \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;
        }
    }
}
