/*
         * Pass0: Collect globally (schema) scoped enumerations.
         */
        private void ParseEnumeration0(XmlSchemaSimpleType simpleType, String name, ElementsSubset es)
        {
            if (simpleType.Name == null || simpleType.Name == "")
            {
                // locally scoped simpleType enumeration on an element or attribute.  We don't care about these here.	
                return;
            }
            else
            {
                // globally scoped simpleType at the schema level -- this is what we're searching for here
                name = simpleType.Name;
            }

            if (simpleType.Content is XmlSchemaSimpleTypeRestriction)
            {
                XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content;

                for (int j = 0; j < restriction.Facets.Count; j++)
                {
                    if (restriction.Facets[j] is XmlSchemaEnumerationFacet)
                    {
                        if (!es.SimpleTypes.ContainsKey(name)) es.SimpleTypes.Add(name, name);
                        return;
                    }
                }
            }
        }
        /*
         * Pass0: Gather enumeration types
         */
        private void ParseAttributesPass0(XmlSchemaObjectCollection attributes, ElementsSubset es)
        {
            for (int i = 0; i < attributes.Count; i++)
            {
                if (attributes[i] is XmlSchemaAttributeGroupRef)
                {
                    XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)attributes[i];
                    XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)schema.AttributeGroups[attributeGroupRef.RefName];

                    ParseAttributesPass0(attributeGroup.Attributes, es);
                }
                else if (attributes[i] is XmlSchemaAttribute)
                {
                    XmlSchemaAttribute attributeRef = (XmlSchemaAttribute)attributes[i];
                    XmlSchemaAttribute attribute = (XmlSchemaAttribute)schema.Attributes[attributeRef.QualifiedName];
                    if (attribute == null) return;  //locally definied attributes -- we don't care about these

                    if (attribute.AttributeType is XmlSchemaSimpleType)
                    {
                        // build SimpleType enumeration if needed
                        XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)attribute.AttributeType;
                        ParseEnumeration0(simpleType, attribute.Name, es);
                    }
                }
            }
        }
        //********************************************************************************************
        //********************************************************************************************
        // PASS ZERO ROUTINES -- this is only used when someone uses the /E option for telling the code 
        // generator to only generate classes and types for a specific set of elements from the schema.
        // Purpose of this is to fill out the ElementsSubset referenced complexTypes and simpleTypes.
        // Point is to find just the global elements and types referenced by the passed in element list
        // and build code for those elements.  This will result in a smaller compiled assembly.
        //********************************************************************************************
        //********************************************************************************************

        /// <summary>
        /// Pass0. Collect info on classes, forward declarations, collections (ArrayList subclasses), and any local enumerations (globals have already been added).
        /// </summary>
        /// <param name="complex">Instance of a ComplexType</param>
        /// <param name="qname">QualifiedName object for schema element or schema type</param>
        private void ParseComplexTypePass0(XmlSchemaComplexType complex, String dotnetClassName, XmlQualifiedName qname, string currentNamespace, ElementsSubset es)
        {
            ArrayList childClasses = new ArrayList();

            XmlSchemaComplexType baseSchema = complex.BaseSchemaType as XmlSchemaComplexType;
            if (baseSchema != null)
            {
                if (!es.ComplexTypes.ContainsKey(baseSchema.QualifiedName.Name))
                {
                    es.ComplexTypes.Add(baseSchema.QualifiedName.Name, baseSchema.QualifiedName.Name);
                    ParseComplexTypePass0(baseSchema, baseSchema.QualifiedName.Name, baseSchema.QualifiedName, baseSchema.QualifiedName.Name, es);
                }
            }

            // Gather referenced enumeration types if any
            ParseAttributesPass0(complex.Attributes, es);

            if (complex.Particle is XmlSchemaGroupBase)
            {
                ParseGroupBasePass0((XmlSchemaGroupBase)complex.Particle, dotnetClassName, childClasses, complex.QualifiedName.Namespace, currentNamespace, es);
            }
            else if (complex.Particle is XmlSchemaGroupRef)
            {
                XmlSchemaGroup group = (XmlSchemaGroup)schema.Groups[((XmlSchemaGroupRef)complex.Particle).RefName];
                ParseGroupBasePass0(group.Particle, dotnetClassName, childClasses, complex.QualifiedName.Namespace, currentNamespace, es);
            }
            else if (complex.ContentModel is XmlSchemaSimpleContent)
            {
                XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complex.ContentModel;
                if (simpleContent.Content is XmlSchemaSimpleContentRestriction)
                {
                    XmlSchemaSimpleContentRestriction contentRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content;
                    ParseAttributesPass0(contentRestriction.Attributes, es);
                }
                else if (simpleContent.Content is XmlSchemaSimpleContentExtension)
                {
                    XmlSchemaSimpleContentExtension contentExtension = (XmlSchemaSimpleContentExtension)simpleContent.Content;
                    ParseAttributesPass0(contentExtension.Attributes, es);
                }
            }
            else if (complex.ContentModel is XmlSchemaComplexContent)
            {
                XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complex.ContentModel;
                if (complexContent.Content is XmlSchemaComplexContentRestriction)
                {
                    XmlSchemaComplexContentRestriction contentRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content;

                    if (contentRestriction.Attributes != null)
                        ParseAttributesPass0(contentRestriction.Attributes, es);

                    if (contentRestriction.Particle != null)
                    {
                        if (contentRestriction.Particle is XmlSchemaGroupBase)
                            ParseGroupBasePass0((XmlSchemaGroupBase)contentRestriction.Particle, dotnetClassName, childClasses, complex.QualifiedName.Namespace, currentNamespace, es);
                        else if (contentRestriction.Particle is XmlSchemaGroupRef)
                        {
                            XmlSchemaGroup group = (XmlSchemaGroup)schema.Groups[((XmlSchemaGroupRef)contentRestriction.Particle).RefName];
                            ParseGroupBasePass0(group.Particle, dotnetClassName, childClasses, complex.QualifiedName.Namespace, currentNamespace, es);
                        }
                    }
                }
                else if (complexContent.Content is XmlSchemaComplexContentExtension)
                {
                    XmlSchemaComplexContentExtension contentExtension = (XmlSchemaComplexContentExtension)complexContent.Content;

                    if (contentExtension.Attributes != null)
                        ParseAttributesPass0(contentExtension.Attributes, es);
                    if (contentExtension.Particle != null)
                    {
                        if (contentExtension.Particle is XmlSchemaGroupBase)
                            ParseGroupBasePass0((XmlSchemaGroupBase)contentExtension.Particle, dotnetClassName, childClasses, complex.QualifiedName.Namespace, currentNamespace, es);
                        else if (contentExtension.Particle is XmlSchemaGroupRef)
                        {
                            XmlSchemaGroup group = (XmlSchemaGroup)schema.Groups[((XmlSchemaGroupRef)contentExtension.Particle).RefName];
                            ParseGroupBasePass0(group.Particle, dotnetClassName, childClasses, complex.QualifiedName.Namespace, currentNamespace, es);
                        }
                    }
                }
            }

            for (int i = 0; i < childClasses.Count; i++)
            {
                ChildComplexType child = (ChildComplexType)childClasses[i];
                ParseComplexTypePass0(child.ComplexType, child.DotnetClassName, child.Qname, currentNamespace, es);
            }
        }
        /*
         * Pass0. Collect references to globally defined complextypes and simpletypes. 
         */
        private void ParseGroupBasePass0(XmlSchemaGroupBase groupBase, String dotnetClassName, ArrayList childClasses, string parentNamespace, string currentNamespace, ElementsSubset es)
        {
            for (int i = 0; i < groupBase.Items.Count; i++)
            {
                if (groupBase.Items[i] is XmlSchemaElement)
                {
                    XmlSchemaElement elementRef = (XmlSchemaElement)groupBase.Items[i];
                    XmlSchemaElement element = (XmlSchemaElement)schema.Elements[elementRef.QualifiedName];
                    if (element == null) element = elementRef;
                    string ns = element.QualifiedName.Namespace != "" ? element.QualifiedName.Namespace : parentNamespace;

                    if (element.ElementType is XmlSchemaComplexType && element.SchemaTypeName.Namespace != Globals.XSD_NAMESPACE)
                    {
                        XmlSchemaComplexType elementComplex = (XmlSchemaComplexType)element.ElementType;

                        // The complex type is locally defined so a child class needs to be created.  
                        if ((element == elementRef) && (schema.SchemaTypes[elementComplex.QualifiedName] == null))
                        {
                            // recure these later
                            childClasses.Add(new ChildComplexType(elementComplex, element.Name, "", ns, element.QualifiedName));
                        }

                        if ((schema.Elements[elementRef.QualifiedName] != null) && (elementComplex.Name != null && elementComplex.Name != ""))
                        {
                            // global element who's name and type are set.  Both element and complextype are named.
                            if (!es.Elements.ContainsKey(elementRef.QualifiedName.Name))
                            {
                                // add element and recure it's complextype
                                es.Elements.Add(elementRef.QualifiedName.Name, elementRef.QualifiedName.Name);
                                if (!es.ComplexTypes.ContainsKey(elementComplex.QualifiedName.Name) && !string.IsNullOrEmpty(elementComplex.QualifiedName.Name))
                                {
                                    es.ComplexTypes.Add(elementComplex.QualifiedName.Name, elementComplex.QualifiedName.Name);
                                    ParseComplexTypePass0(elementComplex, elementComplex.QualifiedName.Name, elementComplex.QualifiedName, elementComplex.QualifiedName.Namespace, es);
                                }
                            }

                        }
                        else if (elementComplex.Name != null && elementComplex.Name != "")
                        {
                            // globally defined named schema type
                            if (!es.ComplexTypes.ContainsKey(elementComplex.QualifiedName.Name))
                            {
                                es.ComplexTypes.Add(elementComplex.QualifiedName.Name, elementComplex.QualifiedName.Name);
                                ParseComplexTypePass0(elementComplex, elementComplex.QualifiedName.Name, elementComplex.QualifiedName, elementComplex.QualifiedName.Namespace, es);
                            }
                        }
                        else
                        {
                            // global element complexType -- element is named, but complex type is not
                            if (!es.Elements.ContainsKey(elementRef.QualifiedName.Name))
                            {
                                // add element and recure it's complextype
                                es.Elements.Add(elementRef.QualifiedName.Name, elementRef.QualifiedName.Name);
                                ParseComplexTypePass0(elementComplex, elementRef.QualifiedName.Name, elementRef.QualifiedName, elementRef.QualifiedName.Namespace, es);
                            }
                        }
                    }
                    else
                    {
                        // not a ComplexType

                        string xsdTypeName = element.SchemaTypeName.Name;
                        string clrTypeName = code.FrameworkTypeMapping(xsdTypeName);

                        // build SimpleType enumeration if needed
                        if (element.ElementType is XmlSchemaSimpleType)
                        {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)element.ElementType;
                            ParseEnumeration0(simpleType, element.Name, es);
                        }
                    }
                }
                else if (groupBase.Items[i] is XmlSchemaGroupRef)
                {
                    XmlSchemaGroup group = (XmlSchemaGroup)schema.Groups[((XmlSchemaGroupRef)groupBase.Items[i]).RefName];
                    ParseGroupBasePass0(group.Particle, dotnetClassName, childClasses, parentNamespace, currentNamespace, es);
                }
                else if (groupBase.Items[i] is XmlSchemaGroupBase)
                {
                    // Particle inside a particle : ie. <xsd:sequence> <xsd:choice/> </xsd:sequence>
                    ParseGroupBasePass0((XmlSchemaGroupBase)groupBase.Items[i], dotnetClassName, childClasses, parentNamespace, currentNamespace, es);
                }
            }
        }
        /// <summary>
        /// Executes the code generator.  Called from either the command line exe or the VS.NET wizard.  Only public function.
        /// </summary>
        /// <param name="xsdFile">Path to the XSD file stored on disk</param>
        /// <param name="language">Language for generated code</param>
        /// <param name="genNamespace">.NET namespace containing the generated types</param>
        /// <param name="fileName">File to be generated.  If null, namespace name is used</param>
        /// <param name="outputLocation">Location for the generated output file</param>
        /// <param name="constructRequiredSchema">Build a schema compliancy function -- MakeSchemaCompliant -- into each class</param>
        /// <param name="depthFirstTraversalHooks">Add DepthFirstTraversal hooks to fire custom DepthFirstTraversal events on each generated class</param>
        /// <param name="defaultInitialization">Set schema default values in class constructors</param>
        /// <param name="separateImportedNamespaces">Searate out imported namespaces into their own source files.  Default is all types in one file.</param>
        /// <param name="namespaceTable">Namespace map table.  Null if no imported namespaces exist</param>
        /// <param name="filenameTable">Filenames matching the namespaceTable.  Null if no imported namespaces exist -- and optional.</param>
        /// <param name="partialKeyword">put the .NET 2.0 partial keyword on every class</param>
        /// <param name="optionEElements"></param>
        /// <param name="acordLookupCodesFile">ACORD lookup codes file -- public</param>
        /// <param name="acordLookupCodesFilePrivate">ACORD lookup codes file -- private</param>
        /// <returns>result string</returns>
        public string[] Execute(string xsdFile, Language language, string genNamespace, string fileName,
            string outputLocation, bool constructRequiredSchema, bool depthFirstTraversalHooks, bool defaultInitialization,
            ref Hashtable namespaceTable, Hashtable filenameTable, bool partialKeyword, List<string> optionEElements, string acordLookupCodesFile, string acordLookupCodesFilePrivate)
        {
            FileStream schemaFile = null;

            try
            {
                schemaFile = new FileStream(xsdFile, FileMode.Open, FileAccess.Read);
                if (schemaFile == null) throw new XSDObjectGenException("Could not open the XSD schema file: " + xsdFile);

                schema = XmlSchema.Read(schemaFile, new ValidationEventHandler(ShowCompileError));
                schema.Compile(new ValidationEventHandler(ShowCompileError));

                elementFormDefault = schema.ElementFormDefault;
                attributeFormDefault = schema.AttributeFormDefault;

                if (language == Language.VB)
                {
                    code = (LanguageBase)new VBTemplate();
                }
                else if (language == Language.CS)
                {
                    code = (LanguageBase)new CSharpTemplate();
                }
                else
                {
                    throw new XSDObjectGenException(string.Format("Language {0} not supported.", language.ToString()));
                }

                if (!string.IsNullOrEmpty(acordLookupCodesFile))
                {
                    acordLookup = new XmlDocument();
                    try
                    {
                        acordLookup.Load(acordLookupCodesFile);
                    }
                    catch (Exception)
                    {
                        throw new XSDObjectGenException("Bad ACORD lookup file path or file");
                    }
                }

                if (!string.IsNullOrEmpty(acordLookupCodesFilePrivate))
                {
                    acordLookupPrivate = new XmlDocument();
                    try
                    {
                        acordLookupPrivate.Load(acordLookupCodesFilePrivate);
                    }
                    catch (Exception)
                    {
                        throw new XSDObjectGenException("Bad ACORD private codes lookup file path or file");
                    }
                }

                optionDefaultInitialization = defaultInitialization;
                optionConstructRequiredSchema = constructRequiredSchema;
                optionDepthFirstTraversalHooks = depthFirstTraversalHooks;
                LanguageBase.partialClasses = partialKeyword;
                globalComplexTypeClasses = new Hashtable();
                globalQualifiedComplexTypeClasses = new Hashtable();
                globalQualifiedAbstractTypeClasses = new Hashtable();
                enumerations = new Hashtable();
                enumerableClasses = new Hashtable();
                classesReferencingAbstractTypes = new Hashtable();
                ArrayList parentClassStack = new ArrayList();  // arraylist to collect a stack of parent owner .NET classes for  nested complexTypes 
                Globals.globalSchemaTypeTable.Clear();			// clear globals schema type table as it's a global object created at assembly load scope
                Globals.globalSeparateImportedNamespaces = false;   // means we have imported namespace and will have multiple source files
                Globals.globalClrNamespaceList.Clear();

                // Get list of all imported schemas -- to be used only if separateImportedNamespaces = true
                // Add the main xsd namespace.  If separateImportedNamespaces is false, there will be only
                //    one .net file generated with all of the types from all the xsd namespaces.  Otherwise multiple files. 
                //    First namespace in the list is the namespace for the base leaf schema -- for which code is being generated.
                ArrayList references = new ArrayList();
                if (namespaceTable != null)
                {
                    if (schema.TargetNamespace != null)
                        genNamespace = (string)namespaceTable[schema.TargetNamespace];  // in case it was changed while changing imported ns names
                    else
                        genNamespace = (string)namespaceTable[""];
                }

                if (schema.TargetNamespace != null)
                {
                    namespaces.Add(schema.TargetNamespace, references);
                    namespacesList.Add(schema.TargetNamespace);
                    xsdNsToClrNs.Add(schema.TargetNamespace, genNamespace);
                }
                else
                {
                    // targetNamespace can be null
                    namespaces.Add("", references);
                    namespacesList.Add("");
                    xsdNsToClrNs.Add("", genNamespace);
                }

                // Break down the imported namespaces if any.  There will be one .cs or .vb file generated for each xsd namespace.
                // Set the globalSelectedImportedNamespaces flag to determine if we generate just one file or many files.
                RecurseImportedNamespaces(schema, references);
                if (namespacesList.Count > 1 && namespaceTable == null)
                {
                    namespaceTable = xsdNsToClrNs;
                    return null;
                }
                else if (namespaceTable != null)
                {
                    xsdNsToClrNs = namespaceTable;
                }

                foreach (string clrNs in xsdNsToClrNs.Values)
                {
                    Globals.globalClrNamespaceList.Add(clrNs);
                }

                /*******/
                //   Walk through, prepare and build the global class collections from the xsd complexTypes 
                //   contained in the global scope -- child of the <schema> element.  Point of this stuff is 
                //   to handle all the combination of naming conflicts.
                //      Build and populate these structures
                //          globalQualifiedAbstractTypeClasses
                //          globalQualifiedComplexTypeClasses
                //          globalComplexTypeClasses
                //          globalSchemaTypeTable
                /*******/

                foreach (XmlSchemaType schemaType in schema.SchemaTypes.Values)
                {
                    if (schemaType is XmlSchemaComplexType)
                    {
                        string dotnetTypeName = CalculateUniqueTypeOrFieldName(schemaType.Name, schemaType.QualifiedName.Namespace, globalComplexTypeClasses);
                        globalComplexTypeClasses.Add(dotnetTypeName, schemaType.Name);

                        GlobalSchemaType gst = new GlobalSchemaType(schemaType.QualifiedName.Namespace, schemaType.Name, GlobalXsdType.ComplexType,
                            (string)xsdNsToClrNs[schemaType.QualifiedName.Namespace], dotnetTypeName);
                        Globals.globalSchemaTypeTable.Add(gst.XsdNamespaceAndTypeName, gst);

                        if (globalQualifiedComplexTypeClasses[schemaType.QualifiedName] == null)
                        {
                            globalQualifiedComplexTypeClasses.Add(schemaType.QualifiedName, dotnetTypeName);

                            // collect the list of types marked as abstract.  This is needed to later add XmlIncludeAttribute to their usage.
                            if (((XmlSchemaComplexType)schemaType).IsAbstract)
                            {
                                globalQualifiedAbstractTypeClasses.Add(schemaType.QualifiedName, new Hashtable());
                            }
                        }
                    }
                }
                foreach (XmlSchemaElement element in schema.Elements.Values)
                {
                    if (element.ElementType is XmlSchemaComplexType)
                    {
                        XmlSchemaComplexType complexType = (XmlSchemaComplexType)element.ElementType;

                        string dotnetTypeName = element.Name;

                        if (globalComplexTypeClasses[element.Name] == null)
                        {
                            // Each namespace can have one global schema level CT (schema type) and global schema level element WITH THE SAME NAME.
                            //  We get here assuming a complexType with the same name hasn't already been added (which will be a .NET class).
                            dotnetTypeName = CalculateUniqueTypeOrFieldName(element.Name, element.QualifiedName.Namespace, globalComplexTypeClasses);
                            globalComplexTypeClasses.Add(dotnetTypeName, element.Name);
                        }

                        GlobalSchemaType gst = new GlobalSchemaType(element.QualifiedName.Namespace, element.Name, GlobalXsdType.Element,
                                (string)xsdNsToClrNs[element.QualifiedName.Namespace], dotnetTypeName);
                        Globals.globalSchemaTypeTable.Add(gst.XsdNamespaceAndTypeName, gst);

                        if (globalQualifiedComplexTypeClasses[element.QualifiedName] == null)
                        {
                            globalQualifiedComplexTypeClasses.Add(element.QualifiedName, dotnetTypeName);
                        }
                        else
                        {
                            // Each namespace can have one global schema level CT (schema type) and global schema level element WITH THE SAME NAME.
                            //  Hence schemaType.QualifiedName == element.QualifiedName for this scenerio.  Use a special Globals.ELELENT_DELIMINATOR to flag this.
                            globalQualifiedComplexTypeClasses.Add(Globals.ELELENT_DELIMINATOR + element.QualifiedName, dotnetTypeName);
                        }
                    }
                    else if (element.ElementType is XmlSchemaSimpleType)
                    {
                        XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)element.ElementType;
                        if (IsEnumeration(simpleType))
                        {
                            GlobalSchemaType gst = new GlobalSchemaType(element.QualifiedName.Namespace, element.Name, GlobalXsdType.Enum,
                                (string)xsdNsToClrNs[element.QualifiedName.Namespace], element.Name);
                            Globals.globalSchemaTypeTable.Add(gst.XsdNamespaceAndTypeName, gst);
                        }
                    }
                }
                foreach (XmlSchemaType schemaType in schema.SchemaTypes.Values)
                {
                    if (schemaType is XmlSchemaSimpleType)
                    {
                        XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)schemaType;
                        if (IsEnumeration(simpleType))
                        {
                            GlobalSchemaType gst = new GlobalSchemaType(simpleType.QualifiedName.Namespace, simpleType.Name, GlobalXsdType.Enum,
                                (string)xsdNsToClrNs[simpleType.QualifiedName.Namespace], simpleType.Name);
                            if (Globals.globalSchemaTypeTable[gst.XsdNamespaceAndTypeName] == null)
                                Globals.globalSchemaTypeTable.Add(gst.XsdNamespaceAndTypeName, gst);
                        }
                    }
                }

                outFiles = new string[namespaces.Count];
                int iFiles = 0;

                // Walk through all of the schema namespaces and generate .net types
                for (int i = 0; i < namespacesList.Count; i++)
                {
                    /*******/
                    // Pass1: 
                    // Walk through and add collect infomation for forward declarations (where required),
                    //  collection classes, and enumerations.  The code will be added later.
                    // There are two kinds of complex types.  
                    //	1. ComplexTypes globally defined and "named" in the schema that are not tied to an XML element name.
                    //	2. Globally defined xsd:elements that are complex types and are linked to an xml element
                    // First build classes for the global types, then traverse the elements and add those types.
                    // Note: There are actually 3 different types of ComplexTypes.  The third is a locally defined
                    //  ComplexType that are not a child of <schema>.  These are collected later in the childClasses
                    //  collection.
                    /*******/

                    string ns = (string)namespacesList[i];
                    enumerations.Clear();
                    bool optionE = optionEElements != null && optionEElements.Count > 0;
                    ElementsSubset es = new ElementsSubset();

                    // Pass0.  Uses Pass0 routines.  Only used if Option E is sent in.
                    if (optionE)
                    {
                        // Handle special optionE processing.  Parse down and build the references for this element
                        foreach (XmlSchemaElement element in schema.Elements.Values)
                        {
                            if (optionEElements.Contains(element.QualifiedName.Name))
                            {
                                XmlSchemaComplexType complexType = (XmlSchemaComplexType)element.ElementType;

                                if (!es.Elements.ContainsKey(element.QualifiedName.Name))
                                {
                                    es.Elements.Add(element.QualifiedName.Name, element.QualifiedName.Name);
                                    if (!string.IsNullOrEmpty(complexType.QualifiedName.Name) && !es.ComplexTypes.ContainsKey(complexType.QualifiedName.Name))
                                        es.ComplexTypes.Add(complexType.QualifiedName.Name, complexType.QualifiedName.Name);
                                    ParseComplexTypePass0(complexType, element.QualifiedName.Name, element.QualifiedName, element.QualifiedName.Namespace, es);
                                }
                            }
                        }
                    }

                    // Pass1 officially starts here.  Uses Pass1 routines.

                    foreach (XmlSchemaType schemaType in schema.SchemaTypes.Values)
                    {
                        // Add global schema type enumerations.  Locally scoped ones will be added later during ParseComplexTypePass1.
                        if (schemaType is XmlSchemaSimpleType && (!Globals.globalSeparateImportedNamespaces || ns == schemaType.QualifiedName.Namespace))
                        {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)schemaType;
                            if (optionE && !es.SimpleTypes.ContainsKey(simpleType.Name)) continue;  // only build specific classes

                            if (IsEnumeration(simpleType))
                            {
                                string globalEnumName = ParseEnumeration1(simpleType, simpleType.Name);
                            }
                        }
                    }
                    foreach (XmlSchemaElement element in schema.Elements.Values)
                    {
                        // Add global schema element enumerations.  Locally scoped ones will be added later during ParseComplexTypePass1.
                        if (element.ElementType is XmlSchemaSimpleType && (!Globals.globalSeparateImportedNamespaces || ns == element.QualifiedName.Namespace))
                        {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)element.ElementType;
                            if (optionE && !es.SimpleTypes.ContainsKey(simpleType.Name)) continue;  // only build specific classes

                            if (IsEnumeration(simpleType))
                            {
                                string globalEnumName = ParseEnumeration1(simpleType, element.Name);
                            }
                        }
                    }

                    // now deep-dive and parse into each global schema element and type

                    foreach (XmlSchemaType schemaType in schema.SchemaTypes.Values)
                    {
                        if (schemaType is XmlSchemaComplexType && (!Globals.globalSeparateImportedNamespaces || ns == schemaType.QualifiedName.Namespace))
                        {
                            if (optionE && !es.ComplexTypes.ContainsKey(schemaType.QualifiedName.Name)) continue;  // only build specific classes

                            parentClassStack.Clear();
                            string dotnetTypeName = (string)globalQualifiedComplexTypeClasses[schemaType.QualifiedName];
                            ParseComplexTypePass1((XmlSchemaComplexType)schemaType, dotnetTypeName, parentClassStack, schemaType.QualifiedName, ns);
                        }
                    }
                    foreach (XmlSchemaElement element in schema.Elements.Values)
                    {
                        if (element.ElementType is XmlSchemaComplexType &&
                            (!Globals.globalSeparateImportedNamespaces || ns == element.QualifiedName.Namespace) &&
                            (element.SchemaTypeName.Name == null || element.SchemaTypeName.Name == ""))
                        {
                            if (optionE && !es.Elements.ContainsKey(element.QualifiedName.Name)) continue;  // only build specific classes

                            // If element.SchemaTypeName.Name is set, then this is a global element with it's type set to a schema type.  
                            //  i.e. <xs:element name="DataServiceResponse" type="DataServiceResponseType" />
                            //  This results in a simple class in code which inherits from the SchemaType and no child fields -- so don't do anything further

                            parentClassStack.Clear();
                            XmlSchemaComplexType complexType = (XmlSchemaComplexType)element.ElementType;

                            string dotnetTypeName = GlobalElementToClrMap(element.QualifiedName);
                            ParseComplexTypePass1(complexType, dotnetTypeName, parentClassStack, element.QualifiedName, ns);
                        }
                    }

                    // ****************************
                    // Start writing out code
                    // ****************************

                    FileStream classFile = null;

                    if (outputLocation == "" || outputLocation == null)
                        outFiles[iFiles] = "";
                    else if (outputLocation[outputLocation.Length - 1] == '\\')
                        outFiles[iFiles] = outputLocation;
                    else if (outputLocation[outputLocation.Length - 1] != '\\')
                        outFiles[iFiles] = outputLocation + "\\";

                    string codeFile;
                    string targetNamespace;
                    string dotnetNamespace;

                    if (i == 0 && namespacesList.Count == 1)  // no imported namespaces
                    {
                        // first namespace in the list is the main xsd namespace we're building from
                        targetNamespace = ns;
                        codeFile = genNamespace;  // this is the default filename if not overriden with /f or /z
                        dotnetNamespace = genNamespace;

                        // use "fileName" for the main xsd generated .net file, if passed in from UI
                        if (fileName != null && fileName != "")
                            codeFile = fileName;
                    }
                    else
                    {
                        // imported namespaces
                        targetNamespace = ns;
                        dotnetNamespace = (string)xsdNsToClrNs[targetNamespace];
                        codeFile = (string)xsdNsToClrNs[targetNamespace];  // this is the default filename if not overriden with /f or /z
                        if (filenameTable != null && filenameTable.Count > 0)
                            codeFile = (string)filenameTable[targetNamespace];  // /z override
                    }


                    if (language == Language.VB)
                    {
                        if (!codeFile.ToLower().EndsWith(".vb"))
                            codeFile = codeFile + ".vb";
                    }
                    else //(language == Language.CS)
                    {
                        if (!codeFile.ToLower().EndsWith(".cs"))
                            codeFile = codeFile + ".cs";
                    }

                    outFiles[iFiles] = outFiles[iFiles] + codeFile;
                    classFile = new FileStream(outFiles[iFiles], FileMode.Create);
                    outStream = new StreamWriter(classFile);

                    // Add namespace, using statement, forward declarations, and enumerations
                    string schemaFileName = schemaFile.Name;
                    int slashIndex = 0;
                    while ((slashIndex = schemaFileName.IndexOf("\\")) >= 0)
                        schemaFileName = schemaFileName.Substring(slashIndex + 1);

                    if (genNamespace == null || genNamespace == "")
                    {
                        // the VB case where explicit namespaces are not in the code
                        code.NamespaceHeaderCode(outStream, genNamespace, schemaFileName, null,
                            targetNamespace, enumerations, optionDepthFirstTraversalHooks, (ArrayList)namespaces[targetNamespace]);
                    }
                    else
                    {
                        code.NamespaceHeaderCode(outStream, dotnetNamespace, schemaFileName, null,
                            targetNamespace, enumerations, optionDepthFirstTraversalHooks, (ArrayList)namespaces[targetNamespace]);
                    }

                    // Re-add all the globally scoped enumerations to the enumerations list.  This is done again so in Pass2 we handle locally scoped
                    //  simpleType enumerations that have duplicate names.  We go through the name calculation again for duplicate enums -- as a way
                    //  to match up the enum type name (when duplicates occur) with the enum field variables.  The assumption is made that the parsing
                    //  order of Pass1 is equal to that of Pass2 -- otherwise the duplicate locally scoped enums won't match their respective
                    //  enumeration type that was collected during Pass1.  
                    //  Note that in most schemas there won't be locally scoped duplicate enumeration names -- so this really won't matter.  And if there is,
                    //  it's probably not a good schema design.
                    enumerations.Clear();  // clear enumerations list as they will be recollected to properly account for locally scoped duplicates
                    foreach (XmlSchemaType schemaType in schema.SchemaTypes.Values)
                    {
                        if (schemaType is XmlSchemaSimpleType && (!Globals.globalSeparateImportedNamespaces || ns == schemaType.QualifiedName.Namespace))
                        {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)schemaType;
                            if (optionE && !es.SimpleTypes.ContainsKey(simpleType.Name)) continue;  // only build specific classes

                            if (IsEnumeration(simpleType) && (!Globals.globalSeparateImportedNamespaces || ns == simpleType.QualifiedName.Namespace))
                                enumerations.Add(LanguageBase.ReplaceInvalidChars(simpleType.Name), "");
                        }
                    }
                    foreach (XmlSchemaElement element in schema.Elements.Values)
                    {
                        if (element.ElementType is XmlSchemaSimpleType && (!Globals.globalSeparateImportedNamespaces || ns == element.QualifiedName.Namespace))
                        {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)element.ElementType;
                            if (optionE && !es.SimpleTypes.ContainsKey(simpleType.Name)) continue;  // only build specific classes

                            if (IsEnumeration(simpleType) && (!Globals.globalSeparateImportedNamespaces || ns == element.QualifiedName.Namespace))
                            {
                                if (enumerations[LanguageBase.ReplaceInvalidChars(element.Name)] == null)
                                    enumerations.Add(LanguageBase.ReplaceInvalidChars(element.Name), "");
                            }
                        }
                    }

                    /*******/
                    // Pass2: 
                    //  Walk through and build code for all complex types (these will be classes in .NET)
                    //  First add the globally defined classes, then add the classes for the schema level 
                    //  ComplexType elements.
                    /*******/

                    foreach (XmlSchemaType schemaType in schema.SchemaTypes.Values)
                    {
                        if (schemaType is XmlSchemaComplexType && (!Globals.globalSeparateImportedNamespaces || ns == schemaType.QualifiedName.Namespace))
                        {
                            if (optionE && !es.ComplexTypes.ContainsKey(schemaType.QualifiedName.Name)) continue;  // only build specific classes

                            parentClassStack.Clear();
                            string dotnetTypeName = (string)globalQualifiedComplexTypeClasses[schemaType.QualifiedName];

                            // If schema type and a global element have the same name, don't create a class for the element
                            // This will be a special case where the schema type .net class has both XmlTypeAttribute and XmlElementAttribute.
                            bool globalElementAndSchemaTypeHaveSameName = false;
                            if (schema.Elements[schemaType.QualifiedName] != null)
                                globalElementAndSchemaTypeHaveSameName = true;

                            ParseComplexTypePass2((XmlSchemaComplexType)schemaType, dotnetTypeName, schemaType.Name, true, false,
                                schemaType.QualifiedName.Namespace, parentClassStack, "", "", false, globalElementAndSchemaTypeHaveSameName);
                        }
                    }
                    foreach (XmlSchemaElement element in schema.Elements.Values)
                    {
                        if (element.ElementType is XmlSchemaComplexType && (!Globals.globalSeparateImportedNamespaces || ns == element.QualifiedName.Namespace))
                        {
                            if (optionE && !es.Elements.ContainsKey(element.QualifiedName.Name)) continue;  // only build specific classes

                            parentClassStack.Clear();
                            string dotnetTypeName = GlobalElementToClrMap(element.QualifiedName);
                            string elementSchemaType = "";

                            if (element.SchemaTypeName.Name != null && element.SchemaTypeName.Name != "")
                            {
                                // global element with it's type set to a schema type
                                elementSchemaType = (string)globalQualifiedComplexTypeClasses[element.SchemaTypeName];

                                // If schema type and global element have the same name, don't create a class for the element
                                // This will be a special case where the schema type .net class has both XmlTypeAttribute and XmlElementAttribute.
                                if (element.QualifiedName == element.SchemaTypeName)
                                    continue;
                            }

                            //		// don't generate a class for root level schema-typed elements that are abstract -- since these classes can't be created externally.
                            //		if (elementSchemaType != "" && element.IsAbstract)
                            //			continue; 

                            ParseComplexTypePass2((XmlSchemaComplexType)element.ElementType, dotnetTypeName, element.Name, false, false,
                                element.QualifiedName.Namespace, parentClassStack, elementSchemaType, element.SchemaTypeName.Namespace, element.IsNillable, false);
                        }
                    }

                    code.NamespaceTrailerCode(outStream, dotnetNamespace);
                    outStream.Flush();

                    iFiles++;
                    outStream.Close();
                    schemaFile.Close();
                    // Finished writing out .net for a xsd namespace
                }	// End of foreach imported namespace

                System.Diagnostics.EventLog.WriteEntry("XSDSchemaParser", String.Format("Done. Writing files"));
                return outFiles;
            }
            catch (XSDObjectGenException e)
            {
                // code logic specific exceptions
                throw e;
            }
            catch (FileNotFoundException e)
            {
                // inbound xsd file cannot be loaded
                throw new XSDObjectGenException(e.Message);
            }
            catch (UnauthorizedAccessException e)
            {
                // security 
                throw new XSDObjectGenException(e.Message);
            }
            catch (XmlSchemaException e)
            {
                // xsd schema compiler exception.  xsd has some type of error.
                if (outStream != null)
                {
                    outStream.WriteLine();
                    outStream.WriteLine("LineNumber = {0}", e.LineNumber);
                    outStream.WriteLine("LinePosition = {0}", e.LinePosition);
                    outStream.WriteLine("Message = {0}", e.Message);
                    outStream.WriteLine("Source = {0}", e.Source);
                }

                throw new XSDObjectGenException(string.Format(
                    ".NET Framework XSD Schema compile error.\nError occurred : {0}", e.Message));
            }
            catch (XmlException e)
            {
                // bad xml document -- schema cannot be read because it's not valid xml
                if (outStream != null)
                {
                    outStream.WriteLine();
                    outStream.WriteLine("LineNumber = {0}", e.LineNumber);
                    outStream.WriteLine("LinePosition = {0}", e.LinePosition);
                    outStream.WriteLine("Message = {0}", e.Message);
                    outStream.WriteLine("Source = {0}", e.Source);
                }

                throw new XSDObjectGenException(string.Format(
                    ".NET Framework could not read the XSD file.  Bad XML file.\nError occurred : {0}", e.Message));
            }
            catch (Exception e)
            {
                // unexpected exceptions
                System.Diagnostics.EventLog.WriteEntry("Unexpected XSDObjectGen exception", e.Message, System.Diagnostics.EventLogEntryType.Error);

                if (outStream != null)
                {
                    outStream.WriteLine();
                    outStream.WriteLine("Error message : {0}", e.Message);
                    outStream.WriteLine("Source : {0}", e.Source);
                    outStream.WriteLine("Stack : {0}", e.StackTrace);
                }

                throw new Exception("Unexpected XSDObjectGen Exception", e);
            }
            finally
            {
                if (outStream != null) outStream.Close();
                if (schemaFile != null) schemaFile.Close();
            }
        }