alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.schema2beansdev;

import org.netbeans.modules.schema2beansdev.gen.JavaUtil;
import org.netbeans.modules.schema2beansdev.gen.XMLWriter;

import java.io.*;
import java.util.*;

import org.w3c.dom.*;
import org.xml.sax.*;

import org.netbeans.modules.schema2beans.*;

/**
 * This class will represent a schema for XML as a Java object.
 * (This implementation isn't complete, but does enough for my purposes
 * for now.)
 *
 * @author  cliffwd
 */
public class SchemaRep {
    public static boolean debug = false;

    public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";

    /*
     * The Schema Representation is internally made up of a tree of
     * Element Expressions (ElementExpr).
     */
    ////////////////////////////////////////////////////////////////
    public abstract class ElementExpr {
        public abstract String getName();
        public abstract void writeDTD(StringBuffer out);

        // writeDTDName returns true if there were any named elements
        public abstract boolean writeDTDName(StringBuffer out);
        public abstract void writeXMLSchema(XMLWriter out) throws IOException;

        // validate checks to make sure everything is okay
        public abstract void validate();

        // optimize returns a replacement node.  null means delete.
        public abstract ElementExpr optimize();
        public abstract void readSchema(org.w3c.dom.Element node);

        // Return null for getContentName if this expr doesn't have one.
        public abstract String getContentName();
        protected ElementExpr parentExpr;
        protected void setParentExpr(ElementExpr ee) {
            parentExpr = ee;
            fullContentName = null;
        }
        public ElementExpr getParentExpr() {
            return parentExpr;
        }
        private String fullContentName = null;
        public String getFullContentName() {
            if (fullContentName == null) {
                String contentName = getContentName();
                if (parentExpr == null) {
                    if (contentName == null)
                        fullContentName = "/";
                    else
                        fullContentName = ("/" + contentName).intern();
                } else {
                    String parentFullContentName = parentExpr.getFullContentName();
                    if (contentName == null)
                        fullContentName = parentFullContentName;
                    else if (parentFullContentName == "/")
                        fullContentName = (parentFullContentName + contentName).intern();
                    else
                        fullContentName = (parentFullContentName + "/" + contentName).intern();
                }
            }
            return fullContentName;
        }
        protected String uniquifyFullContentName() {
            fullContentName = (getFullContentName()+"/#").intern();
            return fullContentName;
        }
    }

    ////////////////////////////////////////////////////////////////
    // This class represents all elements (or nodes in the metadata)
    // that can have subelements.
    public abstract class ContainsSubElements extends ElementExpr {
        protected List subElements;  // List

        public ContainsSubElements() {
            subElements = new LinkedList();
        }
        
        public void addSubElement(ElementExpr subElement) {
            //System.out.println("Adding:"+subElement);
            subElement.setParentExpr(this);
            if (subElement instanceof Element) {
                String subElementFullContentName;
                boolean checkAgain;
                do {
                    checkAgain = false;
                    subElementFullContentName = subElement.getFullContentName();
                    Iterator it = subElements.iterator();
                    while (it.hasNext()) {
                        ElementExpr otherElement = (ElementExpr) it.next();
                        String otherElementFullContentName = otherElement.getFullContentName();
                        if (subElementFullContentName == otherElementFullContentName) {
                            if (debug)
                                System.out.println("Found duplicate fullContentName for "+otherElement.getName()+" : "+subElementFullContentName);
                            subElement.uniquifyFullContentName();
                            checkAgain = true;
                        }
                    }
                } while (checkAgain);
            }
            subElements.add(subElement);
        }

        public void addSubElement(List se) {
            //System.out.println("Adding: "+se+" to:"+toString());
            Iterator it = se.iterator();
            while (it.hasNext()) {
                addSubElement((ElementExpr) it.next());
            }
        }

        public Iterator subElementsIterator() {
            return subElements.iterator();
        }

        public ElementExpr findSubElement(String nodeName) {
            //System.out.println("Looking for subelement "+nodeName);
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                if (el.getName().equals(nodeName))
                    return el;
            }
            //System.out.println("Did not find it");
            return null;
        }

