All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.axis.wsdl.symbolTable.SchemaUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.axis.wsdl.symbolTable;

import org.apache.axis.Constants;
import org.apache.axis.i18n.Messages;
import org.apache.axis.utils.JavaUtils;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.namespace.QName;
import javax.xml.rpc.holders.BooleanHolder;
import javax.xml.rpc.holders.IntHolder;
import javax.xml.rpc.holders.QNameHolder;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
import java.io.IOException;

/**
 * This class contains static utility methods specifically for schema type queries.
 *
 * @author Rich Scheuerle  ([email protected])
 */
public class SchemaUtils {

    /** Field VALUE_QNAME */
    static final QName VALUE_QNAME = Utils.findQName("", "_value");

    /**
     * This method checks mixed=true attribute is set either on
     * complexType or complexContent element.
     */
    public static boolean isMixed(Node node) {
        // Expecting a schema complexType
        if (isXSDNode(node, "complexType")) {
            String mixed = ((Element)node).getAttribute("mixed");
            if (mixed != null && mixed.length() > 0) {
                return ("true".equalsIgnoreCase(mixed) ||
                        "1".equals(mixed));
            }
            // Under the complexType there could be complexContent with
            // mixed="true"
            NodeList children = node.getChildNodes();

            for (int j = 0; j < children.getLength(); j++) {
                Node kid = children.item(j);
                if (isXSDNode(kid, "complexContent")) {
                    mixed = ((Element)kid).getAttribute("mixed");
                    return ("true".equalsIgnoreCase(mixed) ||
                            "1".equals(mixed));
                }
            }
        }
        return false;
    }

    public static Node getUnionNode(Node node) {
        // Expecting a schema complexType
        if (isXSDNode(node, "simpleType")) {
            // Under the simpleType there could be union
            NodeList children = node.getChildNodes();
            for (int j = 0; j < children.getLength(); j++) {
                Node kid = children.item(j);
                if (isXSDNode(kid, "union")) {
                    return kid;
                }
            }
        }
        return null;
    }

    public static Node getListNode(Node node) {
        // Expecting a schema simpleType
        if (isXSDNode(node, "simpleType")) {
            // Under the simpleType there could be list
            NodeList children = node.getChildNodes();
            for (int j = 0; j < children.getLength(); j++) {
                Node kid = children.item(j);
                if (isXSDNode(kid, "list")) {
                    return kid;
                }
            }
        }
        return null;
    }

    public static boolean isSimpleTypeWithUnion(Node node) {
        return (getUnionNode(node) != null);
    }

  /**
   * This method checks out if the given node satisfies the 3rd condition
   * of the "wrapper" style:
   * such an element (a wrapper) must be of a complex type defined using the
   * xsd:sequence compositor and containing only elements declarations.
   * (excerpt from JAX-RPC spec 1.1 Maintenanace Review 2 Chapter 6 Section 4.1.)
   *
   * @param node
   * @return
   */
  public static boolean isWrappedType(Node node) {

    if (node == null) {
      return false;
    }

    // If the node kind is an element, dive into it.
    if (isXSDNode(node, "element")) {
      NodeList children = node.getChildNodes();
      boolean hasComplexType = false;
      for (int j = 0; j < children.getLength(); j++) {
        Node kid = children.item(j);
        if (isXSDNode(kid, "complexType")) {
          node = kid;
          hasComplexType = true;
          break;
        }
      }
      if (!hasComplexType) {
        return false;
      }
    }

    // Expecting a schema complexType
    if (isXSDNode(node, "complexType")) {
      // Under the complexType there could be complexContent/simpleContent
      // and extension elements if this is a derived type.
      // A wrapper element must be complex-typed.

      NodeList children = node.getChildNodes();

      for (int j = 0; j < children.getLength(); j++) {
        Node kid = children.item(j);

        if (isXSDNode(kid, "complexContent")) {
          return false;
        } else if (isXSDNode(kid, "simpleContent")) {
          return false;
        }
      }

      // Under the complexType there may be choice, sequence, group and/or all nodes.
      // (There may be other #text nodes, which we will ignore).
      // The complex type of a wrapper element must have only sequence
      // and again element declarations in the sequence.
      children = node.getChildNodes();
      int len =  children.getLength();
      for (int j = 0; j < len; j++) {
          Node kid = children.item(j);
          String localName = kid.getLocalName();
          if (localName != null &&
              Constants.isSchemaXSD(kid.getNamespaceURI())) {
              if (localName.equals("sequence")) {
                  Node sequenceNode = kid;
                  NodeList sequenceChildren = sequenceNode.getChildNodes();
                  int sequenceLen = sequenceChildren.getLength();
                  for (int k = 0; k < sequenceLen; k++) {
                      Node sequenceKid = sequenceChildren.item(k);
                      String sequenceLocalName = sequenceKid.getLocalName();
                      if (sequenceLocalName != null &&
                          Constants.isSchemaXSD(sequenceKid.getNamespaceURI())) {
                          // allow choice with element children
                          if (sequenceLocalName.equals("choice")) {
                              Node choiceNode = sequenceKid;
                              NodeList choiceChildren = choiceNode.getChildNodes();
                              int choiceLen = choiceChildren.getLength();
                              for (int l = 0; l < choiceLen; l++) {
                                  Node choiceKid = choiceChildren.item(l);
                                  String choiceLocalName = choiceKid.getLocalName();
                                  if (choiceLocalName != null &&
                                      Constants.isSchemaXSD(choiceKid.getNamespaceURI())) {
                                      if (!choiceLocalName.equals("element")) {
                                          return false;
                                      }
                                  }
                              }
                          }
                          else
                          if (!sequenceLocalName.equals("element")) {
                              return false;
                          }
                      }
                  }
                  return true;
              } else {
                  return false;
              }
          }
      }
    }
    // allows void type
    return true;
  }

