mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			840 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			840 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Java
		
	
	
	
/* XMLSchemaBuilder.java --
 | 
						|
   Copyright (C) 2006  Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
package gnu.xml.validation.xmlschema;
 | 
						|
 | 
						|
import java.util.LinkedHashSet;
 | 
						|
import java.util.Set;
 | 
						|
import java.util.StringTokenizer;
 | 
						|
import javax.xml.XMLConstants;
 | 
						|
import javax.xml.namespace.QName;
 | 
						|
import org.relaxng.datatype.DatatypeException;
 | 
						|
import org.relaxng.datatype.DatatypeLibrary;
 | 
						|
import org.relaxng.datatype.helpers.DatatypeLibraryLoader;
 | 
						|
import org.w3c.dom.NamedNodeMap;
 | 
						|
import org.w3c.dom.Node;
 | 
						|
import gnu.xml.validation.datatype.Annotation;
 | 
						|
import gnu.xml.validation.datatype.SimpleType;
 | 
						|
import gnu.xml.validation.datatype.Type;
 | 
						|
 | 
						|
/**
 | 
						|
 * Parses an XML Schema DOM tree, constructing a compiled internal
 | 
						|
 * representation.
 | 
						|
 *
 | 
						|
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 | 
						|
 */
 | 
						|
class XMLSchemaBuilder
 | 
						|
{
 | 
						|
 | 
						|
  XMLSchema schema;
 | 
						|
  final DatatypeLibrary typeLibrary;
 | 
						|
 | 
						|
  XMLSchemaBuilder()
 | 
						|
  {
 | 
						|
    final String ns = XMLConstants.W3C_XML_SCHEMA_NS_URI;
 | 
						|
    typeLibrary = new DatatypeLibraryLoader().createDatatypeLibrary(ns);
 | 
						|
  }
 | 
						|
 | 
						|
  void parseSchema(Node node)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    String uri = node.getNamespaceURI();
 | 
						|
    String name = node.getLocalName();
 | 
						|
    if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
        node.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
      {
 | 
						|
        if ("schema".equals(name))
 | 
						|
          {
 | 
						|
            NamedNodeMap attrs = node.getAttributes();
 | 
						|
            String targetNamespace = getAttribute(attrs, "targetNamespace");
 | 
						|
            String version = getAttribute(attrs, "version");
 | 
						|
            String fd = getAttribute(attrs, "finalDefault");
 | 
						|
            int finalDefault = parseFullDerivationSet(fd);
 | 
						|
            String bd = getAttribute(attrs, "blockDefault");
 | 
						|
            int blockDefault = parseBlockSet(bd);
 | 
						|
            String afd = getAttribute(attrs, "attributeFormDefault");
 | 
						|
            boolean attributeFormQualified = "qualified".equals(afd);
 | 
						|
            String efd = getAttribute(attrs, "elementFormDefault");
 | 
						|
            boolean elementFormQualified = "qualified".equals(efd);
 | 
						|
            schema = new XMLSchema(targetNamespace, version,
 | 
						|
                                   finalDefault, blockDefault,
 | 
						|
                                   attributeFormQualified,
 | 
						|
                                   elementFormQualified);
 | 
						|
            for (Node child = node.getFirstChild(); child != null;
 | 
						|
                 child = child.getNextSibling())
 | 
						|
              {
 | 
						|
                parseTopLevelElement(child);
 | 
						|
              }
 | 
						|
            return;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    // TODO throw schema exception
 | 
						|
  }
 | 
						|
 | 
						|
  void parseTopLevelElement(Node node)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    String uri = node.getNamespaceURI();
 | 
						|
    String name = node.getLocalName();
 | 
						|
    if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
        node.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
      {
 | 
						|
        if ("element".equals(name))
 | 
						|
          {
 | 
						|
            ElementDeclaration ed =
 | 
						|
              (ElementDeclaration) parseElement(node, null);
 | 
						|
            schema.elementDeclarations.put(ed.name, ed);
 | 
						|
            // TODO
 | 
						|
          }
 | 
						|
        else if ("attribute".equals(name))
 | 
						|
          {
 | 
						|
            AttributeDeclaration ad =
 | 
						|
              (AttributeDeclaration) parseAttribute(node, true);
 | 
						|
            schema.attributeDeclarations.put(ad.name, ad);
 | 
						|
            // TODO
 | 
						|
          }
 | 
						|
        else if ("type".equals(name))
 | 
						|
          {
 | 
						|
            // TODO
 | 
						|
          }
 | 
						|
        else if ("group".equals(name))
 | 
						|
          {
 | 
						|
            // TODO
 | 
						|
          }
 | 
						|
        else if ("attributeGroup".equals(name))
 | 
						|
          {
 | 
						|
            // TODO
 | 
						|
          }
 | 
						|
        else if ("notation".equals(name))
 | 
						|
          {
 | 
						|
            // TODO
 | 
						|
          }
 | 
						|
        else if ("identityConstraint".equals(name))
 | 
						|
          {
 | 
						|
            // TODO
 | 
						|
          }
 | 
						|
      }
 | 
						|
    // TODO throw schema exception
 | 
						|
  }
 | 
						|
 | 
						|
  Object parseAttribute(Node node, boolean scope)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    NamedNodeMap attrs = node.getAttributes();
 | 
						|
    String def = getAttribute(attrs, "default");
 | 
						|
    String fixed = getAttribute(attrs, "fixed");
 | 
						|
    int constraintType = AttributeDeclaration.NONE;
 | 
						|
    String constraintValue = null;
 | 
						|
    if (def != null)
 | 
						|
      {
 | 
						|
        constraintType = AttributeDeclaration.DEFAULT;
 | 
						|
        constraintValue = def;
 | 
						|
      }
 | 
						|
    else if (fixed != null)
 | 
						|
      {
 | 
						|
        constraintType = AttributeDeclaration.FIXED;
 | 
						|
        constraintValue = fixed;
 | 
						|
      }
 | 
						|
    // TODO form = (qualified | unqualified)
 | 
						|
    String attrName = getAttribute(attrs, "name");
 | 
						|
    String attrNamespace = getAttribute(attrs, "targetNamespace");
 | 
						|
    String ref = getAttribute(attrs, "ref");
 | 
						|
    String use = getAttribute(attrs, "use");
 | 
						|
    String type = getAttribute(attrs, "type");
 | 
						|
    SimpleType datatype = (type == null) ? null :
 | 
						|
      parseSimpleType(asQName(type, node));
 | 
						|
    Annotation annotation = null;
 | 
						|
    for (Node child = node.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("annotation".equals(name))
 | 
						|
              {
 | 
						|
                annotation = parseAnnotation(child);
 | 
						|
              }
 | 
						|
            else if ("simpleType".equals(name))
 | 
						|
              {
 | 
						|
                datatype = parseSimpleType(child);
 | 
						|
              }
 | 
						|
            else
 | 
						|
              {
 | 
						|
                // TODO throw schema exception
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    if (scope)
 | 
						|
      {
 | 
						|
        return new AttributeDeclaration(scope,
 | 
						|
                                        constraintType,
 | 
						|
                                        constraintValue,
 | 
						|
                                        new QName(attrNamespace, attrName),
 | 
						|
                                        datatype,
 | 
						|
                                        annotation);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        boolean required = "required".equals(use);
 | 
						|
        // TODO ref
 | 
						|
        AttributeDeclaration decl = (ref == null) ?
 | 
						|
              new AttributeDeclaration(scope,
 | 
						|
                                       AttributeDeclaration.NONE,
 | 
						|
                                       null,
 | 
						|
                                       new QName(attrNamespace, attrName),
 | 
						|
                                       datatype,
 | 
						|
                                       annotation) :
 | 
						|
              /*schema.getAttributeDeclaration(ref)*/ null;
 | 
						|
        return new AttributeUse(required,
 | 
						|
                                constraintType,
 | 
						|
                                constraintValue,
 | 
						|
                                decl);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  int parseFullDerivationSet(String value)
 | 
						|
  {
 | 
						|
    int ret = XMLSchema.FINAL_NONE;
 | 
						|
    if ("#all".equals(value))
 | 
						|
      {
 | 
						|
        ret = XMLSchema.FINAL_ALL;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        StringTokenizer st = new StringTokenizer(value, " ");
 | 
						|
        while (st.hasMoreTokens())
 | 
						|
          {
 | 
						|
            String token = st.nextToken();
 | 
						|
            if ("extension".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_EXTENSION;
 | 
						|
              }
 | 
						|
            else if ("restriction".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_RESTRICTION;
 | 
						|
              }
 | 
						|
            else if ("list".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_LIST;
 | 
						|
              }
 | 
						|
            else if ("union".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_UNION;
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  int parseSimpleTypeDerivationSet(String value)
 | 
						|
  {
 | 
						|
    int ret = XMLSchema.FINAL_NONE;
 | 
						|
    if ("#all".equals(value))
 | 
						|
      {
 | 
						|
        ret = XMLSchema.FINAL_LIST |
 | 
						|
          XMLSchema.FINAL_UNION |
 | 
						|
          XMLSchema.FINAL_RESTRICTION;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        StringTokenizer st = new StringTokenizer(value, " ");
 | 
						|
        while (st.hasMoreTokens())
 | 
						|
          {
 | 
						|
            String token = st.nextToken();
 | 
						|
            if ("list".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_LIST;
 | 
						|
              }
 | 
						|
            else if ("union".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_UNION;
 | 
						|
              }
 | 
						|
            else if ("restriction".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_RESTRICTION;
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  int parseComplexTypeDerivationSet(String value)
 | 
						|
  {
 | 
						|
    int ret = XMLSchema.FINAL_NONE;
 | 
						|
    if ("#all".equals(value))
 | 
						|
      {
 | 
						|
        ret = XMLSchema.FINAL_EXTENSION | XMLSchema.FINAL_RESTRICTION;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        StringTokenizer st = new StringTokenizer(value, " ");
 | 
						|
        while (st.hasMoreTokens())
 | 
						|
          {
 | 
						|
            String token = st.nextToken();
 | 
						|
            if ("extension".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_EXTENSION;
 | 
						|
              }
 | 
						|
            else if ("restriction".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.FINAL_RESTRICTION;
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  int parseBlockSet(String value)
 | 
						|
  {
 | 
						|
    int ret = XMLSchema.BLOCK_NONE;
 | 
						|
    if ("#all".equals(value))
 | 
						|
      {
 | 
						|
        ret = XMLSchema.BLOCK_ALL;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        StringTokenizer st = new StringTokenizer(value, " ");
 | 
						|
        while (st.hasMoreTokens())
 | 
						|
          {
 | 
						|
            String token = st.nextToken();
 | 
						|
            if ("extension".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.BLOCK_EXTENSION;
 | 
						|
              }
 | 
						|
            else if ("restriction".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.BLOCK_RESTRICTION;
 | 
						|
              }
 | 
						|
            else if ("substitution".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.BLOCK_SUBSTITUTION;
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  int parseComplexTypeBlockSet(String value)
 | 
						|
  {
 | 
						|
    int ret = XMLSchema.BLOCK_NONE;
 | 
						|
    if ("#all".equals(value))
 | 
						|
      {
 | 
						|
        ret = XMLSchema.BLOCK_EXTENSION | XMLSchema.BLOCK_RESTRICTION;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        StringTokenizer st = new StringTokenizer(value, " ");
 | 
						|
        while (st.hasMoreTokens())
 | 
						|
          {
 | 
						|
            String token = st.nextToken();
 | 
						|
            if ("extension".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.BLOCK_EXTENSION;
 | 
						|
              }
 | 
						|
            else if ("restriction".equals(token))
 | 
						|
              {
 | 
						|
                ret |= XMLSchema.BLOCK_RESTRICTION;
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  Object parseElement(Node node, ElementDeclaration parent)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    NamedNodeMap attrs = node.getAttributes();
 | 
						|
    Integer minOccurs = null;
 | 
						|
    Integer maxOccurs = null;
 | 
						|
    Node parentNode = node.getParentNode();
 | 
						|
    boolean notTopLevel = !"schema".equals(parentNode.getLocalName());
 | 
						|
    if (notTopLevel)
 | 
						|
      {
 | 
						|
        String ref = getAttribute(attrs, "ref");
 | 
						|
        if (ref != null)
 | 
						|
          {
 | 
						|
            minOccurs = getOccurrence(getAttribute(attrs, "minOccurs"));
 | 
						|
            maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs"));
 | 
						|
            // TODO resolve top-level element declaration
 | 
						|
            ElementDeclaration ad = null;
 | 
						|
            return new Particle(minOccurs, maxOccurs, ad);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    String elementName = getAttribute(attrs, "name");
 | 
						|
    String elementNamespace = getAttribute(attrs, "targetNamespace");
 | 
						|
    String type = getAttribute(attrs, "type");
 | 
						|
    Type datatype = (type != null) ?
 | 
						|
      parseSimpleType(asQName(type, node)) : null;
 | 
						|
    int scope = (parent == null) ?
 | 
						|
      XMLSchema.GLOBAL :
 | 
						|
      XMLSchema.LOCAL;
 | 
						|
    String def = getAttribute(attrs, "default");
 | 
						|
    String fixed = getAttribute(attrs, "fixed");
 | 
						|
    int constraintType = AttributeDeclaration.NONE;
 | 
						|
    String constraintValue = null;
 | 
						|
    if (def != null)
 | 
						|
      {
 | 
						|
        constraintType = AttributeDeclaration.DEFAULT;
 | 
						|
        constraintValue = def;
 | 
						|
      }
 | 
						|
    else if (fixed != null)
 | 
						|
      {
 | 
						|
        constraintType = AttributeDeclaration.FIXED;
 | 
						|
        constraintValue = fixed;
 | 
						|
      }
 | 
						|
    String sg = getAttribute(attrs, "substitutionGroup");
 | 
						|
    QName substitutionGroup = QName.valueOf(sg);
 | 
						|
    String sgPrefix = substitutionGroup.getPrefix();
 | 
						|
    if (sgPrefix != null && !"".equals(sgPrefix))
 | 
						|
      {
 | 
						|
        String sgName = substitutionGroup.getLocalPart();
 | 
						|
        String sgNamespace = node.lookupNamespaceURI(sgPrefix);
 | 
						|
        substitutionGroup = new QName(sgNamespace, sgName);
 | 
						|
      }
 | 
						|
 | 
						|
    String block = getAttribute(attrs, "block");
 | 
						|
    int substitutionGroupExclusions = (block == null) ?
 | 
						|
      schema.blockDefault :
 | 
						|
      parseBlockSet(block);
 | 
						|
    String final_ = getAttribute(attrs, "final");
 | 
						|
    int disallowedSubstitutions = (final_ == null) ?
 | 
						|
      schema.finalDefault :
 | 
						|
      parseFullDerivationSet(final_);
 | 
						|
 | 
						|
    boolean nillable = "true".equals(getAttribute(attrs, "nillable"));
 | 
						|
    boolean isAbstract = "true".equals(getAttribute(attrs, "abstract"));
 | 
						|
 | 
						|
    if (notTopLevel)
 | 
						|
      {
 | 
						|
        minOccurs = getOccurrence(getAttribute(attrs, "minOccurs"));
 | 
						|
        maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs"));
 | 
						|
        String form = getAttribute(attrs, "form");
 | 
						|
        if (form != null)
 | 
						|
          {
 | 
						|
            if ("qualified".equals(form))
 | 
						|
              {
 | 
						|
                elementNamespace = schema.targetNamespace;
 | 
						|
              }
 | 
						|
          }
 | 
						|
        else if (schema.elementFormQualified)
 | 
						|
          {
 | 
						|
            elementNamespace = schema.targetNamespace;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    ElementDeclaration ed =
 | 
						|
      new ElementDeclaration(new QName(elementNamespace, elementName),
 | 
						|
                             datatype,
 | 
						|
                             scope, parent,
 | 
						|
                             constraintType, constraintValue,
 | 
						|
                             nillable,
 | 
						|
                             substitutionGroup,
 | 
						|
                             substitutionGroupExclusions,
 | 
						|
                             disallowedSubstitutions,
 | 
						|
                             isAbstract);
 | 
						|
 | 
						|
    for (Node child = node.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("annotation".equals(name))
 | 
						|
              {
 | 
						|
                ed.annotation = parseAnnotation(child);
 | 
						|
              }
 | 
						|
            else if ("simpleType".equals(name) && datatype == null)
 | 
						|
              {
 | 
						|
                ed.datatype = parseSimpleType(child);
 | 
						|
              }
 | 
						|
            else if ("complexType".equals(name) && datatype == null)
 | 
						|
              {
 | 
						|
                ed.datatype = parseComplexType(child, ed);
 | 
						|
              }
 | 
						|
            else
 | 
						|
              {
 | 
						|
                // throw schema exception
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
 | 
						|
    if (notTopLevel)
 | 
						|
      {
 | 
						|
        return new Particle(minOccurs, maxOccurs, ed);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        return ed;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  Integer getOccurrence(String value)
 | 
						|
  {
 | 
						|
    if (value == null)
 | 
						|
      {
 | 
						|
        return new Integer(1);
 | 
						|
      }
 | 
						|
    else if ("unbounded".equals(value))
 | 
						|
      {
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        return new Integer(value);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleType parseSimpleType(QName typeName)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    SimpleType type = (SimpleType) schema.types.get(typeName);
 | 
						|
    if (!XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(typeName.getNamespaceURI()))
 | 
						|
      return null;
 | 
						|
    String localName = typeName.getLocalPart();
 | 
						|
    return (SimpleType) typeLibrary.createDatatype(localName);
 | 
						|
  }
 | 
						|
 | 
						|
  SimpleType parseSimpleType(Node simpleType)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    NamedNodeMap attrs = simpleType.getAttributes();
 | 
						|
    String typeFinal = getAttribute(attrs, "final");
 | 
						|
    if (typeFinal == null)
 | 
						|
      {
 | 
						|
        Node schema = simpleType.getParentNode();
 | 
						|
        while (schema != null && !"schema".equals(schema.getLocalName()))
 | 
						|
          {
 | 
						|
            schema = schema.getParentNode();
 | 
						|
          }
 | 
						|
        if (schema != null)
 | 
						|
          {
 | 
						|
            NamedNodeMap schemaAttrs = schema.getAttributes();
 | 
						|
            typeFinal = getAttribute(schemaAttrs, "finalDefault");
 | 
						|
          }
 | 
						|
      }
 | 
						|
    int typeFinality = parseSimpleTypeDerivationSet(typeFinal);
 | 
						|
    QName typeName = asQName(getAttribute(attrs, "name"), simpleType);
 | 
						|
    int variety = 0;
 | 
						|
    Set facets = new LinkedHashSet();
 | 
						|
    int fundamentalFacets = 0; // TODO
 | 
						|
    SimpleType baseType = null; // TODO
 | 
						|
    Annotation annotation = null;
 | 
						|
    // TODO use DatatypeBuilder
 | 
						|
    for (Node child = simpleType.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("annotation".equals(name))
 | 
						|
              {
 | 
						|
                annotation = parseAnnotation(child);
 | 
						|
              }
 | 
						|
            else if ("restriction".equals(name))
 | 
						|
              {
 | 
						|
                // TODO
 | 
						|
              }
 | 
						|
            else if ("list".equals(name))
 | 
						|
              {
 | 
						|
                variety = SimpleType.LIST;
 | 
						|
                // TODO
 | 
						|
              }
 | 
						|
            else if ("union".equals(name))
 | 
						|
              {
 | 
						|
                variety = SimpleType.UNION;
 | 
						|
                // TODO
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return new SimpleType(typeName, variety, facets, fundamentalFacets,
 | 
						|
                          baseType, annotation);
 | 
						|
  }
 | 
						|
 | 
						|
  Type parseComplexType(Node complexType, ElementDeclaration parent)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    NamedNodeMap attrs = complexType.getAttributes();
 | 
						|
    QName typeName = asQName(getAttribute(attrs, "name"), complexType);
 | 
						|
    boolean isAbstract = "true".equals(getAttribute(attrs, "abstract"));
 | 
						|
    String block = getAttribute(attrs, "block");
 | 
						|
    int prohibitedSubstitutions = (block == null) ?
 | 
						|
      schema.blockDefault :
 | 
						|
      parseComplexTypeBlockSet(block);
 | 
						|
    String final_ = getAttribute(attrs, "final");
 | 
						|
    int finality = (final_ == null) ?
 | 
						|
      schema.finalDefault :
 | 
						|
      parseComplexTypeDerivationSet(final_);
 | 
						|
    ComplexType type = new ComplexType(typeName, isAbstract,
 | 
						|
                                       prohibitedSubstitutions, finality);
 | 
						|
    boolean mixed = "true".equals(getAttribute(attrs, "mixed"));
 | 
						|
    for (Node child = complexType.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("simpleContent".equals(name))
 | 
						|
              {
 | 
						|
                parseSimpleContent(child, type);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    if (mixed)
 | 
						|
      {
 | 
						|
        type.contentType = XMLSchema.CONTENT_MIXED;
 | 
						|
      }
 | 
						|
    return type;
 | 
						|
  }
 | 
						|
 | 
						|
  void parseSimpleContent(Node simpleContent, ComplexType type)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    for (Node child = simpleContent.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("annotation".equals(name))
 | 
						|
              {
 | 
						|
                type.annotations.add(parseAnnotation(child));
 | 
						|
              }
 | 
						|
            else if ("restriction".equals(name))
 | 
						|
              {
 | 
						|
                type.derivationMethod = XMLSchema.FINAL_RESTRICTION;
 | 
						|
                parseRestriction(child, type);
 | 
						|
              }
 | 
						|
            else if ("extension".equals(name))
 | 
						|
              {
 | 
						|
                type.derivationMethod = XMLSchema.FINAL_EXTENSION;
 | 
						|
                parseExtension(child, type);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  void parseRestriction(Node restriction, ComplexType type)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    NamedNodeMap attrs = restriction.getAttributes();
 | 
						|
    String base = getAttribute(attrs, "base");
 | 
						|
    QName baseType = asQName(base, restriction);
 | 
						|
    SimpleType simpleType = null;
 | 
						|
    for (Node child = restriction.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("annotation".equals(name))
 | 
						|
              {
 | 
						|
                type.annotations.add(parseAnnotation(child));
 | 
						|
              }
 | 
						|
            else if ("simpleType".equals(name))
 | 
						|
              {
 | 
						|
                type.contentType = XMLSchema.CONTENT_SIMPLE;
 | 
						|
                simpleType = parseSimpleType(child);
 | 
						|
              }
 | 
						|
            else if ("minExclusive".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("minInclusive".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("maxExclusive".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("maxInclusive".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("totalDigits".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("fractionDigits".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("length".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("minLength".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("maxLength".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("enumeration".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("whiteSpace".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("pattern".equals(name))
 | 
						|
              {
 | 
						|
              }
 | 
						|
            else if ("attribute".equals(name))
 | 
						|
              {
 | 
						|
                AttributeUse use =
 | 
						|
                  (AttributeUse) parseAttribute(child, false);
 | 
						|
                schema.attributeDeclarations.put(use.declaration.name,
 | 
						|
                                                 use.declaration);
 | 
						|
                type.attributeUses.add(use);
 | 
						|
              }
 | 
						|
            else if ("attributeGroup".equals(name))
 | 
						|
              {
 | 
						|
                NamedNodeMap agAttrs = child.getAttributes();
 | 
						|
                String ref = getAttribute(agAttrs, "ref");
 | 
						|
                QName ag = asQName(ref, child);
 | 
						|
                type.attributeUses.add(ag);
 | 
						|
              }
 | 
						|
            else if ("anyAttribute".equals(name))
 | 
						|
              {
 | 
						|
                type.attributeWildcard = parseAnyAttribute(child);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  void parseExtension(Node extension, ComplexType type)
 | 
						|
    throws DatatypeException
 | 
						|
  {
 | 
						|
    NamedNodeMap attrs = extension.getAttributes();
 | 
						|
    String base = getAttribute(attrs, "base");
 | 
						|
    QName baseType = asQName(base, extension);
 | 
						|
    for (Node child = extension.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("annotation".equals(name))
 | 
						|
              {
 | 
						|
                type.annotations.add(parseAnnotation(child));
 | 
						|
              }
 | 
						|
            else if ("attribute".equals(name))
 | 
						|
              {
 | 
						|
                AttributeUse use =
 | 
						|
                  (AttributeUse) parseAttribute(child, false);
 | 
						|
                schema.attributeDeclarations.put(use.declaration.name,
 | 
						|
                                                 use.declaration);
 | 
						|
                type.attributeUses.add(use);
 | 
						|
              }
 | 
						|
            else if ("attributeGroup".equals(name))
 | 
						|
              {
 | 
						|
                NamedNodeMap agAttrs = child.getAttributes();
 | 
						|
                String ref = getAttribute(agAttrs, "ref");
 | 
						|
                QName ag = asQName(ref, child);
 | 
						|
                type.attributeUses.add(ag);
 | 
						|
              }
 | 
						|
            else if ("anyAttribute".equals(name))
 | 
						|
              {
 | 
						|
                type.attributeWildcard = parseAnyAttribute(child);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  AnyAttribute parseAnyAttribute(Node node)
 | 
						|
  {
 | 
						|
    NamedNodeMap attrs = node.getAttributes();
 | 
						|
    String namespace = getAttribute(attrs, "namespace");
 | 
						|
    String pc = getAttribute(attrs, "processContents");
 | 
						|
    int processContents = AnyAttribute.STRICT;
 | 
						|
    if ("lax".equals(pc))
 | 
						|
      {
 | 
						|
        processContents = AnyAttribute.LAX;
 | 
						|
      }
 | 
						|
    else if ("skip".equals(pc))
 | 
						|
      {
 | 
						|
        processContents = AnyAttribute.SKIP;
 | 
						|
      }
 | 
						|
    AnyAttribute ret = new AnyAttribute(namespace, processContents);
 | 
						|
    for (Node child = node.getFirstChild(); child != null;
 | 
						|
         child = child.getNextSibling())
 | 
						|
      {
 | 
						|
        String uri = child.getNamespaceURI();
 | 
						|
        String name = child.getLocalName();
 | 
						|
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 | 
						|
            child.getNodeType() == Node.ELEMENT_NODE)
 | 
						|
          {
 | 
						|
            if ("annotation".equals(name))
 | 
						|
              {
 | 
						|
                ret.annotation = parseAnnotation(child);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  Annotation parseAnnotation(Node node)
 | 
						|
  {
 | 
						|
    // TODO
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  private static String getAttribute(NamedNodeMap attrs, String name)
 | 
						|
  {
 | 
						|
    Node attr = attrs.getNamedItem(name);
 | 
						|
    return (attr == null) ? null : attr.getNodeValue();
 | 
						|
  }
 | 
						|
 | 
						|
  private static QName asQName(String text, Node resolver)
 | 
						|
  {
 | 
						|
    QName name = QName.valueOf(text);
 | 
						|
    String prefix = name.getPrefix();
 | 
						|
    if (prefix != null && prefix.length() > 0)
 | 
						|
      {
 | 
						|
        String uri = resolver.lookupNamespaceURI(prefix);
 | 
						|
        name = new QName(uri, name.getLocalPart());
 | 
						|
      }
 | 
						|
    return name;
 | 
						|
  }
 | 
						|
 | 
						|
}
 |