/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.xmlbeans.impl.schema;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.NameUtil;

import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.*;

public class StscJavaizer {

    private static final Logger LOG = LogManager.getLogger(StscJavaizer.class);

    /**
     * XMLBEANS-307
     * if enumeration count is greater than 3668,
     * xmlbeans scomp will fail with a code too large error
     */
    private static final int MAX_ENUM_COUNT = 3668;

    /**
     * Does a topo walk of all the types to resolve them.
     */
    public static void javaizeAllTypes(boolean javaize) {
        StscState state = StscState.get();

        List<SchemaType> allSeenTypes = new ArrayList<>();
        allSeenTypes.addAll(Arrays.asList(state.documentTypes()));
        allSeenTypes.addAll(Arrays.asList(state.attributeTypes()));
        allSeenTypes.addAll(Arrays.asList(state.globalTypes()));

        // First distribute the global names among the top entities.
        if (javaize) {
            assignGlobalJavaNames(allSeenTypes);
        }

        // now fully javaize everything deeply.
        for (int i = 0; i < allSeenTypes.size(); i++) {
            SchemaType gType = allSeenTypes.get(i);
            if (javaize) {
                javaizeType((SchemaTypeImpl) gType);
                String className = gType.getFullJavaName();
                if (className != null) {
                    state.addClassname(className.replace('$', '.'), gType);
                }
            } else {
                skipJavaizingType((SchemaTypeImpl) gType);
            }
            allSeenTypes.addAll(Arrays.asList(gType.getAnonymousTypes()));
            // We need to javaize the anonymous types defined inside redefined types
            // since redefined type do not get a Java class of their own.
            // The exception is complex types derived by restriction, since in this case
            // anonymous types are not inherited
            addAnonymousTypesFromRedefinition(gType, allSeenTypes);
        }
    }

    static void assignGlobalJavaNames(Collection<SchemaType> schemaTypes) {
        HashSet<String> usedNames = new HashSet<>();
        StscState state = StscState.get();

        for (SchemaType schemaType : schemaTypes) {
            SchemaTypeImpl sImpl = (SchemaTypeImpl) schemaType;
            QName topName = findTopName(sImpl);
            String pickedName = state.getJavaname(topName, sImpl.isDocumentType() ?
                BindingConfig.QNAME_DOCUMENT_TYPE : BindingConfig.QNAME_TYPE);
            if (sImpl.isUnjavaized()) {
                sImpl.setFullJavaName(pickFullJavaClassName(usedNames, findTopName(sImpl), pickedName, sImpl.isDocumentType(), sImpl.isAttributeType()));
                sImpl.setFullJavaImplName(pickFullJavaImplName(usedNames, sImpl.getFullJavaName()));

                setExtensions(sImpl, state);
            }
        }

        setUserTypes(state);

        verifyInterfaceNameCollisions(usedNames, state);
    }

    private static void verifyInterfaceNameCollisions(Set<String> usedNames, StscState state) {
        BindingConfig config = state.getBindingConfig();
        if (config == null) {
            return;
        }

        InterfaceExtension[] exts = config.getInterfaceExtensions();
        for (InterfaceExtension ext : exts) {
            if (usedNames.contains(ext.getInterface().toLowerCase(Locale.ROOT))) {
                state.error("InterfaceExtension interface '" + ext.getInterface() + "' creates a name collision with one of the generated interfaces or classes.", XmlError.SEVERITY_ERROR, null);
            }

            String handler = ext.getStaticHandler();
            if (handler != null && usedNames.contains(handler.toLowerCase(Locale.ROOT))) {
                state.error("InterfaceExtension handler class '" + handler + "' creates a name collision with one of the generated interfaces or classes.", XmlError.SEVERITY_ERROR, null);
            }
        }

        PrePostExtension[] prepost = config.getPrePostExtensions();
        for (PrePostExtension prePostExtension : prepost) {
            String handler = prePostExtension.getStaticHandler();
            if (handler != null && usedNames.contains(handler.toLowerCase(Locale.ROOT))) {
                state.error("PrePostExtension handler class '" + handler + "' creates a name collision with one of the generated interfaces or classes.", XmlError.SEVERITY_ERROR, null);
            }
        }
    }

