| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| // (c) Copyright IBM Corp. 2004, 2005 All Rights Reserved |
| * |
| * 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.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 java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| import java.util.Vector; |
| /** |
| * This class contains static utility methods specifically for schema type queries. |
| * |
| * @author Rich Scheuerle (scheu@us.ibm.com) |
| */ |
| public class CSchemaUtils extends 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(); |
| CElementDecl elem = new CElementDecl(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++) |
| { |
| TypeEntry 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 CElementDecl(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")) |
| { |
| CElementDecl elem = processChildElementNode(kid, symbolTable); |
| |
| if (elem != null) |
| { |
| elem.setChoiceElement(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. |
| TypeEntry type = symbolTable.getType(Constants.XSD_ANY); |
| CElementDecl elem = new CElementDecl(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. |
| TypeEntry type = symbolTable.getType(Constants.XSD_ANY); |
| CElementDecl elem = new CElementDecl(type, Utils.findQName("", "any")); |
| |
| elem.setAnyElement(true); |
| v.add(elem); |
| } |
| else if (localName.equals("element")) |
| { |
| CElementDecl 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 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'. |
| TypeEntry type = symbolTable.getTypeEntry(nodeType, false); |
| |
| if (type != null && type.getNode() != null) |
| { |
| 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")) |
| { |
| CElementDecl elem = processChildElementNode(kid, symbolTable); |
| |
| if (elem != null) |
| { |
| elem.setAllElement(true); |
| v.add(elem); |
| } |
| } |
| } |
| |
| return v; |
| } |
| |
| /** |
| * Invoked by getContainedElementDeclarations to get the child element type |
| * and child element name for a child element node. |
| * <p/> |
| * 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 CElementDecl 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); |
| |
| // We want to treat schema references same way we treat anyType. |
| if (type == null |
| && nodeType.getLocalPart().equals("schema") |
| && nodeType.getNamespaceURI().equals("http://www.w3.org/2001/XMLSchema")) |
| { |
| forElement.value = false; |
| type = symbolTable.getTypeEntry(nodeType, forElement.value); |
| } |
| |
| //The boolean field 'qualified' is set to true |
| //if the element is namespace qualified. |
| //The default value is unqualified. |
| boolean qualified = false; |
| |
| // 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")) |
| nodeName = Utils.findQName("", nodeName.getLocalPart()); |
| else if ((form != null) && form.equals("qualified")) |
| qualified = true; |
| else if (form == null) |
| { |
| // check elementFormDefault on schema element |
| String def = Utils.getScopedAttribute(elementNode, "elementFormDefault"); |
| |
| if ((def == null) || def.equals("unqualified")) |
| nodeName = Utils.findQName("", nodeName.getLocalPart()); |
| else if ((def == null) || def.equals("qualified")) |
| qualified = true; |
| } |
| } |
| |
| if (type != null) |
| { |
| CElementDecl elem = new CElementDecl(type, nodeName); |
| elem.setDocumentation(comments); |
| |
| String minOccurs = Utils.getAttribute(elementNode, "minOccurs"); |
| if (minOccurs != null) { |
| elem.setMinOccurs(Integer.parseInt(minOccurs)); |
| } |
| |
| String maxOccurs = Utils.getAttribute(elementNode, "maxOccurs"); |
| if (maxOccurs != null) { |
| if (maxOccurs.equals("unbounded")) { |
| elem.setMaxOccurs(CElementDecl.UNBOUNDED); |
| } |
| else |
| elem.setMaxOccurs(Integer.parseInt(maxOccurs)); |
| } |
| |
| elem.setNillable(JavaUtils.isTrueExplicitly(Utils.getAttribute(elementNode, "nillable"))); |
| |
| String useValue = Utils.getAttribute(elementNode, "use"); |
| |
| if (useValue != null) |
| elem.setOptional(useValue.equalsIgnoreCase("optional")); |
| |
| elem.setNsQualified(qualified); |
| |
| 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 <tt>node</tt> is not null, belongs to the XML |
| * Schema namespace, and has a localName that matches |
| * <tt>schemaLocalName</tt> |
| * <p/> |
| * This can be used to determine that a given Node defines a |
| * schema "complexType" "element" and so forth. |
| * |
| * @param node a <code>Node</code> value |
| * @param schemaLocalName a <code>String</code> 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, |
| SymbolTable symbolTable) |
| { |
| dims.value = 1; // assume 1 dimension |
| |
| QName qName = getCollectionComponentQName(node); |
| |
| if (qName == null) |
| qName = getArrayComponentQName_JAXRPC(node, dims, symbolTable); |
| |
| return qName; |
| } |
| |
| /** |
| * If the specified node represents an element that references a collection |
| * then return the qname repesenting the component of the collection. |
| * <p/> |
| * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/> |
| * returns qname for"xsd:string" |
| * <p/> |
| * <xsd:complexType> |
| * <xsd:sequence> |
| * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/> |
| * </xsd:sequence> |
| * </xsd:complexType> |
| * returns qname for"xsd:string" |
| * <p/> |
| * <xsd:element ref="alias" maxOccurs="unbounded"/> |
| * returns qname for "alias" |
| * |
| * @param node is the Node |
| * @return QName of the compoent of the collection |
| */ |
| public static QName getCollectionComponentQName(Node node) |
| { |
| if (node == null) |
| return null; |
| |
| // If the node kind is an element, dive get its type. |
| if (isXSDNode(node, "element")) |
| { |
| // Compare the componentQName with the name of the |
| // full name. If different, return componentQName |
| BooleanHolder forElement = new BooleanHolder(); |
| QName componentQName = Utils.getTypeQName(node, forElement, true); |
| |
| if (componentQName != null) |
| { |
| QName fullQName = Utils.getTypeQName(node, forElement, false); |
| |
| if (!componentQName.equals(fullQName)) |
| return componentQName; |
| } |
| } |
| |
| 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 |
| * <p/> |
| * JAX-RPC Style 2: |
| * <xsd:complexType name="hobbyArray"> |
| * <xsd:complexContent> |
| * <xsd:restriction base="soapenc:Array"> |
| * <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/> |
| * </xsd:restriction> |
| * </xsd:complexContent> |
| * </xsd:complexType> |
| * <p/> |
| * JAX-RPC Style 3: |
| * <xsd:complexType name="petArray"> |
| * <xsd:complexContent> |
| * <xsd:restriction base="soapenc:Array"> |
| * <xsd:sequence> |
| * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/> |
| * </xsd:sequence> |
| * </xsd:restriction> |
| * </xsd:complexContent> |
| * </xsd:complexType> |
| */ |
| private static QName getArrayComponentQName_JAXRPC(Node node, |
| IntHolder dims, |
| SymbolTable symbolTable) |
| { |
| |
| dims.value = 0; // Assume 0 |
| |
| 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. |
| // <complexType name="ArrayOfString"> |
| // <complexContent> |
| // <restriction base="soapenc:Array"> |
| // <sequence/> |
| // <attribute ref="soapenc:arrayType" wsdl:arrayType="string[]"/> |
| // </restriction> |
| // </complexContent> |
| // </complexType> |
| 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 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")) |
| 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)) |
| { |
| CContainedAttribute attr = new CContainedAttribute(type, attributeName); |
| |
| String useValue = Utils.getAttribute(child, "use"); |
| if (useValue != null) |
| attr.setOptional(useValue.equalsIgnoreCase("optional")); |
| |
| String fixedValue = Utils.getAttribute(child, "fixed"); |
| if (fixedValue != null) |
| attr.setFixedValue(fixedValue); |
| |
| String defaultValue = Utils.getAttribute(child, "default"); |
| if (defaultValue != null) |
| attr.setDefaultValue(defaultValue); |
| |
| 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) |
| v.add(new CContainedAttribute(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). |
| * <p/> |
| * Example: |
| * <complexType name="Person"> |
| * <sequence> |
| * <element minOccurs="1" maxOccurs="1" name="Age" type="double" /> |
| * <element minOccurs="1" maxOccurs="1" name="ID" type="xsd:float" /> |
| * </sequence> |
| * <attribute name="Name" type="string" /> |
| * <attribute name="Male" type="boolean" /> |
| * <attributeGroup ref="s0:MyAttrSet" /> |
| * </complexType> |
| * |
| * @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 <attribute> 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")) |
| { |
| 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 <xsd:simpleType> |
| * with a nested <xsd:list itemType="...">. |
| * @param node |
| * @return |
| */ |
| public static boolean isListWithItemType(Node node) |
| { |
| return getListItemType(node) != null; |
| } |
| |
| /** |
| * Returns the value of itemType attribute of <xsd:list> in <xsd:simpleType> |
| * @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; |
| } |
| |
| /* |
| * check whether node should be namespace qualified or not by checking for "form" |
| * attribute. If "form" attribute not specified, the defaultAnswer is returned. |
| */ |
| public static boolean shouldWeNamespaceQualifyNode(Node elementNode, boolean defaultAnswer) |
| { |
| if (null == elementNode || elementNode.getNodeType() != Node.ELEMENT_NODE) |
| return defaultAnswer; |
| |
| // Ensure node represents an "element" node. If not, get the parent. |
| if (!elementNode.getLocalName().equals("element")) |
| return shouldWeNamespaceQualifyNode(elementNode.getParentNode(), defaultAnswer); |
| |
| String form = Utils.getAttribute(elementNode, "form"); |
| if (form != null) |
| { |
| if (form.equals("qualified")) |
| return true; |
| else |
| return false; |
| } |
| else |
| return defaultAnswer; |
| } |
| |
| /* |
| * Find out whether schema's elementFormDefault is "qualified" or not. This is done by |
| * recursively interrogating parent nodes until it is found or not. |
| */ |
| public static boolean isElementFormDefaultQualified(Node elementNode) |
| { |
| if (elementNode != null) |
| { |
| String def = Utils.getScopedAttribute(elementNode, "elementFormDefault"); |
| if ((def != null) && def.equals("qualified")) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /* |
| * Find out whether schema's attributeFormDefault is "qualified" or not. This is done by |
| * recursively interrogating parent nodes until it is found or not. |
| */ |
| public static boolean isAttributeFormDefaultQualified(Node attributeNode) |
| { |
| if (attributeNode != null) |
| { |
| String def = Utils.getScopedAttribute(attributeNode, "attributeFormDefault"); |
| if ((def != null) && def.equals("qualified")) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| } |