    /**
     * If the specified node represents a supported JAX-RPC complexType or
     * simpleType, a Vector is returned which contains ElementDecls for the
     * child element names.
     * If the element is a simpleType, an ElementDecls is built representing
     * the restricted type with the special name "value".
     * If the element is a complexType which has simpleContent, an ElementDecl
     * is built representing the extended type with the special name "value".
     * This method does not return attribute names and types
     * (use the getContainedAttributeTypes)
     * If the specified node is not a supported
     * JAX-RPC complexType/simpleType/element null is returned.
     *
     * @param node
     * @param symbolTable
     * @return
     */
    public static Vector getContainedElementDeclarations(Node node,
                                                         SymbolTable symbolTable) {

        if (node == null) {
            return null;
        }

        // If the node kind is an element, dive into it.
        if (isXSDNode(node, "element")) {
            NodeList children = node.getChildNodes();

            for (int j = 0; j < children.getLength(); j++) {
                Node kid = children.item(j);

                if (isXSDNode(kid, "complexType")) {
                    node = kid;

                    break;
                }
            }
        }

        // Expecting a schema complexType or simpleType
        if (isXSDNode(node, "complexType")) {

            // Under the complexType there could be complexContent/simpleContent
            // and extension elements if this is a derived type.  Skip over these.
            NodeList children = node.getChildNodes();
            Node complexContent = null;
            Node simpleContent = null;
            Node extension = null;

            for (int j = 0; j < children.getLength(); j++) {
                Node kid = children.item(j);

                if (isXSDNode(kid, "complexContent")) {
                    complexContent = kid;

                    break;    // REMIND: should this be here or on either branch?
                } else if (isXSDNode(kid, "simpleContent")) {
                    simpleContent = kid;
                }
            }

            if (complexContent != null) {
                children = complexContent.getChildNodes();

                for (int j = 0;
                     (j < children.getLength()) && (extension == null);
                     j++) {
                    Node kid = children.item(j);

                    if (isXSDNode(kid, "extension")
                            || isXSDNode(kid, "restriction")) {
                        extension = kid;
                    }
                }
            }

            if (simpleContent != null) {
                children = simpleContent.getChildNodes();

                int len =  children.getLength();
                for (int j = 0;
                     (j < len) && (extension == null);
                     j++) {
                    Node kid = children.item(j);
                    String localName = kid.getLocalName();

                    if ((localName != null)
                        && (localName.equals("extension") || localName.equals("restriction"))
                        && Constants.isSchemaXSD(kid.getNamespaceURI())) {

                        // get the type of the extension/restriction from the "base" attribute
                        QName extendsOrRestrictsTypeName =
                                Utils.getTypeQName(children.item(j),
                                        new BooleanHolder(), false);

                        TypeEntry extendsOrRestrictsType =
                            symbolTable.getTypeEntry(extendsOrRestrictsTypeName,
                                                    false);

                        // If this type extends a simple type, then add the
                        // special "value" ElementDecl, else this type is
                        // extending another simpleContent type and will
                        // already have a "value".

                        if (extendsOrRestrictsType == null ||
                            extendsOrRestrictsType.isBaseType())
                        {
                        // Return an element declaration with a fixed name
                        // ("value") and the correct type.
                        Vector v = new Vector();
                            ElementDecl elem =
                                new ElementDecl(extendsOrRestrictsType,
                                    VALUE_QNAME);
                        v.add(elem);

                        return v;
                    }
                        else
                        {
                            // There can't be any other elements in a
                            // simpleContent node.
                            return null;
                        }
                    }
                }
            }

            if (extension != null) {
                node = extension;    // Skip over complexContent and extension
            }

            // Under the complexType there may be choice, sequence, group and/or all nodes.
            // (There may be other #text nodes, which we will ignore).
            children = node.getChildNodes();

            Vector v = new Vector();
            int len = children.getLength();
            for (int j = 0; j < len; j++) {
                Node kid = children.item(j);
                String localName = kid.getLocalName();
                if (localName != null &&
                    Constants.isSchemaXSD(kid.getNamespaceURI())) {
                    if (localName.equals("sequence")) {
                        v.addAll(processSequenceNode(kid, symbolTable));
                    } else if (localName.equals("all")) {
                        v.addAll(processAllNode(kid, symbolTable));
                    } else if (localName.equals("choice")) {
                        v.addAll(processChoiceNode(kid, symbolTable));
                    } else if (localName.equals("group")) {
                        v.addAll(processGroupNode(kid, symbolTable));
                    }
                }
            }

            return v;
        } else if (isXSDNode(node, "group")) {
            /*
			* Does this else clause make any sense anymore if
			* we're treating refs to xs:groups like a macro inclusion
			* into the referencing type?
			* Maybe this else clause should never be possible?
			*
            NodeList children = node.getChildNodes();
            Vector v = new Vector();
            int len = children.getLength();
            for (int j = 0; j < len; j++) {
                Node kid = children.item(j);
                String localName = kid.getLocalName();
                if (localName != null &&
                    Constants.isSchemaXSD(kid.getNamespaceURI())) {
                    if (localName.equals("sequence")) {
                        v.addAll(processSequenceNode(kid, symbolTable));
                    } else if (localName.equals("all")) {
                        v.addAll(processAllNode(kid, symbolTable));
                    } else if (localName.equals("choice")) {
                        v.addAll(processChoiceNode(kid, symbolTable));
                    }
                }
            }
            return v;
            */
                return null;
        } else {

            // This may be a simpleType, return the type with the name "value"
            QName[] simpleQName = getContainedSimpleTypes(node);

            if (simpleQName != null) {
                Vector v = null;

                for (int i = 0; i < simpleQName.length; i++) {

                    Type simpleType = symbolTable.getType(simpleQName[i]);

                    if (simpleType != null) {
                        if (v == null) {
                            v = new Vector();
                        }

                        QName qname = null;
                        if (simpleQName.length > 1) {
                            qname = new QName("", simpleQName[i].getLocalPart() + "Value");
                        } else {
                            qname = new QName("", "value");
                        }

                        v.add(new ElementDecl(simpleType, qname));
                    }
                }

                return v;
            }
        }

        return null;
    }