    private static void setUserTypes(StscState state) {
        BindingConfig config = state.getBindingConfig();

        if (config != null) {
            for (UserType utype : config.getUserTypes()) {
                SchemaTypeImpl sImpl = state.findGlobalType(utype.getName(), null, null);
                if (sImpl != null) {
                    sImpl.setUserTypeName(utype.getJavaName());
                    sImpl.setUserTypeHandlerName(utype.getStaticHandler());
                } else {
                    LOG.atWarn().log("Cannot match user type for {}", utype.getName());
                }
            }
        }
    }

    private static void setExtensions(SchemaTypeImpl sImpl, StscState state) {
        String javaName = sImpl.getFullJavaName();
        BindingConfig config = state.getBindingConfig();

        if (javaName != null && config != null) {
            sImpl.setInterfaceExtensions(config.getInterfaceExtensions(javaName));
            sImpl.setPrePostExtension(config.getPrePostExtension(javaName));
        }
    }

    private static boolean isStringType(SchemaType type) {
        if (type == null || type.getSimpleVariety() != SchemaType.ATOMIC) {
            return false;
        }
        return (type.getPrimitiveType().getBuiltinTypeCode() == SchemaType.BTC_STRING);
    }

    static String pickConstantName(Set<String> usedNames, String words) {
        String base = NameUtil.upperCaseUnderbar(words);

        if (base.length() == 0) {
            base = "X";
        }

        if (base.startsWith("INT_")) {
            // reserved for int codes
            base = "X_" + base;
        }

        String uniqName;
        int index = 1;
        for (uniqName = base; usedNames.contains(uniqName); ) {
            index++;
            uniqName = base + "_" + index;
        }

        usedNames.add(uniqName);

        return uniqName;
    }

    static void skipJavaizingType(SchemaTypeImpl sImpl) {
        if (sImpl.isJavaized()) {
            return;
        }

        SchemaTypeImpl baseType = (SchemaTypeImpl) sImpl.getBaseType();
        if (baseType != null) {
            skipJavaizingType(baseType);
        }

        sImpl.startJavaizing();
        secondPassProcessType(sImpl);
        sImpl.finishJavaizing();
    }

    static void secondPassProcessType(SchemaTypeImpl sImpl) {
        if (!isStringType(sImpl)) {
            return;
        }

        XmlAnySimpleType[] enumVals = sImpl.getEnumerationValues();

        // if this is an enumerated string type, values are to be
        // javaized as constants.
        if (enumVals == null) {
            return;
        }

        // ERROR is found at > 3668
        if (enumVals.length > MAX_ENUM_COUNT) {
            StscState.get().warning("SchemaType Enumeration found with too many enumeration values to create a Java " +
                                    "enumeration. The base SchemaType \"" + sImpl.getBaseEnumType() + "\" will be used instead", XmlError.SEVERITY_WARNING, null);
            return;
        }
        SchemaType basedOn = sImpl.getBaseEnumType();
        if (basedOn == null) {
            return;
        }

        SchemaStringEnumEntry[] entryArray = new SchemaStringEnumEntry[enumVals.length];
        if (basedOn == sImpl) {
            Set<String> usedNames = new HashSet<>();
            for (int i = 0; i < enumVals.length; i++) {
                String val = enumVals[i].getStringValue();
                entryArray[i] = new SchemaStringEnumEntryImpl(val, i + 1, pickConstantName(usedNames, val));
            }
        } else {
            for (int i = 0; i < enumVals.length; i++) {
                String val = enumVals[i].getStringValue();
                entryArray[i] = basedOn.enumEntryForString(val);
            }
        }
        sImpl.setStringEnumEntries(entryArray);
    }

    static void javaizeType(SchemaTypeImpl sImpl) {
        if (sImpl.isJavaized()) {
            return;
        }

        SchemaTypeImpl baseType = (SchemaTypeImpl) sImpl.getBaseType();
        if (baseType != null) {
            javaizeType(baseType);
        }
        if (sImpl.getContentBasedOnType() != null && sImpl.getContentBasedOnType() != baseType) {
            javaizeType((SchemaTypeImpl) sImpl.getContentBasedOnType());
        }

        sImpl.startJavaizing();

        sImpl.setCompiled(true);

        secondPassProcessType(sImpl);

        if (!sImpl.isSimpleType()) {
            SchemaProperty[] eltProps = sImpl.getElementProperties();
            SchemaProperty[] attrProps = sImpl.getAttributeProperties();

            // Handing out java names - this permits us to avoid collisions.
            Set<String> usedPropNames = new HashSet<>();

            // First, copy all used property names from base, since these
            // cannnot be changed at this point and they may be arbitrary
            // because of derivation by restriction and the "nopvr" switch
            SchemaProperty[] baseProps = baseType.getProperties();
            for (SchemaProperty baseProp : baseProps) {
                String name = baseProp.getJavaPropertyName();
                assert !usedPropNames.contains(name);
                usedPropNames.add(name);
            }

            // count in the methods from extension interfaces
            avoidExtensionMethods(usedPropNames, sImpl);

            // Assign names in two passes: first inherited names, then others.
            for (boolean doInherited = true; ; doInherited = false) {
                if (eltProps.length > 0) {
                    assignJavaPropertyNames(usedPropNames, eltProps, baseType, doInherited);
                }

                assignJavaPropertyNames(usedPropNames, attrProps, baseType, doInherited);

                if (!doInherited) {
                    break;
                }
            }

            SchemaProperty[] allprops = sImpl.getProperties();

            // determine whether order insensitive
            boolean insensitive = isPropertyModelOrderInsensitive(allprops);

            // Fill in the java type codes now.
            // This depends on recursive type information, so it's done in typechecking
            assignJavaTypeCodes(allprops);

            sImpl.setOrderSensitive(!insensitive);
        }

        // assign java type names to anonymous types
        // for redefined types, this step was performed when javaizing the redefinition
        if (sImpl.getFullJavaName() != null || sImpl.getOuterType() != null) {
            assignJavaAnonymousTypeNames(sImpl);
        }

        sImpl.finishJavaizing();
    }

    private static final String[] PREFIXES = new String[]{"get", "xget", "isNil", "isSet", "sizeOf", "set",
        "xset", "addNew", "setNil", "unset", "insert", "add", "insertNew", "addNew", "remove"};

    private static void avoidExtensionMethods(Set<String> usedPropNames, SchemaTypeImpl sImpl) {
        InterfaceExtension[] exts = sImpl.getInterfaceExtensions();
        if (exts != null) {
            for (InterfaceExtension ext : exts) {
                InterfaceExtension.MethodSignature[] methods = ext.getMethods();
                for (InterfaceExtension.MethodSignature method : methods) {
                    String methodName = method.getName();
                    for (String prefix : PREFIXES) {
                        if (methodName.startsWith(prefix)) {
                            usedPropNames.add(methodName.substring(prefix.length()));
                        }
                    }
                }
            }
        }
    }

    static void assignJavaAnonymousTypeNames(SchemaTypeImpl outerType) {
        Set<String> usedTypeNames = new HashSet<>();
        SchemaType[] anonymousTypes = outerType.getAnonymousTypes();
        StscState state = StscState.get();

        int nrOfAnonTypes = anonymousTypes.length;
        if (outerType.isRedefinition()) {
            // We have to add the anonymous types for redefinitions to the list
            // since they don't have another outer class
            ArrayList<SchemaType> list = new ArrayList<>();
            addAnonymousTypesFromRedefinition(outerType, list);
            if (list.size() > 0) {
                SchemaType[] temp = new SchemaType[nrOfAnonTypes + list.size()];
                list.toArray(temp);
                System.arraycopy(anonymousTypes, 0, temp, list.size(), nrOfAnonTypes);
                anonymousTypes = temp;
            }
        }

        // Because we generate nested java interfaces, and nested
        // interface names must not be the same as an ancestor, use up
        // the ancestors

        for (SchemaType scanOuterType = outerType;
             scanOuterType != null;
             scanOuterType = scanOuterType.getOuterType()) {
            usedTypeNames.add(scanOuterType.getShortJavaName());
        }

        for (SchemaType scanOuterType = outerType;
             scanOuterType != null;
             scanOuterType = scanOuterType.getOuterType()) {
            usedTypeNames.add(scanOuterType.getShortJavaImplName());
        }

        // and because things are problematic if an inner type name
        // is the same as a top-level package name, also get rid of that
        // collision
        usedTypeNames.add(getOutermostPackage(outerType.getFullJavaName()));

        // assign names
        for (int i = 0; i < anonymousTypes.length; i++) {
            SchemaTypeImpl sImpl = (SchemaTypeImpl) anonymousTypes[i];
            if (sImpl == null) // already handled in first pass
            {
                continue;
            }
            if (sImpl.isSkippedAnonymousType()) {
                continue;
            }
            String localname = null;
            String javaname;

            SchemaField containerField = sImpl.getContainerField();
            if (containerField != null) {
                QName qname = sImpl.getContainerField().getName();
                localname = qname.getLocalPart();
                javaname = state.getJavaname(sImpl.getContainerField().getName(), BindingConfig.QNAME_TYPE);
            } else {
                // not defined inside an Elt or Attr: must be a nested simple type
                switch (sImpl.getOuterType().getSimpleVariety()) {
                    case SchemaType.UNION:
                        javaname = "Member";
                        break;
                    case SchemaType.LIST:
                        javaname = "Item";
                        break;
                    case SchemaType.ATOMIC:
                    default:
                        assert (false) : "Weird type " + sImpl.toString();
                        javaname = "Base";
                        break;
                }
            }

            if (i < nrOfAnonTypes) {
                sImpl.setShortJavaName(
                    pickInnerJavaClassName(usedTypeNames, localname, javaname));
                sImpl.setShortJavaImplName(
                    pickInnerJavaImplName(usedTypeNames, localname, javaname == null ? null : javaname + "Impl"));
            } else {
                // This comes from redefined types, so we have to compute the
                // full name here
                sImpl.setFullJavaName(outerType.getFullJavaName() + "$" +
                                      pickInnerJavaClassName(usedTypeNames, localname, javaname));
                sImpl.setFullJavaImplName(outerType.getFullJavaImplName() + "$" +
                                          pickInnerJavaImplName(usedTypeNames, localname, javaname == null ? null : javaname + "Impl"));
            }

            // TODO(radup) why is this inside this loop here?
            setExtensions(sImpl, state);
        }
    }

    static void assignJavaPropertyNames(Set<String> usedNames, SchemaProperty[] props, SchemaType baseType, boolean doInherited) {
        StscState state = StscState.get();

        // two passes: first deal with inherited properties, then with new ones.
        // this ensures that we match up with base class definitions cleanly
        // BUGBUG(radup) We have to look for particles that have been removed
        // in the derivation tree for this type using derivation by restriction,
        // because they have not been removed in Java and may collide with
        // this type's properties.

        for (SchemaProperty prop : props) {
            SchemaPropertyImpl sImpl = (SchemaPropertyImpl) prop;

            SchemaProperty baseProp =
                (sImpl.isAttribute() ?
                    baseType.getAttributeProperty(sImpl.getName()) :
                    baseType.getElementProperty(sImpl.getName()));

            if ((baseProp == null) == doInherited) {
                continue;
            }

            QName propQName = sImpl.getName();

            String theName;

            if (baseProp == null) {
                theName = pickJavaPropertyName(usedNames, propQName.getLocalPart(),
                    state.getJavaname(propQName, sImpl.isAttribute() ? BindingConfig.QNAME_ACCESSOR_ATTRIBUTE :
                        BindingConfig.QNAME_ACCESSOR_ELEMENT));
            } else {
                theName = baseProp.getJavaPropertyName();
            }

            sImpl.setJavaPropertyName(theName);

            boolean isArray = (sImpl.getMaxOccurs() == null ||
                               sImpl.getMaxOccurs().compareTo(BigInteger.ONE) > 0);
            boolean isSingleton = !isArray && (sImpl.getMaxOccurs().signum() > 0);
            boolean isOption = isSingleton && (sImpl.getMinOccurs().signum() == 0);
            SchemaType javaBasedOnType = sImpl.getType();

            if (baseProp != null) {
                if (baseProp.extendsJavaArray()) {
                    isSingleton = false;
                    isOption = false;
                    isArray = true;
                }
                if (baseProp.extendsJavaSingleton()) {
                    isSingleton = true;
                }
                if (baseProp.extendsJavaOption()) {
                    isOption = true;
                }
                javaBasedOnType = baseProp.javaBasedOnType();
            }

            sImpl.setExtendsJava(javaBasedOnType.getRef(), isSingleton, isOption, isArray);
        }

    }

    static void assignJavaTypeCodes(SchemaProperty[] properties) {
        for (SchemaProperty property : properties) {
            SchemaPropertyImpl sImpl = (SchemaPropertyImpl) property;
            SchemaType sType = sImpl.javaBasedOnType();
            sImpl.setJavaTypeCode(javaTypeCodeForType(sType));
        }
    }

    static int javaTypeCodeInCommon(SchemaType[] types) {
        if (types == null || types.length == 0) {
            return SchemaProperty.XML_OBJECT;
        }

        int code = javaTypeCodeForType(types[0]);
        if (code == SchemaProperty.JAVA_OBJECT) {
            return code;
        }
        for (int i = 1; i < types.length; i++) {
            // if any two are different, the answer is java.lang.Object
            if (code != javaTypeCodeForType(types[i])) {
                return SchemaProperty.JAVA_OBJECT;
            }
        }
        return code;
    }

    static int javaTypeCodeForType(SchemaType sType) {
        if (!sType.isSimpleType()) {
            return SchemaProperty.XML_OBJECT;
        }

        if (((SchemaTypeImpl) sType).getUserTypeHandlerName() != null) {
            return SchemaProperty.JAVA_USER;
        }

        if (sType.getSimpleVariety() == SchemaType.UNION) {
            // see if we can find an interesting common base type, e.g., for string enums
            SchemaType baseType = sType.getUnionCommonBaseType();
            if (baseType != null && !baseType.isURType()) {
                sType = baseType;
            } else {
                return javaTypeCodeInCommon(sType.getUnionConstituentTypes());
            }
        }

        if (sType.getSimpleVariety() == SchemaType.LIST) {
            return SchemaProperty.JAVA_LIST;
        }

        if (sType.isURType()) {
            return SchemaProperty.XML_OBJECT;
        }

        switch (sType.getPrimitiveType().getBuiltinTypeCode()) {
            case SchemaType.BTC_ANY_SIMPLE:
                // return SchemaProperty.XML_OBJECT;
                return SchemaProperty.JAVA_STRING;

            case SchemaType.BTC_BOOLEAN:
                return SchemaProperty.JAVA_BOOLEAN;

            case SchemaType.BTC_BASE_64_BINARY:
                return SchemaProperty.JAVA_BYTE_ARRAY;

            case SchemaType.BTC_HEX_BINARY:
                return SchemaProperty.JAVA_BYTE_ARRAY;

            case SchemaType.BTC_ANY_URI:
                return SchemaProperty.JAVA_STRING;

            case SchemaType.BTC_QNAME:
                return SchemaProperty.JAVA_QNAME;

            case SchemaType.BTC_NOTATION:
                return SchemaProperty.XML_OBJECT;

            case SchemaType.BTC_FLOAT:
                return SchemaProperty.JAVA_FLOAT;

            case SchemaType.BTC_DOUBLE:
                return SchemaProperty.JAVA_DOUBLE;

            case SchemaType.BTC_DECIMAL:
                switch (sType.getDecimalSize()) {
                    case SchemaType.SIZE_BYTE:
                        return SchemaProperty.JAVA_BYTE;
                    case SchemaType.SIZE_SHORT:
                        return SchemaProperty.JAVA_SHORT;
                    case SchemaType.SIZE_INT:
                        return SchemaProperty.JAVA_INT;
                    case SchemaType.SIZE_LONG:
                        return SchemaProperty.JAVA_LONG;
                    case SchemaType.SIZE_BIG_INTEGER:
                        return SchemaProperty.JAVA_BIG_INTEGER;
                    case SchemaType.SIZE_BIG_DECIMAL:
                    default:
                        return SchemaProperty.JAVA_BIG_DECIMAL;
                }

            case SchemaType.BTC_STRING:
                if (isStringType(sType.getBaseEnumType())) {
                    // This is necessary for local types, etc.
                    // schema enums with > ~3668 cause a Java Src file to be created
                    // that cannot be compiled due to JVM restrictions
                    // FIXFIX: http://issues.apache.org/jira/browse/XMLBEANS-307
                    // FIXFIX: XMLBeans scomp throws error "code too large"
                    if (sType.getEnumerationValues() != null &&
                        sType.getEnumerationValues().length > MAX_ENUM_COUNT) {
                        return SchemaProperty.JAVA_STRING;
                    } else {
                        return SchemaProperty.JAVA_ENUM;
                    }
                }
                return SchemaProperty.JAVA_STRING;

            case SchemaType.BTC_DURATION:
                return SchemaProperty.JAVA_GDURATION;

            case SchemaType.BTC_DATE_TIME:
            case SchemaType.BTC_DATE:
                // return SchemaProperty.JAVA_DATE; // converted to calendar

            case SchemaType.BTC_TIME:
            case SchemaType.BTC_G_YEAR_MONTH:
            case SchemaType.BTC_G_YEAR:
            case SchemaType.BTC_G_MONTH_DAY:
            case SchemaType.BTC_G_DAY:
            case SchemaType.BTC_G_MONTH:
                // return SchemaProperty.JAVA_GDATE; // converted to calendar (JAX-B)
                return SchemaProperty.JAVA_CALENDAR;

            default:
                assert (false) : "unrecognized code " + sType.getPrimitiveType().getBuiltinTypeCode();
                throw new IllegalStateException("unrecognized code " + sType.getPrimitiveType().getBuiltinTypeCode() + " of " + sType.getPrimitiveType().getName());
        }
    }

