/*
 * 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.sdo.helper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelProject;
import org.eclipse.persistence.internal.oxm.schema.model.All;
import org.eclipse.persistence.internal.oxm.schema.model.Annotation;
import org.eclipse.persistence.internal.oxm.schema.model.Any;
import org.eclipse.persistence.internal.oxm.schema.model.Attribute;
import org.eclipse.persistence.internal.oxm.schema.model.AttributeGroup;
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.Group;
import org.eclipse.persistence.internal.oxm.schema.model.Import;
import org.eclipse.persistence.internal.oxm.schema.model.Include;
import org.eclipse.persistence.internal.oxm.schema.model.List;
import org.eclipse.persistence.internal.oxm.schema.model.NestedParticle;
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.Union;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.helper.extension.SDOUtil;
import org.eclipse.persistence.sdo.types.SDODataType;
import org.eclipse.persistence.sdo.types.SDOWrapperType;
import org.eclipse.persistence.sessions.Project;

import commonj.sdo.Property;
import commonj.sdo.Type;
import commonj.sdo.helper.HelperContext;

/**
 * <p><b>Purpose</b>: Called from XSDHelper define methods to generate SDO Types from a Schema
 *
 * @see commonj.sdo.helper.XSDHelper
 */
public class SDOTypesGenerator {
    private Project schemaProject;
    private Schema rootSchema;
    private HashMap processedComplexTypes;
    private HashMap processedSimpleTypes;
    private HashMap processedElements;
    private HashMap processedAttributes;
    private Map itemNameToSDOName;
    private boolean processImports;
    private boolean returnAllTypes;
    private java.util.List<NamespaceResolver> namespaceResolvers;
    private boolean inRestriction;
    // hold the context containing all helpers so that we can preserve inter-helper relationships
    private HelperContext aHelperContext;

    private java.util.List<SDOType> anonymousTypes;
    private java.util.Map<QName, Type> generatedTypes;
    private java.util.Map<QName, SDOType> generatedTypesByXsdQName;
    private java.util.Map<QName, Property> generatedGlobalElements;
    private java.util.Map<QName, Property> generatedGlobalAttributes;
    private String packageName;
    private java.util.List<NonContainmentReference> nonContainmentReferences;
    private Map<Type, java.util.List<GlobalRef>> globalRefs;
    private boolean isImportProcessor;

    public SDOTypesGenerator(HelperContext aContext) {
        anonymousTypes = new ArrayList<SDOType>();
        generatedTypesByXsdQName = new HashMap<QName, SDOType>();
        processedComplexTypes = new HashMap();
        processedSimpleTypes = new HashMap();
        processedElements = new HashMap();
        processedAttributes = new HashMap();
        itemNameToSDOName = new HashMap();
        namespaceResolvers = new ArrayList();
        this.aHelperContext = aContext;
    }

    public java.util.List<Type> define(Source xsdSource, SchemaResolver schemaResolver) {
        return define(xsdSource, schemaResolver, false, true);
    }

    public java.util.List<Type> define(Source xsdSource, SchemaResolver schemaResolver, boolean includeAllTypes, boolean processImports) {
        Schema schema = getSchema(xsdSource, schemaResolver, false);
        return define(schema, includeAllTypes, processImports);
    }

    public java.util.List<Type> define(Schema schema, boolean includeAllTypes, boolean processImports) {
        // Initialize the List of Types before we process the schema
        java.util.List<Type> returnList = new ArrayList<Type>();

        setReturnAllTypes(includeAllTypes);
        setProcessImports(processImports);
        processSchema(schema);

        returnList.addAll(getGeneratedTypes().values());
        returnList.addAll(anonymousTypes);

        if (!this.isImportProcessor()) {
            java.util.List descriptorsToAdd = new ArrayList(returnList);
            Iterator<Type> iter = descriptorsToAdd.iterator();
            while (iter.hasNext()) {
                SDOType nextSDOType = (SDOType) iter.next();
                if (!nextSDOType.isFinalized()) {
                    //Only throw this error if we're not processing an import.
                    throw SDOException.typeReferencedButNotDefined(nextSDOType.getURI(), nextSDOType.getName());
                }

                Iterator<Property> propertiesIter = nextSDOType.getProperties().iterator();
                while (propertiesIter.hasNext()) {
                    SDOProperty prop = (SDOProperty) propertiesIter.next();
                    if (prop.getType().isDataType() && prop.isContainment()) {
                        // If isDataType is true, then isContainment has to be false.
                        // This property was likely created as a stub, and isContainment never got reset
                        // when the property was fully defined.
                        // This problem was uncovered in bug 6809767
                        prop.setContainment(false);
                    }
                }

            }
            Iterator<Property> propertiesIter = getGeneratedGlobalElements().values().iterator();
            while (propertiesIter.hasNext()) {
                SDOProperty nextSDOProperty = (SDOProperty) propertiesIter.next();
                if (!nextSDOProperty.isFinalized()) {
                    //Only throw this error if we're not processing an import.
                    throw SDOException.referencedPropertyNotFound(nextSDOProperty.getUri(), nextSDOProperty.getName());
                }
            }

            propertiesIter = getGeneratedGlobalAttributes().values().iterator();
            while (propertiesIter.hasNext()) {
                SDOProperty nextSDOProperty = (SDOProperty) propertiesIter.next();
                if (!nextSDOProperty.isFinalized()) {
                    //Only throw this error if we're not processing an import.
                    throw SDOException.referencedPropertyNotFound(nextSDOProperty.getUri(), nextSDOProperty.getName());
                }
            }

            iter = getGeneratedTypes().values().iterator();
            //If we get here all types were finalized correctly
            while (iter.hasNext()) {
                SDOType nextSDOType = (SDOType) iter.next();
                ((SDOTypeHelper) aHelperContext.getTypeHelper()).addType(nextSDOType);
            }

            Iterator anonymousIterator = getAnonymousTypes().iterator();

            while (anonymousIterator.hasNext()) {
                SDOType nextSDOType = (SDOType) anonymousIterator.next();
                ((SDOTypeHelper) aHelperContext.getTypeHelper()).getAnonymousTypes().add(nextSDOType);
            }

            // add any base types to the list
            for (int i=0; i<descriptorsToAdd.size(); i++) {
                SDOType nextSDOType = (SDOType) descriptorsToAdd.get(i);
                if (!nextSDOType.isDataType() && !nextSDOType.isSubType() && nextSDOType.isBaseType()) {
                    nextSDOType.setupInheritance(null);
                } else if (!nextSDOType.isDataType() && nextSDOType.isSubType() && !getGeneratedTypes().values().contains(nextSDOType.getBaseTypes().get(0))) {
                    SDOType baseType = (SDOType) nextSDOType.getBaseTypes().get(0);
                    while (baseType != null) {
                        descriptorsToAdd.add(baseType);
                        if (baseType.getBaseTypes().size() == 0) {
                            // baseType should now be root of inheritance
                            baseType.setupInheritance(null);
                            baseType = null;
                        } else {
                            baseType = (SDOType) baseType.getBaseTypes().get(0);
                        }
                    }
                }
            }

            ((SDOXMLHelper) aHelperContext.getXMLHelper()).addDescriptors(descriptorsToAdd);

            //go through generatedGlobalProperties and add to xsdhelper
            Iterator<QName> qNameIter = getGeneratedGlobalElements().keySet().iterator();
            while (qNameIter.hasNext()) {
                QName nextQName = qNameIter.next();
                SDOProperty nextSDOProperty = (SDOProperty) getGeneratedGlobalElements().get(nextQName);
                ((SDOXSDHelper) aHelperContext.getXSDHelper()).addGlobalProperty(nextQName, nextSDOProperty, true);
            }

            qNameIter = getGeneratedGlobalAttributes().keySet().iterator();
            while (qNameIter.hasNext()) {
                QName nextQName = qNameIter.next();
                SDOProperty nextSDOProperty = (SDOProperty) getGeneratedGlobalAttributes().get(nextQName);
                ((SDOXSDHelper) aHelperContext.getXSDHelper()).addGlobalProperty(nextQName, nextSDOProperty, false);
            }

            Iterator<java.util.List<GlobalRef>> globalRefsIter = getGlobalRefs().values().iterator();
            while (globalRefsIter.hasNext()) {
                java.util.List<GlobalRef> nextList = globalRefsIter.next();
                if (nextList.size() > 0) {
                    GlobalRef ref = nextList.get(0);
                    throw SDOException.referencedPropertyNotFound(((SDOProperty) ref.getProperty()).getUri(), ref.getProperty().getName());
                }
            }
        }

        return returnList;
    }

    private void processSchema(Schema parsedSchema) {
        rootSchema = parsedSchema;
        initialize();
        namespaceResolvers.add(rootSchema.getNamespaceResolver());
        processIncludes(rootSchema.getIncludes());
        processImports(rootSchema.getImports());
        preprocessGlobalTypes(rootSchema);
        processGlobalAttributes(rootSchema);
        processGlobalElements(rootSchema);
        processGlobalSimpleTypes(rootSchema);
        processGlobalComplexTypes(rootSchema);

        postProcessing();
    }

    private void processImports(java.util.List imports) {
        if ((imports == null) || (imports.size() == 0) || !isProcessImports()) {
            return;
        }
        Iterator iter = imports.iterator();
        while (iter.hasNext()) {
            Import nextImport = (Import) iter.next();
            try {
                processImportIncludeInternal(nextImport);
            } catch (Exception e) {
                throw SDOException.errorProcessingImport(nextImport.getSchemaLocation(), nextImport.getNamespace(), e);
            }
        }
    }

    private void processIncludes(java.util.List includes) {
        if ((includes == null) || (includes.size() == 0) || !isProcessImports()) {
            return;
        }
        Iterator iter = includes.iterator();
        while (iter.hasNext()) {
            Include nextInclude = (Include) iter.next();
            try {
                processImportIncludeInternal(nextInclude);
            } catch (Exception e) {
                throw SDOException.errorProcessingInclude(nextInclude.getSchemaLocation(), e);
            }
        }
    }

    /**
     * INTERNAL:
     * This function is referenced by processImport or processInclude possibly recursively
     * @param Include theImportOrInclude
     * @throws Exception
     */
    private void processImportIncludeInternal(Include theImportOrInclude) throws Exception {
        if (theImportOrInclude.getSchema() != null) {
            SDOTypesGenerator generator = new SDOTypesGenerator(aHelperContext);
            generator.setAnonymousTypes(getAnonymousTypes());
            generator.setGeneratedTypes(getGeneratedTypes());
            generator.setGeneratedTypesByXsdQName(getGeneratedTypesByXsdQName());
            generator.setGeneratedGlobalElements(getGeneratedGlobalElements());
            generator.setGeneratedGlobalAttributes(getGeneratedGlobalAttributes());
            // Both imports and includes are treated the same when checking for a mid-schema tree walk state
            generator.setIsImportProcessor(true);
            // May throw an IAE if a global type: local part cannot be null when creating a QName
            java.util.List<Type> importedTypes = generator.define(theImportOrInclude.getSchema(), isReturnAllTypes(), isProcessImports());
            processedComplexTypes.putAll(generator.processedComplexTypes);
            processedSimpleTypes.putAll(generator.processedSimpleTypes);
            processedElements.putAll(generator.processedElements);
            processedAttributes.putAll(generator.processedAttributes);
            for (int i = 0, size = importedTypes.size(); i < size; i++) {
                SDOType nextType = (SDOType) importedTypes.get(i);
                getGeneratedTypes().put(nextType.getQName(), nextType);
            }

            //copy over any global properties
            Iterator<QName> globalPropsIter = generator.getGeneratedGlobalElements().keySet().iterator();
            while (globalPropsIter.hasNext()) {
                QName nextKey = globalPropsIter.next();
                getGeneratedGlobalElements().put(nextKey, generator.getGeneratedGlobalElements().get(nextKey));
            }

            globalPropsIter = generator.getGeneratedGlobalAttributes().keySet().iterator();
            while (globalPropsIter.hasNext()) {
                QName nextKey = globalPropsIter.next();
                getGeneratedGlobalAttributes().put(nextKey, generator.getGeneratedGlobalAttributes().get(nextKey));
            }

            //copy over any unfinished globalRefs
            Iterator<Type> globalRefsIter = generator.getGlobalRefs().keySet().iterator();
            while (globalRefsIter.hasNext()) {
                Type nextKey = globalRefsIter.next();
                getGlobalRefs().put(nextKey, generator.getGlobalRefs().get(nextKey));
            }
        }
    }

