/*   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.xmlbeans.*;
import org.apache.xmlbeans.impl.common.NameUtil;

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

public class StscJavaizer {

    /**
     * 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()));

                setUserTypes(sImpl, state);

                setExtensions(sImpl, 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())) {
                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())) {
                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())) {
                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(SchemaTypeImpl sImpl, StscState state) {
        BindingConfig config = state.getBindingConfig();

        if (config != null) {
            UserType utype = config.lookupUserTypeForQName(sImpl.getName());
            if (utype != null) {
                sImpl.setUserTypeName(utype.getJavaName());
                sImpl.setUserTypeHandlerName(utype.getStaticHandler());
            }
        }
    }

    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()) || uniqName.equals(outermostPkg)) {
            index++;
            uniqName = base + index;
        }

        usedNames.add(uniqName.toLowerCase());

        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())) {
            index++;
            uniqName = base + index;
        }

        usedNames.add(uniqName.toLowerCase());

        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));
            }
        }
    }
}