    static boolean isPropertyModelOrderInsensitive(SchemaProperty[] properties) {
        for (SchemaProperty prop : properties) {
            if (prop.hasNillable() == SchemaProperty.VARIABLE) {
                return false;
            }
            if (prop.hasDefault() == SchemaProperty.VARIABLE) {
                return false;
            }
            if (prop.hasFixed() == SchemaProperty.VARIABLE) {
                return false;
            }
            if (prop.hasDefault() != SchemaProperty.NEVER &&
                prop.getDefaultText() == null) {
                return false;
            }
        }
        return true;
    }

    static boolean protectReservedGlobalClassNames(String name) {
        int i = name.lastIndexOf('.');
        String lastSegment = name.substring(i + 1);
        return lastSegment.endsWith("Document") && !lastSegment.equals("Document");
    }

    static boolean protectReservedInnerClassNames(String name) {
        return (name.equals("Enum") || name.equals("Factory"));
    }

    static String[] PROTECTED_PROPERTIES = {
        "StringValue",
        "BooleanValue",
        "ByteValue",
        "ShortValue",
        "IntValue",
        "LongValue",
        "BigIntegerValue",
        "BigDecimalValue",
        "FloatValue",
        "DoubleValue",
        "ByteArrayValue",
        "EnumValue",
        "CalendarValue",
        "DateValue",
        "GDateValue",
        "GDurationValue",
        "QNameValue",
        "ListValue",
        "ObjectValue",
        "Class",
    };
    static Set<String> PROTECTED_PROPERTIES_SET = new HashSet<>(Arrays.asList(PROTECTED_PROPERTIES));

    static boolean protectReservedPropertyNames(String name) {
        return PROTECTED_PROPERTIES_SET.contains(name) ||
               (name.endsWith("Array") && !name.equals("Array"));
    }

    static String pickFullJavaClassName(Set<String> usedNames, QName qName, String configname, boolean isDocument, boolean isAttrType) {
        String base;
        boolean protect;

        if (configname != null && configname.indexOf('.') >= 0) {
            // a configname with dots defines the fully qualified java class name
            base = configname;
            protect = protectReservedGlobalClassNames(base);
        } else {
            StscState state = StscState.get();
            String uri = qName.getNamespaceURI();

            base = NameUtil.getClassNameFromQName(qName);

            // Check to see if we have a mapping from namespace URI to Java package
            // name. If so, apply the mapped package prefix at the beginning of
            // the base name

            String pkgPrefix = state.getPackageOverride(uri);

            if (pkgPrefix != null) {
                // Form the new qualified class name from the new package name
                // and the old class name
                base = pkgPrefix + "." + base.substring(base.lastIndexOf('.') + 1);
            }

            // See if there is a prefix...
            String javaPrefix = state.getJavaPrefix(uri);
            if (javaPrefix != null) {
                base = base.substring(0, base.lastIndexOf('.') + 1) + javaPrefix + base.substring(base.lastIndexOf('.') + 1);
            }

            // a configname without dots may override the shortname part.
            if (configname != null) {
                base = base.substring(0, base.lastIndexOf('.') + 1) + configname;
            }

            protect = protectReservedGlobalClassNames(base);
            if (configname == null) {
                // add special suffix
                if (isDocument) {
                    base = base + "Document";
                } else if (isAttrType) {
                    base = base + "Attribute";
                }

                // add configured suffix
                String javaSuffix = state.getJavaSuffix(uri);
                if (javaSuffix != null) {
                    base = base + javaSuffix;
                }
            }
        }

        String outermostPkg = getOutermostPackage(base);

        int index = 1;
        String uniqName;
        if (protect) {
            uniqName = base + index;
        } else {
            uniqName = base;
        }
        while (usedNames.contains(uniqName.toLowerCase(Locale.ROOT)) || uniqName.equals(outermostPkg)) {
            index++;
            uniqName = base + index;
        }

        usedNames.add(uniqName.toLowerCase(Locale.ROOT));

        return uniqName;
    }

    static String getOutermostPackage(String fqcn) {
        if (fqcn == null) {
            return "";
        }

        // remove class name
        int lastdot = fqcn.indexOf('.');
        if (lastdot < 0) {
            return "";
        }

        // remove outer package names
        return fqcn.substring(0, lastdot);
    }

    static String pickFullJavaImplName(Set<String> usedNames, String intfName) {
        // Strip off the package from the class name so we can replace it
        String className = intfName;
        String pkgName = null;
        int index = intfName.lastIndexOf('.');
        if (index >= 0) {
            className = intfName.substring(index + 1);
            pkgName = intfName.substring(0, index);
        }

        // Form the new qualified class name from the new package name
        // and the old class name
        String base = pkgName + ".impl." + className + "Impl";

        index = 1;
        String uniqName = base;
        while (usedNames.contains(uniqName.toLowerCase(Locale.ROOT))) {
            index++;
            uniqName = base + index;
        }

        usedNames.add(uniqName.toLowerCase(Locale.ROOT));

        return uniqName;
    }

    static String pickJavaPropertyName(Set<String> usedNames, String localName, String javaName) {
        if (javaName == null) {
            javaName = NameUtil.upperCamelCase(localName);
        }
        boolean protect = protectReservedPropertyNames(javaName);
        String uniqName;
        int index = 1;
        if (protect) {
            uniqName = javaName + index;
        } else {
            uniqName = javaName;
        }
        while (usedNames.contains(uniqName)) {
            index++;
            uniqName = javaName + index;
        }

        usedNames.add(uniqName);

        return uniqName;
    }

    static String pickInnerJavaClassName(Set<String> usedNames, String localName, String javaName) {
        if (javaName == null) {
            javaName = NameUtil.upperCamelCase(localName);
        }
        boolean protect = protectReservedInnerClassNames(javaName);
        String uniqName;
        int index = 1;
        if (protect) {
            uniqName = javaName + index;
        } else {
            uniqName = javaName;
        }
        while (usedNames.contains(uniqName)) {
            index++;
            uniqName = javaName + index;
        }

        usedNames.add(uniqName);

        return uniqName;
    }

    static String pickInnerJavaImplName(Set<String> usedNames, String localName, String javaName) {
        if (javaName == null) {
            javaName = NameUtil.upperCamelCase(localName) + "Impl";
        }
        String uniqName = javaName;
        int index = 1;
        while (usedNames.contains(uniqName)) {
            index++;
            uniqName = javaName + index;
        }

        usedNames.add(uniqName);

        return uniqName;
    }

    static QName findTopName(SchemaType sType) {
        if (sType.getName() != null) {
            return sType.getName();
        }

        if (sType.isDocumentType()) {
            // A document type must have a content model consisting of a single elt
            if (sType.getContentModel() == null || sType.getContentModel().getParticleType() != SchemaParticle.ELEMENT) {
                throw new IllegalStateException();
            }
            return (sType.getDocumentElementName());
        }

        if (sType.isAttributeType()) {
            if (sType.getAttributeModel() == null || sType.getAttributeModel().getAttributes().length != 1) {
                throw new IllegalStateException();
            }
            return sType.getAttributeTypeAttributeName();
        }

        SchemaField sElt = sType.getContainerField();
        assert (sElt != null);
        assert (sType.getOuterType() == null);
        return sElt.getName();
    }

    static void addAnonymousTypesFromRedefinition(SchemaType sType, List<SchemaType> result) {
        while (((SchemaTypeImpl) sType).isRedefinition() &&
               (sType.getDerivationType() == SchemaType.DT_EXTENSION ||
                sType.isSimpleType())) {
            sType = sType.getBaseType();
            SchemaType[] newAnonTypes = sType.getAnonymousTypes();
            if (newAnonTypes.length > 0) {
                result.addAll(Arrays.asList(newAnonTypes));
            }
        }
    }
}