    private boolean typesExists(String targetNamespace, String sdoTypeName) {
        boolean alreadyProcessed = false;

        if ((targetNamespace != null) && (targetNamespace.equals(SDOConstants.SDOJAVA_URL) || targetNamespace.equals(SDOConstants.SDO_URL) || targetNamespace.equals(SDOConstants.SDOXML_URL))) {
            alreadyProcessed = true;
        } else {
            QName qname = new QName(targetNamespace, sdoTypeName);
            Object processed = processedComplexTypes.get(qname);
            if (processed != null) {
                alreadyProcessed = true;
            }
        }

        if (!alreadyProcessed) {
            SDOType lookup = (SDOType) aHelperContext.getTypeHelper().getType(targetNamespace, sdoTypeName);
            if ((lookup != null) && lookup.isFinalized()) {
                if (isReturnAllTypes()) {
                    QName qname = new QName(targetNamespace, sdoTypeName);
                    getGeneratedTypes().put(qname, lookup);
                }
                return true;
            } else if (lookup == null) {
                QName qname = new QName(targetNamespace, sdoTypeName);
                SDOType processed = (SDOType) getGeneratedTypes().get(qname);
                if (processed != null && processed.isFinalized()) {
                    alreadyProcessed = true;
                }
            }
        }

        return alreadyProcessed;
    }

    private void processGlobalComplexTypes(Schema schema) {
        Collection complexTypes = schema.getTopLevelComplexTypes().values();
        if (complexTypes == null) {
            return;
        }

        Iterator complexTypesIter = complexTypes.iterator();
        while (complexTypesIter.hasNext()) {
            ComplexType complexType = (ComplexType) complexTypesIter.next();
            String targetNamespace = schema.getTargetNamespace();
            if(null == targetNamespace) {
                targetNamespace = "";
            }
            processGlobalComplexType(targetNamespace, schema.getDefaultNamespace(), complexType);
        }
    }

    private void processGlobalComplexType(String targetNamespace, String defaultNamespace, ComplexType complexType) {
        QName qname = new QName(targetNamespace, complexType.getName());
        Object processed = processedComplexTypes.get(qname);

        if (processed == null) {
            processComplexType(targetNamespace, defaultNamespace, complexType.getName(), complexType);
            processedComplexTypes.put(qname, complexType);
        }
    }

    private SDOType processComplexType(String targetNamespace, String defaultNamespace, String name, ComplexType complexType) {
        if (complexType == null) {
            return null;
        }
        boolean addedNR = addNextNamespaceResolver(complexType.getAttributesMap());
        SDOType newType = startComplexType(targetNamespace, defaultNamespace, name, complexType);
        if (newType != null) {
            if (complexType.getComplexContent() != null) {
                processComplexContent(targetNamespace, defaultNamespace, complexType.getComplexContent(), newType);
                finishComplexType(newType);
            } else if (complexType.getSimpleContent() != null) {
                processSimpleContent(targetNamespace, defaultNamespace, complexType.getSimpleContent(), newType);
                finishComplexType(newType);
            } else {
                if (complexType.getChoice() != null) {
                    processChoice(targetNamespace, defaultNamespace, newType, complexType.getChoice(), false);
                } else if (complexType.getSequence() != null) {
                    processSequence(targetNamespace, defaultNamespace, newType, complexType.getSequence(), false);
                } else if (complexType.getAll() != null) {
                    processAll(targetNamespace, defaultNamespace, newType, complexType.getAll(), false);
                }

                processOrderedAttributes(targetNamespace, defaultNamespace, newType, complexType.getOrderedAttributes());
                finishComplexType(newType);
            }
        }
        if (addedNR) {
            namespaceResolvers.remove(namespaceResolvers.size() - 1);
        }

        return newType;
    }

    //return true if a new type was created
    private SDOType startComplexType(String targetNamespace, String defaultNamespace, String name, ComplexType complexType) {
        String nameValue = (String) complexType.getAttributesMap().get(SDOConstants.SDOXML_NAME_QNAME);
        String originalName = name;
        if (nameValue != null) {
            itemNameToSDOName.put(name, nameValue);
            originalName = name;
            name = nameValue;
        }

        //check if already processed, if yes return false because a new type was not started else start new type and return true
        boolean alreadyExists = false;
        if(null != complexType.getName()) {
            alreadyExists = typesExists(targetNamespace, name);
        }

        if (!alreadyExists) {
            return startNewComplexType(targetNamespace, name, originalName, complexType);
        }

        return null;
    }

    private SDOType startNewComplexType(String targetNamespace, String sdoTypeName, String xsdLocalName, ComplexType complexType) {
        SDOType currentType;
        if(null == complexType.getName()) {
            currentType = createSDOTypeForName(targetNamespace, sdoTypeName, xsdLocalName);
        } else {
            currentType = getGeneratedTypesByXsdQName().get(new QName(targetNamespace, complexType.getName()));
        }

        if (complexType.isMixed()) {
            currentType.setMixed(true);
            currentType.setSequenced(true);
            // currentType.setOpen(true); Remove as part of SDO JIRA-106
        }

        if (complexType.getAnyAttribute() != null) {
            currentType.setOpen(true);
        }
        currentType.setAbstract(complexType.isAbstractValue());
        currentType.setDataType(false);

        String value = (String) complexType.getAttributesMap().get(SDOConstants.SDOXML_ALIASNAME_QNAME);
        if (value != null) {
            XMLConversionManager xmlConversionManager = ((SDOXMLHelper) aHelperContext.getXMLHelper()).getXmlConversionManager();
            java.util.List names = (java.util.List) xmlConversionManager.convertObject(value, java.util.List.class);
            currentType.setAliasNames(names);
        }

        String sequencedValue = (String) complexType.getAttributesMap().get(SDOConstants.SDOXML_SEQUENCE_QNAME);
        if (sequencedValue != null) {
            currentType.setSequenced(Boolean.parseBoolean(sequencedValue));
        }
        Annotation annotation = complexType.getAnnotation();
        if (annotation != null) {
            java.util.List documentation = annotation.getDocumentation();
            if ((documentation != null) && (documentation.size() > 0)) {
                currentType.setInstanceProperty(SDOConstants.DOCUMENTATION_PROPERTY, documentation);
            }
        }
        currentType.preInitialize(packageName, namespaceResolvers);
        if (complexType.getAnnotation() != null) {
            currentType.setAppInfoElements(complexType.getAnnotation().getAppInfo());
        }

        return currentType;
    }

    private void finishComplexType(SDOType currentType) {
        currentType.postInitialize();
    }

    private void processOrderedAttributes(String targetNamespace, String defaultNamespace, SDOType owningType, java.util.List orderedAttributes) {
        for (int i = 0; i < orderedAttributes.size(); i++) {
            Object next = orderedAttributes.get(i);
            if (next instanceof Attribute) {
                processAttribute(targetNamespace, defaultNamespace, owningType, (Attribute) next, false);
            } else if (next instanceof AttributeGroup) {
                processAttributeGroup(targetNamespace, defaultNamespace, owningType, (AttributeGroup) next);
            }
        }
    }

    private void processGlobalAttributes(Schema schema) {
        Collection attributes = schema.getTopLevelAttributes().values();
        if (attributes == null) {
            return;
        }
        Iterator attributesIter = attributes.iterator();
        while (attributesIter.hasNext()) {
            Attribute nextAttribute = (Attribute) attributesIter.next();
            String targetNamespace = schema.getTargetNamespace();
            if(null == targetNamespace) {
                targetNamespace = "";
            }
            processGlobalAttribute(targetNamespace, schema.getDefaultNamespace(), nextAttribute);
        }
    }

    private void processGlobalAttribute(String targetNamespace, String defaultNamespace, Attribute attribute) {
        if (attribute.getName() != null) {
            QName qname = new QName(targetNamespace, attribute.getName());
            Object processed = processedAttributes.get(qname);

            if (processed == null) {
                SDOType attributeType = processAttribute(targetNamespace, defaultNamespace, null, attribute, true);
                processedAttributes.put(qname, attribute);
                if(null != attributeType && !getGeneratedTypes().containsKey(attributeType.getQName())) {
                    getGeneratedTypes().put(attributeType.getQName(), attributeType);
                    anonymousTypes.remove(attributeType);
                }
            }
        } else {
            processAttribute(targetNamespace, defaultNamespace, null, attribute, true);
        }
    }

    private void processGroup(String targetNamespace, String defaultNamespace, SDOType owningType, TypeDefParticle typeDefParticle, Group group, boolean isMany) {
        if (!isMany && maxOccursGreaterThanOne(group.getMaxOccurs())) {
            isMany = true;
        }

        String groupName = group.getRef();
        if (groupName != null) {
            int idx = groupName.indexOf(':');
            String prefix = null;
            String localName = null;
            String uri = null;
            if (idx > -1) {
                localName = groupName.substring(idx + 1, groupName.length());
                prefix = groupName.substring(0, idx);
                uri = getURIForPrefix(prefix);
            } else {
                localName = groupName;
                uri = targetNamespace;
            }
            Group globalGroup = rootSchema.getGroup(uri, localName);
            if (globalGroup != null) {
                if (globalGroup.getChoice() != null) {
                    globalGroup.getChoice().setMaxOccurs(group.getMaxOccurs());
                    processChoice(targetNamespace, defaultNamespace, owningType, globalGroup.getChoice(), isMany);
                } else if (globalGroup.getSequence() != null) {
                    globalGroup.getSequence().setMaxOccurs(group.getMaxOccurs());
                    processSequence(targetNamespace, defaultNamespace, owningType, globalGroup.getSequence(), isMany);
                } else if (globalGroup.getAll() != null) {
                    globalGroup.getAll().setMaxOccurs(group.getMaxOccurs());
                    processAll(targetNamespace, defaultNamespace, owningType, globalGroup.getAll(), isMany);
                }
            }
        }
    }

    private SDOType processAttribute(String targetNamespace, String defaultNamespace, SDOType owningType, Attribute attribute, boolean isGlobal) {
        SimpleType simpleType = attribute.getSimpleType();
        if (simpleType != null) {
            SDOType propertyType = processSimpleType(targetNamespace, defaultNamespace, attribute.getName(), simpleType);
            processSimpleAttribute(targetNamespace, defaultNamespace, owningType, attribute, isGlobal, rootSchema.isAttributeFormDefault(), propertyType);
            propertyType.setXsdLocalName(attribute.getName());
            propertyType.setXsd(true);
            return propertyType;
        } else {
            processSimpleAttribute(targetNamespace, defaultNamespace, owningType, attribute, isGlobal, rootSchema.isAttributeFormDefault() || isGlobal, null);
            return null;
        }
    }

    private void processAttributeGroup(String targetNamespace, String defaultNamespace, SDOType owningType, AttributeGroup attributeGroup) {
        String attributeGroupName = attributeGroup.getRef();
        if (attributeGroupName != null) {
            int idx = attributeGroupName.indexOf(':');
            String prefix = null;
            String localName = null;
            String uri = null;
            if (idx > -1) {
                localName = attributeGroupName.substring(idx + 1, attributeGroupName.length());
                prefix = attributeGroupName.substring(0, idx);
                uri = getURIForPrefix(prefix);
            } else {
                localName = attributeGroupName;
                uri = targetNamespace;
            }
            AttributeGroup globalAttributeGroup = rootSchema.getAttributeGroup(uri, localName);
            if (globalAttributeGroup != null) {
                int size = globalAttributeGroup.getAttributes().size();
                if (globalAttributeGroup.getAnyAttribute() != null) {
                    processAnyAttribute(targetNamespace, defaultNamespace, owningType);
                }
                for (int j = 0; j < size; j++) {
                    processAttribute(targetNamespace, defaultNamespace, owningType, (Attribute) globalAttributeGroup.getAttributes().get(j), false);
                }
            }
        }
    }

    private void processAttributes(String targetNamespace, String defaultNamespace, SDOType owningType, java.util.List attributes) {
        if (attributes == null) {
            return;
        }
        for (int i = 0; i < attributes.size(); i++) {
            Attribute nextAttribute = (Attribute) attributes.get(i);
            processAttribute(targetNamespace, defaultNamespace, owningType, nextAttribute, false);
        }
    }

    private void processGlobalSimpleTypes(Schema schema) {
        Collection simpleTypes = schema.getTopLevelSimpleTypes().values();
        if (simpleTypes == null) {
            return;
        }

        Iterator simpleTypesIter = simpleTypes.iterator();
        while (simpleTypesIter.hasNext()) {
            SimpleType simpleType = (SimpleType) simpleTypesIter.next();
            String targetNamespace = schema.getTargetNamespace();
            if(null == targetNamespace) {
                targetNamespace = "";
            }
            processGlobalSimpleType(targetNamespace, schema.getDefaultNamespace(), simpleType);
        }
    }