    /**
     * Invoked by getContainedElementDeclarations to get the child element types
     * and child element names underneath a Choice Node
     *
     * @param choiceNode
     * @param symbolTable
     * @return
     */
    private static Vector processChoiceNode(Node choiceNode,
                                            SymbolTable symbolTable) {

        Vector v = new Vector();
        NodeList children = choiceNode.getChildNodes();
        int len = children.getLength();
        for (int j = 0; j < len; j++) {
            Node kid = children.item(j);
            String localName = kid.getLocalName();
            if (localName != null &&
                Constants.isSchemaXSD(kid.getNamespaceURI())) {
                if (localName.equals("choice")) {
                    v.addAll(processChoiceNode(kid, symbolTable));
                } else if (localName.equals("sequence")) {
                    v.addAll(processSequenceNode(kid, symbolTable));
                } else if (localName.equals("group")) {
                    v.addAll(processGroupNode(kid, symbolTable));
                } else if (localName.equals("element")) {
                    ElementDecl elem = processChildElementNode(kid,
                                                               symbolTable);

                    if (elem != null) {
                        // XXX: forces minOccurs="0" so that a null choice
                        // element can be serialized ok.
                        elem.setMinOccursIs0(true);

                        v.add(elem);
                    }
                } else if (localName.equals("any")) {
                    // Represent this as an element named any of type any type.
                    // This will cause it to be serialized with the element
                    // serializer.
                    Type type = symbolTable.getType(Constants.XSD_ANY);
                    ElementDecl elem = new ElementDecl(type,
                            Utils.findQName("",
                                    "any"));

                    elem.setAnyElement(true);
                    v.add(elem);
                }
            }
        }

        return v;
    }

    /**
     * Returns named child node.
     *
     * @param parentNode Parent node.
     * @param name Element name of child node to return.
     */
    private static Node getChildByName(Node parentNode, String name) throws DOMException {
        if (parentNode == null) return null;
        NodeList children = parentNode.getChildNodes();
        if (children != null) {
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);
                if (child != null) {
                    if ((child.getNodeName() != null && (name.equals(child.getNodeName()))) ||
                        (child.getLocalName() != null && (name.equals(child.getLocalName())))) {
                        return child;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Returns all textual nodes of a subnode defined by a parent node
     * and a path of element names to that subnode.
     *
     * @param root Parent node.
     * @param path Path of element names to text of interest, delimited by "/".
     */
    public static String getTextByPath(Node root, String path) throws DOMException {
        StringTokenizer st = new StringTokenizer(path, "/");
        Node node = root;
        while (st.hasMoreTokens()) {
            String elementName = st.nextToken();
            Node child = getChildByName(node, elementName);
            if (child == null)
                throw new DOMException(DOMException.NOT_FOUND_ERR, "could not find " + elementName);
            node = child;
        }

        // should have found the node
        String text = "";
        NodeList children = node.getChildNodes();
        if (children != null) {
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);
                if (child != null) {
                    if (child.getNodeName() != null
                            && (child.getNodeName().equals("#text")
                            || child.getNodeName().equals("#cdata-section"))) {
                        text += child.getNodeValue();
                    }
                }
            }
        }
        return text;
    }

    /**
     * Returns the complete text of the child xsd:annotation/xsd:documentation
     * element from the provided node.  Only the first annotation element and
     * the first documentation element in the annotation element will be used.
     *
     * @param typeNode Parent node.
     */
    public static String getAnnotationDocumentation(Node typeNode) {
        Node annotationNode = typeNode.getFirstChild();
        while (annotationNode != null) {
            if (isXSDNode(annotationNode, "annotation")) {
                break;
            }
            annotationNode = annotationNode.getNextSibling();
        }
        Node documentationNode;
        if (annotationNode != null) {
            documentationNode = annotationNode.getFirstChild();
            while (documentationNode != null) {
                if (isXSDNode(documentationNode, "documentation")) {
                    break;
                }
                documentationNode = documentationNode.getNextSibling();
            }
        } else {
            documentationNode = null;
        }

        // should have found the node if it exists
        String text = "";
        if (documentationNode != null) {
            NodeList children = documentationNode.getChildNodes();
            if (children != null) {
                for (int i = 0; i < children.getLength(); i++) {
                    Node child = children.item(i);
                    if (child != null) {
                        if (child.getNodeName() != null
                                && (child.getNodeName().equals("#text")
                                || child.getNodeName().equals("#cdata-section"))) {
                            text += child.getNodeValue();
                        }
                    }
                }
            }
        }
        return text;
    }

    /**
     * Invoked by getContainedElementDeclarations to get the child element types
     * and child element names underneath a Sequence Node
     *
     * @param sequenceNode
     * @param symbolTable
     * @return
     */
    private static Vector processSequenceNode(Node sequenceNode,
                                              SymbolTable symbolTable) {

        Vector v = new Vector();
        NodeList children = sequenceNode.getChildNodes();
        int len = children.getLength();
        for (int j = 0; j < len; j++) {
            Node kid = children.item(j);
            String localName = kid.getLocalName();

            if (localName != null &&
                Constants.isSchemaXSD(kid.getNamespaceURI())) {
                if (localName.equals("choice")) {
                    v.addAll(processChoiceNode(kid, symbolTable));
                } else if (localName.equals("sequence")) {
                    v.addAll(processSequenceNode(kid, symbolTable));
                } else if (localName.equals("group")) {
                    v.addAll(processGroupNode(kid, symbolTable));
                } else if (localName.equals("any")) {
                    // Represent this as an element named any of type any type.
                    // This will cause it to be serialized with the element
                    // serializer.
                    Type type = symbolTable.getType(Constants.XSD_ANY);
                    ElementDecl elem = new ElementDecl(type,
                            Utils.findQName("",
                                    "any"));

                    elem.setAnyElement(true);
                    v.add(elem);
                } else if (localName.equals("element")) {
                    ElementDecl elem = processChildElementNode(kid,
                                                               symbolTable);

                    if (elem != null) {
                        v.add(elem);
                    }
                }
            }
        }

        return v;
    }

    /**
     * Invoked by getContainedElementDeclarations to get the child element types
     * and child element names underneath a group node. If a ref attribute is
     * specified, only the referenced group element is returned.
     *
     * @param groupNode
     * @param symbolTable
     * @return
     */
    private static Vector processGroupNode(Node groupNode,
                                           SymbolTable symbolTable) {

        Vector v = new Vector();
        if (groupNode.getAttributes().getNamedItem("ref") == null) {
            NodeList children = groupNode.getChildNodes();
            int len = children.getLength();
            for (int j = 0; j < len; j++) {
                Node kid = children.item(j);
                String localName = kid.getLocalName();
                if (localName != null &&
                    Constants.isSchemaXSD(kid.getNamespaceURI())) {
                    if (localName.equals("choice")) {
                        v.addAll(processChoiceNode(kid, symbolTable));
                    } else if (localName.equals("sequence")) {
                        v.addAll(processSequenceNode(kid, symbolTable));
                    } else if (localName.equals("all")) {
                        v.addAll(processAllNode(kid, symbolTable));
                    }
                }
            }
        } else {
            QName nodeName = Utils.getNodeNameQName(groupNode);
            QName nodeType = Utils.getTypeQName(groupNode, new BooleanHolder(), false);
            // The value of the second argument is 'false' since global model group
            // definitions are always represented by objects whose type is
            // assignment compatible with 'org.apache.axis.wsdl.symbolTable.Type'.
            Type type = (Type) symbolTable.getTypeEntry(nodeType, false);

            if (type != null && type.getNode() != null) {
                //v.add(new ElementDecl(type, nodeName));
                Node node = type.getNode();
                NodeList children = node.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    QName subNodeKind = Utils.getNodeQName(children.item(j));
                    if ((subNodeKind != null)
                        && Constants.isSchemaXSD(
                            subNodeKind.getNamespaceURI())) {
                        if (subNodeKind.getLocalPart().equals("sequence")) {
                            v.addAll(processSequenceNode(children.item(j),
                                 symbolTable));
                        } else if (subNodeKind.getLocalPart().equals("all")) {
                            v.addAll(processAllNode(children.item(j), symbolTable));
                            } else if (subNodeKind.getLocalPart().equals("choice")) {
                                v.addAll(processChoiceNode(children.item(j),
                                    symbolTable));
                        }
                    }
                }
            }
        }
        return v;
    }