        public ElementExpr findSubElement(Class type) {
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                if (type.isAssignableFrom(el.getClass()))
                    return el;
            }
            return null;
        }

        /**
         * This will do an xpath like search.
         */
        public ElementExpr findSubElement(String[] nodeNames) {
            ContainsSubElements current = this;
            for (int i = 0; i < nodeNames.length; ++i) {
                ElementExpr ee = current.findSubElement(nodeNames[i]);
                if (ee == null)
                    return null;
                if (ee instanceof ContainsSubElements)
                    current = (ContainsSubElements) ee;
                else if (i+1 != nodeNames.length)
                    return null;
            }
            return current;
        }

        /**
         * Find all matching sub elements and put them into lst.
         */
        public void findAllSubElements(String name, List lst) {
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                if (el.getName().equals(name))
                    lst.add(el);
                if (el instanceof ContainsSubElements)
                    ((ContainsSubElements)el).findAllSubElements(name, lst);
            }
        }

        /**
         * Find all matching sub elements and put them into lst.
         */
        public void findAllSubElements(Class type, List lst) {
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                if (type.isAssignableFrom(el.getClass()))
                    lst.add(el);
                if (el instanceof ContainsSubElements)
                    ((ContainsSubElements)el).findAllSubElements(type, lst);
            }
        }

        public void validate() {
            //System.out.println("** validate: "+this);
            Map possibleSubElements = validSubElementTypeMap();
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr ee = (ElementExpr) it.next();
                if (!possibleSubElements.containsKey(ee.getClass())) {
                    throw new IllegalStateException(Common.getMessage("MSG_InvalidContents", toString(), ee.getName(), getFullContentName()));
                }
                ee.validate();
            }
        }

        public abstract Map validSubElementTypeMap();

        public void writeDTD(StringBuffer out) {
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                el.writeDTD(out);
            }
        }

        /**
         * Return the attributes as a string for the XML Schema.
         * null means that we have no attributes to add.
         */
        public String getAttributeString() {
            return null;
        }

        /**
         * If whitespace is used on the outside of this element.
         */
        public boolean compressWhiteSpaceOuter() {
            return false;
        }
        
        /**
         * If whitespace is used on the inside of this element.
         */
        public boolean compressWhiteSpaceInner() {
            return false;
        }
        
        public void writeXMLSchema(XMLWriter out) throws IOException {
            writeXMLSchema(out, true);
        }

        /**
         * If @printMyElement is false, then we only print subelements.
         */
        public void writeXMLSchema(XMLWriter out, boolean printMyElement) throws IOException {
            if (printMyElement) {
                //if (!compressWhiteSpaceOuter())
                //    out.indentRight();
                out.startTag(getXSDNamespace(), getName(), false);
                String attrs = getAttributeString();
                if (attrs != null)
                    out.write(attrs);
                out.finishStartTag(subElements.size() > 0, !compressWhiteSpaceInner());
                if (subElements.size() == 0)
                    return;
            }
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                el.writeXMLSchema(out);
            }
            if (printMyElement) {
                //if (!compressWhiteSpaceInner())
                //    out.indentLeft();
                out.endTag(!compressWhiteSpaceOuter());
            }
        }

        protected boolean writeDTDSubElementNames(StringBuffer out) {
            return writeDTDSubElementNames(out, true);
        }
        protected boolean writeDTDSubElementNames(StringBuffer out, boolean writeParens) {
            if (subElements.size() == 0)
                return false;
            boolean first = true;
            Iterator it = subElements.iterator();
            boolean hasNamedSubElements = false;
            // Put all of the DTD names of our subelements into subOut
            StringBuffer subOut = new StringBuffer();
            // Let each individual subelement do it's work in freshOut
            // (it's always empty at the top of the loop).
            StringBuffer freshOut = new StringBuffer();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                boolean anyNamed = el.writeDTDName(freshOut);
                if (anyNamed) {
                    hasNamedSubElements = true;
                    if (first)
                        first = false;
                    else
                        subOut.append(", ");	// NOI18N
                    subOut.append(freshOut.toString());
                    freshOut = new StringBuffer();
                }
            }
            if (!hasNamedSubElements)
                return false;
            if (writeParens && subElements.size() >= 2)
                out.append("(");	// NOI18N
            out.append(subOut);
            if (writeParens && subElements.size() >= 2)
                out.append(")");	// NOI18N
            return hasNamedSubElements;
        }

        // Inserts String's into @param list.
        public void findSubElementNames(List list) {
            Iterator it = subElements.iterator();
            StringBuffer freshOut = new StringBuffer();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                boolean anyNamed = el.writeDTDName(freshOut);
            }
        }

        public String toString() {
            String attributeString = getAttributeString();
            if (attributeString == null)
                return getName();
            else
                return getName()+attributeString;
        }

        public boolean equals(Object o) {
            if (!(o instanceof ContainsSubElements))
                return false;
            ContainsSubElements e = (ContainsSubElements) o;
            //System.out.println("Checking for equals of ContainsSubElements");
            if (subElements.size() != e.subElements.size())
                return false;
            Iterator it = subElements.iterator();
            Iterator ite = e.subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                ElementExpr ele = (ElementExpr) ite.next();
                //System.out.println("el="+el);
                //System.out.println("ele="+ele);
                if (!el.equals(ele))
                    return false;
            }
            return true;
        }

        public int hashCode() {
            int result = 17;
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                result = 37*result + el.hashCode();
            }
            return result;
        }

        public ElementExpr optimize() {
            ListIterator it = subElements.listIterator();
            while (it.hasNext()) {
                ElementExpr el = (ElementExpr) it.next();
                ElementExpr result = el.optimize();
                //System.out.println("optimize: result="+result);
                if (result == null) {
                    el.setParentExpr(null);
                    it.remove();
                } else if (el != result)
                    it.set(result);
            }
            return this;
        }

        public String getJavaTypeName() {
            Iterator it = subElements.iterator();
            while (it.hasNext()) {
                Object o = it.next();
                if (o instanceof HasJavaTypeName) {
                    //System.out.println("Container: getJavaTypeName: o="+o);
                    return ((HasJavaTypeName)o).getJavaTypeName();
                }
            }
            return null;
        }
    }

    public interface HasJavaTypeName {
        public String getJavaTypeName();
    }

    public interface MinMaxOccurs {
        public String getMinOccurs();
        public String getMaxOccurs();
    }

    public interface CanRef {
        public boolean hasRef();
        /**
         * @return the name of the ref or null if !hasRef()
         */
        public String getRef();
        public ElementExpr getRefElementExpr();
    }

    ////////////////////////////////////////////////////////////////
    // Top of an XML Schema
    public class SchemaNode extends ContainsSubElements {
        protected String targetNamespace;
        protected boolean elementFormQualified = false;
        protected boolean attributeFormQualified = false;
        
        public SchemaNode() {
        }

        public String getName() {
            return "schema";
        }

        public String getContentName() {
            return null;
        }

        public void setTargetNamespace(String tn) {
            targetNamespace = tn;
        }

        public String getTargetNamespace() {
            return targetNamespace;
        }

        public boolean isElementFormQualified() {
            return elementFormQualified;
        }

        public boolean isAttributeFormQualified() {
            return attributeFormQualified;
        }

        public void readSchema(org.w3c.dom.Element node) {
            String tns = node.getAttribute("targetNamespace");	// NOI18N
            String efd = node.getAttribute("elementFormDefault");	// NOI18N
            String afd = node.getAttribute("attributeFormDefault");	// NOI18N
            if (tns != null && !"".equals(tns))
                targetNamespace = tns;
            elementFormQualified = "qualified".equals(efd);
            attributeFormQualified = "qualified".equals(afd);
        }
        
        public void addSubElement(ElementExpr subElement) {
            if (subElement instanceof Element) {
                Element el = (Element) subElement;
                //System.out.println("SchemaNode.addSubElement: el="+el);
                if (el.isDefiningNewType()) {
                    if (debug)
                        System.out.println("SchemaNode new element type: name="+el.getElementName());
                    definedTypes.put(el.getElementName(), el);
                    definedTypesFull.put(canonicalQName(el.getElementNamespace(), el.getElementName()), el);
                }
            }
            if (subElement instanceof Attribute) {
                Attribute attr = (Attribute) subElement;
                //System.out.println("SchemaNode.addSubElement: attr="+attr);
                if (attr.isDefiningNewType()) {
                    if (debug)
                        System.out.println("SchemaNode new element type: attr="+attr);
                    definedAttributes.put(attr.getAttributeName(), attr);
                }
            }
            super.addSubElement(subElement);
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer(" xmlns:"+getXSDNamespace()+"='"+getNamespaceURI(getXSDNamespace())+"'");	// NOI18N
            if (targetNamespace != null)
                sb.append(" targetNamespace='"+getTargetNamespace()+"'");	// NOI18N
            if (documentNamespace != null) {
                sb.append(" xmlns='"+documentNamespace+"'");	// NOI18N
            }
            if (isElementFormQualified())
                sb.append(" elementFormDefault='qualified'");
            if (isAttributeFormQualified())
                sb.append(" attributeFormDefault='qualified'");
            return sb.toString();
        }

        public void writeXMLSchema(XMLWriter out) throws IOException {
            out.startTag(getXSDNamespace(), getName(), getAttributeString());	// NOI18N
            out.cr();
            Iterator it = requiredPredefinedTypes.keySet().iterator();
            while (it.hasNext()) {
                String type = (String) it.next();
                //System.out.println("Required predefined type "+type);
                ElementExpr el = (ElementExpr) optionallyDefinedTypes.get(type);
                el.writeXMLSchema(out);
            }

            super.writeXMLSchema(out, false);
            out.endTag();	// NOI18N
        }
        
        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public Map validSubElementTypeMap() {
            return schemaValidSubElementTypeMap;
        }

        public boolean equals(Object o) {
            if (!(o instanceof SchemaNode))
                return false;
            SchemaNode el = (SchemaNode) o;
            if (targetNamespace == null) {
                if (el.targetNamespace != null)
                    return false;
            } else {
                if (!targetNamespace.equals(el.targetNamespace))
                    return false;
            }
            if (elementFormQualified != el.elementFormQualified)
                return false;
            if (attributeFormQualified != el.attributeFormQualified)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((targetNamespace == null) ? 0 : targetNamespace.hashCode());
            result = 37*result + (elementFormQualified ? 1 : 0);
            result = 37*result + (attributeFormQualified ? 1 : 0);
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map schemaValidSubElementTypeMap = null;
    static {
        schemaValidSubElementTypeMap = new HashMap();
        schemaValidSubElementTypeMap.put(Annotation.class, null);
        schemaValidSubElementTypeMap.put(SimpleType.class, null);
        schemaValidSubElementTypeMap.put(ComplexType.class, null);
        schemaValidSubElementTypeMap.put(Element.class, null);
        schemaValidSubElementTypeMap.put(Attribute.class, null);
        schemaValidSubElementTypeMap.put(AttributeGroup.class, null);
        schemaValidSubElementTypeMap.put(Include.class, null);
        schemaValidSubElementTypeMap.put(Import.class, null);
        schemaValidSubElementTypeMap.put(Group.class, null);
    }
    
    ////////////////////////////////////////////////////////////////
    // See XML Schema complexType
    public class ComplexType extends ContainsSubElements implements HasJavaTypeName {
        protected String typeName;
        private boolean mixed = false;
        private boolean abstractType = false;
        
        public ComplexType() {
        }

        public ComplexType(String typeName) {
            if (typeName != null && !typeName.equals("")) {
                this.typeName = normalizeTargetNamespace(typeName).intern();
                putSchemaTypeDef(this.typeName, this);
            }
        }

        public String getName() {
            return "complexType";
        }

        public String getContentName() {
            return typeName;
        }

        public boolean isMixed() {
            return mixed;
        }

        public boolean isAbstract() {
            return abstractType;
        }

        /**
         * Can return null.
         */
        public String getTypeName() {
            return typeName;
        }

        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public String getAttributeString() {
            String result = "";
            if (typeName != null)
                result += " name='"+typeName+"'";
            if (mixed)
                result += " mixed='true'";
            if (abstractType)
                result += " abstract='true'";
            return result;
        }

        public Map validSubElementTypeMap() {
            return complexTypeValidSubElementTypeMap;
        }

        public void readSchema(org.w3c.dom.Element node) {
            String elementType = node.getAttribute("name");	// NOI18N
            String myMixed = node.getAttribute("mixed");	// NOI18N
            String myAbstract = node.getAttribute("abstract");	// NOI18N
            ComplexType el = new ComplexType(elementType);
            if (myMixed != null && (myMixed.equals("true") || myMixed.equals("yes") || myMixed.equals("on")))
                el.mixed = true;
            if (myAbstract != null && (myAbstract.equals("true") || myAbstract.equals("yes") || myAbstract.equals("on")))
                el.abstractType = true;
            if (debug)
                System.out.println("Created complexType "+elementType);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public boolean equals(Object o) {
            if (!(o instanceof ComplexType))
                return false;
            ComplexType el = (ComplexType) o;
            if (typeName != el.typeName)
                return false;
            if (mixed != el.mixed)
                return false;
            if (abstractType != el.abstractType)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((typeName == null) ? 0 : typeName.hashCode());
            result = 37*result + (mixed ? 1 : 0);
            result = 37*result + (abstractType ? 1 : 0);
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map complexTypeValidSubElementTypeMap = null;
    static {
        complexTypeValidSubElementTypeMap = new HashMap();
        complexTypeValidSubElementTypeMap.put(Annotation.class, null);
        complexTypeValidSubElementTypeMap.put(Choice.class, null);
        complexTypeValidSubElementTypeMap.put(Group.class, null);
        complexTypeValidSubElementTypeMap.put(Sequence.class, null);
        complexTypeValidSubElementTypeMap.put(All.class, null);
        complexTypeValidSubElementTypeMap.put(Attribute.class, null);
        complexTypeValidSubElementTypeMap.put(AttributeGroup.class, null);
        complexTypeValidSubElementTypeMap.put(AnyAttribute.class, null);
        complexTypeValidSubElementTypeMap.put(SimpleContent.class, null);
        complexTypeValidSubElementTypeMap.put(ComplexContent.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class SimpleContent extends ContainsSubElements implements HasJavaTypeName {
        public SimpleContent() {
        }

        public String getName() {
            return "simpleContent";
        }

        public String getContentName() {
            return null;
        }

        public void validate() {
        }

        public ElementExpr optimize() {
            return this;
        }

        public void readSchema(org.w3c.dom.Element node) {
            SimpleContent el = new SimpleContent();
            pushCurrent(el);
            read(node);
            popCurrent();
        }
        
        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public Map validSubElementTypeMap() {
            return simpleContentValidSubElementTypeMap;
        }
    }
    static private Map simpleContentValidSubElementTypeMap = null;
    static {
        simpleContentValidSubElementTypeMap = new HashMap();
        simpleContentValidSubElementTypeMap.put(Annotation.class, null);
        simpleContentValidSubElementTypeMap.put(Restriction.class, null);
        simpleContentValidSubElementTypeMap.put(Extension.class, null);
    }


    ////////////////////////////////////////////////////////////////
    public class ComplexContent extends ContainsSubElements implements HasJavaTypeName {
        private boolean mixed;
        
        public ComplexContent() {
        }

        public String getName() {
            return "complexContent";
        }

        public String getContentName() {
            return null;
        }

        public void validate() {
        }

        public ElementExpr optimize() {
            return this;
        }

        public boolean isMixed() {
            return mixed;
        }

        public void readSchema(org.w3c.dom.Element node) {
            ComplexContent el = new ComplexContent();
            String myMixed = node.getAttribute("mixed");	// NOI18N
            if (myMixed != null && (myMixed.equals("true") || myMixed.equals("yes") || myMixed.equals("on")))
                el.mixed = true;
            pushCurrent(el);
            read(node);
            popCurrent();
        }
        
        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public Map validSubElementTypeMap() {
            return complexContentValidSubElementTypeMap;
        }

        public boolean equals(Object o) {
            if (!(o instanceof ComplexContent))
                return false;
            ComplexContent el = (ComplexContent) o;
            if (mixed != el.mixed)
                return false;
            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + (mixed ? 0 : 1);
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map complexContentValidSubElementTypeMap = null;
    static {
        complexContentValidSubElementTypeMap = new HashMap();
        complexContentValidSubElementTypeMap.put(Annotation.class, null);
        complexContentValidSubElementTypeMap.put(Restriction.class, null);
        complexContentValidSubElementTypeMap.put(Extension.class, null);
    }


    ////////////////////////////////////////////////////////////////
    // See XML Schema simpleType
    public class SimpleType extends ContainsSubElements implements HasJavaTypeName {
        private String typeName = null;
        private String javaTypeName = null;
        
        public SimpleType(String tn) {
            //System.out.println("SimpleType1: tn="+tn);
            if (tn != null && !tn.equals("")) {
                typeName = normalizeTargetNamespace(tn).intern();
                ElementExpr previousDef = getSchemaTypeDef(typeName);
                if (previousDef instanceof SimpleType && (((SimpleType)previousDef).javaTypeName != null || ((SimpleType)previousDef).subElements.size() > 0)) {
                    // The previous definition has more information.  Keep it.
                    System.out.println("Keeping schemaTypeDefs1 for "+previousDef);
                } else {
                    if (previousDef != null)
                        System.out.println("!!! Overwriting schemaTypeDefs1 ("+previousDef+") for "+this);
                    putSchemaTypeDef(typeName, this);
                }
            }
        }

        /**
         * @param tn is the type
         * @param javaTypeName is a java type to associate with @param tn
         *    and should be linearly dependent.
         */
        public SimpleType(String tn, String javaTypeName) {
            super();
            //System.out.println("SimpleType2: tn="+tn+" javaTypeName="+javaTypeName);
            typeName = (tn == null) ? null : normalizeTargetNamespace(tn).intern();
            this.javaTypeName = (javaTypeName == null) ? null : javaTypeName.intern();
            /*
            if (schemaTypeDefs.get(typeName) != null)
                System.out.println("!!! Overwriting schemaTypeDefs2 for "+this);
            */
            putSchemaTypeDef(this.typeName, this);
        }

        public SimpleType(String tn, Restriction restrict) {
            super();
            //System.out.println("SimpleType3: tn="+tn+" restrict="+restrict);
            typeName = (tn == null) ? null : normalizeTargetNamespace(tn).intern();
            this.addSubElement(restrict);
            /*
            if (schemaTypeDefs.get(typeName) != null)
                System.out.println("!!! Overwriting schemaTypeDefs3 for "+this);
            */
            putSchemaTypeDef(this.typeName, this);
        }

        public String getName() {
            return "simpleType";
        }

        public String getContentName() {
            return typeName;
        }

        public String getTypeName() {
            return typeName;
        }

        // This may return null
        public String getJavaTypeName() {
            if (javaTypeName != null)
                return javaTypeName;
            return super.getJavaTypeName();
        }

        public String getAttributeString() {
            if (typeName == null)
                return null;
            return (" name='"+typeName+"'");
        }
        
        public boolean compressWhiteSpaceInner() {
            if (subElements.size() == 0)
                return true;
            ElementExpr subElement = (ElementExpr) subElementsIterator().next();
            if (subElement instanceof ContainsSubElements)
                return ((ContainsSubElements)subElement).compressWhiteSpaceOuter();
            return true;
        }
        
        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public void readSchema(org.w3c.dom.Element node) {
            String elementType = node.getAttribute("name");	// NOI18N
            SimpleType el = new SimpleType(elementType);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public Map validSubElementTypeMap() {
            return simpleTypeValidSubElementTypeMap;
        }

        public String toString() {
            if (javaTypeName == null)
                return "simpleType "+typeName;	// NOI18N
            else
                return "simpleType "+typeName+" "+javaTypeName;	// NOI18N
        }

        public boolean equals(Object o) {
            if (!(o instanceof SimpleType))
                return false;
            SimpleType el = (SimpleType) o;
            if (typeName != el.typeName)
                return false;
            // javaTypeName ought to be redundant to typeName
            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + typeName.hashCode();
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map simpleTypeValidSubElementTypeMap = null;
    static {
        simpleTypeValidSubElementTypeMap = new HashMap();
        simpleTypeValidSubElementTypeMap.put(Annotation.class, null);
        simpleTypeValidSubElementTypeMap.put(Restriction.class, null);
        simpleTypeValidSubElementTypeMap.put(ListElement.class, null);
    }

    public interface EncodingStyle {
    }

    public class HexBinary extends SimpleType implements EncodingStyle {
        public HexBinary() {
            super(getXSDNamespace()+":hexBinary", "byte[]");
        }

        public String toString() {
            return "hexBinary";
        }
    }

    public class Base64Binary extends SimpleType implements EncodingStyle {
        public Base64Binary() {
            super(getXSDNamespace()+":base64Binary", "byte[]");
        }

        public String toString() {
            return "base64Binary";
        }
    }

    ////////////////////////////////////////////////////////////////
    // See XML Schema restriction (usually underneath simpleType)
    public class Restriction extends ContainsSubElements implements HasJavaTypeName {
        protected String base;
        public Restriction() {
        }

        public Restriction(String base) {
            setBase(base);
        }

        public String getName() {
            return "restriction";
        }

        public String getContentName() {
            return null;
        }

        public void setBase(String b) {
            if (b == null) {
                base = null;
                return;
            }
            base = normalizeDocumentNamespace(b).intern();
        }

        public String getBase() {
            return base;
        }

        public String getJavaTypeName() {
            return schemaTypeToJavaType(base);
        }

        public boolean compressWhiteSpaceOuter() {
            return subElements.size() == 0;
        }
        
        public boolean compressWhiteSpaceInner() {
            return subElements.size() == 0;
        }
        
        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public String getAttributeString() {
            if (base == null)
                return null;
            return (" base='"+getBase()+"'");
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String base = node.getAttribute("base");	// NOI18N
            Restriction el = new Restriction(base);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public Map validSubElementTypeMap() {
            return restrictionValidSubElementTypeMap;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Restriction))
                return false;
            Restriction el = (Restriction) o;
            if (base == null) {
                if (el.base != null)
                    return false;
            } else {
                if (!base.equals(el.base))
                    return false;
            }

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((base == null) ? 0: base.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map restrictionValidSubElementTypeMap = null;
    static {
        restrictionValidSubElementTypeMap = new HashMap();
        restrictionValidSubElementTypeMap.put(Annotation.class, null);
        restrictionValidSubElementTypeMap.put(SimpleType.class, null);
        restrictionValidSubElementTypeMap.put(All.class, null);
        restrictionValidSubElementTypeMap.put(Choice.class, null);
        restrictionValidSubElementTypeMap.put(Sequence.class, null);
        restrictionValidSubElementTypeMap.put(Group.class, null);
        restrictionValidSubElementTypeMap.put(Attribute.class, null);
        restrictionValidSubElementTypeMap.put(AttributeGroup.class, null);
        restrictionValidSubElementTypeMap.put(AnyAttribute.class, null);
        restrictionValidSubElementTypeMap.put(MinExclusive.class, null);
        restrictionValidSubElementTypeMap.put(MaxExclusive.class, null);
        restrictionValidSubElementTypeMap.put(Enumeration.class, null);
        restrictionValidSubElementTypeMap.put(Pattern.class, null);
        restrictionValidSubElementTypeMap.put(MinLength.class, null);
        restrictionValidSubElementTypeMap.put(MaxLength.class, null);
        restrictionValidSubElementTypeMap.put(TotalDigits.class, null);
        restrictionValidSubElementTypeMap.put(MinInclusive.class, null);
        restrictionValidSubElementTypeMap.put(MaxInclusive.class, null);
        restrictionValidSubElementTypeMap.put(FractionDigits.class, null);
        restrictionValidSubElementTypeMap.put(Length.class, null);
        restrictionValidSubElementTypeMap.put(WhiteSpace.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class Extension extends ContainsSubElements implements HasJavaTypeName {
        protected String base;
        public Extension() {
        }

        public Extension(String base) {
            setBase(base);
        }

        public String getContentName() {
            return null;
        }

        public String getName() {
            return "extension";
        }

        public void setBase(String b) {
            base = normalizeDocumentNamespace(b);
        }

        public String getBase() {
            return base;
        }

        public String getJavaTypeName() {
            return schemaTypeToJavaType(base);
        }

        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public String getAttributeString() {
            if (base == null)
                return null;
            return (" base='"+getBase()+"'");
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String base = node.getAttribute("base");	// NOI18N
            Extension el = new Extension(base);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public Map validSubElementTypeMap() {
            return extensionValidSubElementTypeMap;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Extension))
                return false;
            Extension el = (Extension) o;
            if (base == null) {
                if (el.base != null)
                    return false;
            } else {
                if (!base.equals(el.base))
                    return false;
            }

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((base == null) ? 0: base.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map extensionValidSubElementTypeMap = null;
    static {
        extensionValidSubElementTypeMap = new HashMap();
        extensionValidSubElementTypeMap.put(Annotation.class, null);
        extensionValidSubElementTypeMap.put(Attribute.class, null);
        extensionValidSubElementTypeMap.put(AttributeGroup.class, null);
        extensionValidSubElementTypeMap.put(AnyAttribute.class, null);
        extensionValidSubElementTypeMap.put(Choice.class, null);
        extensionValidSubElementTypeMap.put(Group.class, null);
        extensionValidSubElementTypeMap.put(Sequence.class, null);
        extensionValidSubElementTypeMap.put(All.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class ListElement extends ContainsSubElements {
        protected String itemType;
        public ListElement() {
        }

        public ListElement(String itemType) {
            this.itemType = itemType;
        }

        public String getContentName() {
            return null;
        }

        public String getName() {
            return "list";
        }

        public void setItemType(String b) {
            itemType = b;
        }

        public String getItemType() {
            return itemType;
        }

        public String getJavaTypeName() {
            return schemaTypeToJavaType(itemType);
        }

        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public String getAttributeString() {
            if (itemType == null)
                return null;
            return (" itemType='"+getItemType()+"'");
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String itemType = node.getAttribute("itemType");	// NOI18N
            ListElement el = new ListElement(itemType);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public Map validSubElementTypeMap() {
            return listValidSubElementTypeMap;
        }

        public boolean equals(Object o) {
            if (!(o instanceof ListElement))
                return false;
            ListElement el = (ListElement) o;
            if (itemType == null) {
                if (el.itemType != null)
                    return false;
            } else {
                if (!itemType.equals(el.itemType))
                    return false;
            }

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((itemType == null) ? 0: itemType.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map listValidSubElementTypeMap = null;
    static {
        listValidSubElementTypeMap = new HashMap();
        listValidSubElementTypeMap.put(Annotation.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public abstract class RestrictionType extends ElementExpr {
        protected String value;

        public RestrictionType(String value) {
            super();
            this.value = (value == null) ? null : value.intern();
        }
        
        public String getContentName() {
            return null;
        }

        public String getValue() {
            return value;
        }

        public void writeDTD(StringBuffer out) {
            // Has no bearing on a DTD
        }
        public boolean writeDTDName(StringBuffer out) {
            // Has no bearing on a DTD
            return false;
        }

        public void validate() {
        }

        public ElementExpr optimize() {
            return this;
        }

        public void writeXMLSchema(XMLWriter out) throws IOException {
            out.startTag(getXSDNamespace(), getName(), false);
            out.write(" value='");
            XMLUtil.printXML(out, value);
            out.write("'");
            out.finishStartTag(false, true);
        }

        public void readSchema(org.w3c.dom.Element node) {
            String myValue = node.getAttribute("value");	// NOI18N
            RestrictionType el = newInstance(myValue);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        protected abstract RestrictionType newInstance(String value);

        /*
        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("// FIXME "+getClass()+"\n");
        }
        */

        public String toString() {
            return getName()+" ("+value+")";
        }
    }

    ////////////////////////////////////////////////////////////////
    public class MaxExclusive extends RestrictionType implements DataTypeRestriction {
        public MaxExclusive(String value) {
            super(value);
        }

        public String getName() {
            return "maxExclusive";
        }

        protected RestrictionType newInstance(String value) {
            return new MaxExclusive(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if ("+JavaUtil.compareToText(var, type, value)+" >= 0) {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class MinExclusive extends RestrictionType implements DataTypeRestriction {
        public MinExclusive(String value) {
            super(value);
        }

        public String getName() {
            return "minExclusive";
        }

        protected RestrictionType newInstance(String value) {
            return new MinExclusive(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if ("+JavaUtil.compareToText(var, type, value)+" <= 0) {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class Enumeration extends RestrictionType implements DataEnumRestriction {
        public Enumeration(String value) {
            super(value);
        }

        public String getName() {
            return "enumeration";
        }

        protected RestrictionType newInstance(String value) {
            return new Enumeration(value);
        }

        public void genRestriction(Writer out, String type) throws IOException {
            out.write(JavaUtil.instanceFrom(type, value));
        }
    }

    ////////////////////////////////////////////////////////////////
    public class Pattern extends RestrictionType implements DataTypeRestriction {
        public Pattern(String value) {
            super(value);
        }

        public String getName() {
            return "pattern";
        }

        protected RestrictionType newInstance(String value) {
            return new Pattern(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if (!("+JavaUtil.typeToString(type, var)+").matches("+JavaUtil.instanceFrom("java.lang.String", value)+")) {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class MinLength extends RestrictionType implements DataTypeRestriction {
        public MinLength(String value) {
            super(value);
        }

        public String getName() {
            return "minLength";
        }

        protected RestrictionType newInstance(String value) {
            return new MinLength(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if (("+JavaUtil.typeToString(type, var)+").length() < "+value+") {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class MaxLength extends RestrictionType implements DataTypeRestriction {
        public MaxLength(String value) {
            super(value);
        }

        public String getName() {
            return "maxLength";
        }

        protected RestrictionType newInstance(String value) {
            return new MaxLength(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if (("+JavaUtil.typeToString(type, var)+").length() > "+value+") {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class TotalDigits extends RestrictionType implements DataTypeRestriction {
        public TotalDigits(String value) {
            super(value);
        }

        public String getName() {
            return "totalDigits";
        }

        protected RestrictionType newInstance(String value) {
            return new TotalDigits(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("{\n");
            out.write("String _tmp = "+JavaUtil.typeToString(type, var)+";\n");
            out.write("int digitCount = 0;\n");
            out.write("for (int _index = 0; _index < _tmp.length(); ++_index) {\n");
            out.write("if (Character.isDigit(_tmp.charAt(_index))) {\n");
            out.write("++digitCount;\n");
            out.write("if (digitCount > "+value+") {\n");
            out.write(failVar+" = true;\n");
            out.write("break;\n");
            out.write("}\n");
            out.write("}\n");
            out.write("}\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class MinInclusive extends RestrictionType implements DataTypeRestriction {
        public MinInclusive(String value) {
            super(value);
        }

        public String getName() {
            return "minInclusive";
        }

        protected RestrictionType newInstance(String value) {
            return new MinInclusive(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if ("+JavaUtil.compareToText(var, type, value)+" < 0) {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class MaxInclusive extends RestrictionType implements DataTypeRestriction {
        public MaxInclusive(String value) {
            super(value);
        }

        public String getName() {
            return "maxInclusive";
        }

        protected RestrictionType newInstance(String value) {
            return new MaxInclusive(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if ("+JavaUtil.compareToText(var, type, value)+" > 0) {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class FractionDigits extends RestrictionType implements DataTypeRestriction {
        public FractionDigits(String value) {
            super(value);
        }

        public String getName() {
            return "fractionDigits";
        }

        protected RestrictionType newInstance(String value) {
            return new FractionDigits(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("{\n");
            out.write("String _tmp = "+JavaUtil.typeToString(type, var)+";\n");
            out.write("int dotPos = _tmp.indexOf('.');\n");
            out.write("if (dotPos >= 0) {\n");
            out.write("_tmp = _tmp.substring(dotPos+1, _tmp.length());\n");
            out.write("int digitCount = 0;\n");
            out.write("for (int _index = 0; _index < _tmp.length(); ++_index) {\n");
            out.write("if (Character.isDigit(_tmp.charAt(_index))) {\n");
            out.write("++digitCount;\n");
            out.write("if (digitCount > "+value+") {\n");
            out.write(failVar+" = true;\n");
            out.write("break;\n");
            out.write("}\n");
            out.write("}\n");
            out.write("}\n");
            out.write("}\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class Length extends RestrictionType implements DataTypeRestriction {
        public Length(String value) {
            super(value);
        }

        public String getName() {
            return "length";
        }

        protected RestrictionType newInstance(String value) {
            return new Length(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            out.write("if ("+JavaUtil.typeToString(type, var)+".length() != "+value+") {\n");
            out.write(failVar+" = true;\n");
            out.write("}\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    public class WhiteSpace extends RestrictionType implements DataTypeRestriction {
        public WhiteSpace(String value) {
            super(value);
        }

        public String getName() {
            return "whiteSpace";
        }

        public boolean isPreserve() {
            return "preserve" == value;
        }

        public boolean isReplace() {
            return "replace" == value;
        }

        public boolean isCollapse() {
            return "collapse" == value;
        }

        public void validate() {
            super.validate();
            if (value == null || value.equals(""))
                throw new IllegalStateException(Common.getMessage("MSG_InvalidWhiteSpaceValue", value));
            if (!(value == "preserve" || value == "replace" || value == "collapse"))
                throw new IllegalStateException(Common.getMessage("MSG_InvalidWhiteSpaceValue", value));
        }

        protected RestrictionType newInstance(String value) {
            return new WhiteSpace(value);
        }

        public void genRestriction(Writer out, String var, String type, String failVar) throws IOException {
            // Does not cause verify changes
            out.write("// has whitespace restriction\n");
        }
    }

    ////////////////////////////////////////////////////////////////
    // the parent class for some others
    public abstract class ElementInformationItem extends ContainsSubElements {
        private String id;
        private String name;

        public ElementInformationItem() {
        }
        
        public ElementInformationItem(String id, String name) {
            this.id = id;
            this.name = name;
        }

        public String getContentName() {
            return name;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getElementName() {
            return name;
        }

        public void setElementName(String name) {
            this.name = name;
        }

        public boolean writeDTDName(StringBuffer out) {
            boolean hasNamedSubElements = writeDTDSubElementNames(out, true);
            return hasNamedSubElements;
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (name != null)
                sb.append(" name='"+name+"'");
            if (id != null)
                sb.append(" id='"+id+"'");
            return sb.toString();
        }

        public void readSchema(org.w3c.dom.Element node) {
            String id = node.getAttribute("id");	// NOI18N
            String name = node.getAttribute("name");	// NOI18N
            ElementInformationItem el = newInstance();
            pushCurrent(el);
            if (id != null && !id.equals(""))
                el.setId(id);
            if (name != null && !name.equals(""))
                el.setElementName(name);
            read(node);
            popCurrent();
        }

        protected abstract ElementInformationItem newInstance();
        
        public boolean equals(Object o) {
            if (!(o instanceof ElementInformationItem))
                return false;
            ElementInformationItem el = (ElementInformationItem) o;
            if (id != el.id)
                return false;
            if (name != el.name)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((id == null) ? 0 : id.hashCode());
            result = 37*result + ((name == null) ? 0 : name.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }

    ////////////////////////////////////////////////////////////////
    public class Key extends ElementInformationItem {
        public Key() {
        }

        public String getName() {
            return "key";
        }

        public Map validSubElementTypeMap() {
            return keyValidSubElementTypeMap;
        }

        protected ElementInformationItem newInstance() {
            return new Key();
        }
    }
    static private Map keyValidSubElementTypeMap = null;
    static {
        keyValidSubElementTypeMap = new HashMap();
        keyValidSubElementTypeMap.put(Annotation.class, null);
        keyValidSubElementTypeMap.put(Selector.class, null);
        keyValidSubElementTypeMap.put(Field.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class Unique extends ElementInformationItem {
        public Unique() {
        }

        public String getName() {
            return "unique";
        }

        public Map validSubElementTypeMap() {
            return uniqueValidSubElementTypeMap;
        }

        protected ElementInformationItem newInstance() {
            return new Unique();
        }
    }
    static private Map uniqueValidSubElementTypeMap = null;
    static {
        uniqueValidSubElementTypeMap = new HashMap();
        uniqueValidSubElementTypeMap.put(Annotation.class, null);
        uniqueValidSubElementTypeMap.put(Selector.class, null);
        uniqueValidSubElementTypeMap.put(Field.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class KeyRef extends ElementInformationItem {
        private String refer;
        
        public KeyRef() {
        }

        public String getName() {
            return "keyref";
        }

        public void setRefer(String refer) {
            this.refer = refer;
        }

        public String getRefer() {
            return refer;
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer(super.getAttributeString());
            if (refer != null)
                sb.append(" refer='"+refer+"'");
            return sb.toString();
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String id = node.getAttribute("id");	// NOI18N
            String name = node.getAttribute("name");	// NOI18N
            String refer = node.getAttribute("refer");	// NOI18N
            KeyRef el = new KeyRef();
            pushCurrent(el);
            if (id != null && !id.equals(""))
                el.setId(id);
            if (name != null && !name.equals(""))
                el.setElementName(name);
            if (refer != null && !refer.equals(""))
                el.setRefer(refer);
            read(node);
            popCurrent();
        }
        
        public Map validSubElementTypeMap() {
            return keyrefValidSubElementTypeMap;
        }

        protected ElementInformationItem newInstance() {
            return new KeyRef();
        }
    }
    static private Map keyrefValidSubElementTypeMap = null;
    static {
        keyrefValidSubElementTypeMap = new HashMap();
        keyrefValidSubElementTypeMap.put(Annotation.class, null);
        keyrefValidSubElementTypeMap.put(Selector.class, null);
        keyrefValidSubElementTypeMap.put(Field.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public abstract class SelectorOrField extends ContainsSubElements {
        private String id;
        private String xpath;
        
        public SelectorOrField() {
        }

        public String getContentName() {
            return null;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getXPath() {
            return xpath;
        }

        public void setXPath(String xpath) {
            this.xpath = xpath;
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (xpath != null)
                sb.append(" xpath='"+xpath+"'");
            if (id != null)
                sb.append(" id='"+id+"'");
            return sb.toString();
        }

        public void readSchema(org.w3c.dom.Element node) {
            String id = node.getAttribute("id");	// NOI18N
            String xpath = node.getAttribute("xpath");	// NOI18N
            SelectorOrField el = newInstance();
            pushCurrent(el);
            if (id != null && !id.equals(""))
                el.setId(id);
            if (xpath != null && !xpath.equals(""))
                el.setXPath(xpath);
            read(node);
            popCurrent();
        }

        protected abstract SelectorOrField newInstance();

        public void writeDTD(StringBuffer out) {
            // ?
        }

        public boolean writeDTDName(StringBuffer out) {
            // ?
            return false;
        }

        public boolean equals(Object o) {
            if (!(o instanceof SelectorOrField))
                return false;
            SelectorOrField el = (SelectorOrField) o;
            if (id == null) {
                if (el.id != null)
                    return false;
            } else if (id != el.id)
                return false;
            if (xpath == null) {
                if (el.xpath != null)
                    return false;
            } else if (xpath != el.xpath)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((id == null) ? 0 : id.hashCode());
            result = 37*result + ((xpath == null) ? 0 : xpath.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }

    ////////////////////////////////////////////////////////////////
    public class Selector extends SelectorOrField {
        public Selector() {
        }

        public String getName() {
            return "selector";
        }

        public Map validSubElementTypeMap() {
            return selectorValidSubElementTypeMap;
        }

        protected SelectorOrField newInstance() {
            return new Selector();
        }
    }
    static private Map selectorValidSubElementTypeMap = null;
    static {
        selectorValidSubElementTypeMap = new HashMap();
        selectorValidSubElementTypeMap.put(Annotation.class, null);
    }
    
    public class Field extends SelectorOrField {
        public Field() {
        }

        public String getName() {
            return "field";
        }

        public Map validSubElementTypeMap() {
            return fieldValidSubElementTypeMap;
        }

        protected SelectorOrField newInstance() {
            return new Field();
        }
    }
    static private Map fieldValidSubElementTypeMap = null;
    static {
        fieldValidSubElementTypeMap = new HashMap();
        fieldValidSubElementTypeMap.put(Annotation.class, null);
    }
    
    ////////////////////////////////////////////////////////////////
    public class Include extends ElementExpr {
        private String schemaLocation;
        
        public Include(String schemaLocation) {
            this.schemaLocation = schemaLocation;
        }

        public String getContentName() {
            return null;
        }

        public void readSchema(org.w3c.dom.Element node) {
            String schemaLocation = node.getAttribute("schemaLocation");	// NOI18N
            if (includedAlready.containsKey(schemaLocation))
                return;
            includedAlready.put(schemaLocation, null);

            //System.out.println("Attempting to include "+schemaLocation);
            String oldTargetNamespace = targetNamespace;
            String oldDocumentNamespace = documentNamespace;
            /*
              Map oldNamespaceTable = null;
              if (namespaceTable instanceof HashMap)
              oldNamespaceTable = (Map) ((HashMap)namespaceTable).clone();
            */
            try {
                readSchemaFromLocation(schemaLocation);
            } catch (org.xml.sax.SAXException e) {
                throw new Schema2BeansRuntimeException(Common.getMessage("MSG_FailedToParse", schemaLocation), e);
            } catch (java.io.IOException e) {
                throw new Schema2BeansRuntimeException(Common.getMessage("MSG_FailedToParse", schemaLocation), e);
            } finally {
                targetNamespace = oldTargetNamespace;
                documentNamespace = oldDocumentNamespace;
            }
            //System.out.println("Finished reading include\n");
            /*
              if (oldNamespaceTable != null)
              namespaceTable = oldNamespaceTable;
            */
        }

        public ElementExpr optimize() {
            return this;
        }

        public void validate() {
        }

        public String getName() {
            return "include";
        }

        public void writeDTD(StringBuffer out) {
            // ?
        }

        public boolean writeDTDName(StringBuffer out) {
            // ?
            return false;
        }

        public void writeXMLSchema(XMLWriter out) throws IOException {
            out.startTag(getXSDNamespace(), getName(), false);
            if (schemaLocation != null) {
                out.write(" schemaLocation='");
                out.write(schemaLocation);
                out.write("'");
            }
            out.finishStartTag(false, true);
        }

        public String toString() {
            if (schemaLocation == null)
                return getName();
            else
                return getName()+" schemaLocation="+schemaLocation;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Include))
                return false;
            Include el = (Include) o;
            if (schemaLocation == null) {
                if (el.schemaLocation != null)
                    return false;
            } else if (!schemaLocation.equals(el.schemaLocation))
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((schemaLocation == null) ? 0 : schemaLocation.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    
    ////////////////////////////////////////////////////////////////
    public class Import extends ElementExpr {
        private String theNamespace;
        private String schemaLocation;
        
        public Import() {
        }

        public String getContentName() {
            return null;
        }

        public String getNamespace() {
            return theNamespace;
        }

        public void setNamespace(String namespace) {
            theNamespace = namespace;
        }

        public String getSchemaLocation() {
            return schemaLocation;
        }

        public void setSchemaLocation(String schemaLocation) {
            this.schemaLocation = schemaLocation;
        }

        public void readSchema(org.w3c.dom.Element node) {
            String namespace = node.getAttribute("namespace");	// NOI18N
            String schemaLocation = node.getAttribute("schemaLocation");	// NOI18N
            //System.out.println("Attempting to import "+schemaLocation);
            String oldTargetNamespace = targetNamespace;
            String oldDocumentNamespace = documentNamespace;
            if (namespace != null && !namespace.equals(""))
                targetNamespace = namespace;
            /*
              Map oldNamespaceTable = null;
              if (namespaceTable instanceof HashMap)
              oldNamespaceTable = (Map) ((HashMap)namespaceTable).clone();
            */
            try {
                readSchemaFromLocation(schemaLocation);
            } catch (org.xml.sax.SAXException e) {
                throw new Schema2BeansRuntimeException(Common.getMessage("MSG_FailedToParse", schemaLocation), e);
            } catch (java.io.IOException e) {
                throw new Schema2BeansRuntimeException(Common.getMessage("MSG_FailedToParse", schemaLocation), e);
            } finally {
                targetNamespace = oldTargetNamespace;
                documentNamespace = oldDocumentNamespace;
            }
            //System.out.println("Finished reading import\n");
            /*
              if (oldNamespaceTable != null)
              namespaceTable = oldNamespaceTable;
            */
        }

        public ElementExpr optimize() {
            return this;
        }

        public void validate() {
        }

        public String getName() {
            return "import";
        }

        public void writeDTD(StringBuffer out) {
            // ?
        }

        public boolean writeDTDName(StringBuffer out) {
            // ?
            return false;
        }

        public void writeXMLSchema(XMLWriter out) throws IOException {
            out.startTag(getXSDNamespace(), getName(), false);
            if (theNamespace != null) {
                out.write(" theNamespace='");
                out.write(theNamespace);
                out.write("'");
            }
            if (schemaLocation != null) {
                out.write(" schemaLocation='");
                out.write(schemaLocation);
                out.write("'");
            }
            out.finishStartTag(false, true);
        }

        public boolean equals(Object o) {
            if (!(o instanceof Import))
                return false;
            Import el = (Import) o;
            if (theNamespace == null) {
                if (el.theNamespace != null)
                    return false;
            } else if (!theNamespace.equals(el.theNamespace))
                return false;
            if (schemaLocation == null) {
                if (el.schemaLocation != null)
                    return false;
            } else if (!schemaLocation.equals(el.schemaLocation))
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((theNamespace == null) ? 0 : theNamespace.hashCode());
            result = 37*result + ((schemaLocation == null) ? 0 : schemaLocation.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    
    ////////////////////////////////////////////////////////////////
    // See XML Schema sequence.
    public abstract class ModelGroup extends ContainsSubElements implements MinMaxOccurs {
        private String minOccurs;
        private String maxOccurs;
        
        public ModelGroup() {
            super();
            minOccurs = "1";
            maxOccurs = "1";
        }

        public String getContentName() {
            return null;
        }

        public void setMinOccurs(String mino) {
            if (mino == null)
                mino = "1";
            minOccurs = mino.intern();
        }

        public void setMaxOccurs(String maxo) {
            if (maxo == null)
                maxo = "1";
            maxOccurs = maxo.intern();
        }

        public String getMinOccurs() {
            return minOccurs;
        }

        public String getMaxOccurs() {
            return maxOccurs;
        }

        /**
         * If we have no subelements, we ask to be deleted.
         * If we have only 1 element and attributes haven't been set, then
         * we replace ourselves with that element.
         */
        public ElementExpr optimize() {
            super.optimize();
            if (subElements.size() == 0)
                return null;
            /*
            if (subElements.size() == 1 && minOccurs == "1" && maxOccurs == "1")
                return (ElementExpr) subElements.iterator().next();
            */
            return this;
        }

        public boolean writeDTDName(StringBuffer out) {
            boolean many = ("unbounded" == maxOccurs);
            boolean hasNamedSubElements = writeDTDSubElementNames(out, true);
            if (many)
                out.append("*");
            return hasNamedSubElements;
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (minOccurs != "1")
                sb.append(" minOccurs='"+minOccurs+"'");
            if (maxOccurs != "1")
                sb.append(" maxOccurs='"+maxOccurs+"'");
            return sb.toString();
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String minOccurs = node.getAttribute("minOccurs");	// NOI18N
            String maxOccurs = node.getAttribute("maxOccurs");	// NOI18N
            ModelGroup el = newInstance();
            pushCurrent(el);
            if (minOccurs != null && !minOccurs.equals(""))
                el.setMinOccurs(minOccurs);
            if (maxOccurs != null && !maxOccurs.equals(""))
                el.setMaxOccurs(maxOccurs);
            read(node);
            popCurrent();
        }

        protected abstract ModelGroup newInstance();

        public boolean equals(Object o) {
            if (!(o instanceof ModelGroup))
                return false;
            ModelGroup el = (ModelGroup) o;
            if (minOccurs != el.minOccurs)
                return false;
            if (maxOccurs != el.maxOccurs)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((minOccurs == null) ? 0 : minOccurs.hashCode());
            result = 37*result + ((maxOccurs == null) ? 0 : maxOccurs.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }

    ////////////////////////////////////////////////////////////////
    // See XML Schema sequence.
    public class Sequence extends ModelGroup {
        public Sequence() {
        }

        public String getName() {
            return "sequence";
        }

        public Map validSubElementTypeMap() {
            return sequenceValidSubElementTypeMap;
        }

        protected ModelGroup newInstance() {
            return new Sequence();
        }
    }
    static private Map sequenceValidSubElementTypeMap = null;
    static {
        sequenceValidSubElementTypeMap = new HashMap();
        sequenceValidSubElementTypeMap.put(Annotation.class, null);
        sequenceValidSubElementTypeMap.put(Element.class, null);
        sequenceValidSubElementTypeMap.put(Any.class, null);
        sequenceValidSubElementTypeMap.put(Choice.class, null);
        sequenceValidSubElementTypeMap.put(Sequence.class, null);
        sequenceValidSubElementTypeMap.put(Group.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class Choice extends ModelGroup {
        public Choice() {
        }

        public String getName() {
            return "choice";
        }

        public Map validSubElementTypeMap() {
            return choiceValidSubElementTypeMap;
        }

        protected ModelGroup newInstance() {
            return new Choice();
        }
    }
    static private Map choiceValidSubElementTypeMap = null;
    static {
        choiceValidSubElementTypeMap = new HashMap();
        choiceValidSubElementTypeMap.put(Annotation.class, null);
        choiceValidSubElementTypeMap.put(Element.class, null);
        choiceValidSubElementTypeMap.put(Any.class, null);
        choiceValidSubElementTypeMap.put(Choice.class, null);
        choiceValidSubElementTypeMap.put(Sequence.class, null);
        choiceValidSubElementTypeMap.put(Group.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class All extends ModelGroup {
        public All() {
        }

        public String getName() {
            return "all";
        }

        public Map validSubElementTypeMap() {
            return allValidSubElementTypeMap;
        }

        protected ModelGroup newInstance() {
            return new All();
        }
    }
    static private Map allValidSubElementTypeMap = null;
    static {
        allValidSubElementTypeMap = new HashMap();
        allValidSubElementTypeMap.put(Annotation.class, null);
        allValidSubElementTypeMap.put(Element.class, null);
        allValidSubElementTypeMap.put(Any.class, null);
    }

    ////////////////////////////////////////////////////////////////
    public class Group extends ModelGroup implements CanRef {
        private String name;
        private String ref;
        
        public Group() {
        }

        public Group(String n) {
            if (n != null && !n.equals("")) {
                name = normalizeTargetNamespace(n).intern();
                putSchemaTypeDef(name, this);
            }
        }

        public ElementExpr optimize() {
            if (ref != null)
                return this;
            return super.optimize();
        }
        
        public String getName() {
            return "group";
        }

        public String getGroupName() {
            return name;
        }

        public boolean hasRef() {
            return getRef() != null;
        }

        /**
         * May return null.
         */
        public String getRef() {
            return ref;
        }

        public Group getRefGroup() {
            if (ref == null)
                return null;
            Object o = getSchemaTypeDef(ref);
            if (o instanceof Group) {
                Group referredGroup = (Group) o;
                return referredGroup;
            } else {
                throw new IllegalStateException(Common.getMessage("MSG_FailedToFindRef",
                                                                  ref.toString(),
                                                                  this.toString()));
            }
        }

        public ElementExpr getRefElementExpr() {
            return getRefGroup();
        }

        public Map validSubElementTypeMap() {
            return groupValidSubElementTypeMap;
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (name != null)
                sb.append(" name='"+name+"'");
            if (ref != null)
                sb.append(" ref='"+ref+"'");
            return sb.toString();
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String myName = node.getAttribute("name");	// NOI18N
            String myRef = node.getAttribute("ref");	// NOI18N
            Group g = new Group(myName);
            if (myRef != null && !myRef.equals(""))
                g.ref = myRef.intern();
            pushCurrent(g);
            read(node);
            popCurrent();
        }

        protected ModelGroup newInstance() {
            return new Group();
        }

        public boolean equals(Object o) {
            if (!(o instanceof AttributeGroup))
                return false;
            AttributeGroup el = (AttributeGroup) o;
            if (name != el.name)
                return false;
            if (ref != el.ref)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((name == null) ? 0 : name.hashCode());
            result = 37*result + ((ref == null) ? 0 : ref.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map groupValidSubElementTypeMap = null;
    static {
        groupValidSubElementTypeMap = new HashMap();
        groupValidSubElementTypeMap.put(All.class, null);
        groupValidSubElementTypeMap.put(Choice.class, null);
        groupValidSubElementTypeMap.put(Sequence.class, null);
        groupValidSubElementTypeMap.put(Annotation.class, null);
    }

    ////////////////////////////////////////////////////////////////
    // See XML Schema annotation
    // (an XML Schema comment)
    public class Annotation extends ContainsSubElements {
        public Annotation() {
        }

        public String getName() {
            return "annotation";
        }

        public String getContentName() {
            return null;
        }

        public ElementExpr optimize() {
            super.optimize();
            if (subElements.size() == 0)
                return null;
            return this;
        }

        public boolean compressWhiteSpaceInner() {
            return true;
        }
        
        public boolean writeDTDName(StringBuffer out) {
            return false;
        }

        public void readSchema(org.w3c.dom.Element node) {
            Annotation el = new Annotation();
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public Map validSubElementTypeMap() {
            return annotationValidSubElementTypeMap;
        }
    }
    static private Map annotationValidSubElementTypeMap = null;
    static {
        annotationValidSubElementTypeMap = new HashMap();
        annotationValidSubElementTypeMap.put(AppInfo.class, null);
        annotationValidSubElementTypeMap.put(Documentation.class, null);
    }


    ////////////////////////////////////////////////////////////////
    // See XML Schema appInfo
    public class AppInfo extends ContainsSubElements {
        public AppInfo() {
        }

        public String getContentName() {
            return null;
        }

        public boolean compressWhiteSpaceOuter() {
            return true;
        }
        
        public boolean compressWhiteSpaceInner() {
            return true;
        }
        
        public String getName() {
            return "appinfo";
        }

        public ElementExpr optimize() {
            super.optimize();
            if (subElements.size() == 0)
                return null;
            return this;
        }

        public boolean writeDTDName(StringBuffer out) {
            return false;
        }

        public void readSchema(org.w3c.dom.Element node) {
            AppInfo el = new AppInfo();
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public Map validSubElementTypeMap() {
            return appInfoValidSubElementTypeMap;
        }
    }
    static private Map appInfoValidSubElementTypeMap = null;
    static {
        appInfoValidSubElementTypeMap = new HashMap();
        appInfoValidSubElementTypeMap.put(AnyNode.class, null);
        appInfoValidSubElementTypeMap.put(TextNode.class, null);
    }


    ////////////////////////////////////////////////////////////////
    // See XML Schema documentation
    public class Documentation extends ContainsSubElements {
        public Documentation() {
        }

        public String getContentName() {
            return null;
        }

        public boolean compressWhiteSpaceOuter() {
            return true;
        }
        
        public boolean compressWhiteSpaceInner() {
            return true;
        }
        
        public String getName() {
            return "documentation";
        }

        public boolean writeDTDName(StringBuffer out) {
            return false;
        }

        public void readSchema(org.w3c.dom.Element node) {
            Documentation el = new Documentation();
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public Map validSubElementTypeMap() {
            return documentationValidSubElementTypeMap;
        }
    }
    static private Map documentationValidSubElementTypeMap = null;
    static {
        documentationValidSubElementTypeMap = new HashMap();
        documentationValidSubElementTypeMap.put(AnyNode.class, null);
        documentationValidSubElementTypeMap.put(TextNode.class, null);
    }


    ////////////////////////////////////////////////////////////////
    // This represents any undefined node
    public class AnyNode extends ContainsSubElements {
        protected String name;
        protected String value;

        public AnyNode(String n, String v) {
            name = n;
            value = v;
        }

        public String getContentName() {
            return name;
        }

        public String getName() {
            return name;
        }

        public String getValue() {
            return value;
        }

        public boolean compressWhiteSpaceInner() {
            return findSubElement("TextNode") != null;
        }
        
        public ElementExpr optimize() {
            super.optimize();
            if (name == null && value == null && subElements.size() == 0)
                return null;
            return this;
        }

        public boolean writeDTDName(StringBuffer out) {
            return false;
        }

        public void writeXMLSchema(XMLWriter out) throws IOException {
            if (value == null)
                this.writeXMLSchema(out, true);
            else {
                out.startTag(getName());
                XMLUtil.printXML(out, value, false);
                this.writeXMLSchema(out, false);
                out.endTag();
            }
        }

        public void readSchema(org.w3c.dom.Element node) {
            String myName = node.getLocalName();
            String myValue = node.getNodeValue();
            AnyNode el = new AnyNode(myName, myValue);

            // Should read in attributes too.
            //System.out.println("Just read AnyNode: myName="+myName+" myValue="+myValue);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public String toString() {
            return "AnyNode("+name+")";
        }

        public Map validSubElementTypeMap() {
            return anyNodeValidSubElementTypeMap;
        }

        public boolean equals(Object o) {
            if (!(o instanceof AnyNode))
                return false;
            AnyNode el = (AnyNode) o;
            //System.out.println("value="+value+" el.value="+el.value);
            if (value == null) {
                if (el.value != null)
                    return false;
            } else if (!value.equals(el.value))
                return false;
            if (name == null) {
                if (el.name != null)
                    return false;
            } else if (!name.equals(el.name))
                return false;
            return true;
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((value == null) ? 0 : value.hashCode());
            result = 37*result + ((name == null) ? 0 : name.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map anyNodeValidSubElementTypeMap = null;
    static {
        anyNodeValidSubElementTypeMap = new HashMap();
        anyNodeValidSubElementTypeMap.put(AnyNode.class, null);
        anyNodeValidSubElementTypeMap.put(TextNode.class, null);
    }

    ////////////////////////////////////////////////////////////////
    // This represents a text element and allows for subelements.
    public class TextNode extends ContainsSubElements {
        protected String text;

        public TextNode(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public String getName() {
            return "TextNode";
        }

        public String getContentName() {
            return null;
        }

        public boolean compressWhiteSpaceInner() {
            return true;
        }
        
        public ElementExpr optimize() {
            super.optimize();
            if (text == null || text.equals(""))
                return null;
            return this;
        }

        public boolean writeDTDName(StringBuffer out) {
            return false;
        }

        public void writeXMLSchema(XMLWriter out) throws IOException {
            XMLUtil.printXML(out, text, false);
            this.writeXMLSchema(out, false);
        }

        public void readSchema(org.w3c.dom.Element node) {
            readSchema((Text) node);
        }

        public void readSchema(Text node) {
            TextNode el = new TextNode(node.getData());
            //System.out.println("Just read TextNode: myName="+myName+" myValue="+myValue);
            pushCurrent(el);
            read(node);
            popCurrent();
        }
        
        public String toString() {
            return "TextNode("+text+")";
        }

        public Map validSubElementTypeMap() {
            return textNodeValidSubElementTypeMap;
        }

        public boolean equals(Object o) {
            if (!(o instanceof TextNode))
                return false;
            TextNode el = (TextNode) o;
            if (text == null) {
                if (el.text != null)
                    return false;
            } else if (!text.equals(el.text))
                return false;
            return true;
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((text == null) ? 0 : text.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map textNodeValidSubElementTypeMap = null;
    static {
        textNodeValidSubElementTypeMap = new HashMap();
        textNodeValidSubElementTypeMap.put(AnyNode.class, null);
        textNodeValidSubElementTypeMap.put(TextNode.class, null);
    }

    ////////////////////////////////////////////////////////////////
    // See XML Schema element
    // This implementation is missing attributes right now.
    public class Element extends ContainsSubElements implements MinMaxOccurs, CanRef {
        private String elementName;
        private String elementNamespace;
        // If type is set and there are subelements, then the type
        // is a "comment" about which java type should be used.
        private String type;
        private String xmlSchemaType;
        private String ref;
        private String minOccurs;
        private String maxOccurs;
        private boolean nillable = false;
        private String defaultValue;

        protected Element(String n, String t) {
            this(n);
            setType(t);
            putSchemaTypeDef(type, this);
        }

        protected Element(String n) {
            init();
            setElementName(n);
            type = null;
        }

        private void init() {
            minOccurs = "1";
            maxOccurs = "1";
        }

        public String getName() {
            return "element";
        }

        public String getContentName() {
            return elementName;
        }

        private void setElementName(String n) {
            if (n != null && !n.equals("")) {
                elementNamespace = namespaceOf(n);
                if (elementNamespace == null) {
                    elementNamespace = targetNamespace;
                    elementName = n;
                } else {
                    elementName = removeNamespace(n);
                }
            } else {
                elementName = null;
                elementNamespace = null;
            }
        }
        
        public String getElementName() {
            return elementName;
        }

        public String getElementNamespace() {
            return elementNamespace;
        }

        public String getType() {
            return type;
        }

        public boolean hasRef() {
            return getRef() != null;
        }

        /**
         * May return null.
         */
        public String getRef() {
            return ref;
        }

        public Element getRefElement() {
            if (ref == null)
                return null;
            Element referredElement = getDefinedElement(ref);
            return referredElement;
        }

        public ElementExpr getRefElementExpr() {
            return getRefElement();
        }

        /**
         * Set the type of this element.  The String passed in, @t, should
         * be a java type like 'java.lang.Integer' or
         * 'com.sun.forte4j.webdesigner.SOAPTest.Foo' or 'float'.  
         * This type will later get converted into the XML Schema type
         * ('int' -> 'xsd:int', 'java.lang.String' -> 'xsd:string').
         */
        public void setType(String t) {
            if (t != null)
                t = t.intern();
            if ("void" == t)
                t = null;
            String oldType = type;
            type = t;
            if (schemaTypeDefs.containsKey(oldType))  // FIXME
                schemaTypeDefs.remove(oldType);
            if (t == null)
                return;
            putSchemaTypeDef(type, this);
            ref = null;
            if (debug)
                System.out.println("setType("+t+")");
            if (optionallyDefinedTypes.containsKey(t)) {
                //System.out.println("Found it!");
                requiredPredefinedTypes.put(t, "keep");  // Keep this one.  NOI18N
            }
        }

        /**
         * Bypass setType's converstion from java type to XML Schema type.
         * @t should be the XML Schema type.  This should only be used
         * for types that are defined previously in this schema
         * or have special meaning to the eventual reader of this schema
         * (like, 'SOAP-INC:Array').
         */
        public void setXMLSchemaType(String t) {
            if (t == null) {
                xmlSchemaType = null;
            } else {
                xmlSchemaType = normalizeDocumentNamespace(t).intern();
                ref = null;
            }
        }

        public String getJavaType() {
            //System.out.println("Element.getJavaType: type="+type+" ref="+ref+" xmlSchemaType="+xmlSchemaType);
            if (type != null)
                return type;
            if (ref != null) {
                Element referredElement = getRefElement();
                //System.out.println("Found "+referredElement);
                return referredElement.getJavaType();
            }
            if (xmlSchemaType == null)
                return null;
            String javaType = schemaTypeToJavaType(xmlSchemaType);
            if (nillable) {
                javaType = JavaUtil.toObjectType(javaType);
            }
            return javaType;
        }

        public String getXMLSchemaType() {
            return xmlSchemaType;
        }
        
        public void setMinOccurs(String mino) {
            if (mino == null)
                mino = "1";
            minOccurs = mino.intern();
        }

        public void setMaxOccurs(String maxo) {
            if (maxo == null)
                maxo = "1";
            maxOccurs = maxo.intern();
        }

        public String getMinOccurs() {
            return minOccurs;
        }

        public String getMaxOccurs() {
            return maxOccurs;
        }

        public boolean isNillable() {
            return nillable;
        }

        public String getDefault() {
            return defaultValue;
        }

        public void setDefault(String d) {
            defaultValue = d;
        }

        public void writeDTD(StringBuffer out) {
            Element firstElement = (Element) elementTable.get(getElementName());
            if (firstElement == null)
                elementTable.put(getElementName(), this);
            else {
                // Gotta compare
                if (debug)
                    System.out.println("Found another element named "+getElementName());
                if (!equals(firstElement)) {
                    throw new RuntimeException(Common.getMessage("MSG_SameNameDifferentContents", getElementName()));
                }
                return;
            }

            out.append("\n");

            // Now tell the subelements to print themselves out too
            super.writeDTD(out);
        }

        public boolean hasNamedSubElements() {
            if (subElements.size() == 0) {
                return false;
            } else {
                if (!writeDTDSubElementNames(new StringBuffer()))
                    return false;
                else
                    return true;
            }
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (elementName != null) {
                sb.append(" name='");
                if (elementNamespace != null && !elementNamespace.equals(targetNamespace)) {
                    sb.append(getNamespace(elementNamespace));
                    sb.append(':');
                }
                sb.append(elementName);
                sb.append("'");
            }
            if (ref != null) {
                sb.append(" ref='");
                sb.append(ref);
                sb.append("'");
            }
            if (xmlSchemaType != null) {
                sb.append(" type='");
                sb.append(xmlSchemaType);
                sb.append("'");
            } else if (type != null) {
                String theXmlSchemaType = javaType2XMLSchemaTypeComplex(getType());
                if (theXmlSchemaType != null) {
                    sb.append(" type='");
                    sb.append(theXmlSchemaType);
                    sb.append("'");
                } else {
                    //throw new IllegalStateException(Common.getMessage("MSG_FailedToFindXMLSchemaType", type));
                }
            }
            if (minOccurs != "1")
                sb.append(" minOccurs='"+minOccurs+"'");
            if (maxOccurs != "1")
                sb.append(" maxOccurs='"+maxOccurs+"'");
            if (nillable)
                sb.append(" nillable='true'");
            if (defaultValue != null)
                sb.append(" default='"+defaultValue+"'");
            return sb.toString();
        }

        public boolean isDefiningNewType() {
            if (ref == null)
                return true;
            return (subElements.size() >= 1 && type != null);
        }
        
        public boolean writeDTDName(StringBuffer out) {
            out.append(getElementName());
            if ("unbounded" == maxOccurs)
                out.append("*");
            return true;
        }

        public Map validSubElementTypeMap() {
            return elementValidSubElementTypeMap;
        }

        public void readSchema(org.w3c.dom.Element node) {
            String elementName = node.getAttribute("name");	// NOI18N
            String elementType = node.getAttribute("type");	// NOI18N
            String elementRef = node.getAttribute("ref");	// NOI18N
            String minOccurs = node.getAttribute("minOccurs");	// NOI18N
            String maxOccurs = node.getAttribute("maxOccurs");	// NOI18N
            String myNillable = node.getAttribute("nillable");	// NOI18N
            String myDefault = node.getAttribute("default");	// NOI18N
            Element el = new Element(elementName);
            if (elementRef != null && !elementRef.equals(""))
                el.ref = elementRef.intern();
            if (elementType != null && !elementType.equals(""))
                el.setXMLSchemaType(elementType);
            if (minOccurs != null && !minOccurs.equals(""))
                el.setMinOccurs(minOccurs);
            if (maxOccurs != null && !maxOccurs.equals(""))
                el.setMaxOccurs(maxOccurs);
            if (myNillable != null && (myNillable.equals("true") || myNillable.equals("yes") || myNillable.equals("on")))
                el.nillable = true;
            if (myDefault != null && !"".equals(myDefault))
                el.setDefault(myDefault);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public boolean equals(Object o) {
            if (!(o instanceof Element))
                return false;
            Element el = (Element) o;
            //System.out.println("type="+type);
            if (type != el.type)
                return false;
            if (ref != el.ref)
                return false;
            if (xmlSchemaType != el.xmlSchemaType)
                return false;
            if (minOccurs != el.minOccurs)
                return false;
            if (maxOccurs != el.maxOccurs)
                return false;
            if (nillable != el.nillable)
                return false;

            if (!elementName.equals(el.elementName))
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((type == null) ? 0 : type.hashCode());
            result = 37*result + ((ref == null) ? 0 : ref.hashCode());
            result = 37*result + ((xmlSchemaType == null) ? 0 : xmlSchemaType.hashCode());
            result = 37*result + ((minOccurs == null) ? 0 : minOccurs.hashCode());
            result = 37*result + ((maxOccurs == null) ? 0 : maxOccurs.hashCode());
            result = 37*result + (nillable ? 1 : 0);
            result = 37*result + ((elementName == null) ? 0 : elementName.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map elementValidSubElementTypeMap = null;
    static {
        elementValidSubElementTypeMap = new HashMap();
        elementValidSubElementTypeMap.put(Annotation.class, null);
        elementValidSubElementTypeMap.put(SimpleType.class, null);
        elementValidSubElementTypeMap.put(ComplexType.class, null);
        elementValidSubElementTypeMap.put(Unique.class, null);
        elementValidSubElementTypeMap.put(Key.class, null);
        elementValidSubElementTypeMap.put(KeyRef.class, null);
    }

    public class Any extends ContainsSubElements implements MinMaxOccurs {
        private String minOccurs;
        private String maxOccurs;
        private String namespace;
        private String processContents;

        public Any() {
            init();
        }

        private void init() {
            minOccurs = "1";
            maxOccurs = "1";
        }

        public String getName() {
            return "any";
        }

        public String getContentName() {
            return null;
        }

        public String getNamespace() {
            return namespace;
        }

        public void setNamespace(String n) {
            namespace = (n == null) ? null : n.intern();
        }

        public String getProcessContents() {
            return processContents;
        }

        public void setProcessContents(String pc) {
            processContents = (pc == null) ? null : pc.intern();
        }

        public void setMinOccurs(String mino) {
            if (mino == null)
                mino = "1";
            minOccurs = mino.intern();
        }

        public void setMaxOccurs(String maxo) {
            if (maxo == null)
                maxo = "1";
            maxOccurs = maxo.intern();
        }

        public String getMinOccurs() {
            return minOccurs;
        }

        public String getMaxOccurs() {
            return maxOccurs;
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (minOccurs != "1")
                sb.append(" minOccurs='"+minOccurs+"'");
            if (maxOccurs != "1")
                sb.append(" maxOccurs='"+maxOccurs+"'");
            if (namespace != null)
                sb.append(" namespace='"+namespace+"'");
            if (processContents != null)
                sb.append(" processContents='"+processContents+"'");
             return sb.toString();
       }

        public Map validSubElementTypeMap() {
            return anyValidSubElementTypeMap;
        }

        public boolean writeDTDName(StringBuffer out) {
            return false;
        }

        public void readSchema(org.w3c.dom.Element node) {
            String namespace = node.getAttribute("namespace");	// NOI18N
            String processContents = node.getAttribute("processContents");	// NOI18N
            String minOccurs = node.getAttribute("minOccurs");	// NOI18N
            String maxOccurs = node.getAttribute("maxOccurs");	// NOI18N
            Any el = new Any();
            if (namespace != null && !namespace.equals(""))
                el.setNamespace(namespace);
            if (processContents != null && !processContents.equals(""))
                el.setProcessContents(processContents);
            if (minOccurs != null && !minOccurs.equals(""))
                el.setMinOccurs(minOccurs);
            if (maxOccurs != null && !maxOccurs.equals(""))
                el.setMaxOccurs(maxOccurs);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public boolean equals(Object o) {
            if (!(o instanceof Any))
                return false;
            Any el = (Any) o;
            if (minOccurs != el.minOccurs)
                return false;
            if (maxOccurs != el.maxOccurs)
                return false;
            if (namespace != el.namespace)
                return false;
            if (processContents != el.processContents)
                return false;
            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((namespace == null) ? 0 : namespace.hashCode());
            result = 37*result + ((processContents == null) ? 0 : processContents.hashCode());
            result = 37*result + ((minOccurs == null) ? 0 : minOccurs.hashCode());
            result = 37*result + ((maxOccurs == null) ? 0 : maxOccurs.hashCode());
            return result;
        }
    }
    static private Map anyValidSubElementTypeMap = null;
    static {
        anyValidSubElementTypeMap = new HashMap();
        anyValidSubElementTypeMap.put(Annotation.class, null);
    }
    
    public class AnyAttribute extends ContainsSubElements {
        private String namespace;
        private String processContents;

        public AnyAttribute() {
        }

        public String getName() {
            return "anyAttribute";
        }

        public String getContentName() {
            return null;
        }

        public String getNamespace() {
            return namespace;
        }

        public void setNamespace(String n) {
            namespace = (n == null) ? null : n.intern();
        }

        public String getProcessContents() {
            return processContents;
        }

        public void setProcessContents(String pc) {
            processContents = (pc == null) ? null : pc.intern();
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (namespace != null)
                sb.append(" namespace='"+namespace+"'");
            if (processContents != null)
                sb.append(" processContents='"+processContents+"'");
             return sb.toString();
       }

        public Map validSubElementTypeMap() {
            return anyAttributeValidSubElementTypeMap;
        }

        public boolean writeDTDName(StringBuffer out) {
            return false;
        }

        public void readSchema(org.w3c.dom.Element node) {
            String namespace = node.getAttribute("namespace");	// NOI18N
            String processContents = node.getAttribute("processContents");	// NOI18N
            AnyAttribute el = new AnyAttribute();
            if (namespace != null && !namespace.equals(""))
                el.setNamespace(namespace);
            if (processContents != null && !processContents.equals(""))
                el.setProcessContents(processContents);
            pushCurrent(el);
            read(node);
            popCurrent();
        }

        public boolean equals(Object o) {
            if (!(o instanceof AnyAttribute))
                return false;
            AnyAttribute el = (AnyAttribute) o;
            if (namespace != el.namespace)
                return false;
            if (processContents != el.processContents)
                return false;
            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((namespace == null) ? 0 : namespace.hashCode());
            result = 37*result + ((processContents == null) ? 0 : processContents.hashCode());
            return result;
        }
    }
    static private Map anyAttributeValidSubElementTypeMap = null;
    static {
        anyAttributeValidSubElementTypeMap = new HashMap();
        anyAttributeValidSubElementTypeMap.put(Annotation.class, null);
    }
    
    ////////////////////////////////////////////////////////////////
    // An Schema Attribute
    // An XML Schema attribute may contain simpleType as a subelement
    // and/or annotation.
    public class Attribute extends ContainsSubElements implements CanRef {
        private String namespace;
        private String name;
        private String type;
        private String defaultValue;
        private String id;
        private String ref;
        private String fixed;
        private String use;
        private String arrayType;	// for rpc/encoded WSDL

        public Attribute(String n) {
            this(n, targetNamespace);
        }

        public Attribute(String n, String ns) {
            this(n, ns, null);
        }
        
        public Attribute(String n, String ns, String type) {
            if (n == null || n.equals(""))
                name = null;
            else
                name = n.intern();
            namespace = ns;
            setType(type);
        }

        public String getName() {
            return "attribute";
        }

        public String getContentName() {
            return "@"+name;
        }

        public String getAttributeName() {
            if (namespace == null || namespace.equals(targetNamespace)) {
                return name;
            }
            return getNamespace(namespace)+":"+name;
        }

        public String getAttributeNamespace() {
            return namespace;
        }

        public String getAttributeNameNoNS() {
            return name;
        }

        private void setType(String ty) {
            if (ty == null) {
                type = null;
                return;
            }
            type = normalizeDocumentNamespace(ty).intern();
        }

        public String getType() {
            return type;
        }

        public String getJavaType() {
            if (type == null)
                return null;
            String javaType = schemaTypeToJavaType(type);
            if (false) {
                javaType = JavaUtil.toObjectType(javaType);
            }
            return javaType;
        }

        public String getFixed() {
            return fixed;
        }

        public boolean isRequired() {
            return use == "required";
        }

        public boolean isOptional() {
            return use == "optional";
        }

        public boolean isProhibited() {
            return use == "prohibited";
        }

        public boolean isAttributeNamed(String n) {
            n = resolveNamespace(n);
            String fullName = resolveNamespace(namespace, name);
            return n.equals(fullName);
        }
        
        public boolean hasRef() {
            return getRef() != null;
        }

        /**
         * May return null.
         */
        public String getRef() {
            return ref;
        }

        public Attribute getRefAttribute() {
            if (ref == null)
                return null;
            Object o = definedAttributes.get(ref);
            if (o instanceof Attribute) {
                Attribute referredAttribute = (Attribute) o;
                return referredAttribute;
            } else {
                throw new IllegalStateException(Common.getMessage("MSG_FailedToFindRef",
                                                                  ref.toString(),
                                                                  this.toString()));
            }
        }

        public ElementExpr getRefElementExpr() {
            return getRefAttribute();
        }

        public boolean isDefiningNewType() {
            if (ref == null)
                return true;
            return (subElements.size() >= 1 && type != null);
        }

        public String getArrayType() {
            return arrayType;
        }

        public String getDefaultValue() {
            return defaultValue;
        }

        public void writeDTD(StringBuffer out) {
            writeDTD(out, "UNKNOWN");
        }
        
        public void writeDTD(StringBuffer out, String elementName) {
            out.append("\n");
        }
        
        public boolean writeDTDName(StringBuffer out) {
            out.append(name);
            return false;
        }

        public void validate() {
            
            super.validate();
        }

        public Map validSubElementTypeMap() {
            return attributeValidSubElementTypeMap;
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (name != null)
                sb.append(" name='"+getAttributeName()+"'");
            if (type != null)
                sb.append(" type='"+type+"'");
            if (fixed != null) {
                sb.append(" fixed='");
                XMLUtil.printXML(sb, fixed, true);
                sb.append("'");
            }
            if (ref != null)
                sb.append(" ref='"+ref+"'");
            if (id != null)
                sb.append(" id='"+id+"'");
            if (defaultValue != null) {
                sb.append(" default='");
                XMLUtil.printXML(sb, defaultValue, true);
                sb.append("'");
            }
            if (use != null)
                sb.append(" use='"+use+"'");
            if (arrayType != null)
                sb.append(" wsdl:arrayType='"+arrayType+"'");
            return sb.toString();
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String myName = node.getAttribute("name");	// NOI18N
            String myType = node.getAttribute("type");	// NOI18N
            String myFixed = node.getAttribute("fixed");	// NOI18N
            String myRef = node.getAttribute("ref");	// NOI18N
            String myId = node.getAttribute("id");	// NOI18N
            String myDefault = node.getAttribute("default");	// NOI18N
            String myUse = node.getAttribute("use");	// NOI18N
            String myArrayType = node.getAttributeNS("http://schemas.xmlsoap.org/wsdl/", "arrayType");

            Attribute attr = new Attribute(myName);
            if (myType != null && !myType.equals(""))
                attr.setType(myType.intern());
            if (myFixed != null && !myFixed.equals(""))
                attr.fixed = myFixed.intern();
            if (myRef != null && !myRef.equals(""))
                attr.ref = myRef.intern();
            if (myId != null && !myId.equals(""))
                attr.id = myId.intern();
            if (myDefault != null && !myDefault.equals(""))
                attr.defaultValue = myDefault.intern();
            if (myUse != null && !myUse.equals(""))
                attr.use = myUse.intern();
            if (myArrayType != null && !myArrayType.equals(""))
                attr.arrayType = myArrayType.intern();
            pushCurrent(attr);
            read(node);
            popCurrent();
        }

        public boolean equals(Object o) {
            if (!(o instanceof Attribute))
                return false;
            Attribute el = (Attribute) o;
            if (name != el.name)
                return false;
            if (type != el.type)
                return false;
            if (fixed != el.fixed)
                return false;
            if (ref != el.ref)
                return false;
            if (id != el.id)
                return false;
            if (use != el.use)
                return false;
            if (arrayType != el.arrayType)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((name == null) ? 0 : name.hashCode());
            result = 37*result + ((type == null) ? 0 : type.hashCode());
            result = 37*result + ((fixed == null) ? 0 : fixed.hashCode());
            result = 37*result + ((ref == null) ? 0 : ref.hashCode());
            result = 37*result + ((id == null) ? 0 : id.hashCode());
            result = 37*result + ((use == null) ? 0 : use.hashCode());
            result = 37*result + ((arrayType == null) ? 0 : arrayType.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map attributeValidSubElementTypeMap = null;
    static {
        attributeValidSubElementTypeMap = new HashMap();
        attributeValidSubElementTypeMap.put(Annotation.class, null);
        attributeValidSubElementTypeMap.put(SimpleType.class, null);
    }


    ////////////////////////////////////////////////////////////////
    // An Schema AttributeGroup
    public class AttributeGroup extends ContainsSubElements implements CanRef {
        private String name;
        private String ref;

        public AttributeGroup() {
        }

        /**
         * Create it by name.
         */
        public AttributeGroup(String n) {
            if (n != null && !n.equals("")) {
                name = normalizeTargetNamespace(n).intern();
                putSchemaTypeDef(name, this);
            }
        }

        public Map validSubElementTypeMap() {
            return attributeGroupValidSubElementTypeMap;
        }

        public String getName() {
            return "attributeGroup";
        }

        public String getContentName() {
            return name;
        }

        public String getGroupName() {
            return name;
        }

        public boolean hasRef() {
            return getRef() != null;
        }

        public String getRef() {
            return ref;
        }

        public AttributeGroup getRefAttributeGroup() {
            if (ref == null)
                return null;
            Object o = getSchemaTypeDef(ref);
            if (o instanceof AttributeGroup) {
                AttributeGroup referredGroup = (AttributeGroup) o;
                return referredGroup;
            } else {
                throw new IllegalStateException(Common.getMessage("MSG_FailedToFindRef",
                                                                  ref.toString(),
                                                                  this.toString()));
            }
        }

        public ElementExpr getRefElementExpr() {
            return getRefAttributeGroup();
        }
        
        public boolean writeDTDName(StringBuffer out) {
            return writeDTDSubElementNames(out, false);
        }

        public String getAttributeString() {
            StringBuffer sb = new StringBuffer();
            if (name != null)
                sb.append(" name='"+name+"'");
            if (ref != null)
                sb.append(" ref='"+ref+"'");
            return sb.toString();
        }
        
        public void readSchema(org.w3c.dom.Element node) {
            String myName = node.getAttribute("name");	// NOI18N
            String myRef = node.getAttribute("ref");	// NOI18N
            AttributeGroup ag = new AttributeGroup(myName);
            if (myRef != null && !myRef.equals(""))
                ag.ref = myRef.intern();
            pushCurrent(ag);
            read(node);
            popCurrent();
        }

        public boolean equals(Object o) {
            if (!(o instanceof AttributeGroup))
                return false;
            AttributeGroup el = (AttributeGroup) o;
            if (name != el.name)
                return false;
            if (ref != el.ref)
                return false;

            return super.equals(el);
        }

        public int hashCode() {
            int result = 17;
            result = 37*result + ((name == null) ? 0 : name.hashCode());
            result = 37*result + ((ref == null) ? 0 : ref.hashCode());
            result = 37*result + super.hashCode();
            return result;
        }
    }
    static private Map attributeGroupValidSubElementTypeMap = null;
    static {
        attributeGroupValidSubElementTypeMap = new HashMap();
        attributeGroupValidSubElementTypeMap.put(Annotation.class, null);
        attributeGroupValidSubElementTypeMap.put(Attribute.class, null);
        attributeGroupValidSubElementTypeMap.put(AttributeGroup.class, null);
        attributeGroupValidSubElementTypeMap.put(AnyAttribute.class, null);
    }

    ////////////////////////////////////////////////////////////////

    //protected String docType;  // Not implemented
    protected Map namespaceTable;	// Map  example: 
    protected String targetNamespace;
    protected String documentNamespace;
    protected ContainsSubElements rootElement;

    // elementTable is used when creating the DTD to make sure that only
    // 1 element of a particular name is ever created.
    protected Map elementTable;   // Map

    // Several simple types are hard coded into this class and put into
    // optionallyDefinedTypes.  They define how to map these simple types into
    // XML Schema types ('java.lang.Integer' -> 'xsd:int').
    protected static Map optionallyDefinedTypes = null;   // Map

    // Top types defined in this schema.  Mapping of java type name into
    // element expressions (just like optionallyDefinedTypes)
    protected Map definedTypes;   // Map
    protected Map definedTypesFull;   // Map

    protected Map definedAttributes;	// Map

    // Standard types
    protected Map predefinedSchemaTypes;	// Map

    // requiredPredefinedTypes gets an entry whenever something in
    // optionallyDefinedTypes is used.
    protected Map requiredPredefinedTypes;   // Map

    // The client adds elements to the current thing on the stack
    protected Stack currentElementStack;  // Stack

    // It's possible to have an Annotation added to the top level
    // and it's checked in writeXMLSchemaStandalone.
    protected Annotation topAnnotation;

    // It's useful for some clients to know what the last popped was.
    protected ElementExpr lastPopped;

    // A sample instance of every node that can be read in.
    protected Map sampleNodes;

    // map from type name to ElementExpr
    private Map schemaTypeDefs;	// Map

    // Whether or not a URL has been included already or not.
    protected Map includedAlready = new HashMap();	// 

    private String currentParsedURI;

    private boolean useBigDataTypes = true;

    public SchemaRep() {
        init();
    }

    public SchemaRep(Document schemaDoc, String uri) {
        init();
        currentParsedURI = uri;
        readDocument(schemaDoc);
    }

    public SchemaRep(Document schemaDoc, String uri, boolean useBigDataTypes) {
        this.useBigDataTypes = useBigDataTypes;
        init();
        currentParsedURI = uri;
        readDocument(schemaDoc);
    }

    private void init() {
        targetNamespace = null;
        documentNamespace = null;
        namespaceTable = new HashMap();
        addToNamespace("xml", "http://www.w3.org/XML/1998/namespace");
        addToNamespace("xsd", XSD_NS);

        schemaTypeDefs = new HashMap();
        predefinedSchemaTypes = new HashMap();
        insertPredefinedSchemaTypes(predefinedSchemaTypes);

        currentElementStack = new Stack();
        topAnnotation = null;
        definedTypes = new HashMap();
        definedTypesFull = new HashMap();
        definedAttributes = new HashMap();
        //mapSimpleJavaTypesPredefined(definedTypes);
        mapSimpleAttributes(definedAttributes);
        requiredPredefinedTypes = new HashMap();
        if (optionallyDefinedTypes == null) {
            optionallyDefinedTypes = new HashMap();
            mapSimpleJavaTypesOptional(optionallyDefinedTypes);
        }

        // sampleNodes are used while reading an XML Schema in
        sampleNodes = new HashMap();
        putSampleNode(new Element("dummy"));	// NOI18N
        putSampleNode(new ComplexType());
        putSampleNode(new SimpleType(null));	// NOI18N
        putSampleNode(new Restriction());
        putSampleNode(new Sequence());
        putSampleNode(new Choice());
        putSampleNode(new All());
        putSampleNode(new Group());
        putSampleNode(new Annotation());
        putSampleNode(new AppInfo());
        putSampleNode(new Documentation());
        putSampleNode(new Attribute("dummy"));	// NOI18N
        putSampleNode(new AttributeGroup());
        putSampleNode(new MaxExclusive("dummy"));	// NOI18N
        putSampleNode(new MinExclusive("dummy"));	// NOI18N
        putSampleNode(new Enumeration("dummy"));	// NOI18N
        putSampleNode(new Pattern("dummy"));	// NOI18N
        putSampleNode(new MinLength("0"));	// NOI18N
        putSampleNode(new MaxLength("0"));	// NOI18N
        putSampleNode(new TotalDigits("dummy"));	// NOI18N
        putSampleNode(new MinInclusive("dummy"));	// NOI18N
        putSampleNode(new MaxInclusive("dummy"));	// NOI18N
        putSampleNode(new FractionDigits("dummy"));	// NOI18N
        putSampleNode(new Length("dummy"));	// NOI18N
        putSampleNode(new WhiteSpace("dummy"));	// NOI18N
        putSampleNode(new Key());
        putSampleNode(new Unique());
        putSampleNode(new KeyRef());
        putSampleNode(new Selector());
        putSampleNode(new Field());
        putSampleNode(new Include("dummy"));	// NOI18N
        putSampleNode(new Import());
        putSampleNode(new SimpleContent());
        putSampleNode(new ComplexContent());
        putSampleNode(new Extension());
        putSampleNode(new ListElement());
        putSampleNode(new Any());
        putSampleNode(new AnyAttribute());
    }


    /**
     * Example: ns=xsd, URI=http://www.w3.org/2001/XMLSchema
     */
    public void addToNamespace(String ns, String URI) {
        //System.out.println("Adding namespace "+ns+" as "+URI);
        namespaceTable.put(ns, URI);
    }

    /**
     * Return the namespace URI for a given namespace name.
     * Will return null if the namespace URI is unheard of.
     * Example: ns="xsd", returns "http://www.w3.org/2001/XMLSchema"
     */
    public String getNamespaceURI(String ns) {
        return (String) namespaceTable.get(ns);
    }

    /**
     * Return a namespace name for a given namespace URI.  One will
     * be made up, if it doesn't already exist.
     * Example: URI="http://www.w3.org/2001/XMLSchema", returns "xsd"
     */
    public String getNamespace(String URI) {
        //assert !URI.equals("xml");
        String ns;
        Iterator it = namespaceTable.keySet().iterator();
        while (it.hasNext()) {
            ns = (String) it.next();
            if (URI.equals(namespaceTable.get(ns)))
                return ns;
        }
        ns = guessPrefix(URI);
        //System.out.println("guessing ns: ns="+ns+" gets="+namespaceTable.get(ns)+" URI="+URI);
        String baseNs = ns;
        for (int count = 2; namespaceTable.containsKey(ns); ++count)
            ns = baseNs+count;
        namespaceTable.put(ns, URI);
        return ns;
    }

    /**
     * @return the Set of all namespace prefixes in use.
     */
    public Set getAllNamespaces() {
        return namespaceTable.keySet();
    }

    public String getXSDNamespace() {
        String ns = getNamespace(XSD_NS);
        if (ns == null)
            return "xsd";
        return ns;
    }

    public String getXMLNamespace() {
        String ns = getNamespace("http://www.w3.org/XML/1998/namespace");
        if (ns == null)
            return "xml";
        return ns;
    }

    public Attribute getAttribute(String name) {
        if (name == null)
            return null;
        String ns = namespaceOf(name);
        if (ns == null)
            name = resolveNamespace(documentNamespace, removeNamespace(name));
        else
            name = resolveNamespace(ns, removeNamespace(name));
        //System.out.println("getAttribute: looking up "+name);
        Attribute result = (Attribute) definedAttributes.get(name);
        if (result == null && ns == null) {
            // try the other namespace
            name = resolveNamespace(targetNamespace, name);
            //System.out.println("getAttribute2: looking up "+name);
            result = (Attribute) definedAttributes.get(name);
        }
        return result;
    }

    protected void putSampleNode(ElementExpr ee) {
        sampleNodes.put(ee.getName(), ee);
    }

    protected ElementExpr getSampleNode(String name) {
        return (ElementExpr) sampleNodes.get(name);
    }

    public void setTargetNamespace(String ns) {
        targetNamespace = ns;
    }

    public String getTargetNamespace() {
        return targetNamespace;
    }

    public void setCurrentParsedURI(String uri) {
        currentParsedURI = uri;
    }

    protected String getCurrentParsedURI() {
        return currentParsedURI;
    }

    public void setRootElement(ContainsSubElements el) {
        if (debug)
            System.out.println("Changing rootElement of "+this+" to "+el);
        rootElement = el;
    }

    public ContainsSubElements getRootElement() {
        return rootElement;
    }

    public void addToTopAnnotation(ElementExpr subElement) {
        if (topAnnotation == null)
            topAnnotation = new Annotation();
        topAnnotation.addSubElement(subElement);
    }

    public void addAppInfoToTopAnnotation(String name, String value) {
        AppInfo ai = new AppInfo();
        AnyNode ue = new AnyNode(name, value);
        ai.addSubElement(ue);
        addToTopAnnotation(ai);
    }
    
    public void pushCurrent(ElementExpr el) {
        if (currentElementStack.empty()) {
            //System.out.println("Pushing '"+el+"'");
            setRootElement((ContainsSubElements)el);
        } else {
            //System.out.println("Pushing '"+el+"' into '"+peekCurrent()+"'");
            peekCurrentNeedSub().addSubElement(el);
        }
        currentElementStack.push(el);
    }

    /**
     * Create the element, then push it onto the stack, making it the
     * current one.
     */
    public void pushElement(String elementName, String elementType) {
        pushCurrent(createElement(elementName, elementType));
    }

    public void pushSchemaNode() {
        pushCurrent(new SchemaNode());
    }

    public void pushComplexType() {
        pushCurrent(new ComplexType());
    }
    
    public void pushSequence() {
        pushCurrent(new Sequence());
    }
    
    public ElementExpr popCurrent() {
        lastPopped = (ElementExpr) currentElementStack.pop();
        return lastPopped;
    }

    public ElementExpr peekCurrent() {
        return (ElementExpr) currentElementStack.peek();
    }

    /**
     * Same thing as peekCurrent, but the caller needs it to be a
     * ContainsSubElements.  If it isn't an exception is thrown.
     */
    public ContainsSubElements peekCurrentNeedSub() {
        return (ContainsSubElements) currentElementStack.peek();
    }

    public ElementExpr getLastPopped() {
        return lastPopped;
    }

    /**
     * Create an Element an add it to the current one in the stack.
     */
    public void addElement(String name, String type) {
        Element el = createElement(name);
        el.setType(type);
        if (currentElementStack.empty())
            setRootElement(el);
        else
            peekCurrentNeedSub().addSubElement(el);
    }

    /**
     * Create AppInfo and add it to the current thing in the stack.
     */
    public void addAppInfo(String name, String value) {
        ElementExpr e = peekCurrent();
        Annotation ann;
        if (e instanceof Annotation)
            ann = (Annotation) e;
        else
            ann = new Annotation();
        AppInfo ai = new AppInfo();
        AnyNode ue = new AnyNode(name, value);
        ai.addSubElement(ue);
        ann.addSubElement(ai);
        peekCurrentNeedSub().addSubElement(ann);
    }

    /**
     * Only works if the current thing in the stack is an Element.
     * @t should be a java type.
     */
   public void setType(String t) {
        ElementExpr e = peekCurrent();
        if (e instanceof Element)
            ((Element)e).setType(t);
        else
            throw new IllegalStateException(Common.getMessage("MSG_TryingToCallOnWrongClass", "setType", e.getClass()));
    }

    public List findAllSubElements(String name) {
        List lst = new LinkedList();
        rootElement.findAllSubElements(name, lst);
        return lst;
    }

    /**
     * Only works if the current thing in the stack is an Element.
     * @t should be a java type.
     */
    /*
   public void setDefiningType(String t) {
        ElementExpr e = peekCurrent();
        if (e instanceof Element) {
            Element el = (Element) e;
            el.setDefiningType(t);
        } else
            throw new IllegalStateException(Common.getMessage("MSG_TryingToCallOnWrongClass", "setDefiningType", e.getClass()));
    }
    */

    /**
     * Only works if the current thing in the stack is an Element.
     * @t should be a XML Schema type.
     */
   public void setXMLSchemaType(String t) {
        ElementExpr e = peekCurrent();
        if (e instanceof Element)
            ((Element)e).setXMLSchemaType(t);
        else
            throw new IllegalStateException(Common.getMessage("MSG_TryingToCallOnWrongClass", "setXMLSchemaType", e.getClass()));
    }

    /**
     * Only works if the current thin in the stack is an Element or ModelGroup.
     */
    public void setMinOccurs(String t) {
        ElementExpr e = peekCurrent();
        if (e instanceof Element)
            ((Element)e).setMinOccurs(t);
        else if (e instanceof ModelGroup)
            ((ModelGroup)e).setMinOccurs(t);
        else
            throw new IllegalStateException(Common.getMessage("MSG_TryingToCallOnWrongClass", "setMinOccurs", e.getClass()));
    }

    /**
     * Only works if the current thin in the stack is an Element or ModelGroup.
     */
    public void setMaxOccurs(String t) {
        ElementExpr e = peekCurrent();
        if (e instanceof Element)
            ((Element)e).setMaxOccurs(t);
        else if (e instanceof ModelGroup)
            ((ModelGroup)e).setMaxOccurs(t);
        else
            throw new IllegalStateException(Common.getMessage("MSG_TryingToCallOnWrongClass", "setMaxOccurs", e.getClass()));
    }

    /**
     * Return an Element that represents an ELEMENT.
     */
    public Element createElement(String name) {
        Element el = new Element(name);
        return el;
    }

    /**
     * Return an Element that represents an ELEMENT.
     */
    public Element createElement(String name, String type) {
        Element el = new Element(name);
        el.setType(type);
        return el;
    }

    /*
    public Attribute createAttirbute(String name) {
        Attribute attr = (Attribute) attributeTable.get(name);
        if (attr == null) {
            attr = new Attribute(name);
            attributeTable.put(name, attr);
        }
        return attr;
    }
    */

    public void addSubElement(String elementName, ElementExpr subElement) {
        Element el = createElement(elementName);
        el.addSubElement(subElement);
    }

    public void addSubElement(String elementName, List subElements) {
        Element el = createElement(elementName);
        el.addSubElement(subElements);
    }

    public void addSubElement(String elementName, String subElementName) {
        Element subElement = createElement(subElementName);
        addSubElement(elementName, subElement);
    }

    /**
     * This addSubElement creates an Element and then adds it underneath
     * the current one.
     */
    public void addSubElementCurrent(String subElementName) {
        Element subElement = createElement(subElementName);
        peekCurrentNeedSub().addSubElement(subElement);
    }

    /**
     * This is called before writing out a schema.
     */
    public ElementExpr optimize() {
        if (rootElement == null)
            return null;
        return rootElement.optimize();
    }

    /**
     * Returns false if the schema is too simpile to need binding classes.
     */
    /*
    public boolean needsBindingClasses() {
        if (rootElement == null)
            return false;
        System.out.println("rootElement="+rootElement+" .class="+rootElement.getClass());
        if (rootElement instanceof Element) {
            Element root = (Element) rootElement;
            return root.hasNamedSubElements();
        }
        return true;
    }
    */

    /**
     * If you want a DTD written to a Writer, this is the method
     * to call.
     */
    public void writeDTD(Writer out) throws java.io.IOException {
        if (rootElement == null)
            return;
        elementTable = new HashMap();
        optimize();
        rootElement.validate();
        StringBuffer outBuffer = new StringBuffer();
        rootElement.writeDTD(outBuffer);
        out.write(outBuffer.toString());
        elementTable = null;
    }

    /**
     * nice method which returns writeDTD in an InputStream.
     */
    public InputStream dtdInputStream() throws java.io.IOException {
        StringWriter strWriter = new StringWriter();
        PrintWriter pw = new PrintWriter(strWriter);
        writeDTD(pw);
        pw.flush();
        ByteArrayInputStream bais = new ByteArrayInputStream(strWriter.toString().getBytes());
        return bais;
    }

    /**
     * If you want an XML Schema written to a Writer, this is the method
     * to call.
     */
    public void writeXMLSchemaStandalone(Writer out) throws java.io.IOException {
        if (rootElement == null)
            return;
        XMLWriter xw = new XMLWriter();
        ContainsSubElements realRootElement = rootElement;
        if (!(realRootElement instanceof SchemaNode)) {
            SchemaNode sn = new SchemaNode();
            sn.addSubElement(realRootElement);
            realRootElement = sn;
            if (topAnnotation != null) {
                sn.addSubElement(topAnnotation);
            }
        }

        if (true || optimize() != null) {
            realRootElement.validate();
            realRootElement.writeXMLSchema(xw);
        }
        xw.writeTo(out);
    }

    /**
     * Convience method which returns writeXMLSchemaStandalone in an
     * InputStream.
     */
    public InputStream xmlSchemaInputStream() throws java.io.IOException {
        StringWriter strWriter = new StringWriter();
        PrintWriter pw = new PrintWriter(strWriter);
        writeXMLSchemaStandalone(pw);
        pw.flush();
        ByteArrayInputStream bais = new ByteArrayInputStream(strWriter.toString().getBytes());
        return bais;
    }

    public void writeXMLSchema(XMLWriter out) throws IOException {
        if (rootElement == null)
            return;
        rootElement.writeXMLSchema(out);
    }

    public void readSchemaFromLocation(String schemaLocation) throws IOException, SAXException {
        if (debug)
            System.out.println("Reading schema from "+schemaLocation);
        if (schemaLocation == null || "".equals(schemaLocation))
            return;
        
        String oldParsedURI = currentParsedURI;
        try {
            javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            dbf.setIgnoringComments(true);
            dbf.setIgnoringElementContentWhitespace(true);
            javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = null;
            IOException ioException = null;
            SAXException saxException = null;
            try {
                doc = db.parse(schemaLocation);
                currentParsedURI = schemaLocation;
            } catch (java.io.FileNotFoundException e) {
                ioException = e;
            } catch (org.xml.sax.SAXParseException e) {
                // Apache will throw this one for a file not found error,
                // it really should be java.io.FileNotFoundException
                saxException = e;
            }
            if (ioException != null || saxException != null) {
                //System.out.println("currentParsedURI="+currentParsedURI);
                if (currentParsedURI != null) {
                    // Try making a relative URI out of this.
                    java.net.URI uri;
                    try {
                        uri = new java.net.URI(currentParsedURI);
                    } catch (java.net.URISyntaxException e) {
                        uri = new File(currentParsedURI).toURI();
                    }
                    if (debug)
                        System.out.println("uri="+uri);
                    java.net.URI schemaLocationURI = uri.resolve(schemaLocation);
                    currentParsedURI = schemaLocationURI.toString();
                    if (debug)
                        System.out.println("Since the first try failed, now trying to read currentParsedURI:"+ currentParsedURI);
                    doc = db.parse(currentParsedURI);
                    ioException = null;
                    saxException = null;
                }
            }
            if (ioException != null)
                throw ioException;
            if (saxException != null)
                throw saxException;
            org.w3c.dom.Element childNode = doc.getDocumentElement();
            if (childNode != null) {
                if (!childNode.getLocalName().equals("schema"))	// NOI18N
                    throw new IllegalStateException(Common.getMessage("MSG_ExpectedNode", "schema", childNode.getNodeName()));
                // Make sure to preserve the old stuff.
                readSchemaElement(childNode);
            }
        } catch (javax.xml.parsers.ParserConfigurationException e) {
            throw new Schema2BeansRuntimeException(Common.getMessage("MSG_FailedToParse", schemaLocation), e);
        } finally {
            currentParsedURI = oldParsedURI;
        }
    }

    public void readDocument(Document doc) {
        includedAlready.clear();
        org.w3c.dom.Element childNode = doc.getDocumentElement();
        if (childNode != null) {
            if (!childNode.getLocalName().equals("schema"))	// NOI18N
                throw new IllegalStateException(Common.getMessage("MSG_ExpectedNode", "schema", childNode.getNodeName()));
            pushSchemaNode();
            peekCurrentNeedSub().readSchema(childNode);
            readSchemaElement(childNode);
            popCurrent();
        }
    }

    public void readSchemaElement(org.w3c.dom.Element el) {
        NamedNodeMap attrs = el.getAttributes();
        String theTargetNamespace = null;
        String theDocumentNamespaceURI = null;
        for (int i = 0, size = attrs.getLength(); i < size; ++i) {
            Node attr = attrs.item(i);
            //System.out.println("readSchemaElement: attr.prefix="+attr.getPrefix()+" localname="+attr.getLocalName()+" nodename="+attr.getNodeName()+" nodevalue="+attr.getNodeValue());
            if ("xmlns".equals(attr.getPrefix())) {
                addToNamespace(attr.getLocalName(), attr.getNodeValue());
            } else if ("targetNamespace".equals(attr.getNodeName())) {
                theTargetNamespace = attr.getNodeValue();
            } else if ("xmlns".equals(attr.getNodeName())) {
                theDocumentNamespaceURI = attr.getNodeValue();
            }
        }
        if (theDocumentNamespaceURI != null) {
            documentNamespace = theDocumentNamespaceURI;
            //System.out.println("readSchemaElement: just set documentNamespace to "+documentNamespace);
        }
        if (theTargetNamespace != null) {
            // This needs to be done after all the namespaces have been read
            targetNamespace = theTargetNamespace;
            //System.out.println("readSchemaElement: just set targetNamespace to "+targetNamespace);
        }
        read(el);
    }

    protected void read(Node node) {
        String nodeName;
        boolean ignoreUnknown = false;
        boolean keepText = false;
        if (peekCurrent() instanceof AnyNode || peekCurrent() instanceof Documentation || peekCurrent() instanceof AppInfo || peekCurrent() instanceof TextNode) {
            keepText = true;
            ignoreUnknown = true;
        }
        AnyNode anyNode = new AnyNode("dummy1", "dummy2");	// NOI18N
        TextNode textNode = new TextNode("dummy"); 	// NOI18N
        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); ++i) {
            Node childNode = children.item(i);
            if (childNode instanceof org.w3c.dom.Element) {
                org.w3c.dom.Element childElement = (org.w3c.dom.Element) childNode;
                //nodeName = childElement.getNodeName().intern();
                nodeName = childElement.getLocalName().intern();
                //System.out.println("Found a "+nodeName);
                ElementExpr ee = getSampleNode(nodeName);
                if (ee == null) {
                    if (!ignoreUnknown)
                        System.out.println("SchemaRep Warning: unknown node at "+getXPathExpr(childElement));
                    anyNode.readSchema(childElement);
                } else {
                    ee.readSchema(childElement);
                }
            } else if (keepText && childNode instanceof Text) {
                textNode.readSchema((Text)childNode);
            }
        }
    }

    static public String getXPathExpr(Node node) {
        return getXPathExpr(node, true);
    }
    
    static public String getXPathExpr(Node node, boolean addDescription) {
        if (node instanceof Document)
            return "/";
        Node parentNode = node.getParentNode();
        if (parentNode instanceof Document)
            return "/" + node.getNodeName();
        String curNodeName = node.getNodeName();
        if (addDescription && node instanceof org.w3c.dom.Element) {
            String nameAttr = ((org.w3c.dom.Element)node).getAttribute("name");
            if (nameAttr != null && !"".equals(nameAttr))
                curNodeName += " name='"+nameAttr+"'";
        }
        return getXPathExpr(node.getParentNode(), addDescription) + "/" + curNodeName;
    }

    public String schemaTypeToJavaType(String xmlSchemaType) {
        ElementExpr schemaTypeDef = getSchemaTypeDef(xmlSchemaType);
        if (schemaTypeDef == null) {
            System.out.println(Common.getMessage("MSG_UnableToFindTypeDef", xmlSchemaType));
            return null;
        }
        
        String javaType = null;
        //System.out.println("schemaTypeToJavaType: "+xmlSchemaType+" schemaTypeDef="+schemaTypeDef);
        if (schemaTypeDef instanceof HasJavaTypeName) {
            javaType = ((SchemaRep.HasJavaTypeName)schemaTypeDef).getJavaTypeName();
        } else {
            System.out.println("!!! What's the java type of "+schemaTypeDef+" for "+xmlSchemaType);
        }
        //System.out.println("schemaTypeToJavaType: "+xmlSchemaType+" -> "+javaType);
        return javaType;
    }

    /**
     * Get an ElementExpr node for a named type.
     * null is an acceptable return value if not found.
     * If @param typeName is null, null is returned.
     * If @param typeName's namespace is not set, then we first
     * check the documentNamespace, then the targetNamespace.
     */
    public ElementExpr getSchemaTypeDef(String origTypeName) {
        String typeName = origTypeName;
        //System.out.println("getSchemaTypeDef: looking up "+typeName);
        if (typeName == null)
            return null;
        typeName = resolveNamespace(typeName);
        ElementExpr result = (ElementExpr) schemaTypeDefs.get(typeName);
        if (result != null)
            return result;
        String ns = namespaceOf(origTypeName);
        if (ns == null)
            typeName = canonicalQName(documentNamespace,
                                      removeNamespace(origTypeName));
        result = (ElementExpr) schemaTypeDefs.get(typeName);
        if (result != null)
            return result;
        /*
        if (result == null && ns == null) {
            // try the other namespace
            typeName = resolveNamespace(targetNamespace, typeName);
            System.out.println("getSchemaTypeDef2: looking up "+typeName);
            result = (ElementExpr) schemaTypeDefs.get(typeName);
        }
        */
        return (ElementExpr) definedTypes.get(origTypeName);
    }

    /**
     * Same thing as getSchemaTypeDef, but for already resolved type names.
     */
    public ElementExpr getSchemaTypeDefResolvedNamespace(String typeName) {
        ElementExpr result = (ElementExpr) schemaTypeDefs.get(typeName);
        if (result == null) {
            result = (ElementExpr) definedTypes.get(typeName);
        }
        return result;
    }

    
    public Element getDefinedElement(String typeName) {
        String t = resolveNamespace(typeName);
        return getDefinedElementResolvedNamespace(t);
    }
    
    /**
     *@param typeName is the resolved type name "{http://foo}login"
     */ 
    public Element getDefinedElementResolvedNamespace(String typeName) {
        return (Element) definedTypesFull.get(typeName);
    }

    public void putSchemaTypeDef(String typeName, ElementExpr ee) {
        if (typeName == null)
            return;
        String ns = namespaceOf(typeName);
        if (ns == null)
            typeName = resolveNamespace(targetNamespace, removeNamespace(typeName));
        else
            typeName = resolveNamespace(ns, removeNamespace(typeName));
        //System.out.println("putSchemaTypeDef: putting in "+typeName);
        schemaTypeDefs.put(typeName, ee);
    }

    /**
     * Will convert a typeName into {namespace}typeName format.
     * eg: 'xsd:string' -> '{http://www.w3.org/2001/XMLSchema}string'
     * eg: 'item' -> 'item'
     */
    public String resolveNamespace(String typeName) {
        return resolveNamespaceDefault(typeName, targetNamespace);
    }

    protected String resolveNamespaceDefault(String typeName, String defaultNS) {
        if (typeName == null)
            return null;
        String ns = namespaceOf(typeName);
        //System.out.println("resolveNamespace1: ns="+ns+" typeName="+typeName);
        typeName = resolveNamespaceDefault(ns, defaultNS, removeNamespace(typeName));
        //System.out.println("resolveNamespace2: typeName="+typeName);
        return typeName;
    }

    public String resolveNamespace(String ns, String type) {
        return resolveNamespaceDefault(ns, targetNamespace, type);
    }
    
    protected String resolveNamespaceDefault(String ns, String defaultNS, String type) {
        String uri;
        if (ns == null) {
            if (defaultNS == null)
                return type;
            uri = defaultNS;
        } else {
            uri = getNamespaceURI(ns);
            if (uri == null) {
                System.out.println("resolveNamespace: Namespace prefix '"+ns+"' was not found (type="+type+").");
                new Exception().printStackTrace();
            }
        }
        return canonicalQName(uri, type);
    }

    public static String canonicalQName(String namespaceURI, String localPart) {
        if (namespaceURI == null || namespaceURI.equals(""))
            return localPart;
        return "{" + namespaceURI + "}" + localPart;
    }

    /**
     * Will add a namespace prefix to a type if the targetNamespace != null.
     * eg: targetNamespace='j2ee' type='ejbType' -> 'j2ee:ejbType'
     * eg: targetNamespace='j2ee' type='xsd:string' -> 'xsd:string'
     * eg: targetNamespace=null type='item' -> 'item'
     */
    protected String normalizeTargetNamespace(String type) {
        if (type == null)
            return null;
        if (targetNamespace == null)
            return type;
        if (type.indexOf(':') >= 0)
            return type;
        String prefix = getNamespace(targetNamespace);
        return prefix + ":" + type;
    }

    protected String normalizeDocumentNamespace(String type) {
        if (type == null)
            return null;
        if (documentNamespace == null)
            return type;
        if (type.indexOf(':') >= 0)
            return type;
        String prefix = getNamespace(documentNamespace);
        return prefix + ":" + type;
    }

    /**
     * @param schemaTypeName The name of a leaf schema element, like 'integer'.
     * @param javaType  The java class schemaTypeName gets mapped to, like 'int'.
     */
    public void setSchemaTypeMapping(String schemaTypeNamespace,
                                     String schemaTypeName, String javaType) {
        //System.out.println("setSchemaTypeMapping: schemaTypeNamespace="+schemaTypeNamespace+" schemaTypeName="+schemaTypeName+" javaType="+javaType);
        String ns;
        SimpleType st;
        if (schemaTypeNamespace == null) {
            st = new SimpleType(schemaTypeName, javaType);
        } else {
            ns = getNamespace(schemaTypeNamespace);
            st = new SimpleType(ns+":"+schemaTypeName, javaType);
        }
    }

    /**
     * Setup the schema to java type mapping to make more sense for J2ME.
     */
    public void setSchemaTypesForME(boolean isFloatingPoint) {
        setSchemaTypeMapping(XSD_NS, "anyURI", "java.lang.String");
        setSchemaTypeMapping(XSD_NS, "decimal", isFloatingPoint ? "double" : "java.lang.String");
        setSchemaTypeMapping(XSD_NS, "integer", "long");
        if (!isFloatingPoint) {
            setSchemaTypeMapping(XSD_NS, "double", "java.lang.String");
            setSchemaTypeMapping(XSD_NS, "float", "java.lang.String");
        }
    }

    private void insertPredefinedSchemaTypes(Map st) {
        //System.out.println("Hit insertPredefinedSchemaTypes");
        String namespace = getXSDNamespace()+":";
        String[] types = new String[] {"java.lang.String", "java.util.Calendar", "java.util.Calendar",
             "long", "int", "char", "short", "double", "float", "byte", "boolean",
             "java.lang.String", "long", "long", "long", "long", "long", "int", "short",
             "byte", "java.net.URI", "javax.xml.namespace.QName", "java.lang.String", "java.lang.String",
             "java.lang.String", "java.lang.String", "java.lang.String",
             "java.lang.String", "java.lang.String"};
        String[] schemaType = new String[] {"string", "dateTime", "date",
             "long", "int", "char", "short", "double", "float", "byte", "boolean",
             "NMTOKEN", "positiveInteger", "nonNegativeInteger", "nonPositiveInteger", "negativeInteger", "unsignedLong", "unsignedInt", "unsignedShort",
             "unsignedByte", "anyURI", "QName", "NCName", "Name",
             "duration", "time", "ID",
             "token", "normalizedString"};
        for (int i = 0; i < schemaType.length; ++i)
            st.put(schemaType[i], new SimpleType(namespace+schemaType[i], types[i]));
        if (useBigDataTypes) {
            st.put("decimal", new SimpleType(namespace+"decimal", "java.math.BigDecimal"));
            st.put("integer", new SimpleType(namespace+"integer", "java.math.BigInteger"));
        } else {
            st.put("decimal", new SimpleType(namespace+"decimal", "double"));
            st.put("integer", new SimpleType(namespace+"integer", "long"));
        }
        String[] whiteSpaceReplace =
            new String[] {"normalizedString"};
        for (int i = 0; i < whiteSpaceReplace.length; ++i) {
            SimpleType t = (SimpleType) st.get(whiteSpaceReplace[i]);
            Restriction restrict = new Restriction(namespace+"string");
            t.addSubElement(restrict);
            WhiteSpace ws = new WhiteSpace("replace");
            restrict.addSubElement(ws);
        }
        String[] whiteSpaceCollapse =
            new String[] {"token", "NMTOKEN", "Name", "NCName", "ID"};
        for (int i = 0; i < whiteSpaceCollapse.length; ++i) {
            SimpleType t = (SimpleType) st.get(whiteSpaceCollapse[i]);
            Restriction restrict = new Restriction(namespace+"normalizedString");
            t.addSubElement(restrict);
            WhiteSpace ws = new WhiteSpace("collapse");
            restrict.addSubElement(ws);
        }
        addRestriction((SimpleType) st.get("nonPositiveInteger"), namespace+"integer", new MaxInclusive("0"));
        addRestriction((SimpleType) st.get("negativeInteger"), namespace+"nonPositiveInteger", new MaxExclusive("0"));
        addRestriction((SimpleType) st.get("nonNegativeInteger"), namespace+"integer", new MinInclusive("0"));
        addRestriction((SimpleType) st.get("unsignedLong"), namespace+"nonNegativeInteger", new MinInclusive("0"));
        addRestriction((SimpleType) st.get("unsignedInt"), namespace+"unsignedLong", new MinInclusive("0"));
        addRestriction((SimpleType) st.get("positiveInteger"), namespace+"nonNegativeInteger", new MinExclusive("0"));

        st.put("hexBinary", new HexBinary());
        st.put("base64Binary", new Base64Binary());
    }

    protected void addRestriction(ContainsSubElements cse,
                                  String restrictionBase, RestrictionType rt) {
        Restriction restrict = new Restriction(restrictionBase);
        cse.addSubElement(restrict);
        restrict.addSubElement(rt);
    }

    /**
     * Map simple types to our schema.
     */
    public void mapSimpleJavaTypesOptional(Map optionalElementMap) {
        //System.out.println("Hit mapSimpleJavaTypesOptional");
        String namespace = getXSDNamespace()+":";
        // These guys are ones that we are willing to add to the XML Schema,
        // but are optional (not everyone uses everyone of them).
        String[] types = new String[] {"java.lang.Integer", "java.lang.Short", "java.lang.Long", "java.lang.Double", "java.lang.Float", "java.lang.Boolean", "java.lang.Character", "java.lang.StringBuffer", "java.lang.Byte", "java.math.BigInteger", "char[]", "char"};
        String[] restrictions = new String[] {"int", "short", "long", "double", "float", "boolean", "string", "string", "byte", "integer", "string", "string"};
        for (int i = 0; i < types.length; ++i)
            optionalElementMap.put(types[i], new SimpleType(javaType2XMLSchemaType(types[i]), new Restriction(namespace+restrictions[i])));
    }

    private void mapSimpleAttributes(Map a) {
        a.put("xml:lang", new Attribute("lang", getNamespaceURI("xml"),
                                        "xsd:string"));
    }

    /**
     * Map simple types to our schema.
     */
    public void mapSimpleJavaTypesPredefined(Map definedElementMap) {
        //System.out.println("Hit mapSimpleJavaTypesPredefined");
        String namespace = getXSDNamespace()+":";
        // These guys are already defined in XML Schema.  The java 
        // types have 1-to-1 mappings.
        String[] types = new String[] {"java.lang.String", "String", "java.math.BigDecimal", "java.util.Calendar", "long", "int", "char", "short", "double", "float", "byte", "boolean"};
        String[] schemaType = new String[] {"string", "string", "decimal", "dateTime", "long", "int", "char", "short", "double", "float", "byte", "boolean"};
        for (int i = 0; i < types.length; ++i) {
            ElementExpr def = getSchemaTypeDef(schemaType[i]);
            if (def == null)
                def = new SimpleType(namespace+schemaType[i], types[i]);
            definedElementMap.put(types[i], def);
        }
    }

    /**
     * Define some helpful java to XML Schema data types that allow us
     * to go back and forth between the two (allows me to setup a 1-to-1
     * mapping with the client proxy generator).
     */
    public static void printExtraJavaTypes(Writer out, int level) throws java.io.IOException {
        // Create one of ourselves to get around the problem of calling
        // a nonstatic method (that does not need any context)
        // from a static method.
        SchemaRep schema = new SchemaRep();
        Map elementMap = new HashMap();
        schema.mapSimpleJavaTypesOptional(elementMap);
        Iterator it = elementMap.keySet().iterator();
        XMLWriter xw = new XMLWriter(false);
        while (it.hasNext()) {
            Object key = it.next();
            ElementExpr el = (ElementExpr) elementMap.get(key);
            el.writeXMLSchema(xw);
        }
        xw.writeTo(out);
        out.write("\n");	// NOI18N
    }

    private static String javaType2XMLSchemaType(String typeName) {
        return javaType2XMLSchemaType(typeName, false);
    }
    /**
     * Convert a java type into an XML Schema type.
     * eg, java.lang.String -> xsd:string
     */
    private static String javaType2XMLSchemaType(String typeName,
                                                boolean unknownOkay) {
        // BEGIN_NOI18N
        if ("java.lang.String".equals(typeName) || "String".equals(typeName))
            return "xsd:string";
        if ("java.lang.Integer".equals(typeName) || 
            "java.lang.Short".equals(typeName) ||
            "java.lang.Long".equals(typeName) ||
            "java.lang.Double".equals(typeName) ||
            "java.lang.Boolean".equals(typeName) ||
            "java.lang.Character".equals(typeName) ||
            "java.lang.Float".equals(typeName) ||
            "java.lang.StringBuffer".equals(typeName) ||
            "java.lang.Byte".equals(typeName) ||
            "java.math.BigInteger".equals(typeName) ||
            "char".equals(typeName))
            return typeName;
        if ("char[]".equals(typeName))
            return "char_lb_rb";
        if (JavaUtil.isPrimitiveType(typeName))
            return "xsd:"+typeName;
        if ("java.math.BigDecimal".equals(typeName))
            return "xsd:decimal";
        if ("java.util.Calendar".equals(typeName))
            return "xsd:dateTime";
        if ("java.net.URI".equals(typeName))
            return "xsd:anyURI";
        if ("javax.xml.namespace.QName".equals(typeName))
            return "xsd:QName";
        if (!unknownOkay) {
            String err = "javaType2XMLSchemaType: No known XML Schema type for '"+typeName+"'.";
            System.out.println(err);
            return typeName;
        }
        return null;
        // END_NOI18N
    }

    /**
     * Takes a Java type (like 'java.lang.String' or 'double') and
     * says whether or not javaType2XMLSchemaType will return a good,
     * predefined type for it.
     */
    private static boolean isXMLSchemaDefinedType(String typeName) {
        if (javaType2XMLSchemaType(typeName, true) == null)
            return false;
        return true;
    }

    public String javaType2XMLSchemaTypeComplex(String type) {
        //System.out.println("javaType2XMLSchemaTypeComplex type="+type);
        Object el;
        el = definedTypes.get(type);
        if (el == null)
            el = optionallyDefinedTypes.get(type);
        if (el == null) {
            if (debug)
                System.out.println("No type found for "+type);
            return null;
        }
        if (el instanceof SimpleType)
            return ((SimpleType)el).getTypeName();
        if (el instanceof String)
            return (String) el;
        if (el instanceof Element)
            return ((Element)el).getElementName();
        return el.getClass().toString();
    }

    public boolean isDefinedType(String type) {
        if (optionallyDefinedTypes.containsKey(type))
            return true;
        if (definedTypes.containsKey(type))
            return true;
        return false;
    }
 
    /*
     * Removes any namespace prefix.
     *    eg: 'xsd:element' -> 'element'
     */
    public static String removeNamespace(String typeName) {
        int pos = typeName.indexOf(':');
        if (pos < 0)
            return typeName;
        return typeName.substring(pos+1);
    }

    /**
     * eg: 'xsd:element' -> 'xsd'
     */
    public static String namespaceOf(String typeName) {
        int pos = typeName.indexOf(':');
        if (pos < 0)
            return null;
        return typeName.substring(0, pos);
    }

    /**
     * Guess what a prefix of this namespaceURI might be.
     */
    public static String guessPrefix(String namespaceURI) {
        if ("http://www.w3.org/XML/1998/namespace".equals(namespaceURI))
            return "xml";
        String prefix;
        int pos = namespaceURI.lastIndexOf('/');
        if (pos >= 0)
            prefix = namespaceURI.substring(pos+1, namespaceURI.length());
        else
            prefix = namespaceURI;
        prefix = prefix.replace('#', '_').replace('\'', '_').replace('"', '_').
            replace(':', '_');
        // Not supposed to have a prefix that starts with xml
        if (prefix.startsWith("xml"))
            prefix = "x"+prefix;
        return prefix;
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.