    private void processGlobalSimpleType(String targetNamespace, String defaultNamespace, SimpleType simpleType) {
        QName qname = new QName(targetNamespace, simpleType.getName());
        if (!processedSimpleTypes.containsKey(qname)) {
            processSimpleType(targetNamespace, defaultNamespace, simpleType.getName(), simpleType);
            processedSimpleTypes.put(qname, simpleType);
        }
    }

    private SDOType startSimpleType(String targetNamespace, String defaultNamespace, String name, String xsdLocalName, SimpleType simpleType) {
        boolean alreadyExists = typesExists(targetNamespace, name);
        if (!alreadyExists) {
            return startNewSimpleType(targetNamespace, defaultNamespace, name, xsdLocalName, simpleType);
        }
        if(this.returnAllTypes) {
            return this.getExisitingType(targetNamespace, name);
        } else {
            return null;
        }
    }

    private SDOType startNewSimpleType(String targetNamespace, String defaultNamespace, String sdoTypeName, String xsdLocalName, SimpleType simpleType) {
        SDOType currentType;
         if(null == simpleType.getName()) {
            currentType = createSDOTypeForName(targetNamespace, sdoTypeName, xsdLocalName);
            currentType.setDataType(true);
        } else {
            currentType = getGeneratedTypesByXsdQName().get(new QName(targetNamespace, simpleType.getName()));
        }

        // Defining a new simple type from XSD.
        // See also: SDOTypeHelperDelegate:define for "types from DataObjects" equivalent

        SDOTypeHelper typeHelper = ((SDOTypeHelper) aHelperContext.getTypeHelper());

        // If this simple type is a restriction, get the QName for the base type and
        // include it when creating the WrapperType.  The QName will be used during
        // conversions (eg. "myBinaryElement" could be a restriction of base64Binary
        // or hexBinary.

        QName baseTypeQName = null;
        if (simpleType.getRestriction() != null) {
            String baseType = simpleType.getRestriction().getBaseType();
            baseTypeQName = this.getQNameForString(defaultNamespace, baseType);
            SDOType baseSDOType = getTypeForXSDQName(baseTypeQName);
            currentType.addBaseType(baseSDOType);

            currentType.setInstanceClass(baseSDOType.getInstanceClass());
        }

        // Create the new WrapperType
        SDOWrapperType wrapperType = new SDOWrapperType(currentType, sdoTypeName, typeHelper, baseTypeQName);

        // Register WrapperType with maps on TypeHelper
        typeHelper.getWrappersHashMap().put(currentType.getQName(), wrapperType);
        typeHelper.getTypesHashMap().put(wrapperType.getQName(), wrapperType);
        typeHelper.getImplClassesToSDOType().put(wrapperType.getXmlDescriptor().getJavaClass(), wrapperType);

        // Add descriptor to XMLHelper
        ArrayList list = new ArrayList(1);
        list.add(wrapperType);
        ((SDOXMLHelper) aHelperContext.getXMLHelper()).addDescriptors(list);

        if (simpleType.getAnnotation() != null) {
            currentType.setAppInfoElements(simpleType.getAnnotation().getAppInfo());
        }

        return currentType;
    }

    private SDOType processSimpleType(String targetNamespace, String defaultNamespace, String sdoTypeName, SimpleType simpleType) {
        if (simpleType == null) {
            return null;
        }
        boolean addedNR = addNextNamespaceResolver(simpleType.getAttributesMap());
        String name = sdoTypeName;
        String originalName = name;
        String nameValue = (String) simpleType.getAttributesMap().get(SDOConstants.SDOXML_NAME_QNAME);
        if (nameValue != null) {
            itemNameToSDOName.put(sdoTypeName, nameValue);
            name = nameValue;
        }

        SDOType newType = startSimpleType(targetNamespace, defaultNamespace, name, originalName, simpleType);
        if (newType != null) {
            Restriction restriction = simpleType.getRestriction();

            if (restriction != null) {
                processRestriction(targetNamespace, defaultNamespace, newType, restriction);
            }
            List list = simpleType.getList();
            if (list != null) {
                processList(targetNamespace, defaultNamespace, sdoTypeName, list, newType);
            }

            Union union = simpleType.getUnion();
            if (union != null) {
                processUnion(targetNamespace, defaultNamespace, sdoTypeName, union, newType);
            }

            finishSimpleType(targetNamespace, defaultNamespace, sdoTypeName, simpleType, newType);
        }
        if (addedNR) {
            namespaceResolvers.remove(namespaceResolvers.size() - 1);
        }

        return newType;
    }

    private void finishSimpleType(String targetNamespace, String defaultNamespace, String sdoTypeName, SimpleType simpleType, SDOType currentType) {
        String value = (String) simpleType.getAttributesMap().get(SDOConstants.SDOXML_ALIASNAME_QNAME);
        if (value != null) {
            XMLConversionManager xmlConversionManager = ((SDOXMLHelper) aHelperContext.getXMLHelper()).getXmlConversionManager();
            java.util.List names = (java.util.List) xmlConversionManager.convertObject(value, java.util.List.class);
            currentType.setAliasNames(names);
        }

        String instanceClassValue = (String) simpleType.getAttributesMap().get(SDOConstants.SDOJAVA_INSTANCECLASS_QNAME);
        if (instanceClassValue != null) {
            currentType.setInstanceProperty(SDOConstants.JAVA_CLASS_PROPERTY, instanceClassValue);
            currentType.setBaseTypes(null);
        }

        String extendedInstanceClassValue = (String) simpleType.getAttributesMap().get(SDOConstants.SDOJAVA_EXTENDEDINSTANCECLASS_QNAME);
        if (extendedInstanceClassValue != null) {
            currentType.setInstanceClassName(extendedInstanceClassValue);
        }
        currentType.postInitialize();
    }

    private void processChoice(String targetNamespace, String defaultNamespace, SDOType owningType, Choice choice, boolean isMany) {
        if (choice != null) {
            processTypeDef(targetNamespace, defaultNamespace, owningType, choice);

            java.util.List orderedItems = choice.getOrderedElements();
            for (int i = 0; i < orderedItems.size(); i++) {
                Object next = orderedItems.get(i);
                if (!isMany && maxOccursGreaterThanOne(choice.getMaxOccurs())) {
                    isMany = true;
                }

                if (next instanceof Choice) {
                    processChoice(targetNamespace, defaultNamespace, owningType, (Choice) next, isMany);
                } else if (next instanceof Sequence) {
                    processSequence(targetNamespace, defaultNamespace, owningType, (Sequence) next, isMany);
                } else if (next instanceof Any) {
                    processAny(targetNamespace, defaultNamespace, (Any) next, owningType, choice);//isMany??
                } else if (next instanceof Element) {
                    processElement(targetNamespace, defaultNamespace, owningType, choice, (Element) next, false, isMany);
                } else if (next instanceof Group) {
                    processGroup(targetNamespace, defaultNamespace, owningType, choice, (Group) next, isMany);
                }
            }
        }
    }

    private void processSequence(String targetNamespace, String defaultNamespace, SDOType owningType, Sequence sequence, boolean isMany) {
        if (sequence != null) {
            processTypeDef(targetNamespace, defaultNamespace, owningType, sequence);

            java.util.List orderedItems = sequence.getOrderedElements();
            for (int i = 0; i < orderedItems.size(); i++) {
                Object next = orderedItems.get(i);
                if (!isMany && maxOccursGreaterThanOne(sequence.getMaxOccurs())) {
                    isMany = true;
                }
                if (next instanceof Choice) {
                    processChoice(targetNamespace, defaultNamespace, owningType, (Choice) next, isMany);
                } else if (next instanceof Sequence) {
                    processSequence(targetNamespace, defaultNamespace, owningType, (Sequence) next, isMany);
                } else if (next instanceof Any) {
                    processAny(targetNamespace, defaultNamespace, (Any) next, owningType, sequence);//isMany?
                } else if (next instanceof Element) {
                    processElement(targetNamespace, defaultNamespace, owningType, sequence, (Element) next, false, isMany);
                } else if (next instanceof Group) {
                    processGroup(targetNamespace, defaultNamespace, owningType, sequence, (Group) next, isMany);
                }
            }
        }
    }

    private void processAll(String targetNamespace, String defaultNamespace, SDOType owningType, All all, boolean isMany) {
        if (all != null) {
            owningType.setSequenced(true);

            processTypeDef(targetNamespace, defaultNamespace, owningType, all);
            if (!isMany && maxOccursGreaterThanOne(all.getMaxOccurs())) {
                isMany = true;
            }
            java.util.List elements = all.getElements();
            for (int i = 0; i < elements.size(); i++) {
                Object next = elements.get(i);
                if (next instanceof Element) {
                    processElement(targetNamespace, defaultNamespace, owningType, all, (Element) next, false, isMany);
                }
            }
        }
    }

    private void processComplexContent(String targetNamespace, String defaultNamespace, ComplexContent complexContent, SDOType owningType) {
        if (complexContent != null) {
            if (complexContent.getExtension() != null) {
                processExtension(targetNamespace, defaultNamespace, owningType, complexContent.getExtension(), false);
            } else if (complexContent.getRestriction() != null) {
                processRestriction(targetNamespace, defaultNamespace, owningType, complexContent.getRestriction());
            }
        }
    }

    private void processSimpleContent(String targetNamespace, String defaultNamespace, SimpleContent simpleContent, SDOType owningType) {
        if (simpleContent != null) {
            if (simpleContent.getExtension() != null) {
                processExtension(targetNamespace, defaultNamespace, owningType, simpleContent.getExtension(), true);
            } else {
                if (simpleContent.getRestriction() != null) {
                    processRestriction(targetNamespace, defaultNamespace, owningType, simpleContent.getRestriction());
                }
            }
        }
    }

    private void processExtension(String targetNamespace, String defaultNamespace, SDOType owningType, Extension extension, boolean simpleContent) {
        if (extension != null) {
            String qualifiedType = extension.getBaseType();
            SDOType baseType = getSDOTypeForName(targetNamespace, defaultNamespace, qualifiedType);
            QName baseQName = getQNameForString(defaultNamespace, qualifiedType);

            if(baseType != null) {
                if(!baseType.isFinalized() && baseQName.getNamespaceURI().equals(targetNamespace)) {
                    if(baseType.isDataType()) {
                        SimpleType baseSimpleType = (SimpleType) rootSchema.getTopLevelSimpleTypes().get(baseQName.getLocalPart());
                        if(baseSimpleType != null){
                            processGlobalSimpleType(targetNamespace, defaultNamespace, baseSimpleType);
                        }
                    } else {
                        ComplexType baseComplexType = (ComplexType) rootSchema.getTopLevelComplexTypes().get(baseQName.getLocalPart());
                        if(baseComplexType != null){
                            processGlobalComplexType(targetNamespace, defaultNamespace, baseComplexType);
                        }
                    }
                }
                owningType.setOpen(owningType.isOpen() || baseType.isOpen());
            }
            if (qualifiedType != null) {
                processBaseType(baseType, targetNamespace, defaultNamespace, owningType, qualifiedType, simpleContent);
            }
            if (extension.getChoice() != null) {
                processChoice(targetNamespace, defaultNamespace, owningType, extension.getChoice(), false);
            } else if (extension.getSequence() != null) {
                processSequence(targetNamespace, defaultNamespace, owningType, extension.getSequence(), false);
            } else if (extension.getAll() != null) {
            }

            processOrderedAttributes(targetNamespace, defaultNamespace, owningType, extension.getOrderedAttributes());
        }
    }

    private void processRestriction(String targetNamespace, String defaultNamespace, SDOType owningType, Restriction restriction) {
        if (restriction != null) {
            String qualifiedType = restriction.getBaseType();
            Type baseType = processBaseType(targetNamespace, defaultNamespace, owningType, qualifiedType, false, restriction);
            boolean alreadyIn = inRestriction;
            if (!alreadyIn) {
                inRestriction = true;
            }

            if (restriction.getChoice() != null) {
                processChoice(targetNamespace, defaultNamespace, owningType, restriction.getChoice(), false);
            } else if (restriction.getSequence() != null) {
                processSequence(targetNamespace, defaultNamespace, owningType, restriction.getSequence(), false);
            } else if (restriction.getAll() != null) {
                processAll(targetNamespace, defaultNamespace, owningType, restriction.getAll(), false);
            }

            processAttributes(targetNamespace, defaultNamespace, owningType, restriction.getAttributes());
            if (!alreadyIn) {
                inRestriction = false;
            }
            owningType.setOpen(owningType.isOpen() || baseType.isOpen());
        }
    }