    /**
     * Invoked by getContainedElementDeclarations to get the child element types
     * and child element names underneath an all node.
     *
     * @param allNode
     * @param symbolTable
     * @return
     */
    private static Vector processAllNode(Node allNode,
                                         SymbolTable symbolTable) {

        Vector v = new Vector();
        NodeList children = allNode.getChildNodes();

        for (int j = 0; j < children.getLength(); j++) {
            Node kid = children.item(j);

            if (isXSDNode(kid, "element")) {
                ElementDecl elem = processChildElementNode(kid, symbolTable);

                if (elem != null) {
                    v.add(elem);
                }
            }
        }

        return v;
    }

    /**
     * Invoked by getContainedElementDeclarations to get the child element type
     * and child element name for a child element node.
     * 

* If the specified node represents a supported JAX-RPC child element, * we return an ElementDecl containing the child element name and type. * * @param elementNode * @param symbolTable * @return */ private static ElementDecl processChildElementNode(Node elementNode, SymbolTable symbolTable) { // Get the name qnames. QName nodeName = Utils.getNodeNameQName(elementNode); BooleanHolder forElement = new BooleanHolder(); String comments = null; comments = getAnnotationDocumentation(elementNode); // The type qname is used to locate the TypeEntry, which is then // used to retrieve the proper java name of the type. QName nodeType = Utils.getTypeQName(elementNode, forElement, false); TypeEntry type = symbolTable.getTypeEntry(nodeType, forElement.value); // An element inside a complex type is either qualified or unqualified. // If the ref= attribute is used, the name of the ref'd element is used // (which must be a root element). If the ref= attribute is not // used, the name of the element is unqualified. if (!forElement.value) { // check the Form (or elementFormDefault) attribute of this node to // determine if it should be namespace quailfied or not. String form = Utils.getAttribute(elementNode, "form"); if ((form != null) && form.equals("unqualified")) { // Unqualified nodeName nodeName = Utils.findQName("", nodeName.getLocalPart()); } else if (form == null) { // check elementFormDefault on schema element String def = Utils.getScopedAttribute(elementNode, "elementFormDefault"); if ((def == null) || def.equals("unqualified")) { // Unqualified nodeName nodeName = Utils.findQName("", nodeName.getLocalPart()); } } } if (type != null) { ElementDecl elem = new ElementDecl(type, nodeName); elem.setDocumentation(comments); String minOccurs = Utils.getAttribute(elementNode, "minOccurs"); if ((minOccurs != null) && minOccurs.equals("0")) { elem.setMinOccursIs0(true); } String maxOccurs = Utils.getAttribute(elementNode, "maxOccurs"); if (maxOccurs != null) { if (maxOccurs.equals("unbounded")) { elem.setMaxOccursIsUnbounded(true); } else if(maxOccurs.equals("1")) { elem.setMaxOccursIsExactlyOne(true); } } else { elem.setMaxOccursIsExactlyOne(true); } elem.setNillable( JavaUtils.isTrueExplicitly( Utils.getAttribute(elementNode, "nillable"))); String useValue = Utils.getAttribute(elementNode, "use"); if (useValue != null) { elem.setOptional(useValue.equalsIgnoreCase("optional")); } return elem; } return null; } /** * Returns the WSDL2Java QName for the anonymous type of the element * or null. * * @param node * @return */ public static QName getElementAnonQName(Node node) { if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexType") || isXSDNode(kid, "simpleType")) { return Utils.getNodeNameQName(kid); } } } return null; } /** * Returns the WSDL2Java QName for the anonymous type of the attribute * or null. * * @param node * @return */ public static QName getAttributeAnonQName(Node node) { if (isXSDNode(node, "attribute")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexType") || isXSDNode(kid, "simpleType")) { return Utils.getNodeNameQName(kid); } } } return null; } /** * If the specified node is a simple type or contains simpleContent, return true * * @param node * @return */ public static boolean isSimpleTypeOrSimpleContent(Node node) { if (node == null) { return false; } // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexType")) { node = kid; break; } else if (isXSDNode(kid, "simpleType")) { return true; } } } // Expecting a schema complexType or simpleType if (isXSDNode(node, "simpleType")) { return true; } if (isXSDNode(node, "complexType")) { // Under the complexType there could be complexContent/simpleContent // and extension elements if this is a derived type. Skip over these. NodeList children = node.getChildNodes(); Node complexContent = null; Node simpleContent = null; for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexContent")) { complexContent = kid; break; } else if (isXSDNode(kid, "simpleContent")) { simpleContent = kid; } } if (complexContent != null) { return false; } if (simpleContent != null) { return true; } } return false; } /** * Test whether node is not null, belongs to the XML * Schema namespace, and has a localName that matches * schemaLocalName *

* This can be used to determine that a given Node defines a * schema "complexType" "element" and so forth. * * @param node a Node value * @param schemaLocalName a String value * @return true if the node is matches the name in the schema namespace. */ private static boolean isXSDNode(Node node, String schemaLocalName) { if (node == null) { return false; } String localName = node.getLocalName(); if (localName == null) { return false; } return (localName.equals(schemaLocalName) && Constants.isSchemaXSD(node.getNamespaceURI())); } /** * Look for the base type of node iff node is a complex type that has been * derived by restriction; otherwise return null. * * @param node * @param symbolTable * @return */ public static TypeEntry getComplexElementRestrictionBase(Node node, SymbolTable symbolTable) { if (node == null) { return null; } // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); Node complexNode = null; for (int j = 0; (j < children.getLength()) && (complexNode == null); j++) { if (isXSDNode(children.item(j), "complexType")) { complexNode = children.item(j); node = complexNode; } } } // Expecting a schema complexType if (isXSDNode(node, "complexType")) { // Under the complexType there could be should be a complexContent & // restriction elements if this is a derived type. NodeList children = node.getChildNodes(); Node content = null; Node restriction = null; for (int j = 0; (j < children.getLength()) && (content == null); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) { content = kid; } } if (content != null) { children = content.getChildNodes(); for (int j = 0; (j < children.getLength()) && (restriction == null); j++) { Node kid = children.item(j); if (isXSDNode(kid, "restriction")) { restriction = kid; } } } if (restriction == null) { return null; } else { // Get the QName of the extension base QName restrictionType = Utils.getTypeQName(restriction, new BooleanHolder(), false); if (restrictionType == null) { return null; } else { // Return associated Type return symbolTable.getType(restrictionType); } } } else { return null; } } /** * If the specified node represents a supported JAX-RPC complexType/element * which extends another complexType. The Type of the base is returned. * * @param node * @param symbolTable * @return */ public static TypeEntry getComplexElementExtensionBase(Node node, SymbolTable symbolTable) { if (node == null) { return null; } TypeEntry cached = (TypeEntry) symbolTable.node2ExtensionBase.get(node); if (cached != null) { return cached; // cache hit } // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); Node complexNode = null; for (int j = 0; (j < children.getLength()) && (complexNode == null); j++) { if (isXSDNode(children.item(j), "complexType")) { complexNode = children.item(j); node = complexNode; } } } // Expecting a schema complexType if (isXSDNode(node, "complexType")) { // Under the complexType there could be should be a complexContent & // extension elements if this is a derived type. NodeList children = node.getChildNodes(); Node content = null; Node extension = null; for (int j = 0; (j < children.getLength()) && (content == null); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) { content = kid; } } if (content != null) { children = content.getChildNodes(); for (int j = 0; (j < children.getLength()) && (extension == null); j++) { Node kid = children.item(j); if (isXSDNode(kid, "extension")) { extension = kid; } } } if (extension == null) { cached = null; } else { // Get the QName of the extension base QName extendsType = Utils.getTypeQName(extension, new BooleanHolder(), false); if (extendsType == null) { cached = null; } else { // Return associated Type cached = symbolTable.getType(extendsType); } } } symbolTable.node2ExtensionBase.put(node, cached); return cached; } /** * If the specified node represents a 'normal' non-enumeration simpleType, * the QName of the simpleType base is returned. * * @param node * @return */ public static QName getSimpleTypeBase(Node node) { QName[] qname = getContainedSimpleTypes(node); if ((qname != null) && (qname.length > 0)) { return qname[0]; } return null; } /** * Method getContainedSimpleTypes * * @param node * @return */ public static QName[] getContainedSimpleTypes(Node node) { QName[] baseQNames = null; if (node == null) { return null; } // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { if (isXSDNode(children.item(j), "simpleType")) { node = children.item(j); break; } } } // Get the node kind, expecting a schema simpleType if (isXSDNode(node, "simpleType")) { // Under the simpleType there should be a restriction. // (There may be other #text nodes, which we will ignore). NodeList children = node.getChildNodes(); Node restrictionNode = null; Node unionNode = null; for (int j = 0; (j < children.getLength()) && (restrictionNode == null); j++) { if (isXSDNode(children.item(j), "restriction")) { restrictionNode = children.item(j); } else if (isXSDNode(children.item(j), "union")) { unionNode = children.item(j); } } // The restriction node indicates the type being restricted // (the base attribute contains this type). if (restrictionNode != null) { baseQNames = new QName[1]; baseQNames[0] = Utils.getTypeQName(restrictionNode, new BooleanHolder(), false); } if (unionNode != null) { baseQNames = Utils.getMemberTypeQNames(unionNode); } // Look for enumeration elements underneath the restriction node if ((baseQNames != null) && (restrictionNode != null) && (unionNode != null)) { NodeList enums = restrictionNode.getChildNodes(); for (int i = 0; i < enums.getLength(); i++) { if (isXSDNode(enums.item(i), "enumeration")) { // Found an enumeration, this isn't a // 'normal' simple type. return null; } } } } return baseQNames; } /** * Returns the contained restriction or extension node underneath * the specified node. Returns null if not found * * @param node * @return */ public static Node getRestrictionOrExtensionNode(Node node) { Node re = null; if (node == null) { return re; } // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node n = children.item(j); if (isXSDNode(n, "simpleType") || isXSDNode(n, "complexType") || isXSDNode(n, "simpleContent")) { node = n; break; } } } // Get the node kind, expecting a schema simpleType if (isXSDNode(node, "simpleType") || isXSDNode(node, "complexType")) { // Under the complexType there could be a complexContent. NodeList children = node.getChildNodes(); Node complexContent = null; if (node.getLocalName().equals("complexType")) { for (int j = 0; (j < children.getLength()) && (complexContent == null); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) { complexContent = kid; } } node = complexContent; } // Now get the extension or restriction node if (node != null) { children = node.getChildNodes(); for (int j = 0; (j < children.getLength()) && (re == null); j++) { Node kid = children.item(j); if (isXSDNode(kid, "extension") || isXSDNode(kid, "restriction")) { re = kid; } } } } return re; } /** * If the specified node represents an array encoding of one of the following * forms, then return the qname repesenting the element type of the array. * * @param node is the node * @param dims is the output value that contains the number of dimensions if return is not null * @param itemQName will end up containing the "inner" QName for a * wrapped literal array * @return QName or null */ public static QName getArrayComponentQName(Node node, IntHolder dims, BooleanHolder underlTypeNillable, QNameHolder itemQName, BooleanHolder forElement, SymbolTable symbolTable) { dims.value = 1; // assume 1 dimension underlTypeNillable.value = false; // assume underlying type is not nillable QName qName = getCollectionComponentQName(node, itemQName, forElement, symbolTable); if (qName == null) { qName = getArrayComponentQName_JAXRPC(node, dims, underlTypeNillable, symbolTable); } return qName; } /** * If the specified node represents an element that references a collection * then return the qname repesenting the component of the collection. *

* * returns qname for"xsd:string" *

* * * * * * returns qname for"xsd:string" *

* * returns qname for "alias" * * @param node is the Node * @return QName of the compoent of the collection */ public static QName getCollectionComponentQName(Node node, QNameHolder itemQName, BooleanHolder forElement, SymbolTable symbolTable) { // If we're going to turn "wrapped" arrays into types such that // // // // becomes just "String []", we need to keep track of the inner // element name "foo" in metadata... This flag indicates whether to // do so. boolean storeComponentQName = false; if (node == null) { return null; } if (itemQName != null && isXSDNode(node, "complexType")) { // If this complexType is a sequence of exactly one element // we will continue processing below using that element, and // let the type checking logic determine if this is an array // or not. Node sequence = SchemaUtils.getChildByName(node, "sequence"); if (sequence == null) { return null; } NodeList children = sequence.getChildNodes(); Node element = null; for (int i = 0; i < children.getLength(); i++) { if (children.item(i).getNodeType() == Node.ELEMENT_NODE) { if (element == null) { element = children.item(i); } else { return null; } } } if (element == null) { return null; } // OK, exactly one element child of , // continue the processing using that element ... node = element; storeComponentQName = true; try { symbolTable.createTypeFromRef(node); } catch (IOException e) { throw new RuntimeException(Messages.getMessage("exception01",e.toString())); } } // If the node kind is an element, dive to get its type. if (isXSDNode(node, "element")) { // Compare the componentQName with the name of the // full name. If different, return componentQName QName componentTypeQName = Utils.getTypeQName(node, forElement, true); if (componentTypeQName != null) { QName fullQName = Utils.getTypeQName(node, forElement, false); if (!componentTypeQName.equals(fullQName)) { if (storeComponentQName) { String name = Utils.getAttribute(node, "name"); if (name != null) { // check elementFormDefault on schema element String def = Utils.getScopedAttribute(node, "elementFormDefault"); String namespace = ""; if ((def != null) && def.equals("qualified")) { namespace = Utils.getScopedAttribute(node, "targetNamespace"); } itemQName.value = new QName(namespace, name); } } return componentTypeQName; } } } return null; } /** * If the specified node represents an array encoding of one of the following * forms, then return the qname repesenting the element type of the array. * * @param node is the node * @param dims is the output value that contains the number of dimensions if return is not null * @return QName or null *

* JAX-RPC Style 2: * * * * * * * *

* JAX-RPC Style 3: * * * * * * * * * */ private static QName getArrayComponentQName_JAXRPC(Node node, IntHolder dims, BooleanHolder underlTypeNillable, SymbolTable symbolTable) { dims.value = 0; // Assume 0 underlTypeNillable.value = false; if (node == null) { return null; } // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexType")) { node = kid; break; } } } // Get the node kind, expecting a schema complexType if (isXSDNode(node, "complexType")) { // Under the complexType there should be a complexContent. // (There may be other #text nodes, which we will ignore). NodeList children = node.getChildNodes(); Node complexContentNode = null; for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) { complexContentNode = kid; break; } } // Under the complexContent there should be a restriction. // (There may be other #text nodes, which we will ignore). Node restrictionNode = null; if (complexContentNode != null) { children = complexContentNode.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "restriction")) { restrictionNode = kid; break; } } } // The restriction node must have a base of soapenc:Array. QName baseType = null; if (restrictionNode != null) { baseType = Utils.getTypeQName(restrictionNode, new BooleanHolder(), false); if (baseType != null) { if (!baseType.getLocalPart().equals("Array") || !Constants.isSOAP_ENC(baseType.getNamespaceURI())) { if (!symbolTable.arrayTypeQNames.contains(baseType)) { baseType = null; // Did not find base=soapenc:Array } } } } // Under the restriction there should be an attribute OR a sequence/all group node. // (There may be other #text nodes, which we will ignore). Node groupNode = null; Node attributeNode = null; if (baseType != null) { children = restrictionNode.getChildNodes(); for (int j = 0; (j < children.getLength()) && (groupNode == null) && (attributeNode == null); j++) { Node kid = children.item(j); if (isXSDNode(kid, "sequence") || isXSDNode(kid, "all")) { groupNode = kid; if (groupNode.getChildNodes().getLength() == 0) { // This covers the rather odd but legal empty sequence. // // // // // // // // groupNode = null; } } if (isXSDNode(kid, "attribute")) { // If the attribute node does not have ref="soapenc:arrayType" // then keep looking. BooleanHolder isRef = new BooleanHolder(); QName refQName = Utils.getTypeQName(kid, isRef, false); if ((refQName != null) && isRef.value && refQName.getLocalPart().equals("arrayType") && Constants.isSOAP_ENC( refQName.getNamespaceURI())) { attributeNode = kid; } } } } // If there is an attribute node, look at wsdl:arrayType to get the element type if (attributeNode != null) { String wsdlArrayTypeValue = null; Vector attrs = Utils.getAttributesWithLocalName(attributeNode, "arrayType"); for (int i = 0; (i < attrs.size()) && (wsdlArrayTypeValue == null); i++) { Node attrNode = (Node) attrs.elementAt(i); String attrName = attrNode.getNodeName(); QName attrQName = Utils.getQNameFromPrefixedName(attributeNode, attrName); if (Constants.isWSDL(attrQName.getNamespaceURI())) { wsdlArrayTypeValue = attrNode.getNodeValue(); } } // The value could have any number of [] or [,] on the end // Strip these off to get the prefixed name. // The convert the prefixed name into a qname. // Count the number of [ and , to get the dim information. if (wsdlArrayTypeValue != null) { int i = wsdlArrayTypeValue.indexOf('['); if (i > 0) { String prefixedName = wsdlArrayTypeValue.substring(0, i); String mangledString = wsdlArrayTypeValue.replace(',', '['); dims.value = 0; int index = mangledString.indexOf('['); while (index > 0) { dims.value++; index = mangledString.indexOf('[', index + 1); } return Utils.getQNameFromPrefixedName(restrictionNode, prefixedName); } } } else if (groupNode != null) { // Get the first element node under the group node. NodeList elements = groupNode.getChildNodes(); Node elementNode = null; for (int i = 0; (i < elements.getLength()) && (elementNode == null); i++) { Node kid = elements.item(i); if (isXSDNode(kid, "element")) { elementNode = elements.item(i); break; } } // The element node should have maxOccurs="unbounded" and // a type if (elementNode != null) { String underlTypeNillableValue = Utils.getAttribute(elementNode, "nillable"); if (underlTypeNillableValue != null && underlTypeNillableValue.equals("true")) { underlTypeNillable.value = true; } String maxOccursValue = Utils.getAttribute(elementNode, "maxOccurs"); if ((maxOccursValue != null) && maxOccursValue.equalsIgnoreCase("unbounded")) { // Get the QName of the type without considering maxOccurs dims.value = 1; return Utils.getTypeQName(elementNode, new BooleanHolder(), true); } } } } return null; } /** * adds an attribute node's type and name to the vector * helper used by getContainedAttributeTypes * * @param v * @param child * @param symbolTable */ private static void addAttributeToVector(Vector v, Node child, SymbolTable symbolTable) { // Get the name and type qnames. // The type qname is used to locate the TypeEntry, which is then // used to retrieve the proper java name of the type. QName attributeName = Utils.getNodeNameQName(child); BooleanHolder forElement = new BooleanHolder(); QName attributeType = Utils.getTypeQName(child, forElement, false); // An attribute is either qualified or unqualified. // If the ref= attribute is used, the name of the ref'd element is used // (which must be a root element). If the ref= attribute is not // used, the name of the attribute is unqualified. if (!forElement.value) { // check the Form (or attributeFormDefault) attribute of // this node to determine if it should be namespace // quailfied or not. String form = Utils.getAttribute(child, "form"); if ((form != null) && form.equals("unqualified")) { // Unqualified nodeName attributeName = Utils.findQName("", attributeName.getLocalPart()); } else if (form == null) { // check attributeFormDefault on schema element String def = Utils.getScopedAttribute(child, "attributeFormDefault"); if ((def == null) || def.equals("unqualified")) { // Unqualified nodeName attributeName = Utils.findQName("", attributeName.getLocalPart()); } } } else { attributeName = attributeType; } // Get the corresponding TypeEntry from the symbol table TypeEntry type = symbolTable.getTypeEntry(attributeType, forElement.value); // Try to get the corresponding global attribute ElementEntry // from the symbol table. if (type instanceof org.apache.axis.wsdl.symbolTable.Element) { type = ((org.apache.axis.wsdl.symbolTable.Element) type).getRefType(); } // add type and name to vector, skip it if we couldn't parse it // XXX - this may need to be revisited. if ((type != null) && (attributeName != null)) { ContainedAttribute attr = new ContainedAttribute(type, attributeName); String useValue = Utils.getAttribute(child, "use"); if (useValue != null) { attr.setOptional(useValue.equalsIgnoreCase("optional")); } v.add(attr); } } /** * adds an attribute to the vector * helper used by addAttributeGroupToVector * * @param v * @param symbolTable * @param type * @param name */ private static void addAttributeToVector(Vector v, SymbolTable symbolTable, QName type, QName name) { TypeEntry typeEnt = symbolTable.getTypeEntry(type, false); if (typeEnt != null) // better not be null { v.add(new ContainedAttribute(typeEnt, name)); } } /** * adds each attribute group's attribute node to the vector * helper used by getContainedAttributeTypes * * @param v * @param attrGrpnode * @param symbolTable */ private static void addAttributeGroupToVector(Vector v, Node attrGrpnode, SymbolTable symbolTable) { // get the type of the attributeGroup QName attributeGroupType = Utils.getTypeQName(attrGrpnode, new BooleanHolder(), false); TypeEntry type = symbolTable.getTypeEntry(attributeGroupType, false); if (type != null) { if (type.getNode() != null) { // for each attribute or attributeGroup defined in the attributeGroup... NodeList children = type.getNode().getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node kid = children.item(j); if (isXSDNode(kid, "attribute")) { addAttributeToVector(v, kid, symbolTable); } else if (isXSDNode(kid, "attributeGroup")) { addAttributeGroupToVector(v, kid, symbolTable); } } } else if (type.isBaseType()) { // soap/encoding is treated as a "known" schema // so let's act like we know it if (type.getQName().equals(Constants.SOAP_COMMON_ATTRS11)) { // 1.1 commonAttributes contains two attributes addAttributeToVector(v, symbolTable, Constants.XSD_ID, new QName(Constants.URI_SOAP11_ENC, "id")); addAttributeToVector(v, symbolTable, Constants.XSD_ANYURI, new QName(Constants.URI_SOAP11_ENC, "href")); } else if (type.getQName().equals( Constants.SOAP_COMMON_ATTRS12)) { // 1.2 commonAttributes contains one attribute addAttributeToVector(v, symbolTable, Constants.XSD_ID, new QName(Constants.URI_SOAP12_ENC, "id")); } else if (type.getQName().equals( Constants.SOAP_ARRAY_ATTRS11)) { // 1.1 arrayAttributes contains two attributes addAttributeToVector(v, symbolTable, Constants.XSD_STRING, new QName(Constants.URI_SOAP12_ENC, "arrayType")); addAttributeToVector(v, symbolTable, Constants.XSD_STRING, new QName(Constants.URI_SOAP12_ENC, "offset")); } else if (type.getQName().equals( Constants.SOAP_ARRAY_ATTRS12)) { // 1.2 arrayAttributes contains two attributes // the type of "arraySize" is really "2003soapenc:arraySize" // which is rather of a hairy beast that is not yet supported // in Axis, so let's just use string; nobody should care for // now because arraySize wasn't used at all up until this // bug 23145 was fixed, which had nothing to do, per se, with // adding support for arraySize addAttributeToVector(v, symbolTable, Constants.XSD_STRING, new QName(Constants.URI_SOAP12_ENC, "arraySize")); addAttributeToVector(v, symbolTable, Constants.XSD_QNAME, new QName(Constants.URI_SOAP12_ENC, "itemType")); } } } } /** * Return the attribute names and types if any in the node * The even indices are the attribute types (TypeEntry) and * the odd indices are the corresponding names (Strings). *

* Example: * * * * * * * * * * * @param node * @param symbolTable * @return */ public static Vector getContainedAttributeTypes(Node node, SymbolTable symbolTable) { Vector v = null; // return value if (node == null) { return null; } // Check for SimpleContent // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); int len = children.getLength(); for (int j = 0; j < len; j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexType")) { node = kid; break; } } } // Expecting a schema complexType if (isXSDNode(node, "complexType")) { // Under the complexType there could be complexContent/simpleContent // and extension elements if this is a derived type. Skip over these. NodeList children = node.getChildNodes(); Node content = null; int len = children.getLength(); for (int j = 0; j < len; j++) { Node kid = children.item(j); if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) { content = kid; break; } } // Check for extensions or restrictions if (content != null) { children = content.getChildNodes(); len = children.getLength(); for (int j = 0; j < len; j++) { Node kid = children.item(j); if (isXSDNode(kid, "extension") || isXSDNode(kid, "restriction")) { node = kid; break; } } } // examine children of the node for elements children = node.getChildNodes(); len = children.getLength(); for (int i = 0; i < len; i++) { Node child = children.item(i); if (isXSDNode(child, "attributeGroup")) { if (v == null) { v = new Vector(); } addAttributeGroupToVector(v, child, symbolTable); } else if (isXSDNode(child, "anyAttribute")) { // do nothing right now if (v == null) { v = new Vector(); } } else if (isXSDNode(child, "attribute")) { // we have an attribute if (v == null) { v = new Vector(); } addAttributeToVector(v, child, symbolTable); } } } return v; } // list of all of the XSD types in Schema 2001 /** Field schemaTypes[] */ private static String schemaTypes[] = { "string", "normalizedString", "token", "byte", "unsignedByte", "base64Binary", "hexBinary", "integer", "positiveInteger", "negativeInteger", "nonNegativeInteger", "nonPositiveInteger", "int", "unsignedInt", "long", "unsignedLong", "short", "unsignedShort", "decimal", "float", "double", "boolean", "time", "dateTime", "duration", "date", "gMonth", "gYear", "gYearMonth", "gDay", "gMonthDay", "Name", "QName", "NCName", "anyURI", "language", "ID", "IDREF", "IDREFS", "ENTITY", "ENTITIES", "NOTATION", "NMTOKEN", "NMTOKENS", "anySimpleType" }; /** Field schemaTypeSet */ private static final Set schemaTypeSet = new HashSet(Arrays.asList(schemaTypes)); /** * Determine if a string is a simple XML Schema type * * @param s * @return */ private static boolean isSimpleSchemaType(String s) { if (s == null) { return false; } return schemaTypeSet.contains(s); } /** * Determine if a QName is a simple XML Schema type * * @param qname * @return */ public static boolean isSimpleSchemaType(QName qname) { if ((qname == null) || !Constants.isSchemaXSD(qname.getNamespaceURI())) { return false; } return isSimpleSchemaType(qname.getLocalPart()); } /** * Returns the base type of a given type with its symbol table. * This logic is extracted from JavaTypeWriter's constructor() method * for reusing. * * @param type * @param symbolTable * @return */ public static TypeEntry getBaseType(TypeEntry type, SymbolTable symbolTable) { Node node = type.getNode(); TypeEntry base = getComplexElementExtensionBase( node, symbolTable); if (base == null) { base = getComplexElementRestrictionBase(node, symbolTable); } if (base == null) { QName baseQName = getSimpleTypeBase(node); if (baseQName != null) { base = symbolTable.getType(baseQName); } } return base; } /** * Returns whether the specified node represents a * with a nested . * @param node * @return */ public static boolean isListWithItemType(Node node) { return getListItemType(node) != null; } /** * Returns the value of itemType attribute of in * @param node * @return */ public static QName getListItemType(Node node) { if (node == null) { return null; } // If the node kind is an element, dive into it. if (isXSDNode(node, "element")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { if (isXSDNode(children.item(j), "simpleType")) { node = children.item(j); break; } } } // Get the node kind, expecting a schema simpleType if (isXSDNode(node, "simpleType")) { NodeList children = node.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { if (isXSDNode(children.item(j), "list")) { Node listNode = children.item(j); org.w3c.dom.Element listElement = (org.w3c.dom.Element) listNode; String type = listElement.getAttribute("itemType"); if (type.equals("")) { Node localType = null; children = listNode.getChildNodes(); for (j = 0; j < children.getLength() && localType == null; j++) { if (isXSDNode(children.item(j), "simpleType")) { localType = children.item(j); } } if (localType != null) { return getSimpleTypeBase(localType); } return null; } //int colonIndex = type.lastIndexOf(":"); //if (colonIndex > 0) { //type = type.substring(colonIndex + 1); //} //return new QName(Constants.URI_2001_SCHEMA_XSD, type + "[]"); return Utils.getQNameFromPrefixedName(node, type); } } } return null; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy