You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by da...@apache.org on 2004/07/23 14:21:07 UTC

cvs commit: ws-axis/c/src/wsdl/org/apache/axis/wsdl/wsdl2ws WSDL2Ws.java

damitha     2004/07/23 05:21:07

  Modified:    c/src/wsdl/org/apache/axis/wsdl/symbolTable ElementDecl.java
                        SchemaUtils.java
               c/src/wsdl/org/apache/axis/wsdl/wsdl2ws WSDL2Ws.java
  Log:
  Updated the wsdl2ws tool to support latest Axis jars from  axis-1_2beta
  
  Revision  Changes    Path
  1.5       +21 -0     ws-axis/c/src/wsdl/org/apache/axis/wsdl/symbolTable/ElementDecl.java
  
  Index: ElementDecl.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/c/src/wsdl/org/apache/axis/wsdl/symbolTable/ElementDecl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ElementDecl.java	9 Apr 2004 08:49:31 -0000	1.4
  +++ ElementDecl.java	23 Jul 2004 12:21:07 -0000	1.5
  @@ -45,6 +45,9 @@
   	// an xsd:any element
   	private boolean anyElement = false;
   
  +	/** Field documentation */
  +	private String documentation;
  +
   	public ElementDecl() {
   	}
   
  @@ -125,5 +128,23 @@
       public void setNillable(boolean b) {
           nillable = b;
       }
  +
  +    /**
  +     *       Method getDocumentation
  +     *       @return string       
  +     */
  +    
  +    public String getDocumentation() {
  +          return documentation;
  +    }
  +
  +     /**
  +      *       Method setDocumentation
  +      *       @param documentation
  +      */
  +  
  +    public void setDocumentation(String documentation) {
  +           this.documentation = documentation;
  +    }    
   
   }
  
  
  
  1.5       +1222 -355 ws-axis/c/src/wsdl/org/apache/axis/wsdl/symbolTable/SchemaUtils.java
  
  Index: SchemaUtils.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/c/src/wsdl/org/apache/axis/wsdl/symbolTable/SchemaUtils.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SchemaUtils.java	9 Apr 2004 08:49:31 -0000	1.4
  +++ SchemaUtils.java	23 Jul 2004 12:21:07 -0000	1.5
  @@ -1,23 +1,25 @@
   /*
  - *   Copyright 2003-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.
  + * 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.wsdl.wsdl2ws.info.ElementInfo;
  +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;
   
  @@ -27,31 +29,152 @@
   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 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;
  +	}
  +
  +  /**
  +   * 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();
  +	  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")) {
  +			Node sequenceNode = children.item(j);
  +			NodeList sequenceChildren = sequenceNode.getChildNodes();
  +			for (int k = 0; k < sequenceChildren.getLength(); k++) {
  +			  QName sequenceSubNodeKind = Utils.getNodeQName(sequenceChildren.item(k));
  +			  if ((sequenceSubNodeKind != null)
  +				&& Constants.isSchemaXSD(sequenceSubNodeKind.getNamespaceURI())) {
  +				if (!sequenceSubNodeKind.getLocalPart().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 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 
  +	 * 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) {
  +	public static Vector getContainedElementDeclarations(Node node,
  +														 SymbolTable symbolTable) {
  +
   		if (node == null) {
   			return null;
   		}
  @@ -59,10 +182,13 @@
   		// 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;
   				}
   			}
  @@ -70,322 +196,597 @@
   
   		// 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?
  +
  +					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++) {
  +
  +				for (int j = 0;
  +					 (j < children.getLength()) && (extension == null);
  +					 j++) {
   					Node kid = children.item(j);
  -					if (isXSDNode(kid, "extension")) { 
  +
  +					if (isXSDNode(kid, "extension")
  +							|| isXSDNode(kid, "restriction")) {
   						extension = kid;
   					}
   				}
   			}
  +
   			if (simpleContent != null) {
   				children = simpleContent.getChildNodes();
  -				for (int j = 0; j < children.getLength() && extension == null; j++) {
  -					QName extensionOrRestrictionKind = Utils.getNodeQName(children.item(j));
  -					if (extensionOrRestrictionKind != null &&
  -						(extensionOrRestrictionKind.getLocalPart().equals("extension") ||
  -						 extensionOrRestrictionKind.getLocalPart().equals("restriction")) &&
  -						Constants.isSchemaXSD(extensionOrRestrictionKind.getNamespaceURI())) {
  -                        
  +
  +				for (int j = 0;
  +					 (j < children.getLength()) && (extension == null);
  +					 j++) {
  +					QName extensionOrRestrictionKind =
  +							Utils.getNodeQName(children.item(j));
  +
  +					if ((extensionOrRestrictionKind != null)
  +							&& (extensionOrRestrictionKind.getLocalPart().equals(
  +									"extension") || extensionOrRestrictionKind.getLocalPart().equals(
  +											"restriction"))
  +							&& Constants.isSchemaXSD(
  +									extensionOrRestrictionKind.getNamespaceURI())) {
  +
   						// get the type of the extension/restriction from the "base" attribute
   						QName extendsOrRestrictsType =
  -							Utils.getTypeQName(children.item(j), new BooleanHolder(), false);
  -                        
  +								Utils.getTypeQName(children.item(j),
  +										new BooleanHolder(), false);
  +
   						// Return an element declaration with a fixed name
  -						// ("value") and the correct type.                        
  +						// ("value") and the correct type.
   						Vector v = new Vector();
   						ElementDecl elem = new ElementDecl();
  -						elem.setType(symbolTable.getTypeEntry(extendsOrRestrictsType, false));
  +
  +						elem.setType(
  +								symbolTable.getTypeEntry(
  +										extendsOrRestrictsType, false));
   						elem.setName(VALUE_QNAME);
   						v.add(elem);
  +
   						return v;
   					}
   				}
   			}
   
   			if (extension != null) {
  -				node = extension;  // Skip over complexContent and extension
  +				node = extension;    // Skip over complexContent and extension
   			}
   
  -			// Under the complexType there may be choice, sequence, group and/or all nodes.      
  +			// 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();
  +
   			for (int j = 0; j < children.getLength(); j++) {
   				QName subNodeKind = Utils.getNodeQName(children.item(j));
  -				if (subNodeKind != null &&
  -					Constants.isSchemaXSD(subNodeKind.getNamespaceURI())) {
  +
  +				if ((subNodeKind != null)
  +						&& Constants.isSchemaXSD(
  +								subNodeKind.getNamespaceURI())) {
   					if (subNodeKind.getLocalPart().equals("sequence")) {
  -						v.addAll(processSequenceNode(children.item(j), symbolTable));
  +						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));
  +						v.addAll(processChoiceNode(children.item(j),
  +								symbolTable));
   					} else if (subNodeKind.getLocalPart().equals("group")) {
  -						v.addAll(processGroupNode(children.item(j), symbolTable));
  +						v.addAll(processGroupNode(children.item(j),
  +								symbolTable));
  +					}
  +				}
  +			}
  +
  +			return v;
  +		} else if (isXSDNode(node, "group")) {
  +			NodeList children = node.getChildNodes();
  +			Vector v = new Vector();
  +			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;
   		} else {
  +
   			// This may be a simpleType, return the type with the name "value"
  -			QName simpleQName = getSimpleTypeBase(node);
  +			QName[] simpleQName = getContainedSimpleTypes(node);
  +
   			if (simpleQName != null) {
  -				TypeEntry simpleType = symbolTable.getType(simpleQName);
  -				if (simpleType != null) {
  -					Vector v = new Vector();
  -					ElementDecl elem = new ElementDecl();
  -					elem.setType(simpleType);
  -					elem.setName(new javax.xml.namespace.QName("", "value"));
  -					v.add(elem);
  -					return v;
  +				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();
  +						}
  +
  +						ElementDecl elem = new ElementDecl();
  +
  +						elem.setType(simpleType);
  +
  +						if (simpleQName.length > 1) {
  +							elem.setName(
  +									new javax.xml.namespace.QName(
  +											"",
  +											simpleQName[i].getLocalPart() + "Value"));
  +						} else {
  +							elem.setName(
  +									new javax.xml.namespace.QName("", "value"));
  +						}
  +
  +						v.add(elem);
  +					}
   				}
  +
  +				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, 
  +	private static Vector processChoiceNode(Node choiceNode,
   											SymbolTable symbolTable) {
  +
   		Vector v = new Vector();
   		NodeList children = choiceNode.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 != null)
  +					&& Constants.isSchemaXSD(subNodeKind.getNamespaceURI())) {
   				if (subNodeKind.getLocalPart().equals("choice")) {
   					v.addAll(processChoiceNode(children.item(j), symbolTable));
   				} else if (subNodeKind.getLocalPart().equals("sequence")) {
  -					v.addAll(processSequenceNode(children.item(j), symbolTable));
  +					v.addAll(processSequenceNode(children.item(j),
  +							symbolTable));
   				} else if (subNodeKind.getLocalPart().equals("group")) {
   					v.addAll(processGroupNode(children.item(j), symbolTable));
   				} else if (subNodeKind.getLocalPart().equals("element")) {
  -					ElementDecl elem = 
  -							processChildElementNode(children.item(j), 
  -													symbolTable);
  -					if (elem != null)
  +					ElementDecl elem = processChildElementNode(children.item(j),
  +							symbolTable);
  +
  +					if (elem != null) {
   						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())) {
  +						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 root Parent node.
  +	 * @param path Path of element names to text of interest, delimited by "/". 
  +	 */
  +	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, 
  +	private static Vector processSequenceNode(Node sequenceNode,
   											  SymbolTable symbolTable) {
  +
   		Vector v = new Vector();
   		NodeList children = sequenceNode.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 != null)
  +					&& Constants.isSchemaXSD(subNodeKind.getNamespaceURI())) {
   				if (subNodeKind.getLocalPart().equals("choice")) {
   					v.addAll(processChoiceNode(children.item(j), symbolTable));
   				} else if (subNodeKind.getLocalPart().equals("sequence")) {
  -					v.addAll(processSequenceNode(children.item(j), symbolTable));
  +					v.addAll(processSequenceNode(children.item(j),
  +							symbolTable));
   				} else if (subNodeKind.getLocalPart().equals("group")) {
   					v.addAll(processGroupNode(children.item(j), symbolTable));
   				} else if (subNodeKind.getLocalPart().equals("any")) {
  +
   					// Represent this as an element named any of type any type.
  -					// This will cause it to be serialized with the element 
  +					// This will cause it to be serialized with the element
   					// serializer.
   					TypeEntry type = symbolTable.getType(Constants.XSD_ANY);
  -					ElementDecl elem = 
  -						new ElementDecl(type, Utils.findQName("","any"));
  +					ElementDecl elem = new ElementDecl(type,
  +							Utils.findQName("",
  +									"any"));
  +
   					elem.setAnyElement(true);
   					v.add(elem);
   				} else if (subNodeKind.getLocalPart().equals("element")) {
  -					ElementDecl elem = 
  -							processChildElementNode(children.item(j), 
  -													symbolTable);
  -					if (elem != null)
  +					ElementDecl elem = processChildElementNode(children.item(j),
  +							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.
  -	 * (Currently the code only supports a defined group it does not
  -	 * support a group that references a previously defined group)
  +	 * 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) {
  +	private static Vector processGroupNode(Node groupNode,
  +										   SymbolTable symbolTable) {
  +
   		Vector v = new Vector();
  -		NodeList children = groupNode.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("choice")) {
  -					v.addAll(processChoiceNode(children.item(j), symbolTable));
  -				} else 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));
  +		if (groupNode.getAttributes().getNamedItem("ref") == null) {
  +			NodeList children = groupNode.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("choice")) {
  +						v.addAll(processChoiceNode(children.item(j), symbolTable));
  +					} else 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 {
  +			BooleanHolder forElement = new BooleanHolder();
  +			QName nodeName = Utils.getTypeQName(groupNode, forElement, false);
  +			TypeEntry type = symbolTable.getTypeEntry(nodeName, forElement.value);
  +
  +			if (type != null) {
  +				v.add(new ElementDecl(type, nodeName));
  +			}
   		}
   		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) {
  +	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);
  +				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.
  -	 *
  +	 * <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 ElementDecl processChildElementNode(Node elementNode, 
  -												  SymbolTable symbolTable) {
  +	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);
  +		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")) {
  +
  +			if ((form != null) && form.equals("unqualified")) {
  +
   				// Unqualified nodeName
  -				nodeName = Utils.findQName("", nodeName.getLocalPart());            
  +				nodeName = Utils.findQName("", nodeName.getLocalPart());
   			} else if (form == null) {
  +
   				// check elementForDefault on schema element
  -				String def = Utils.getScopedAttribute(elementNode, 
  -													  "elementFormDefault");
  -				if (def == null || def.equals("unqualified")) {
  +				String def = Utils.getScopedAttribute(elementNode,
  +						"elementFormDefault");
  +
  +				if ((def == null) || def.equals("unqualified")) {
  +
   					// Unqualified nodeName
  -					nodeName = Utils.findQName("", nodeName.getLocalPart());            
  +					nodeName = Utils.findQName("", nodeName.getLocalPart());
   				}
   			}
   		}
   
   		if (type != null) {
   			ElementDecl elem = new ElementDecl(type, nodeName);
  -			String minOccurs = Utils.getAttribute(elementNode, "minOccurs");
  -			if (minOccurs != null && minOccurs.equals("0")) {
  +			elem.setDocumentation(comments);
  +			String minOccurs = Utils.getAttribute(elementNode,
  +					"minOccurs");
  +
  +			if ((minOccurs != null) && minOccurs.equals("0")) {
   				elem.setMinOccursIs0(true);
   			}
   			if(minOccurs == null){}
  -			else if("unbounded".equals(minOccurs))
  -				elem.setMinOccurs(ElementInfo.UNBOUNDED);
  -			else{	
  -				elem.setMinOccurs(Integer.parseInt(minOccurs));
  -			}
  +						else if("unbounded".equals(minOccurs))
  +							elem.setMinOccurs(ElementInfo.UNBOUNDED);
  +						else{	
  +							elem.setMinOccurs(Integer.parseInt(minOccurs));
  +						}
   
   			
  -			String maxOccurs = Utils.getAttribute(elementNode, "maxOccurs");
  +						String maxOccurs = Utils.getAttribute(elementNode, "maxOccurs");
   			
  -			if(maxOccurs == null){}
  -			else if("unbounded".equals(maxOccurs))
  -				elem.setMaxOccurs(ElementInfo.UNBOUNDED);
  -			else	
  -				elem.setMaxOccurs(Integer.parseInt(maxOccurs));
  -			String nillable = Utils.getAttribute(elementNode, "nilable");
  -			if(nillable != null && "true".equals(nillable))
  -				elem.setNillable(true);
  +						if(maxOccurs == null){}
  +						else if("unbounded".equals(maxOccurs))
  +							elem.setMaxOccurs(ElementInfo.UNBOUNDED);
  +						else	
  +							elem.setMaxOccurs(Integer.parseInt(maxOccurs));
  +						String nillable = Utils.getAttribute(elementNode, "nilable");
  +						if(nillable != null && "true".equals(nillable))
  +							elem.setNillable(true);
   			
  +						return elem;
  +			
  +
  +			/*elem.setNillable(
  +					JavaUtils.isTrueExplicitly(
  +							Utils.getAttribute(elementNode, "nillable")));
  +
   			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")) {
  +
  +				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")) {
  +
  +				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;
   		}
  @@ -393,12 +794,15 @@
   		// 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")) { 
  +				} else if (isXSDNode(kid, "simpleType")) {
   					return true;
   				}
   			}
  @@ -410,27 +814,34 @@
   		}
   
   		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;
   	}
   
  @@ -438,41 +849,47 @@
   	 * 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 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) && Constants.isSchemaXSD(node.getNamespaceURI())) {
   			String localName = node.getLocalName();
  +
   			return ((localName != null) && localName.equals(schemaLocalName));
   		}
  +
   		return false;
   	}
   
   	/**
  -	 * If the specified node represents a supported JAX-RPC complexType/element
  -	 * which extends another complexType.  The Type of the base is returned.
  +	 * 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 getComplexElementExtensionBase(Node node, SymbolTable symbolTable) {
  +	public static TypeEntry getComplexElementRestrictionBase(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++) {
  +
  +			for (int j = 0;
  +				 (j < children.getLength()) && (complexNode == null); j++) {
   				if (isXSDNode(children.item(j), "complexType")) {
   					complexNode = children.item(j);
   					node = complexNode;
  @@ -484,104 +901,254 @@
   		if (isXSDNode(node, "complexType")) {
   
   			// Under the complexType there could be should be a complexContent &
  -			// extension elements if this is a derived type. 
  +			// restriction 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 restriction = null;
  +
  +			for (int j = 0; (j < children.getLength()) && (content == null);
  +				 j++) {
   				Node kid = children.item(j);
  -				if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) {
  +
  +				if (isXSDNode(kid, "complexContent")) {
   					content = kid;
   				}
   			}
  +
   			if (content != null) {
   				children = content.getChildNodes();
  -				for (int j = 0; j < children.getLength() && extension == null; j++) {
  +
  +				for (int j = 0;
  +					 (j < children.getLength()) && (restriction == null);
  +					 j++) {
   					Node kid = children.item(j);
  -					if (isXSDNode(kid, "extension")) {
  -						extension = kid;
  +
  +					if (isXSDNode(kid, "restriction")) {
  +						restriction = kid;
   					}
   				}
   			}
  -			if (extension == null) {
  -				cached = null;
  +
  +			if (restriction == null) {
  +				return null;
   			} else {
  +
   				// Get the QName of the extension base
  -				QName extendsType = Utils.getTypeQName(extension, new BooleanHolder(), false);
  -				if (extendsType == null) {
  -					cached = null;
  +				QName restrictionType = Utils.getTypeQName(restriction,
  +						new BooleanHolder(),
  +						false);
  +
  +				if (restrictionType == null) {
  +					return null;
   				} else {
  +
   					// Return associated Type
  -					cached = symbolTable.getType(extendsType);
  +					return symbolTable.getType(restrictionType);
   				}
   			}
  +		} else {
  +			return null;
   		}
  -		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.
  +	 * 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 baseQName = null;
  +
  +		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.
  -		QName nodeKind = Utils.getNodeQName(node);
   		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;
  -			for (int j = 0; j < children.getLength() && restrictionNode == null; j++) {
  +			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) {
  -				baseQName = Utils.getTypeQName(restrictionNode, new BooleanHolder(), false);
  +				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 (baseQName != null && restrictionNode != null) {
  +			if ((baseQNames != null) && (restrictionNode != null)
  +					&& (unionNode != null)) {
   				NodeList enums = restrictionNode.getChildNodes();
  -				for (int i=0; i < enums.getLength(); i++) {
  +
  +				for (int i = 0; i < enums.getLength(); i++) {
   					if (isXSDNode(enums.item(i), "enumeration")) {
  -						// Found an enumeration, this isn't a 
  +
  +						// Found an enumeration, this isn't a
   						// 'normal' simple type.
   						return null;
   					}
   				}
   			}
   		}
  -		return baseQName;
  +
  +		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;
   		}
  @@ -589,123 +1156,157 @@
   		// If the node kind is an element, dive into it.
   		if (isXSDNode(node, "element")) {
   			NodeList children = node.getChildNodes();
  -			Node node2 = null;
  +
   			for (int j = 0; j < children.getLength(); j++) {
   				Node n = children.item(j);
  -				if (isXSDNode(n, "simpleType") || isXSDNode(n, "complexType") || isXSDNode(n, "simpleContent")) {
  +
  +				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++) {
  +				for (int j = 0;
  +					 (j < children.getLength()) && (complexContent == null);
  +					 j++) {
   					Node kid = children.item(j);
  -					if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) {
  +
  +					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++) {
  +
  +				for (int j = 0; (j < children.getLength()) && (re == null);
  +					 j++) {
   					Node kid = children.item(j);
  -					if (isXSDNode(kid, "extension") || isXSDNode(kid, "restriction")) {
  +
  +					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
   	 * @return QName or null
   	 */
  -	public static QName getArrayComponentQName(Node node, IntHolder dims) {
  -		dims.value = 1;  // assume 1 dimension
  +	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);
  +			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.
  -	 *
  -	 *  <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/>
  -	 *    returns qname for"xsd:string"
  -	 *  <xsd:element ref="alias"  maxOccurs="unbounded"/>
  -	 *    returns qname for "alias"
  +	 * <p/>
  +	 * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/>
  +	 * returns qname for"xsd:string"
  +	 * <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);
  +			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
  -	 *
  -	 * 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>
  -	 *
  -	 * 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>
  -	 *
  +	 *         <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) {
  -		dims.value = 0;  // Assume 0
  +	private static QName getArrayComponentQName_JAXRPC(Node node,
  +													   IntHolder dims,
  +													   SymbolTable symbolTable)
  +	{
  +
  +		dims.value = 0;    // Assume 0
  +
   		if (node == null) {
   			return null;
   		}
  @@ -713,10 +1314,13 @@
   		// 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;
   				}
   			}
  @@ -724,14 +1328,19 @@
   
   		// 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")) {
  +
  +				if (isXSDNode(kid, "complexContent")
  +						|| isXSDNode(kid, "simpleContent")) {
   					complexContentNode = kid;
  +
   					break;
   				}
   			}
  @@ -739,64 +1348,81 @@
   			// 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.              
  +			// 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 &&
  -					baseType.getLocalPart().equals("Array") &&
  -					Constants.isSOAP_ENC(baseType.getNamespaceURI()))
  -					; // Okay
  -				else
  -					baseType = null;  // Did not find base=soapenc:Array
  -			}
  +				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++) {
  +
  +				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>
  +							// <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())) {
  +						QName refQName = Utils.getTypeQName(kid, isRef,
  +								false);
  +
  +						if ((refQName != null) && isRef.value
  +								&& refQName.getLocalPart().equals("arrayType")
  +								&& Constants.isSOAP_ENC(
  +										refQName.getNamespaceURI())) {
   							attributeNode = kid;
   						}
   					}
  @@ -806,11 +1432,18 @@
   			// 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++) {
  +				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);
  +					QName attrQName =
  +							Utils.getQNameFromPrefixedName(attributeNode, attrName);
  +
   					if (Constants.isWSDL(attrQName.getNamespaceURI())) {
   						wsdlArrayTypeValue = attrNode.getNodeValue();
   					}
  @@ -822,81 +1455,275 @@
   				// 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(',', '[');
  +						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);
  +
  +							index = mangledString.indexOf('[', index + 1);
   						}
  -                        
  -						return Utils.getQNameFromPrefixedName(restrictionNode, prefixedName);
  +
  +						return Utils.getQNameFromPrefixedName(restrictionNode,
  +								prefixedName);
   					}
   				}
   			} else if (groupNode != null) {
   
  -				// Get the first element node under the group node.       
  +				// 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++) {
  +
  +				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")) {
  +					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 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);
  +
  +		// 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)) {
  +			v.add(type);
  +			v.add(attributeName);
  +		}
  +	}
  +
  +	/**
  +	 * 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(typeEnt);
  +			v.add(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 element types (TypeEntry) and
  +	 * 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" />
  +	 * <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>
   	 * 
  -	 */ 
  -	public static Vector getContainedAttributeTypes(Node node, 
  -													SymbolTable symbolTable) 
  -	{
  +	 * @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();
  +
   			for (int j = 0; j < children.getLength(); j++) {
   				Node kid = children.item(j);
  +
   				if (isXSDNode(kid, "complexType")) {
   					node = kid;
  +
   					break;
   				}
   			}
  @@ -904,155 +1731,195 @@
   
   		// 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;
  +
   			for (int j = 0; j < children.getLength(); j++) {
   				Node kid = children.item(j);
  -				if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) {
  +
  +				if (isXSDNode(kid, "complexContent")
  +						|| isXSDNode(kid, "simpleContent")) {
   					content = kid;
  +
   					break;
   				}
   			}
  -			// Check for extensions
  +
  +			// Check for extensions or restrictions
   			if (content != null) {
   				children = content.getChildNodes();
  +
   				for (int j = 0; j < children.getLength(); j++) {
   					Node kid = children.item(j);
  -					if (isXSDNode(kid, "extension")) {
  +
  +					if (isXSDNode(kid, "extension")
  +							|| isXSDNode(kid, "restriction")) {
   						node = kid;
  +
   						break;
   					}
   				}
   			}
  -            
  +
   			// examine children of the node for <attribute> elements
   			children = node.getChildNodes();
  +
   			for (int i = 0; i < children.getLength(); i++) {
   				Node child = children.item(i);
  -				if (! isXSDNode(child, "attribute")) {
  +
  +				if (!isXSDNode(child, "attribute")
  +						&& !isXSDNode(child, "attributeGroup")) {
   					continue;
   				}
  -                
  -				// we have an attribute node
  -				if (v == null)
  +
  +				// we have an attribute or attributeGroup node
  +				if (v == null) {
   					v = new Vector();
  +				}
   
  -				// 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());            
  -						}
  -					}
  +				if (isXSDNode(child, "attributeGroup")) {
  +					addAttributeGroupToVector(v, child, symbolTable);
   				} else {
  -					attributeName = attributeType;
  -				}
  -                
  -				// Get the corresponding TypeEntry from the symbol table
  -				TypeEntry type = symbolTable.getTypeEntry(attributeType, 
  -														  forElement.value);
  -                
  -				// 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) {
  -					v.add(type);
  -					v.add(attributeName);
  +
  +					// we have an attribute
  +					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"
  +		"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"
   	};
   
  -	private static final Set schemaTypeSet = new HashSet(Arrays.asList(schemaTypes));
  -    
  +	/** Field schemaTypeSet */
  +	private static final Set schemaTypeSet =
  +			new HashSet(Arrays.asList(schemaTypes));
  +
   	/**
  -	 * Determine if a string is a simple XML Schema type 
  -	 */ 
  +	 * Determine if a string is a simple XML Schema type
  +	 * 
  +	 * @param s 
  +	 * @return 
  +	 */
   	private static boolean isSimpleSchemaType(String s) {
  -		if (s == null)
  +
  +		if (s == null) {
   			return false;
  +		}
   
   		return schemaTypeSet.contains(s);
   	}
  +
   	/**
  -	 * Determine if a QName is a simple XML Schema type 
  -	 */ 
  +	 * 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())) {
  +
  +		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("")) {
  +						return null;
  +					}
  +					int colonIndex = type.lastIndexOf(":");
  +					if (colonIndex > 0) {
  +						type = type.substring(colonIndex + 1);
  +					}
  +					return new QName(Constants.URI_2001_SCHEMA_XSD, type + "[]");
  +				}
  +			}
  +		}
  +		return null;
   	}
   }
  
  
  
  1.31      +1 -1      ws-axis/c/src/wsdl/org/apache/axis/wsdl/wsdl2ws/WSDL2Ws.java
  
  Index: WSDL2Ws.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/c/src/wsdl/org/apache/axis/wsdl/wsdl2ws/WSDL2Ws.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- WSDL2Ws.java	4 Jul 2004 12:49:17 -0000	1.30
  +++ WSDL2Ws.java	23 Jul 2004 12:21:07 -0000	1.31
  @@ -531,7 +531,7 @@
   		}else{
   			//is this a SOAPEnc array type	
   			QName arrayType =
  -				SchemaUtils.getArrayComponentQName(node, new IntHolder(0));
  +				SchemaUtils.getArrayComponentQName(node, new IntHolder(0),symbolTable);
   			if (arrayType != null) {
   				typedata.setTypeNameForElementName(new ElementInfo(new QName("item"),
   						createTypeInfo(arrayType,targetLanguage)));