    private void processUnion(String targetNamespace, String defaultNamespace, String sdoTypeName, Union union, SDOType type) {
        if (union != null) {
            java.util.List allMemberTypes = union.getAllMemberTypes();
            String firstInstanceClassName = null;
            for (int i = 0; i < allMemberTypes.size(); i++) {
                String nextMemberType = (String) allMemberTypes.get(i);
                SDOType typeForMemberType = getTypeForName(targetNamespace, defaultNamespace, nextMemberType);
                QName baseQName = this.getQNameForString(defaultNamespace, nextMemberType);
                if(!typeForMemberType.isFinalized() && baseQName.getNamespaceURI().equals(targetNamespace)) {
                    SimpleType baseSimpleType = (SimpleType) rootSchema.getTopLevelSimpleTypes().get(baseQName.getLocalPart());
                    processSimpleType(targetNamespace, defaultNamespace, baseQName.getLocalPart(), baseSimpleType);
                }
                if (i == 0) {
                    firstInstanceClassName = typeForMemberType.getInstanceClassName();
                    if (firstInstanceClassName == null) {
                        break;
                    }
                } else {
                    String nextClassName = typeForMemberType.getInstanceClassName();
                    if (!firstInstanceClassName.equals(nextClassName)) {
                        type.setInstanceClass(java.lang.Object.class);
                        return;
                    }
                }

            }
            if (firstInstanceClassName != null) {
                type.setInstanceClassName(firstInstanceClassName);
            } else {
                type.setInstanceClass(java.lang.Object.class);
            }
        }
    }

    private boolean addNextNamespaceResolver(Map attributesMap) {
        NamespaceResolver nr = new NamespaceResolver();
        Iterator iter = attributesMap.keySet().iterator();
        while (iter.hasNext()) {
            QName key = (QName) iter.next();
            if (key.getNamespaceURI().equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
                String value = (String) attributesMap.get(key);
                String prefix = key.getLocalPart();
                int index = prefix.indexOf(':');
                if (index > -1) {
                    prefix = prefix.substring(index + 1, prefix.length());
                }
                nr.put(prefix, value);
            }
        }
        if (nr.getPrefixes().hasMoreElements()) {
            namespaceResolvers.add(nr);
            return true;
        }
        return false;
    }

    private void processList(String targetNamespace, String defaultNamespace, String sdoTypeName, List list, SDOType type) {
        if (list != null) {
            type.setXsdList(true);
            type.setInstanceClass(ClassConstants.List_Class);
        }
    }

    private Type processBaseType(String targetNamespace, String defaultNamespace, SDOType owningType, String qualifiedName, boolean simpleContentExtension, Restriction restriction) {
        if (qualifiedName == null) {
            return null;
        }

        SDOType baseType = getSDOTypeForName(targetNamespace, defaultNamespace, qualifiedName);
        QName baseQName = getQNameForString(defaultNamespace, qualifiedName);

        if(!baseType.isFinalized() && baseQName.getNamespaceURI().equals(targetNamespace)) {
            if(baseType.isDataType()) {
                SimpleType baseSimpleType = (SimpleType) rootSchema.getTopLevelSimpleTypes().get(baseQName.getLocalPart());
                processGlobalSimpleType(targetNamespace, defaultNamespace, baseSimpleType);
            } else {
                ComplexType baseComplexType = (ComplexType) rootSchema.getTopLevelComplexTypes().get(baseQName.getLocalPart());
                processGlobalComplexType(targetNamespace, defaultNamespace, baseComplexType);
            }
        }

        // When the XSD type is one of the following, and there are facets (maxInclusive,
        // maxExclusive) constraining the range to be within the range of int then the
        // Java instance class is int
        if (baseQName.equals(XMLConstants.INTEGER_QNAME) ||
                baseQName.equals(SDOConstants.POSITIVEINTEGER_QNAME) ||
                baseQName.equals(SDOConstants.NEGATIVEINTEGER_QNAME) ||
                baseQName.equals(SDOConstants.NONPOSITIVEINTEGER_QNAME) ||
                baseQName.equals(SDOConstants.NONNEGATIVEINTEGER_QNAME) ||
                baseQName.equals(XMLConstants.LONG_QNAME) ||
                baseQName.equals(SDOConstants.UNSIGNEDLONG_QNAME)) {

            boolean alreadySet = false;
            String value = restriction.getMaxInclusive();
            if (value != null) {
                if (Integer.parseInt(value) <= Integer.MAX_VALUE) {
                    baseType = getTypeForXSDQName(XMLConstants.INT_QNAME);
                    alreadySet = true;
                }
            }
            // if maxInclusive was processed, no need to handle maxExclusive
            if (!alreadySet) {
                value = restriction.getMaxExclusive();
                if (value != null) {
                    if (Integer.parseInt(value) < Integer.MAX_VALUE) {
                        baseType = getTypeForXSDQName(XMLConstants.INT_QNAME);
                    }
                }
            }
        }

        processBaseType(baseType, targetNamespace, defaultNamespace, owningType, qualifiedName, simpleContentExtension);
        return baseType;
    }

    private void processBaseType(SDOType baseType, String targetNamespace, String defaultNamespace, SDOType owningType, String qualifiedName, boolean simpleContentExtension) {
        if (simpleContentExtension && baseType.isDataType()) {
            if (owningType != null) {
                SDOProperty prop = new SDOProperty(aHelperContext);
                prop.setName("value");
                prop.setType(baseType);
                prop.setValueProperty(true);
                prop.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.TRUE);
                owningType.addDeclaredProperty(prop);
                prop.buildMapping(null, -1);
                prop.setFinalized(true);

            }
            return;
        }

        java.util.List<Type> baseTypes = new ArrayList<Type>();
        baseTypes.add(baseType);

        if (owningType != null) {
            if (owningType.isDataType()) {
                owningType.setInstanceClassName(baseType.getInstanceClassName());
                if (baseType.getInstanceClass() != null) {
                    owningType.setInstanceClass(baseType.getInstanceClass());
                }

                QName baseQName = getQNameForString(defaultNamespace, qualifiedName);
                if ((baseQName.equals(XMLConstants.BASE_64_BINARY_QNAME)) || (baseQName.equals(XMLConstants.HEX_BINARY_QNAME)) || (baseQName.equals(XMLConstants.DATE_QNAME)) || (baseQName.equals(XMLConstants.TIME_QNAME))
                        || (baseQName.equals(XMLConstants.DATE_TIME_QNAME))) {
                    owningType.setXsdType(baseQName);
                }
            }

            if (!owningType.getBaseTypes().contains(baseType)) {
                owningType.addBaseType(baseType);
            }
        }
    }

    private void processTypeDef(String targetNamespace, String defaultNamespace, SDOType owningType, TypeDefParticle typeDefParticle) {
        if (maxOccursGreaterThanOne(typeDefParticle.getMaxOccurs())) {
            if (!owningType.isSequenced() && shouldBeSequenced(typeDefParticle)) {
                owningType.setSequenced(true);
            }
        }
    }

    private boolean shouldBeSequenced(TypeDefParticle typeDefParticle) {
        java.util.List elements = typeDefParticle.getElements();
        if ((elements != null) && (elements.size() > 1)) {
            return true;
        }
        if (typeDefParticle instanceof Sequence) {
            java.util.List allItems = ((Sequence) typeDefParticle).getOrderedElements();
            for (int i = 0; i < allItems.size(); i++) {
                Object nextItem = allItems.get(i);
                if (nextItem instanceof TypeDefParticle) {
                    boolean sequenced = shouldBeSequenced((TypeDefParticle) nextItem);
                    if (sequenced) {
                        return true;
                    }
                }
            }
        } else if (typeDefParticle instanceof Choice) {
            java.util.List allItems = ((Choice) typeDefParticle).getOrderedElements();
            for (int i = 0; i < allItems.size(); i++) {
                Object nextItem = allItems.get(i);
                if (nextItem instanceof TypeDefParticle) {
                    boolean sequenced = shouldBeSequenced((TypeDefParticle) nextItem);
                    if (sequenced) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private void processAny(String targetNamespace, String defaultNamespace, Any any, SDOType owningType, TypeDefParticle typeDefParticle) {
        if (any == null) {
            return;
        }

        if (((NestedParticle) typeDefParticle).hasAny()) {
            owningType.setOpen(true);
            owningType.setSequenced(true);
        }

    }

    private void processGlobalElements(Schema schema) {
        Collection elements = schema.getTopLevelElements().values();
        if (elements == null) {
            return;
        }
        Iterator elementsIter = elements.iterator();
        while (elementsIter.hasNext()) {
            Element nextElement = (Element) elementsIter.next();
            String targetNamespace = schema.getTargetNamespace();
            if(null == targetNamespace) {
                targetNamespace = "";
            }
            processGlobalElement(targetNamespace, schema.getDefaultNamespace(), nextElement);
        }
        //process substitution groups after properties have been created for all elements
        processSubstitutionGroups(elements, schema.getTargetNamespace(), schema.getDefaultNamespace());
    }

    private void processGlobalElement(String targetNamespace, String defaultNamespace, Element element) {
        if (element.getName() != null) {
            if(!returnAllTypes && null != aHelperContext.getXSDHelper().getGlobalProperty(targetNamespace, element.getName(), true)) {
                return;
            }
            QName qname = new QName(targetNamespace, element.getName());
            Object processed = processedElements.get(qname);

            if (processed == null) {
                SDOType elementType = processElement(targetNamespace, defaultNamespace, null, null, element, true, true);
                processedElements.put(qname, element);
                if(null != elementType && !getGeneratedTypes().containsKey(elementType.getQName())) {
                    getGeneratedTypes().put(elementType.getQName(), elementType);
                    anonymousTypes.remove(elementType);
                }
            }
        } else {
            processElement(targetNamespace, defaultNamespace, null, null, element, true, true);
        }
    }

    private SDOType processElement(String targetNamespace, String defaultNamespace, SDOType owningType, TypeDefParticle typeDefParticle, Element element, boolean isGlobal, boolean isMany) {
        SDOType type = null;
        boolean addedNR = addNextNamespaceResolver(element.getAttributesMap());

        ComplexType complexType = element.getComplexType();
        boolean qualified = true;
        if (!isGlobal) {
            qualified = rootSchema.isElementFormDefault();
        }
        if (!isMany && maxOccursGreaterThanOne(element.getMaxOccurs())) {
            isMany = true;
        }

        if (complexType != null) {
            type = processComplexType(targetNamespace, defaultNamespace, element.getName(), complexType);
            type.setXsdLocalName(element.getName());
            type.setXsd(true);
            processSimpleElement(targetNamespace, defaultNamespace, owningType, type, typeDefParticle, element, qualified, isGlobal, isMany);
        } else if (element.getSimpleType() != null) {
            type = processSimpleType(targetNamespace, defaultNamespace, element.getName(), element.getSimpleType());
            type.setXsdLocalName(element.getName());
            type.setXsd(true);
            processSimpleElement(targetNamespace, defaultNamespace, owningType, type, typeDefParticle, element, qualified, isGlobal, isMany);
        } else {
            processSimpleElement(targetNamespace, defaultNamespace, owningType, null, typeDefParticle, element, qualified, isGlobal, isMany);
        }
        if (addedNR) {
            namespaceResolvers.remove(namespaceResolvers.size() - 1);
        }
        return type;
    }

    private void processSimpleElement( //
            String targetNamespace,//
            String defaultNamespace,//
            SDOType owningType,//
            SDOType sdoPropertyType,//
            TypeDefParticle typeDefParticle,//
            Element element,//
            boolean isQualified,//
            boolean isGlobal,//
            boolean isMany) {
        if (element == null) {
            return;
        }

        String manyValue = (String) element.getAttributesMap().get(SDOConstants.SDOXML_MANY_QNAME);
        if (manyValue != null) {
            isMany = Boolean.parseBoolean(manyValue);
        }

        SDOProperty p = null;
        String typeName = null;
        String mappingUri = null;
        if (typeDefParticle != null) {
            mappingUri = owningType.getURI();
        }

        if (element.getRef() != null) {
            String ref = element.getRef();
            String localName = null;
            String uri = null;

            int index = ref.indexOf(':');
            if (index != -1) {
                String prefix = ref.substring(0, index);
                localName = ref.substring(index + 1, ref.length());
                uri = getURIForPrefix(prefix);
            } else {
                localName = ref;
                uri = defaultNamespace;
            }

            Property lookedUp = owningType.getProperty(localName);
            if (lookedUp != null) {
                if (inRestriction) {
                    return;
                }
                updateCollisionProperty(owningType, (SDOProperty) lookedUp);
            } else {
                SDOProperty theProp = new SDOProperty(aHelperContext);
                theProp.setName(localName);

                theProp.setGlobal(false);
                theProp.setContainment(true);
                theProp.setXsd(true);
                theProp.setMany(isMany);
                theProp.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.TRUE);
                if (element.getAnnotation() != null) {
                    java.util.List doc = element.getAnnotation().getDocumentation();
                    if (doc != null) {
                        theProp.setInstanceProperty(SDOConstants.DOCUMENTATION_PROPERTY, doc);
                    }
                }

                owningType.addDeclaredProperty(theProp);

                GlobalRef globalRef = new GlobalRef();
                globalRef.setProperty(theProp);

                globalRef.setIsElement(true);
                globalRef.setOwningType(owningType);
                globalRef.setUri(uri);
                globalRef.setLocalName(localName);
                addGlobalRef(globalRef);
            }
            return;
        } else {
            if (isGlobal) {
                SDOProperty lookedUpProp = getExistingGlobalProperty(targetNamespace, element.getName(), true);
                if (lookedUpProp != null && lookedUpProp.isFinalized()) {
                    return;
                }
            }
            p = createNewProperty(targetNamespace, element.getName(), isQualified, isGlobal, true, element.isNillable(), element.getAnnotation());
            if (element.getAnnotation() != null) {
                p.setAppInfoElements(element.getAnnotation().getAppInfo());
            }

            if (element.getType() != null) {
                typeName = element.getType();
                p.setName(element.getName());
                QName qname = getQNameForString(defaultNamespace, typeName);
                if (isGlobal) {
                    // only process the root schema's global items if qname uri == target namespace
                    if (qname.getNamespaceURI().equals(targetNamespace)) {
                        //if type is found set it other wise process new type
                        processGlobalItem(targetNamespace, defaultNamespace, qname.getLocalPart());
                    }
                }

                if ((qname.equals(XMLConstants.QNAME_QNAME)) || (qname.equals(XMLConstants.BASE_64_BINARY_QNAME)) || (qname.equals(XMLConstants.HEX_BINARY_QNAME)) || (qname.equals(XMLConstants.DATE_QNAME)) || (qname.equals(XMLConstants.TIME_QNAME)) || (qname.equals(XMLConstants.DATE_TIME_QNAME))) {
                    p.setXsdType(qname);
                }

                String mimeType = (String) element.getAttributesMap().get(SDOConstants.XML_MIME_TYPE_QNAME);
                if (mimeType != null) {
                    p.setInstanceProperty(SDOConstants.MIME_TYPE_PROPERTY, mimeType);
                }
                String mimeTypePropName = (String) element.getAttributesMap().get(SDOConstants.XML_MIME_TYPE_PROPERTY_QNAME);
                if (mimeTypePropName != null) {
                    p.setInstanceProperty(SDOConstants.MIME_TYPE_PROPERTY_PROPERTY, mimeTypePropName);
                }

                sdoPropertyType = getSDOTypeForName(targetNamespace, defaultNamespace, typeName);
                if(!sdoPropertyType.isFinalized() && qname.getNamespaceURI().equals(targetNamespace)) {
                    if(sdoPropertyType.isDataType()) {
                        SimpleType baseSimpleType = (SimpleType) rootSchema.getTopLevelSimpleTypes().get(qname.getLocalPart());
                        processGlobalSimpleType(targetNamespace, defaultNamespace, baseSimpleType);
                    }
                }

                if ((p.getXsdType() == null) && (sdoPropertyType.getXsdType() != null)) {
                    p.setXsdType(sdoPropertyType.getXsdType());
                }

                if (sdoPropertyType.isDataType()) {
                    p.setContainment(false);
                }
            } else if (element.getComplexType() != null) {
                typeName = element.getName();
                p.setName(element.getComplexType().getNameOrOwnerName());
            } else if (element.getSimpleType() != null) {
                typeName = element.getName();
                p.setName(element.getName());
                if (sdoPropertyType.isDataType()) {
                    p.setContainment(false);
                }
            } else {
                //we assume the xsd type to be any simple type
                p.setName(element.getName());
                sdoPropertyType = ((SDOTypeHelper) aHelperContext.getTypeHelper()).getSDOTypeFromXSDType(SDOConstants.ANY_TYPE_QNAME);
            }
        }
        sdoPropertyType = processSimpleComponentAnnotations(owningType, element, p, targetNamespace, defaultNamespace, sdoPropertyType);

        p.setType(sdoPropertyType);
        setDefaultValue(p, element);

        p.setMany(isMany);

        if (p.getType().isChangeSummaryType()) {
            p.setReadOnly(true);
        }

        if (typeDefParticle != null) {
            updateOwnerAndBuildMapping(owningType, p, defaultNamespace, targetNamespace, element, typeName, mappingUri);
        }
        if (isGlobal) {
            //we have a global element
            addRootElementToDescriptor(p, targetNamespace, element.getName());
        }
        p.setFinalized(true);
    }

    private SDOProperty processRef(GlobalRef globalRef) {
        boolean isElement = globalRef.isElement();
        SDOProperty p = null;

        SDOProperty refProp = getExistingGlobalProperty(globalRef.getUri(), globalRef.getLocalName(), isElement);

        if (refProp != null && refProp.isFinalized()) {
            p = (SDOProperty) globalRef.getProperty();
            p.setValueProperty(refProp.isValueProperty());
            p.setNullable(refProp.isNullable());
            p.setName(refProp.getName());
            p.setXsdLocalName(refProp.getXsdLocalName());
            p.setNamespaceQualified(refProp.isNamespaceQualified());
            if (refProp.hasAliasNames()) {
                p.setAliasNames(refProp.getAliasNames());
            }
            p.setDefault(refProp.getDefault());
            p.setSubstitutable(refProp.isSubstitutable());
            p.setSubstitutableElements(refProp.getSubstitutableElements());

            if (p.getType() == null) {
                p.setType(refProp.getType());
                if (refProp.getType().isDataType()) {
                    p.setContainment(false);
                }
            }
            p.setOpposite(refProp.getOpposite());
            p.setReadOnly(refProp.isReadOnly());
            p.setXsd(refProp.isXsd());
            p.setAppInfoElements(refProp.getAppInfoElements());

            int index = ((SDOProperty) globalRef.getProperty()).getIndexInDeclaredProperties();
            p.buildMapping(globalRef.getUri(), index);
            p.setFinalized(true);
        } else {
            if (isImportProcessor) {
                p = new SDOProperty(aHelperContext);
                p.setGlobal(true);
                p.setUri(globalRef.getUri());
                p.setName(globalRef.getLocalName());
                QName qname = new QName(globalRef.getUri(), globalRef.getLocalName());
                if (isElement) {
                    p.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.TRUE);
                    getGeneratedGlobalElements().put(qname, p);
                } else {
                    getGeneratedGlobalAttributes().put(qname, p);
                }
            } else {
                throw SDOException.referencedPropertyNotFound(globalRef.getUri(), globalRef.getLocalName());
            }
        }
        return p;
    }

    private void updateCollisionProperty(SDOType owningType, SDOProperty p) {
        owningType.setSequenced(true);
        SDOType baseType = owningType;
        while (baseType.isSubType()) {
            baseType = (SDOType) baseType.getBaseTypes().get(0);
            baseType.setSequenced(true);
        }
        p.setNameCollision(true);
        p.setType(SDOConstants.SDO_OBJECT);
        p.setContainment(true);
        p.setMany(true);
        p.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.TRUE);
    }

    private SDOProperty createNewProperty(String targetNamespace, String xsdLocalName, boolean isQualified, boolean isGlobal, boolean isElement, boolean isNillable, Annotation annotation) {
        SDOProperty p = null;
        if (isGlobal) {
            p = getExistingGlobalProperty(targetNamespace, xsdLocalName, isElement);
        }
        if (p == null) {
            p = new SDOProperty(aHelperContext);
        }
        p.setGlobal(isGlobal);
        p.setXsd(true);
        p.setNullable(isNillable);
        if (isElement) {
            p.setInstanceProperty(SDOConstants.XMLELEMENT_PROPERTY, Boolean.TRUE);
        }
        p.setXsdLocalName(xsdLocalName);
        p.setNamespaceQualified(isQualified);
        p.setContainment(true);
        if (isGlobal) {
            QName qname = new QName(targetNamespace, xsdLocalName);
            if (isElement) {
                getGeneratedGlobalElements().put(qname, p);
            } else {
                getGeneratedGlobalAttributes().put(qname, p);
            }
        }

        if (annotation != null) {
            java.util.List documentation = annotation.getDocumentation();
            if ((documentation != null) && (documentation.size() > 0)) {
                p.setInstanceProperty(SDOConstants.DOCUMENTATION_PROPERTY, documentation);
            }
        }

        return p;
    }

    private void addRootElementToDescriptor(SDOProperty p, String targetNamespace, String xsdName) {
        if (!p.getType().isDataType()) {
            String prefix = null;
            if(targetNamespace != null && !XMLConstants.EMPTY_STRING.equals(targetNamespace)) {
                NamespaceResolver nr = p.getType().getXmlDescriptor().getNamespaceResolver();
                if (nr != null) {
                    prefix = nr.resolveNamespaceURI(targetNamespace);
                    if(null == prefix) {
                        prefix = nr.generatePrefix();
                        nr.put(prefix, targetNamespace);
                    }
                }
            }
            if ((prefix == null) || prefix.equals(SDOConstants.EMPTY_STRING)) {
                p.getType().getXmlDescriptor().addRootElement(xsdName);
            } else {
                p.getType().getXmlDescriptor().addRootElement(prefix + //
                        SDOConstants.SDO_XPATH_NS_SEPARATOR_FRAGMENT + xsdName);
            }
        } else {
            // Types from Schema: isDataType() == true so:
            //   - find the SDOWrapperType from TypeHelper's WrappersHashMap
            //   - set the root element name on it
            //   - add the descriptor to XMLContext's DescriptorsByQName map

            // See also: SDOTypeHelperDelegate:defineOpenContentProperty

            SDOTypeHelper typeHelper = (SDOTypeHelper) aHelperContext.getTypeHelper();

            SDOWrapperType wrapperType = (SDOWrapperType) typeHelper.getWrappersHashMap().get(p.getType().getQName());

            XMLDescriptor d = wrapperType.getXmlDescriptor(p.getXsdType());
            if (wrapperType != null) {
                d.addRootElement(xsdName);

                QName descriptorQname = new QName(targetNamespace, xsdName);
                ((SDOXMLHelper) aHelperContext.getXMLHelper()).getXmlContext().addDescriptorByQName(descriptorQname, d);
            }
        }
    }

    private void updateOwnerAndBuildMapping(SDOType owningType, SDOProperty p, String defaultNamespace, String targetNamespace, SimpleComponent simpleComponent, String typeName, String mappingUri) {
        boolean buildMapping = true;
        Property lookedUp = owningType.getProperty(p.getName());

        if (lookedUp != null) {
            p = (SDOProperty) lookedUp;
            if (inRestriction) {
                return;
            }
            updateCollisionProperty(owningType, p);
        } else {
            owningType.addDeclaredProperty(p);
        }

        QName xsdType = getQNameForString(defaultNamespace, typeName);

        if ((xsdType != null) && xsdType.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
            if (xsdType.getLocalPart().equals(SDOConstants.ID)) {
                owningType.setInstanceProperty(SDOConstants.ID_PROPERTY, p.getName());
            } else if (xsdType.getLocalPart().equals(SDOConstants.IDREF)) {
                p.setContainment(false);
                String propertyTypeValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_PROPERTYTYPE_QNAME);
                if (propertyTypeValue != null) {
                    buildMapping = false;
                }
            } else if (xsdType.getLocalPart().equals(SDOConstants.IDREFS)) {
                p.setContainment(false);
                String propertyTypeValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_PROPERTYTYPE_QNAME);
                if (propertyTypeValue != null) {
                    buildMapping = false;
                    p.setMany(true);
                } else {
                    p.setMany(false);
                }
            }
        }

        if (buildMapping) {
            p.buildMapping(mappingUri);
        }
    }

    private void setDefaultValue(SDOProperty p, SimpleComponent sc) {
        if (sc.getFixed() != null) {
            Object convertedValue = convertDefaultValue(p.getType(), sc.getFixed());
            p.setDefault(convertedValue);
        } else if (sc.getDefaultValue() != null) {
            Object convertedValue = convertDefaultValue(p.getType(), sc.getDefaultValue());
            p.setDefault(convertedValue);
        } else {
            if (p.getType().getQName().equals(SDOConstants.SDO_STRING.getQName()) && sc.isSetDefaultValue()) {
                p.setDefault("");
            }
        }
    }

    private Object convertDefaultValue(Type type, String stringValue) {
        if (type != null) {
            Class javaClass = ((SDOTypeHelper) aHelperContext.getTypeHelper()).getJavaWrapperTypeForSDOType(type);
            if (javaClass != null) {
                Object objectValue = ((SDODataHelper) aHelperContext.getDataHelper()).convertFromStringValue(stringValue, javaClass);
                return objectValue;
            }
        }
        return stringValue;
    }

    private void processSimpleAttribute(String targetNamespace, String defaultNamespace, SDOType owningType, Attribute attribute, boolean isGlobal, boolean isQualified, SDOType sdoPropertyType) {
        if (attribute == null) {
            return;
        }

        SDOProperty p = null;

        String typeName = null;
        String mappingUri = null;
        if (owningType != null) {
            mappingUri = owningType.getURI();
        }
        if (attribute.getRef() != null) {
            String ref = attribute.getRef();

            String localName = null;
            String uri = null;

            int index = ref.indexOf(':');
            if (index != -1) {
                String prefix = ref.substring(0, index);
                localName = ref.substring(index + 1, ref.length());
                uri = getURIForPrefix(prefix);
            } else {
                localName = ref;
                uri = defaultNamespace;
            }

            Property lookedUp = owningType.getProperty(localName);
            if (lookedUp != null) {
                if (inRestriction) {
                    return;
                }
                updateCollisionProperty(owningType, (SDOProperty) lookedUp);
            } else {
                SDOProperty theProp = new SDOProperty(aHelperContext);
                SDOProperty lookedUpProp = getExistingGlobalProperty(uri, localName, false);
                if (lookedUpProp != null) {
                    theProp.setNamespaceQualified(lookedUpProp.isNamespaceQualified());
                    theProp.setUri(uri);
                    theProp.setType(lookedUpProp.getType());
                }
                theProp.setName(localName);
                theProp.setGlobal(false);
                theProp.setContainment(false);
                theProp.setXsd(true);
                theProp.setMany(false);
                if (attribute.getAnnotation() != null) {
                    java.util.List doc = attribute.getAnnotation().getDocumentation();
                    if (doc != null) {
                        theProp.setInstanceProperty(SDOConstants.DOCUMENTATION_PROPERTY, doc);
                    }
                }
                theProp.setFinalized(true);
                GlobalRef globalRef = new GlobalRef();
                globalRef.setProperty(theProp);
                owningType.addDeclaredProperty(theProp);

                globalRef.setIsElement(false);
                globalRef.setOwningType(owningType);
                globalRef.setUri(uri);
                globalRef.setLocalName(localName);
                addGlobalRef(globalRef);
            }
            return;

        } else {
            if (isGlobal) {
                SDOProperty lookedUpProp = getExistingGlobalProperty(targetNamespace, attribute.getName(), false);
                if (lookedUpProp != null && lookedUpProp.isFinalized()) {
                    return;
                }
            }

            p = createNewProperty(targetNamespace, attribute.getName(), isQualified, isGlobal, false, false, attribute.getAnnotation());
            if (attribute.getAnnotation() != null) {
                p.setAppInfoElements(attribute.getAnnotation().getAppInfo());
            }

            typeName = attribute.getType();
            if (typeName != null) {
                p.setName(attribute.getName());
                QName qname = getQNameForString(defaultNamespace, typeName);
                if (isGlobal) {
                    //if type is found set it other wise process new type
                    processGlobalItem(targetNamespace, defaultNamespace, typeName);
                }
                if ((qname.equals(XMLConstants.QNAME_QNAME)) || (qname.equals(XMLConstants.BASE_64_BINARY_QNAME)) || (qname.equals(XMLConstants.HEX_BINARY_QNAME)) || (qname.equals(XMLConstants.DATE_QNAME)) || (qname.equals(XMLConstants.TIME_QNAME)) || (qname.equals(XMLConstants.DATE_TIME_QNAME))) {
                    p.setXsdType(qname);
                }
                sdoPropertyType = getSDOTypeForName(targetNamespace, defaultNamespace, typeName);
                if(!sdoPropertyType.isFinalized() && qname.getNamespaceURI().equals(targetNamespace)) {
                    if(sdoPropertyType.isDataType()) {
                        SimpleType baseSimpleType = (SimpleType) rootSchema.getTopLevelSimpleTypes().get(qname.getLocalPart());
                        processGlobalSimpleType(targetNamespace, defaultNamespace, baseSimpleType);
                    }
                }
                if ((p.getXsdType() == null) && (sdoPropertyType.getXsdType() != null)) {
                    p.setXsdType(sdoPropertyType.getXsdType());
                }
            } else if (attribute.getSimpleType() != null) {
                p.setName(attribute.getName());
                typeName = attribute.getName();
            } else {
                p.setName(attribute.getName());
                sdoPropertyType = ((SDOTypeHelper) aHelperContext.getTypeHelper()).getSDOTypeFromXSDType(SDOConstants.ANY_TYPE_QNAME);
            }
        }
        sdoPropertyType = processSimpleComponentAnnotations(owningType, attribute, p, targetNamespace, defaultNamespace, sdoPropertyType);
        p.setType(sdoPropertyType);
        p.setContainment(false);
        setDefaultValue(p, attribute);

        if (p.getType().isChangeSummaryType()) {
            p.setReadOnly(true);
        }

        if (owningType != null) {
            updateOwnerAndBuildMapping(owningType, p, defaultNamespace, targetNamespace, attribute, typeName, mappingUri);
        }
        p.setFinalized(true);
    }

    private SDOType processSimpleComponentAnnotations(SDOType owningType, SimpleComponent simpleComponent, SDOProperty p, String targetNamespace, String defaultNamespace, SDOType sdoPropertyType) {
        //aliasName annotation
        String aliasNamesValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_ALIASNAME_QNAME);
        if (aliasNamesValue != null) {
            XMLConversionManager xmlConversionManager = ((SDOXMLHelper) aHelperContext.getXMLHelper()).getXmlConversionManager();
            java.util.List names = (java.util.List) xmlConversionManager.convertObject(aliasNamesValue, java.util.List.class);
            p.setAliasNames(names);
        }

        //readOnly annotation
        String readOnlyValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_READONLY_QNAME);
        if (readOnlyValue != null) {
            p.setReadOnly(Boolean.parseBoolean(readOnlyValue));
        }

        //dataType annotation
        String dataTypeValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_DATATYPE_QNAME);
        if (dataTypeValue != null) {
            QName xsdQName = ((SDOTypeHelper) aHelperContext.getTypeHelper()).getXSDTypeFromSDOType(sdoPropertyType);
            if ((xsdQName == null) && !sdoPropertyType.isDataType()) {
                xsdQName = new QName(sdoPropertyType.getURI(), sdoPropertyType.getName());
            }
            p.setXsdType(xsdQName);
            SDOType sdoType = getSDOTypeForName(targetNamespace, defaultNamespace, dataTypeValue);
            sdoPropertyType = sdoType;
            Property xmlDataTypeProperty = aHelperContext.getTypeHelper().getOpenContentProperty(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_DATATYPE);
            p.setInstanceProperty(xmlDataTypeProperty, sdoType);
        }

        //string annotation
        String stringValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_STRING_QNAME);
        if (stringValue != null) {
            QName xsdTypeQName = getQNameForString(defaultNamespace, simpleComponent.getType());
            p.setXsdType(xsdTypeQName);
            sdoPropertyType = SDOConstants.SDO_STRING;
        }

        //name annotation
        String nameValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_NAME_QNAME);
        if (nameValue != null) {
            //itemNameToSDOName.put(sdoTypeName, nameValue);
            p.setName(nameValue);
            if (p.isGlobal() && targetNamespace != null) {
                QName propertyName = new QName(targetNamespace, nameValue);
                ((SDOTypeHelper) aHelperContext.getTypeHelper()).getOpenContentProperties().put(propertyName, p);
            }
        } else {
            if (p.isGlobal() && targetNamespace != null) {
                QName propertyName = new QName(targetNamespace, p.getName());
                ((SDOTypeHelper) aHelperContext.getTypeHelper()).getOpenContentProperties().put(propertyName, p);
            }
        }

        // propertyType annotation
        String propertyTypeValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_PROPERTYTYPE_QNAME);
        if (propertyTypeValue != null) {
            String uri = targetNamespace;
            int colonIndex = propertyTypeValue.indexOf(':');
            if (colonIndex > -1) {
                String prefix = propertyTypeValue.substring(0, colonIndex);
                uri = getURIForPrefix(prefix);
            }
            NonContainmentReference nonContainmentReference = new NonContainmentReference();
            nonContainmentReference.setPropertyTypeName(propertyTypeValue);
            nonContainmentReference.setPropertyTypeURI(uri);
            nonContainmentReference.setOwningType(owningType);
            nonContainmentReference.setOwningProp(p);
            String oppositePropValue = (String) simpleComponent.getAttributesMap().get(SDOConstants.SDOXML_OPPOSITEPROPERTY_QNAME);

            nonContainmentReference.setOppositePropName(oppositePropValue);
            getNonContainmentReferences().add(nonContainmentReference);
        }

        return sdoPropertyType;
    }

    private void postProcessing() {
        int size = getNonContainmentReferences().size();
        for (int i = 0; i < size; i++) {
            NonContainmentReference nonContainmentReference = getNonContainmentReferences().get(i);
            SDOType owningType = nonContainmentReference.getOwningType();

            if (owningType != null) {
                String propertyTypeName = nonContainmentReference.getPropertyTypeName();
                String propertyTypeUri = nonContainmentReference.getPropertyTypeURI();

                SDOType oppositeType = getSDOTypeForName(propertyTypeUri, propertyTypeUri, propertyTypeName);
                if (oppositeType != null) {
                    SDOProperty owningProp = nonContainmentReference.getOwningProp();
                    if (owningProp != null) {
                        // Spec sect 9.2 (1) oppositeType.dataType must be false
                        if (oppositeType.isDataType()) {
                            throw SDOException.propertyTypeAnnotationTargetCannotBeDataTypeTrue(//
                                    oppositeType.getName(), owningProp.getName());
                        }
                        owningProp.setType(oppositeType);
                        owningProp.setContainment(false);
                        owningProp.buildMapping(owningProp.getType().getURI());
                        // Bidirectional property name
                        String oppositePropName = nonContainmentReference.getOppositePropName();
                        if (oppositePropName != null) {
                            SDOProperty prop = oppositeType.getProperty(oppositePropName);
                            owningProp.setOpposite(prop);
                            prop.setOpposite(owningProp);
                        }
                    }
                }
            }
        }

        Iterator<Type> iter = getGlobalRefs().keySet().iterator();
        while (iter.hasNext()) {
            Object nextKey = iter.next();
            java.util.List<GlobalRef> value = getGlobalRefs().get(nextKey);
            java.util.List refsToRemove = new ArrayList();
            if (value != null) {
                for (int i = 0; i < value.size(); i++) {
                    GlobalRef nextGlobalRef = value.get(i);
                    SDOProperty p = processRef(nextGlobalRef);
                    if (p.isFinalized()) {
                        refsToRemove.add(nextGlobalRef);
                    }
                }
            }
            for (int i = 0; i < refsToRemove.size(); i++) {
                value.remove(refsToRemove.get(i));
            }
        }
    }

    private void addGlobalRef(GlobalRef ref) {
        java.util.List<GlobalRef> refs = getGlobalRefs().get(ref.getOwningType());
        if (null == refs) {
            refs = new ArrayList<GlobalRef>();
            refs.add(ref);
            getGlobalRefs().put(ref.getOwningType(), refs);
        } else {
            refs.add(ref);
        }
    }

    /**
     * INTERNAL:
     * Initialize this SchemaParser by configuring the package name based on the targetNamespace.
     */
    private void initialize() {
        if (null == packageName) {
            String packageValue = (String) rootSchema.getAttributesMap().get(SDOConstants.SDOJAVA_PACKAGE_QNAME);
            if (null != packageValue) {
                packageName = packageValue;
            } else if ((null == rootSchema.getTargetNamespace()) || rootSchema.getTargetNamespace().equals(SDOConstants.EMPTY_STRING)) {
                packageName = SDOConstants.JAVA_TYPEGENERATION_NO_NAMESPACE;
            } else {
                packageName = SDOUtil.getPackageNameFromURI(rootSchema.getTargetNamespace());
            }
            packageName += SDOConstants.JAVA_PACKAGE_NAME_SEPARATOR;
        }
    }

    private SDOType createSDOTypeForName(String targetNamespace, String name, String xsdLocalName) {
        SDOType returnType = null;
        int index = name.indexOf(':');
        if (index != -1) {
            String prefix = name.substring(0, index);
            String localName = name.substring(index + 1, name.length());
            String theURI = getURIForPrefix(prefix);
            returnType = getOrCreateType(theURI, localName, xsdLocalName);
        } else {
            // returnType = getOrCreateType(targetNamespace, name, xsdLocalName);
            SDOType sdoType = new SDOType(targetNamespace, name, (SDOTypeHelper)aHelperContext.getTypeHelper());
            this.anonymousTypes.add(sdoType);
            return sdoType;
        }
        return returnType;
    }

    private SDOType getSDOTypeForName(String targetNamespace, String defaultNamespace, String name) {
        return getSDOTypeForName(targetNamespace, defaultNamespace, true, name);
    }

    private SDOType getSDOTypeForName(String targetNamespace, String defaultNamespace, boolean checkDefaultNamespace, String name) {
        int index = name.indexOf(':');
        if (index != -1) {
            String prefix = name.substring(0, index);
            String localName = name.substring(index + 1, name.length());
            String theURI = getURIForPrefix(prefix);
            QName qname = new QName(theURI, localName);
            SDOType sdoType = generatedTypesByXsdQName.get(qname);
            if(null == sdoType) {
                sdoType = ((SDOTypeHelper) aHelperContext.getTypeHelper()).getSDOTypeFromXSDType(qname);
                if (null == sdoType) {
                    sdoType = getExisitingType(theURI, localName);
                    if (null == sdoType) {
                        sdoType = findSdoType(targetNamespace, defaultNamespace, name, localName, theURI);
                    }
                }
            }
            if (null == sdoType) {
                sdoType = getOrCreateType(theURI, localName, localName);
                if (!sdoType.isFinalized()) {
                    //if it's not finalized, then it's new, so add it to the generated types map
                    getGeneratedTypes().put(new QName(sdoType.getURI(), sdoType.getName()), sdoType);
                }
            }
            return sdoType;

        } else {
            String sdoName = (String) itemNameToSDOName.get(name);
            if (sdoName != null) {
                name = sdoName;
            }

            SDOType sdoType = null;
            if (checkDefaultNamespace && (defaultNamespace != null)) {
                QName qname = new QName(defaultNamespace, name);
                sdoType = ((SDOTypeHelper) aHelperContext.getTypeHelper()).getSDOTypeFromXSDType(qname);
                if(null == sdoType) {
                    sdoType = generatedTypesByXsdQName.get(qname);
                }
            }
            if (null == sdoType) {
                sdoType = getExisitingType(targetNamespace, name);
                if (null == sdoType) {
                    return findSdoType(targetNamespace, defaultNamespace, name, name, targetNamespace);
                }
                return getOrCreateType(targetNamespace, name, name);
            }
            return sdoType;
        }
    }

    //Since types aren't registered until the end of the define call we need to check typeHelper
    //and the generatedTypesmap to see if a type already exists.  The if the type doesn't exist
    //we create a new one
    private SDOType getOrCreateType(String uri, String typeName, String xsdLocalName) {
        String lookupName = typeName;
        int index = lookupName.indexOf(':');
        if (index != -1) {
            lookupName = lookupName.substring(index + 1, lookupName.length());
        }
        SDOTypeHelper sdoTypeHelper = (SDOTypeHelper) aHelperContext.getTypeHelper();
        SDOType returnType = (SDOType) sdoTypeHelper.getType(uri, lookupName);
        if (returnType == null) {
            QName qname = new QName(uri, lookupName);
            returnType = (SDOType) getGeneratedTypes().get(qname);

            if (returnType == null) {
                QName xsdQName = new QName(uri, xsdLocalName);
                returnType = getTypeForXSDQName(xsdQName);
                if (returnType == null) {
                    returnType = new SDOType(uri, lookupName, sdoTypeHelper);
                    returnType.setXsd(true);
                    returnType.setXsdLocalName(xsdLocalName);
                } else {
                    returnType.setQName(qname);
                }
            }
        }
        return returnType;
    }

    //Since global properties aren't registered until the end of the define call we need to check XSDhelper
    //and the generatedProperties map to see if a type already exists
    private SDOProperty getExistingGlobalProperty(String uri, String localName, boolean isElement) {
        SDOProperty prop = (SDOProperty) aHelperContext.getXSDHelper().getGlobalProperty(uri, localName, isElement);
        if (prop == null) {
            QName qName = new QName(uri, localName);
            if (isElement) {
                prop = (SDOProperty) getGeneratedGlobalElements().get(qName);
            } else {
                prop = (SDOProperty) getGeneratedGlobalAttributes().get(qName);
            }
        }
        return prop;
    }

    //Since types aren't registered until the end of the define call we need to check type helper
    //and the generatedTypesmap to see if a type already exists
    private SDOType getExisitingType(String uri, String localName) {
        SDOType type = (SDOType) aHelperContext.getTypeHelper().getType(uri, localName);
        if (type == null) {
            QName qName = new QName(uri, localName);
            type = (SDOType) getGeneratedTypes().get(qName);
        }
        return type;
    }

    private SDOType findSdoType(String targetNamespace, String defaultNamespace, String qualifiedName, String localName, String theURI) {
        //need to also check imports
        SDOType type = getExisitingType(theURI, localName);

        // Do not execute the following if theURI isn't the target namespace
        if (type == null && ((theURI != null && theURI.equals(targetNamespace)) || (theURI == null && targetNamespace == null))) {
            processGlobalItem(targetNamespace, defaultNamespace, qualifiedName);
            String sdoName = (String) itemNameToSDOName.get(localName);
            if (sdoName != null) {
                localName = sdoName;
            }
            type = getExisitingType(theURI, localName);
        }
        if (null == type) {
            type = getOrCreateType(theURI, localName, localName);

            if (!type.isFinalized()) {
                //if it's not finalized, then it's new, so add it to the generated types map
                getGeneratedTypes().put(new QName(type.getURI(), type.getName()), type);
            }

        }
        return type;
    }

    public void setGeneratedTypes(Map<QName, Type> generatedTypes) {
        this.generatedTypes = generatedTypes;
    }

    public void setGeneratedGlobalElements(Map<QName, Property> generatedElements) {
        this.generatedGlobalElements = generatedElements;
    }

    public void setGeneratedGlobalAttributes(Map<QName, Property> generatedAttributes) {
        this.generatedGlobalAttributes = generatedAttributes;
    }

    public java.util.List<SDOType> getAnonymousTypes() {
        return anonymousTypes;
    }

    public void setAnonymousTypes(java.util.List<SDOType> anonymousTypes) {
        this.anonymousTypes = anonymousTypes;
    }

    public Map<QName, Type> getGeneratedTypes() {
        if (null == generatedTypes) {
            generatedTypes = new HashMap<QName, Type>();
        }
        return generatedTypes;
    }

    public Map<QName, Property> getGeneratedGlobalElements() {
        if (null == generatedGlobalElements) {
            generatedGlobalElements = new HashMap<QName, Property>();
        }
        return generatedGlobalElements;
    }

    public Map<QName, SDOType> getGeneratedTypesByXsdQName() {
        return generatedTypesByXsdQName;
    }

    public void setGeneratedTypesByXsdQName(Map<QName, SDOType> generatedTypesByXsdQName) {
        this.generatedTypesByXsdQName = generatedTypesByXsdQName;
    }

    public Map<QName, Property> getGeneratedGlobalAttributes() {
        if (null == generatedGlobalAttributes) {
            generatedGlobalAttributes = new HashMap<QName, Property>();
        }
        return generatedGlobalAttributes;
    }

    private void processSubstitutionGroups(Collection elements, String targetNamespace, String defaultNamespace) {
        Iterator elementsIter = elements.iterator();
        while (elementsIter.hasNext()) {
            Element nextElement = (Element) elementsIter.next();
            if (nextElement.getSubstitutionGroup() != null) {
                String substitutionGroup = nextElement.getSubstitutionGroup();
                String localName = null;
                String uri = null;

                int index = substitutionGroup.indexOf(':');
                if (index != -1) {
                    String prefix = substitutionGroup.substring(0, index);
                    localName = substitutionGroup.substring(index + 1, substitutionGroup.length());
                    uri = getURIForPrefix(prefix);
                } else {
                    localName = substitutionGroup;
                    uri = defaultNamespace;
                }
                SDOProperty rootProp = getExistingGlobalProperty(uri, localName, true);
                SDOProperty thisProperty = getExistingGlobalProperty(targetNamespace, nextElement.getName(), true);

                if (rootProp != null && thisProperty != null) {
                    if (rootProp.getSubstitutableElements() == null) {
                        rootProp.setSubstitutableElements(new java.util.ArrayList<SDOProperty>());
                        rootProp.setSubstitutable(true);
                    }
                    rootProp.getSubstitutableElements().add(thisProperty);
                }
            }
        }
    }

    private void processAnyAttribute(String targetNamespace, String defaultNamespace, SDOType owningType) {
        owningType.setOpen(true);
    }

    private SDOType getTypeForName(String targetNamespace, String defaultNamespace, String typeName) {
        Object value = getGeneratedTypes().get(getQNameForString(defaultNamespace, typeName));
        if (value != null) {
            return (SDOType) value;
        } else {
            String sdoName = (String) itemNameToSDOName.get(typeName);
            if (sdoName != null) {
                return getTypeForName(targetNamespace, defaultNamespace, sdoName);
            } else {
                return getSDOTypeForName(targetNamespace, defaultNamespace, false, typeName);
            }
        }
    }

    private QName getQNameForString(String defaultNamespace, String name) {
        if (null == name) {
            return null;
        }
        int index = name.indexOf(':');
        if (index != -1) {
            String prefix = name.substring(0, index);
            String localName = name.substring(index + 1, name.length());
            String theURI = getURIForPrefix(prefix);
            QName qname = new QName(theURI, localName);
            return qname;
        } else {
            QName qname = new QName(defaultNamespace, name);
            return qname;
        }
    }

    private void processGlobalItem(String targetNamespace, String defaultNamespace, String qualifiedName) {
        if (rootSchema == null) {
            return;
        }
        String localName = null;
        int index = qualifiedName.indexOf(':');
        if (index != -1) {
            localName = qualifiedName.substring(index + 1, qualifiedName.length());
        } else {
            localName = qualifiedName;
        }

        SimpleType simpleType = (SimpleType) rootSchema.getTopLevelSimpleTypes().get(localName);
        if (simpleType == null) {
            ComplexType complexType = (ComplexType) rootSchema.getTopLevelComplexTypes().get(localName);
            if (complexType == null) {
                Element element = (Element) rootSchema.getTopLevelElements().get(localName);
                if (element == null) {
                    Attribute attribute = (Attribute) rootSchema.getTopLevelAttributes().get(localName);
                    if (attribute != null) {
                        processGlobalAttribute(targetNamespace, defaultNamespace, attribute);
                    }
                } else {
                    processGlobalElement(targetNamespace, defaultNamespace, element);
                }
            } else {
                processGlobalComplexType(targetNamespace, defaultNamespace, complexType);
            }
        } else {
            processGlobalSimpleType(targetNamespace, defaultNamespace, simpleType);
        }
    }

    /**
     * Return a Schema for the given Source object.
     *
     * A SchemaResolverWrapper is created to wrap the given SchemaResolver.  The wrapper
     * will prevent schemas from being processed multiple times (such as in the case of
     * circular includes/imports)
     *
     * This method should not be called recursively if a given schema could potentially
     * and undesirably be processed multiple times (again, such as in the case of
     * circular includes/imports)
     *
     * @param xsdSource
     * @param schemaResolver the schema resolver to be used to resolve imports/includes
     * @return
     */
    public Schema getSchema(Source xsdSource, SchemaResolver schemaResolver, boolean closeStream) {
        // Create a resolver wrapper that will prevent schemas from being processed
        // multiple times (such as in the case of circular includes/imports)
        return getSchema(xsdSource, new SchemaResolverWrapper(schemaResolver), closeStream);
    }

    /**
     * Return a Schema for the given Source object.
     *
     * Since this method is called recursively, and the SchemaResolverWrapper is stateful,
     * the resolver wrapper must be created outside of this method.
     *
     * @param xsdSource
     * @param schemaResolverWrapper wraps the schema resolver to be used to resolve imports/includes
     * @return
     */
    public Schema getSchema(Source xsdSource, SchemaResolverWrapper schemaResolverWrapper, boolean closeStream) {

       xsdSource = schemaResolverWrapper.resolveSchema(xsdSource);

       XMLContext context = new XMLContext(getSchemaProject());
       XMLUnmarshaller unmarshaller = context.createUnmarshaller();
       unmarshaller.setEntityResolver(schemaResolverWrapper.getSchemaResolver());

       Schema schema = (Schema) unmarshaller.unmarshal(xsdSource);
       if(closeStream){

           closeSource(xsdSource);
       }
       //populate Imports
       java.util.List imports = schema.getImports();
       Iterator iter = imports.iterator();
       while (iter.hasNext()) {
           Import nextImport = (Import) iter.next();
           Source referencedSchema = getReferencedSchema(xsdSource, nextImport.getNamespace(), nextImport.getSchemaLocation(), schemaResolverWrapper);
           if (referencedSchema != null) {
               Schema importedSchema = getSchema(referencedSchema, schemaResolverWrapper, true);
               nextImport.setSchema(importedSchema);
            }
       }

       //populate includes
       java.util.List includes = schema.getIncludes();
       Iterator includesIter = includes.iterator();
       while (includesIter.hasNext()) {
            Include nextInclude = (Include) includesIter.next();

            Source referencedSchema = getReferencedSchema(xsdSource, schema.getTargetNamespace(), nextInclude.getSchemaLocation(), schemaResolverWrapper);
            if (referencedSchema != null) {
                Schema includedSchema = getSchema(referencedSchema, schemaResolverWrapper, true);
                nextInclude.setSchema(includedSchema);
            }
        }
        return schema;

    }

    private void closeSource(Source source){
        if(source != null && source instanceof StreamSource){
            StreamSource ss = (StreamSource)source;
            try{
                if(ss.getInputStream() != null){
                   ss.getInputStream().close();
                } else if(ss.getReader() != null){
                   ss.getReader().close();
                }

            }catch (IOException e) {
                throw SDOException.errorResolvingSchema(e);
           }
        }
    }

    private Source getReferencedSchema(Source xsdSource, String namespace, String schemaLocation, SchemaResolverWrapper schemaResolverWrapper) {
        if (namespace.equals(SDOConstants.SDOJAVA_URL) || namespace.equals(SDOConstants.SDO_URL) || namespace.equals(SDOConstants.SDOXML_URL)) {
            return null;
        }
        return schemaResolverWrapper.resolveSchema(xsdSource, namespace, schemaLocation);
    }

    public Project getSchemaProject() {
        if (schemaProject == null) {
            schemaProject = new SchemaModelProject();

        }
        return schemaProject;
    }

    public Schema getRootSchema() {
        return rootSchema;
    }

    public void setProcessImports(boolean processImports) {
        this.processImports = processImports;
    }

    public boolean isProcessImports() {
        return processImports;
    }

    public void setReturnAllTypes(boolean returnAllTypes) {
        this.returnAllTypes = returnAllTypes;
    }

    public boolean isReturnAllTypes() {
        return returnAllTypes;
    }

    private boolean maxOccursGreaterThanOne(String maxOccurs) {
        if (maxOccurs == null) {
            return false;
        }
        if (maxOccurs.equalsIgnoreCase(Occurs.UNBOUNDED)) {
            return true;
        }
        return !maxOccurs.equals(Occurs.ONE);
    }

    private String getURIForPrefix(String prefix) {
        String uri = null;

        for (int i = namespaceResolvers.size() - 1; i >= 0; i--) {
            NamespaceResolver next = namespaceResolvers.get(i);
            uri = next.resolveNamespacePrefix(prefix);
            if ((uri != null) && !uri.equals(SDOConstants.EMPTY_STRING)) {
                break;
            }
        }

        if (null == uri) {
            throw SDOException.prefixUsedButNotDefined(prefix);
        }
        return uri;
    }

    public class NonContainmentReference {
        private SDOType owningType;
        private SDOProperty owningProp;
        private String propertyTypeName;
        private String propertyTypeURI;
        private String oppositePropName;

        public void setOwningType(SDOType owningType) {
            this.owningType = owningType;
        }

        public SDOType getOwningType() {
            return owningType;
        }

        public void setOwningProp(SDOProperty owningProp) {
            this.owningProp = owningProp;
        }

        public SDOProperty getOwningProp() {
            return owningProp;
        }

        public void setPropertyTypeName(String propertyTypeName) {
            this.propertyTypeName = propertyTypeName;
        }

        public String getPropertyTypeName() {
            return propertyTypeName;
        }

        public void setPropertyTypeURI(String propertyTypeURI) {
            this.propertyTypeURI = propertyTypeURI;
        }

        public String getPropertyTypeURI() {
            return propertyTypeURI;
        }

        public void setOppositePropName(String oppositePropName) {
            this.oppositePropName = oppositePropName;
        }

        public String getOppositePropName() {
            return oppositePropName;
        }
    }

    public class GlobalRef {
        private SDOType owningType;
        private boolean isElement;
        private String uri;
        private String localName;
        private Property property;

        public void setOwningType(SDOType owningType) {
            this.owningType = owningType;
        }

        public SDOType getOwningType() {
            return owningType;
        }

        public String getUri() {
            return uri;
        }

        public void setUri(String theUri) {
            uri = theUri;
        }

        public Property getProperty() {
            return property;
        }

        public void setProperty(Property theProperty) {
            property = theProperty;
        }

        public String getLocalName() {
            return localName;
        }

        public void setLocalName(String theLocalName) {
            localName = theLocalName;
        }

        public boolean isElement() {
            return isElement;
        }

        public void setIsElement(boolean isElem) {
            isElement = isElem;
        }
    }

    private java.util.List<NonContainmentReference> getNonContainmentReferences() {
        if (null == nonContainmentReferences) {
            nonContainmentReferences = new ArrayList<NonContainmentReference>();
        }
        return nonContainmentReferences;
    }

    private Map<Type, java.util.List<GlobalRef>> getGlobalRefs() {
        if (null == globalRefs) {
            globalRefs = new HashMap<Type, java.util.List<GlobalRef>>();
        }
        return globalRefs;
    }

    public boolean isImportProcessor() {
        return isImportProcessor;
    }

    public void setIsImportProcessor(boolean isImport) {
        isImportProcessor = isImport;
    }

    private void preprocessGlobalTypes(Schema schema) {
        String targetNamespace = schema.getTargetNamespace();

        // Global Complex Types
        Collection<ComplexType> globalComplexTypes = schema.getTopLevelComplexTypes().values();
        for(ComplexType globalComplexType : globalComplexTypes) {
            QName xsdQName = new QName(targetNamespace, globalComplexType.getName());
            SDOType sdoType = preprocessComplexType(globalComplexType, schema);
            sdoType.setXsdType(xsdQName);
            generatedTypesByXsdQName.put(xsdQName, sdoType);
        }

        // Global Simple Types
        Collection<SimpleType> globalSimpleTypes = schema.getTopLevelSimpleTypes().values();
        for(SimpleType globalSimpleType : globalSimpleTypes) {
            QName xsdQName = new QName(targetNamespace, globalSimpleType.getName());
            SDOType sdoType = preprocessSimpleType(globalSimpleType, schema);
            sdoType.setXsdType(xsdQName);
            generatedTypesByXsdQName.put(xsdQName, sdoType);
        }
    }

    /**
     * Return the SDOType (new or existing) corresponding to this complex type.
     */
    private SDOType preprocessComplexType(ComplexType complexType, Schema schema) {
        String typeName = (String) complexType.getAttributesMap().get(SDOConstants.SDOXML_NAME_QNAME);
        if(null == typeName) {
            typeName = complexType.getName();
        }

        SDOTypeHelper sdoTypeHelper = (SDOTypeHelper) aHelperContext.getTypeHelper();
        String typeURI = schema.getTargetNamespace();
        SDOType sdoType = (SDOType) sdoTypeHelper.getType(typeURI, typeName);
        QName qName = new QName(schema.getTargetNamespace(), complexType.getName());

        if(null == sdoType) {
            sdoType = (SDOType)getGeneratedTypes().get(qName);
            if(sdoType == null) {
                sdoType = new SDOType(typeURI, typeName, sdoTypeHelper);
                sdoType.setXsdLocalName(complexType.getName());
                sdoType.preInitialize(packageName, namespaceResolvers);
            }
            sdoType.setXsd(true);
            if(!sdoType.getQName().equals(sdoType.getXsdType())) {
            // sdoType.setInstanceProperty(nameProperty, typeName);
            }
            getGeneratedTypesByXsdQName().put(qName, sdoType);
            getGeneratedTypes().put(sdoType.getQName(), sdoType);
        } else if(!returnAllTypes) {
            processedComplexTypes.put(qName, complexType);
        }
        return sdoType;
    }

    /**
     * Return the SDODataType (new or existing) corresponding to this simple type.
     */
    private SDODataType preprocessSimpleType(SimpleType simpleType, Schema schema) {
        String typeName = (String) simpleType.getAttributesMap().get(SDOConstants.SDOXML_NAME_QNAME);
        if(null == typeName) {
            typeName = simpleType.getName();
        }

        SDOTypeHelper sdoTypeHelper = (SDOTypeHelper) aHelperContext.getTypeHelper();
        String typeURI = schema.getTargetNamespace();
        SDODataType sdoDataType = (SDODataType) sdoTypeHelper.getType(typeURI, typeName);
        QName qName = new QName(schema.getTargetNamespace(), simpleType.getName());
        if(null == sdoDataType) {
            SDOType existingType = (SDOType)getGeneratedTypes().get(qName);
            if(null == existingType) {
                existingType = (SDOType) aHelperContext.getTypeHelper().getType(qName.getNamespaceURI(), qName.getLocalPart());
            }
            if(existingType != null && existingType.isFinalized()) {
                return (SDODataType)existingType;
            }
            sdoDataType = new SDODataType(typeURI, typeName, sdoTypeHelper);
            String instanceClassValue = (String) simpleType.getAttributesMap().get(SDOConstants.SDOJAVA_INSTANCECLASS_QNAME);
            if (instanceClassValue != null) {
                sdoDataType.setInstanceProperty(SDOConstants.JAVA_CLASS_PROPERTY, instanceClassValue);
            }

            if(existingType != null) {
                //Existing type was started in an import, but not as an instance of
                //SDODataType. Remove original type and copy referencing properties
                generatedTypes.remove(qName);
                generatedTypesByXsdQName.remove(qName);
                Iterator nonFinalizedProps = existingType.getNonFinalizedReferencingProps().iterator();
                Iterator nonFinalizedUris = existingType.getNonFinalizedMappingURIs().iterator();
                while(nonFinalizedProps.hasNext()) {
                    SDOProperty next = (SDOProperty)nonFinalizedProps.next();
                    next.setType(sdoDataType);
                    sdoDataType.getNonFinalizedReferencingProps().add(next);
                    sdoDataType.getNonFinalizedMappingURIs().add(nonFinalizedUris.next());
                }
                if(anonymousTypes.contains(existingType)) {
                  anonymousTypes.remove(existingType);
                }
            }
            sdoDataType.setXsdLocalName(simpleType.getName());
            sdoDataType.setXsd(true);
            if(!sdoDataType.getQName().equals(sdoDataType.getXsdType())) {
                // sdoDataType.setInstanceProperty(nameProperty, typeName);
            }
            generatedTypesByXsdQName.put(qName, sdoDataType);
            getGeneratedTypes().put(sdoDataType.getQName(), sdoDataType);
        } else if(!returnAllTypes) {
            processedSimpleTypes.put(qName, simpleType);
        }
        return sdoDataType;
    }

    private SDOType getTypeForXSDQName(QName xsdQName) {
        SDOType sdoType = generatedTypesByXsdQName.get(xsdQName);
        if(null == sdoType) {
            SDOTypeHelper sdoTypeHelper = (SDOTypeHelper)aHelperContext.getTypeHelper();
            sdoType = sdoTypeHelper.getSDOTypeFromXSDType(xsdQName);
        }
        return sdoType;
    }

}
