/*******************************************************************************
 * Copyright (c) 2001, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.wst.wsdl.validation.internal.wsdl11;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import javax.wsdl.Binding;
import javax.wsdl.BindingFault;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.OperationType;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.ExtensionDeserializer;
import javax.wsdl.extensions.ExtensionRegistry;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.wsdl.factory.WSDLFactory;
import javax.xml.namespace.QName;

import org.apache.xerces.dom.ElementImpl;
import org.apache.xerces.dom.ElementNSImpl;
import org.apache.xerces.xs.XSModel;
import org.eclipse.wst.wsdl.validation.internal.util.MessageGenerator;
import org.eclipse.wst.wsdl.validation.internal.wsdl11.xsd.InlineSchemaValidator;
import org.eclipse.wst.wsdl.validation.internal.xml.ElementLocation;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.ibm.wsdl.Constants;
import com.ibm.wsdl.util.StringUtils;
import com.ibm.wsdl.util.xml.DOMUtils;
import com.ibm.wsdl.util.xml.QNameUtils;
import com.ibm.wsdl.util.xml.XPathUtils;

/**
 * A WSDL document that knows how to parse itself.
 */
public class WSDLDocument
{
  private static final List STYLE_ONE_WAY = Arrays.asList(new String[] { Constants.ELEM_INPUT });
  private static final List STYLE_REQUEST_RESPONSE =
    Arrays.asList(new String[] { Constants.ELEM_INPUT, Constants.ELEM_OUTPUT });
  private static final List STYLE_SOLICIT_RESPONSE =
    Arrays.asList(new String[] { Constants.ELEM_OUTPUT, Constants.ELEM_INPUT });
  private static final List STYLE_NOTIFICATION = Arrays.asList(new String[] { Constants.ELEM_OUTPUT });
  
  private static final String _ERROR_MULTIPLE_TYPES_DEFINED = "_ERROR_MULTIPLE_TYPES_DEFINED";
  private static final String _UNABLE_TO_IMPORT_NO_LOCATION = "_UNABLE_TO_IMPORT_NO_LOCATION";

  protected ExtensionRegistry extReg = null;
  protected String factoryImplName = null;

  // store the element locations within the file - line and column numbers
  // the location info is stored as an int array of length 2 {linenumber, colnumber}
  protected Hashtable elementLocations = new Hashtable();
  
  // hold the reader errors
  protected List readerErrors = new ArrayList();
  protected List readerWarnings = new ArrayList();
  protected MessageGenerator messagegenerator;
  
  private Definition def = null;
  private Set importedDefs = new TreeSet();
  private Element typesEl = null;
  private List messages = new ArrayList();
  private List porttypes = new ArrayList();
  private List bindings = new ArrayList();
  private List services = new ArrayList();
  private List extelements = new ArrayList();
  private int depth;
  // Hold the schemas that are imported or declared inline in this wsdl document.
  private List schemas = new ArrayList();
  private IWSDL11ValidationInfo valinfo;
  
  /**
   * Constructor. Performs a preparse of the document and handles imports and types.
   * 
   * @param documentBaseURI The URI of this WSDL document.
   * @param defEl The definitions element.
   * @param depth The depth of this document in a document tree.
   * @param messagegenerator A messagegenerator used for retrieving strings.
   * @param valinfo A WSDL11ValidationInfo object for reporting messages.
   * @throws WSDLException
   */
  public WSDLDocument(String documentBaseURI, Element defEl, int depth, MessageGenerator messagegenerator, IWSDL11ValidationInfo valinfo) throws WSDLException
  {
    this.messagegenerator = messagegenerator;
    this.valinfo = valinfo;
    this.depth = depth;
    
    checkElementName(defEl, Constants.Q_ELEM_DEFINITIONS);
    
    WSDLFactory factory =
      (factoryImplName != null) ? WSDLFactory.newInstance(factoryImplName) : WSDLFactory.newInstance();
    def = factory.newDefinition();
    // Fix for WSDL4J adding default WSDL namespace when no default
    // namespace has been declared.
    // TODO: Remove this fix once fixed in WSDL4J.
    if(def.getNamespace("") != null)
    	def.getNamespaces().remove("");

    if (extReg != null)
    {
      def.setExtensionRegistry(extReg);
    }

    String name = DOMUtils.getAttribute(defEl, Constants.ATTR_NAME);
    String targetNamespace = DOMUtils.getAttribute(defEl, Constants.ATTR_TARGET_NAMESPACE);
    NamedNodeMap attrs = defEl.getAttributes();

    if (documentBaseURI != null)
    {
      def.setDocumentBaseURI(documentBaseURI);
    }

    if (name != null)
    {
      def.setQName(new QName(targetNamespace, name));
    }

    if (targetNamespace != null)
    {
      def.setTargetNamespace(targetNamespace);
    }

    int size = attrs.getLength();

    for (int i = 0; i < size; i++)
    {
      Attr attr = (Attr)attrs.item(i);
      String namespaceURI = attr.getNamespaceURI();
      String localPart = attr.getLocalName();
      String value = attr.getValue();

      if (namespaceURI != null && namespaceURI.equals(Constants.NS_URI_XMLNS))
      {
        if (localPart != null && !localPart.equals(Constants.ATTR_XMLNS))
        {
          def.addNamespace(localPart, value);
        }
        else
        {
          def.addNamespace(null, value);
        }
      }
    }

    // There are problems when the model is created and the order of elements is not
    // Import - Types - Message - PortType - Binding - Service so we need to read them
    // into the model in that order
    // Performance wise this should be modified as we have to make 5 extra loops through
    // all of the elements as a result

    // take care of Imports, Types, Documentation and extensibleelements together - saves a pass for Documentation 
    // later and Docs don't effect anything else - Imports and Types are essentially the same thing
    // no preconceived ideas about extensible elements
    Element tempEl = DOMUtils.getFirstChildElement(defEl);

    while (tempEl != null)
    {

      if (QNameUtils.matches(Constants.Q_ELEM_IMPORT, tempEl))
      {
        String namespaceURI = DOMUtils.getAttribute(tempEl, Constants.ATTR_NAMESPACE);
        String locationURI = DOMUtils.getAttribute(tempEl, Constants.ATTR_LOCATION);
        if(locationURI == null || locationURI.equals(""))
        {
          addReaderError(def, tempEl, messagegenerator.getString(_UNABLE_TO_IMPORT_NO_LOCATION));
        }
        else
        {
          ImportHolder ih = new ImportHolder(namespaceURI, locationURI, def.getDocumentBaseURI(), this, depth+1, tempEl, messagegenerator, valinfo);
          // Only add the import to the list if it is not an import for this document.
          if(!documentBaseURI.equals(ih.getLocation()))
          {
            importedDefs.add(ih);
          }
        }
        setLocation(tempEl, tempEl);
//        if (importedDefs == null)
//        {
//          importedDefs = new Hashtable();
//        }
//        if (documentBaseURI != null)
//        {
//          importedDefs.put(documentBaseURI, def);
//        }
//        def.addImport(parseImport(tempEl, def, importedDefs));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        def.setDocumentationElement(tempEl);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_TYPES, tempEl))
      {
        if(typesEl != null)
        {
          setLocation(tempEl, tempEl);
          addReaderError(def, tempEl, messagegenerator.getString(_ERROR_MULTIPLE_TYPES_DEFINED));
        }
        else
        {
          typesEl = tempEl;
          parseTypes();
        }
//        def.setTypes(parseTypes(tempEl, def));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_MESSAGE, tempEl))
      {
        messages.add(tempEl);
        //def.addMessage(parseMessage(tempEl, def));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_PORT_TYPE, tempEl))
      {
        porttypes.add(tempEl);
        //             PortType pt = parsePortType(tempEl, def);
        //             if(pt != null)
        //             {
        //          def.addPortType(pt);
        //             }
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_BINDING, tempEl))
      {
        bindings.add(tempEl);
        //def.addBinding(parseBinding(tempEl, def));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_SERVICE, tempEl))
      {
        services.add(tempEl);
        //def.addService(parseService(tempEl, def));
      }
      else
      {
        extelements.add(tempEl);
        //        def.addExtensibilityElement(
        //          parseExtensibilityElement(Definition.class, tempEl, def));
      }
      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

  }
  
  /**
   * Get the definitions element for this document.
   * 
   * @return The definitions element for this document.
   */
  public Definition getDefinition()
  {
    return def;
  }
  
  /**
   * Get a set of the imports in this document.
   * 
   * @return A set of the imports in this document.
   */
  public Set getImports()
  {
    return importedDefs;
  }
  
  /**
   * 
   * @param def
   * @param doc
   * @param namespace
   * @param location
   */
//  public void setImport(Definition def, Element doc, String namespace, String location)
//  {
//    if(location == null || location.equals(""))
//    {
//      valinfo.addError()_UNABLE_TO_IMPORT_NO_LOCATION 
//    }
//    Import imp = def.createImport();
//    imp.setDefinition(def);
//    imp.setDocumentationElement(doc);
//    imp.setNamespaceURI(namespace);
//    imp.setLocationURI(location);
//    def.addImport(imp);
//  }
  
  /**
   * Parse the types in the WSDL document. Handles documentation, import and schema
   * elements.
   */
  public void parseTypes()
  {
    Types types = def.createTypes();

    Element tempEl = DOMUtils.getFirstChildElement(typesEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        types.setDocumentationElement(tempEl);
      }
      else if (tempEl.getLocalName().equalsIgnoreCase("import"))
        //else if (QNameUtils.matches(Constants.Q_ELEM_IMPORT, tempEl))
      {
        // this shouldn't really be used here but a little hack will make
        // life easier
        //parseImport(tempEl, def, (Map)new Hashtable());
        String namespaceURI = DOMUtils.getAttribute(tempEl, Constants.ATTR_NAMESPACE);
        String locationURI = DOMUtils.getAttribute(tempEl, "schemaLocation");
        importedDefs.add(new ImportHolder(namespaceURI, locationURI, def.getDocumentBaseURI(), this, depth+1, tempEl, messagegenerator, valinfo));
        try
        {
          types.addExtensibilityElement(parseExtensibilityElement(Types.class, tempEl, def));
        }
        catch(WSDLException e)
        {
          
        }
      }
      else
      {
        try
        {
          ExtensibilityElement extElem = parseExtensibilityElement(Types.class, tempEl, def);
          types.addExtensibilityElement(extElem);
        }
        catch(WSDLException e)
        {
          
        }
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }
    def.setTypes(types);
    
    valinfo.setElementLocations(elementLocations);
    List typesElems = types.getExtensibilityElements();
    if(typesElems != null)
    {
      Iterator typesElemsIter = typesElems.iterator();
      while(typesElemsIter.hasNext())
      {
        ExtensibilityElement typeElement = (ExtensibilityElement)typesElemsIter.next();
        
        InlineSchemaValidator xsdVal = new InlineSchemaValidator();
        xsdVal.setMessageGenerator(messagegenerator);
    
        List parents = new ArrayList();
        parents.add(def);
        parents.add(0,types);
        xsdVal.validate(typeElement, parents,valinfo);
        XSModel[] typesSchemas = valinfo.getSchemas();
        List typesSchemaList = new ArrayList();
        for(int i = 0; i < typesSchemas.length; i++)
        {  
          typesSchemaList.add(typesSchemas[i]);
        }
        schemas.addAll(typesSchemaList);
        valinfo.clearSchemas();
      }
    }
    valinfo.setElementLocations(null);
  }
  
  /**
   * Parse the messages in this document.
   */
  public void parseMessages()
  {
    for (int i = 0; i < messages.size(); i++)
    {
      try
      {
        def.addMessage(parseMessage((Element)messages.get(i), def));
      }
      catch(WSDLException e)
      {}
    }
  }
  
  /**
   * Parse the portTypes in this document.
   */
  public void parsePorttypes()
  {
    for (int i = 0; i < porttypes.size(); i++)
    {
      try
      {
        PortType pt = parsePortType((Element)porttypes.get(i), def);
        if (pt != null)
        {
          def.addPortType(pt);
        }
      }
      catch(WSDLException e)
      {}
    }
  }
  
  /**
   * Parse the bindings in this document.
   */
  public void parseBindings()
  {
    for (int i = 0; i < bindings.size(); i++)
    {
      try
      {
        def.addBinding(parseBinding((Element)bindings.get(i), def));
      }
      catch(WSDLException e)
      {}
    }
  }
  
  /**
   * Parse the services in this document.
   */
  public void parseServices()
  {
    for (int i = 0; i < services.size(); i++)
    {
      try
      {
        def.addService(parseService((Element)services.get(i), def));
      }
      catch(WSDLException e)
      {}
    }
  }
  
  /**
   * Parse the extensibility elements in this document.
   */
  public void parseExtensibilityElements()
  {
    for (int i = 0; i < extelements.size(); i++)
    {
      try
      {
        def.addExtensibilityElement(parseExtensibilityElement(Definition.class, (Element)extelements.get(i), def));
      }
      catch(WSDLException e)
      {}
    }
  }
  
  /**
   * Add the given list of schemas to the schemas for this document.
   * 
   * @param schemas The list of schemas to add to this document's schemas.
   */
  public void addSchemas(List schemas)
  {
    this.schemas.addAll(schemas);
  }
  
  /**
   * Get the schemas associated with this document.
   * 
   * @return The schemas associated with this document.
   */
  public List getSchemas()
  {
    return schemas;
  }
  
  /**
   * Parse the specified binding.
   * 
   * @param bindingEl The binding element.
   * @param def The definitions element.
   * @return A WSDL binding element.
   * @throws WSDLException
   */
  protected Binding parseBinding(Element bindingEl, Definition def) throws WSDLException
  {
    Binding binding = null;
    String name = DOMUtils.getAttribute(bindingEl, Constants.ATTR_NAME);
    QName portTypeName;
    try
    {
      portTypeName = DOMUtils.getQualifiedAttributeValue(bindingEl, Constants.ATTR_TYPE, Constants.ELEM_BINDING, false);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the message name
      portTypeName = new QName(null, DOMUtils.getAttribute(bindingEl, "type"));
    }

    PortType portType = null;

    if (name != null)
    {
      QName bindingName = new QName(def.getTargetNamespace(), name);

      binding = def.getBinding(bindingName);

      if (binding == null)
      {
        binding = def.createBinding();
        binding.setQName(bindingName);
      }
      // report an error if a binding with this name has already been defined
      else if (!binding.isUndefined())
      {
        //addReaderError(def,bindingEl, "_BINDING_NAME_ALREADY_DEFINED");       
        addReaderError(
          def,
          bindingEl,
          messagegenerator.getString("_BINDING_NAME_ALREADY_DEFINED", "'" + binding.getQName().getLocalPart() + "'"));
      }
    }
    else
    {
      binding = def.createBinding();
    }

    // Whether it was retrieved or created, the definition has been found.
    binding.setUndefined(false);

    if (portTypeName != null)
    {
      portType = def.getPortType(portTypeName);

      if (portType == null)
      {
        portType = def.createPortType();
        portType.setQName(portTypeName);
        def.addPortType(portType);
      }

      binding.setPortType(portType);
    }

    Element tempEl = DOMUtils.getFirstChildElement(bindingEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        binding.setDocumentationElement(tempEl);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_OPERATION, tempEl))
      {
        binding.addBindingOperation(parseBindingOperation(tempEl, portType, def));
      }
      else
      {
        binding.addExtensibilityElement(parseExtensibilityElement(Binding.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(binding, bindingEl);

    return binding;
  }

  /**
   * Parse a specific binding operation.
   * 
   * @param bindingOperationEl The binding operation element.
   * @param portType The portType the binding references.
   * @param def The definitions element.
   * @return A WSDL binding operation element.
   * @throws WSDLException
   */
  protected BindingOperation parseBindingOperation(Element bindingOperationEl, PortType portType, Definition def)
    throws WSDLException
  {
    BindingOperation bindingOperation = def.createBindingOperation();
    String name = DOMUtils.getAttribute(bindingOperationEl, Constants.ATTR_NAME);

    if (name != null)
    {
      bindingOperation.setName(name);
    }

    Element tempEl = DOMUtils.getFirstChildElement(bindingOperationEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        bindingOperation.setDocumentationElement(tempEl);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_INPUT, tempEl))
      {
        bindingOperation.setBindingInput(parseBindingInput(tempEl, def));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_OUTPUT, tempEl))
      {
        bindingOperation.setBindingOutput(parseBindingOutput(tempEl, def));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_FAULT, tempEl))
      {
        bindingOperation.addBindingFault(parseBindingFault(tempEl, def));
      }
      else
      {
        bindingOperation.addExtensibilityElement(parseExtensibilityElement(BindingOperation.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    if (portType != null)
    {
      BindingInput bindingInput = bindingOperation.getBindingInput();
      BindingOutput bindingOutput = bindingOperation.getBindingOutput();
      //String inputName = (bindingInput != null ? bindingInput.getName() : null);
      //String outputName = (bindingOutput != null ? bindingOutput.getName() : null);

      // hack code to get at operations that are defined with the same name but different
      // inputs and outputs 
      Operation op = null;
      List operations = portType.getOperations();
      // get a list of all operations with matching names
      List matchingOperations = new Vector();
      Iterator iOperations = operations.iterator();
      while (iOperations.hasNext())
      {
        Operation oper = (Operation)iOperations.next();
        if (oper.getName().equalsIgnoreCase(bindingOperation.getName()))
        {
          matchingOperations.add(oper);
        }
      }

      if (matchingOperations != null)
      {
        // If there's only one matching operation this is what we're referring to.
        // Only matching if binding operation input name and output name are
        // both null or the same as the portType operation input and output names.
        // the portType operation name
        if (matchingOperations.size() == 1)
        {
          // only say the single operation is the one we're looking for if the names
          // of the binding input and output are not specified
          Operation tempOp = (Operation)matchingOperations.get(0);
          boolean inputOK = false;
          boolean outputOK = false;
          Input tempInput = tempOp.getInput();
          Output tempOutput = tempOp.getOutput();

          // order is important in these conditions. condition 2 must fail for 3 to work
          // check the input
          if (tempInput == null && bindingInput == null)
          {
            inputOK = true;
          }
          else if (bindingInput == null || bindingInput.getName() == null)
          {
            inputOK = true;
          }
          else if (tempInput != null && bindingInput.getName().equals(tempInput.getName()))
          {
            inputOK = true;
          }
          // check the output
          if (tempOutput == null && bindingOutput == null)
          {
            outputOK = true;
          }
          else if (bindingOutput == null || bindingOutput.getName() == null)
          {
            outputOK = true;
          }
          else if (tempOutput != null && bindingOutput.getName().equals(tempOutput.getName()))
          {
            outputOK = true;
          }
          if (inputOK && outputOK)
          {
            op = tempOp;
          }
          //          op = (Operation) matchingOperations.get(0);
        }
        // otherwise find the operation with the same name, inputname, outputname signature
        if (matchingOperations != null && op == null)
        {
          Iterator iMatchingOperations = matchingOperations.iterator();
          while (iMatchingOperations.hasNext())
          {

            boolean inputNamesEqual = false;
            boolean outputNamesEqual = false;
            Operation oper = (Operation)iMatchingOperations.next();
            //          if (oper.getName().equalsIgnoreCase(bindingOperation.getName()))
            //          {
            Input opInput = oper.getInput();
            if (opInput != null && bindingInput != null)
            {
              String opInputName = opInput.getName();
              String bindingInputName = bindingInput.getName();
              if (opInputName != null && opInputName.equalsIgnoreCase(bindingInputName))
              {
                inputNamesEqual = true;
              }
              else if (opInputName == null && bindingInputName == null)
              {
                inputNamesEqual = true;
              }
            }
            else if (opInput == null && bindingInput == null)
            {
              inputNamesEqual = true;
            }
            Output opOutput = oper.getOutput();
            if (opOutput != null && bindingOutput != null)
            {
              String opOutputName = opOutput.getName();
              String bindingOutputName = bindingOutput.getName();
              if (opOutputName != null && opOutputName.equalsIgnoreCase(bindingOutputName))
              {
                outputNamesEqual = true;
              }
              else if (opOutputName == null && bindingOutputName == null)
              {
                outputNamesEqual = true;
              }
            }
            else if (opOutput == null && bindingOutput == null)
            {
              outputNamesEqual = true;
            }
            if (inputNamesEqual && outputNamesEqual)
            {
              op = oper;
              break;
            }
            //}
          }
        }
      }
      //Operation op = portType.getOperation(name, inputName, outputName);

      if (op == null)
      {
        op = def.createOperation();
        op.setName(name);
        portType.addOperation(op);
      }

      bindingOperation.setOperation(op);
    }

    // add the location of this element to elementLocations 
    setLocation(bindingOperation, bindingOperationEl);

    return bindingOperation;
  }
  
  /**
   * Parse a specific binding input element.
   * 
   * @param bindingInputEl The binding input element.
   * @param def The definitions element.
   * @return A WSDL binding input element.
   * @throws WSDLException
   */
  protected BindingInput parseBindingInput(Element bindingInputEl, Definition def) throws WSDLException
  {
    BindingInput bindingInput = def.createBindingInput();
    String name = DOMUtils.getAttribute(bindingInputEl, Constants.ATTR_NAME);

    if (name != null)
    {
      bindingInput.setName(name);
    }

    Element tempEl = DOMUtils.getFirstChildElement(bindingInputEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        bindingInput.setDocumentationElement(tempEl);
      }
      else
      {
        bindingInput.addExtensibilityElement(parseExtensibilityElement(BindingInput.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(bindingInput, bindingInputEl);

    return bindingInput;
  }

  /**
   * Parse a specific binding output element.
   * 
   * @param bindingOutputEl The binding output element.
   * @param def The definitions element.
   * @return A WSDL binding output element.
   * @throws WSDLException
   */
  protected BindingOutput parseBindingOutput(Element bindingOutputEl, Definition def) throws WSDLException
  {
    BindingOutput bindingOutput = def.createBindingOutput();
    String name = DOMUtils.getAttribute(bindingOutputEl, Constants.ATTR_NAME);

    if (name != null)
    {
      bindingOutput.setName(name);
    }

    Element tempEl = DOMUtils.getFirstChildElement(bindingOutputEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        bindingOutput.setDocumentationElement(tempEl);
      }
      else
      {
        bindingOutput.addExtensibilityElement(parseExtensibilityElement(BindingOutput.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(bindingOutput, bindingOutputEl);

    return bindingOutput;
  }

  /**
   * Parse a specific binding fault element.
   * 
   * @param bindingFaultEl The binding fault element.
   * @param def The definitions element.
   * @return A WSDL binding fault element.
   * @throws WSDLException
   */
  protected BindingFault parseBindingFault(Element bindingFaultEl, Definition def) throws WSDLException
  {
    BindingFault bindingFault = def.createBindingFault();
    String name = DOMUtils.getAttribute(bindingFaultEl, Constants.ATTR_NAME);

    if (name != null)
    {
      bindingFault.setName(name);
    }

    Element tempEl = DOMUtils.getFirstChildElement(bindingFaultEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        bindingFault.setDocumentationElement(tempEl);
      }
      else
      {
        bindingFault.addExtensibilityElement(parseExtensibilityElement(BindingFault.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(bindingFault, bindingFaultEl);

    return bindingFault;
  }

  /**
   * Parse a specific message element.
   * 
   * @param msgEl The message element.
   * @param def The definitions element.
   * @return A WSDL message element.
   * @throws WSDLException
   */
  protected Message parseMessage(Element msgEl, Definition def) throws WSDLException
  {
    Message msg = null;
    String name = DOMUtils.getAttribute(msgEl, Constants.ATTR_NAME);

    if (name != null)
    {
      QName messageName = new QName(def.getTargetNamespace(), name);

      msg = def.getMessage(messageName);

      if (msg == null)
      {
        msg = def.createMessage();
        msg.setQName(messageName);
      }
      else if (!msg.isUndefined())
      {
        // produce an error message as a message with this name has already been defined
        addReaderError(
          def,
          msgEl,
          messagegenerator.getString("_MESSAGE_NAME_ALREADY_DEFINED", "'" + msg.getQName().getLocalPart() + "'"));
      }
    }
    else
    {
      msg = def.createMessage();
    }

    // Whether it was retrieved or created, the definition has been found.
    msg.setUndefined(false);

    Element tempEl = DOMUtils.getFirstChildElement(msgEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        msg.setDocumentationElement(tempEl);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_PART, tempEl))
      {
        msg.addPart(parsePart(tempEl, def));
      }
      else
      {
        // XML Validation will catch this
        DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(msg, msgEl);

    return msg;
  }

  /**
   * Parse a specific part element.
   * 
   * @param partEl The part element.
   * @param def The definitions element.
   * @return A WSDL part element.
   * @throws WSDLException
   */
  protected Part parsePart(Element partEl, Definition def) throws WSDLException
  {
    Part part = def.createPart();
    String name = DOMUtils.getAttribute(partEl, Constants.ATTR_NAME);

    QName elementName;
    try
    {
      elementName = DOMUtils.getQualifiedAttributeValue(partEl, Constants.ATTR_ELEMENT, Constants.ELEM_MESSAGE, false);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the element name
      elementName = new QName(null, DOMUtils.getAttribute(partEl, "element"));
    }

    QName typeName;
    try
    {
      typeName = DOMUtils.getQualifiedAttributeValue(partEl, Constants.ATTR_TYPE,
        // Corrected - was ATTR_ELEMENT
  Constants.ELEM_MESSAGE, false);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the element attribute
      typeName = new QName(null, DOMUtils.getAttribute(partEl, "name"));
    }

    if (name != null)
    {
      part.setName(name);
    }

    if (elementName != null)
    {
      part.setElementName(elementName);
    }

    if (typeName != null)
    {
      part.setTypeName(typeName);
    }

    Element tempEl = DOMUtils.getFirstChildElement(partEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        part.setDocumentationElement(tempEl);
      }
      else
      {
        // XML Validation will catch this
        DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    Map extensionAttributes = part.getExtensionAttributes();

    extensionAttributes.putAll(getPartAttributes(partEl, def));

    // Need to do something here to locate part definition.

    // add the location of this element to elementLocations 
    setLocation(part, partEl);

    return part;
  }

  /**
   * Get a map of the part attributes.
   * 
   * @param el The part attributes element.
   * @param def The defintions element.
   * @return A map containing the part attributes.
   * @throws WSDLException
   */
  protected Map getPartAttributes(Element el, Definition def) throws WSDLException
  {
    Map attributes = new HashMap();
    NamedNodeMap nodeMap = el.getAttributes();
    int atts = nodeMap.getLength();

    for (int a = 0; a < atts; a++)
    {
      Attr attribute = (Attr)nodeMap.item(a);
      String lName = attribute.getLocalName();
      String nSpace = attribute.getNamespaceURI();
      String prefix = attribute.getPrefix();
      QName name = new QName(nSpace, lName);

      if (nSpace != null && !nSpace.equals(Constants.NS_URI_WSDL))
      {
        if (!nSpace.equals(Constants.NS_URI_XMLNS))
        {
          String strValue = attribute.getValue();
          QName qValue = null;

          try
          {
            qValue = DOMUtils.getQName(strValue, el);
          }
          catch (WSDLException e)
          {
            qValue = new QName(strValue);
          }

          attributes.put(name, qValue);

          String tempNSUri = def.getNamespace(prefix);

          while (tempNSUri != null && !tempNSUri.equals(nSpace))
          {
            prefix += "_";
            tempNSUri = def.getNamespace(prefix);
          }

          def.addNamespace(prefix, nSpace);
        }
      }
      else if (
        !lName.equals(Constants.ATTR_NAME)
          && !lName.equals(Constants.ATTR_ELEMENT)
          && !lName.equals(Constants.ATTR_TYPE))
      {
        WSDLException wsdlExc =
          new WSDLException(
            WSDLException.INVALID_WSDL,
            "Encountered illegal "
              + "part extension "
              + "attribute '"
              + name
              + "'. Extension "
              + "attributes must be in "
              + "a namespace other than "
              + "WSDL's.");

        wsdlExc.setLocation(XPathUtils.getXPathExprFromNode(el));
        //throw wsdlExc;
      }
    }

    // add the location of this element to elementLocations 
    setLocation(attributes, el);

    return attributes;
  }

  /**
   * Parse a specific portType element.
   * 
   * @param portTypeEl The portType element.
   * @param def The defintions element.
   * @return A WSDL portType element.
   * @throws WSDLException
   */
  protected PortType parsePortType(Element portTypeEl, Definition def) throws WSDLException
  {

    PortType portType = null;
    String name = DOMUtils.getAttribute(portTypeEl, Constants.ATTR_NAME);

    if (name != null)
    {
      QName portTypeName = new QName(def.getTargetNamespace(), name);

      portType = def.getPortType(portTypeName);

      if (portType == null)
      {
        portType = def.createPortType();
        portType.setQName(portTypeName);
      }
      else if (!portType.isUndefined())
      {
        // if the PortType has already been defined produce an error and return null
        addReaderError(
          def,
          portTypeEl,
          messagegenerator.getString("_PORTTYPE_NAME_ALREADY_DEFINED", "'" + portType.getQName().getLocalPart() + "'"));
        return null;
      }
    }
    else
    {
      portType = def.createPortType();
    }

    // Whether it was retrieved or created, the definition has been found.
    portType.setUndefined(false);

    Element tempEl = DOMUtils.getFirstChildElement(portTypeEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        portType.setDocumentationElement(tempEl);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_OPERATION, tempEl))
      {
        // modified so duplicate operations will not be added to porttype 
        Operation op = parseOperation(tempEl, portType, def);
        if (op != null)
        {
          portType.addOperation(op);
        }
        //portType.addOperation(parseOperation(tempEl, portType, def));
      }
      else
      {
        // something else that shouldn't be here
        // NEED TO ADD TO ERROR LIST
        //DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(portType, portTypeEl);

    return portType;
  }

  /**
   * Parse a specific operation element.
   * 
   * @param opEl The operation element.
   * @param portType The portType element.
   * @param def The definitions element.
   * @return A WSDL operation element.
   * @throws WSDLException
   */
  protected Operation parseOperation(Element opEl, PortType portType, Definition def) throws WSDLException
  {
    Operation op = null;
    String name = DOMUtils.getAttribute(opEl, Constants.ATTR_NAME);
    String parameterOrderStr = DOMUtils.getAttribute(opEl, Constants.ATTR_PARAMETER_ORDER);
    Element tempEl = DOMUtils.getFirstChildElement(opEl);
    List messageOrder = new Vector();
    Element docEl = null;
    Input input = null;
    Output output = null;
    List faults = new Vector();

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        docEl = tempEl;
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_INPUT, tempEl))
      {
        input = parseInput(tempEl, def);
        messageOrder.add(Constants.ELEM_INPUT);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_OUTPUT, tempEl))
      {
        output = parseOutput(tempEl, def);
        messageOrder.add(Constants.ELEM_OUTPUT);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_FAULT, tempEl))
      {
        faults.add(parseFault(tempEl, def));
      }
      else
      {
        // invalid element in the operation
        // XML check will catch this
        DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    if (name != null)
    {
      String inputName = (input != null ? input.getName() : null);
      String outputName = (output != null ? output.getName() : null);

      boolean opDefined = false;

      try
      {

        //op = portType.getOperation(name, inputName, outputName);

        //Operation op = null;
        List operations = portType.getOperations();
        if (operations != null)
        {

          Iterator iOperations = operations.iterator();
          while (iOperations.hasNext())
          {
            boolean inputNamesEqual = false;
            boolean outputNamesEqual = false;
            Operation oper = (Operation)iOperations.next();
            if (oper.getName().equals(name))
            {
              Input opInput = oper.getInput();
              if (opInput != null && input != null)
              {
                String opInputName = opInput.getName();
                if (opInputName != null && inputName != null && opInputName.equals(inputName))
                {
                  inputNamesEqual = true;
                }
                else if (opInputName == null && inputName == null)
                {
                  inputNamesEqual = true;
                }
              }
              else if (opInput == null && input == null)
              {
                inputNamesEqual = true;
              }
              Output opOutput = oper.getOutput();
              if (opOutput != null && output != null)
              {
                String opOutputName = opOutput.getName();
                if (opOutputName != null && outputName != null && opOutputName.equals(outputName))
                {
                  outputNamesEqual = true;
                }
                else if (opOutputName == null && outputName == null)
                {
                  outputNamesEqual = true;
                }
              }
              else if (opOutput == null && output == null)
              {
                outputNamesEqual = true;
              }
              if (inputNamesEqual && outputNamesEqual)
              {
                op = oper;
                break;
              }
            }
          }
        }
      }
      catch (Exception e)
      {
        opDefined = true;
      }

      if (op != null /*&& !op.isUndefined()*/
        )
      {
        //op = null;
        opDefined = true;

      }

      if (op != null && !opDefined)
      {
        if (inputName == null)
        {
          Input tempIn = op.getInput();

          if (tempIn != null)
          {
            if (tempIn.getName() != null)
            {
              //op = null;
              opDefined = true;
            }
          }
        }
      }

      if (op != null && !opDefined)
      {
        if (outputName == null)
        {
          Output tempOut = op.getOutput();

          if (tempOut != null)
          {
            if (tempOut.getName() != null)
            {
              //op = null;
              opDefined = true;
            }
          }
        }
      }

      if (opDefined)
      {
        // instead of creating a new one with the same name we're going to return null.
        // According to the WSDL 1.2 working draft operation overloading is no longer allowed.
        // Going to use that here to save a lot of work
        setLocation(op, opEl);
        addReaderError(
          portType,
          op,
          messagegenerator.getString(
            "_DUPLICATE_OPERATION_FOR_PORTTYPE",
            "'" + op.getName() + "'",
            "'" + portType.getQName().getLocalPart() + "'"));
        return null;
      }
      if (op == null)
      {
        op = def.createOperation();
        op.setName(name);

      }
    }
    else
    {
      op = def.createOperation();
    }

    // Whether it was retrieved or created, the definition has been found.
    op.setUndefined(false);

    if (parameterOrderStr != null)
    {
      op.setParameterOrdering(StringUtils.parseNMTokens(parameterOrderStr));
    }

    if (docEl != null)
    {
      op.setDocumentationElement(docEl);
    }

    if (input != null)
    {
      op.setInput(input);
    }

    if (output != null)
    {
      op.setOutput(output);
    }

    if (faults.size() > 0)
    {
      Iterator faultIterator = faults.iterator();

      while (faultIterator.hasNext())
      {
        Fault f = (Fault)faultIterator.next();
        // if the fault isn't defined yet
        if (op.getFault(f.getName()) == null)
        {
          op.addFault(f);
        }
        else
        {
          addReaderError(
            op,
            f,
            messagegenerator.getString("_DUPLICATE_FAULT_NAME", "'" + f.getName() + "'", "'" + op.getName() + "'"));
          //faultErrors.add(new Object[]{f,"Duplicate Name",op});
        }
      }
    }

    OperationType style = null;

    if (messageOrder.equals(STYLE_ONE_WAY))
    {
      style = OperationType.ONE_WAY;
    }
    else if (messageOrder.equals(STYLE_REQUEST_RESPONSE))
    {
      style = OperationType.REQUEST_RESPONSE;
    }
    else if (messageOrder.equals(STYLE_SOLICIT_RESPONSE))
    {
      style = OperationType.SOLICIT_RESPONSE;
    }
    else if (messageOrder.equals(STYLE_NOTIFICATION))
    {
      style = OperationType.NOTIFICATION;
    }

    if (style != null)
    {
      op.setStyle(style);
    }

    // add the location of this element to elementLocations 
    setLocation(op, opEl);

    // modified to remove duplicate operations
    //    if(opDefined)
    //    {
    //      addReaderError(portType,op,ValidateWSDLPlugin.getInstance().getString("_DUPLICATE_OPERATION_FOR_PORTTYPE","'"+op.getName()+"'","'"+portType.getQName().getLocalPart()+"'"));
    //      return null;
    //    }
    return op;
  }

  /**
   * Parse a specific service element.
   * 
   * @param serviceEl The service element.
   * @param def The defintions element.
   * @return A WSDL service element.
   * @throws WSDLException
   */
  protected Service parseService(Element serviceEl, Definition def) throws WSDLException
  {
    Service service = def.createService();
    String name = DOMUtils.getAttribute(serviceEl, Constants.ATTR_NAME);

    if (name != null)
    {
      service.setQName(new QName(def.getTargetNamespace(), name));
    }
    Service s;
    // a service with this name has already been defined
    if ((s = def.getService(service.getQName())) != null)
    {
      addReaderError(
        def,
        serviceEl,
        messagegenerator.getString("_SERVICE_NAME_ALREADY_DEFINED", "'" + s.getQName().getLocalPart() + "'"));
      return s;
    }
    Element tempEl = DOMUtils.getFirstChildElement(serviceEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        service.setDocumentationElement(tempEl);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_PORT, tempEl))
      {
        service.addPort(parsePort(tempEl, def));
      }
      else
      {
        service.addExtensibilityElement(parseExtensibilityElement(Service.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(service, serviceEl);

    return service;
  }
  
  /**
   * Parse a specific port element.
   * 
   * @param portEl The port element.
   * @param def The definitions element.
   * @return A WSDL port element.
   * @throws WSDLException
   */
  protected Port parsePort(Element portEl, Definition def) throws WSDLException
  {
    Port port = def.createPort();
    String name = DOMUtils.getAttribute(portEl, Constants.ATTR_NAME);
    QName bindingStr;
    try
    {
      bindingStr = DOMUtils.getQualifiedAttributeValue(portEl, Constants.ATTR_BINDING, Constants.ELEM_PORT, false);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the message name
      bindingStr = new QName(null, DOMUtils.getAttribute(portEl, "binding"));
    }

    if (name != null)
    {
      port.setName(name);
    }

    if (bindingStr != null)
    {
      Binding binding = def.getBinding(bindingStr);

      if (binding == null)
      {
        binding = def.createBinding();
        binding.setQName(bindingStr);
        def.addBinding(binding);
      }

      port.setBinding(binding);
    }

    Element tempEl = DOMUtils.getFirstChildElement(portEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        port.setDocumentationElement(tempEl);
      }
      else
      {
        port.addExtensibilityElement(parseExtensibilityElement(Port.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(port, portEl);

    return port;
  }

  /**
   * Parse a specific extensibility element.
   * 
   * @param parentType The parent type of the extensibility element.
   * @param el The extensibility element.
   * @param def The definitions element.
   * @return A WSDL extensibility element.
   * @throws WSDLException
   */
  protected ExtensibilityElement parseExtensibilityElement(Class parentType, Element el, Definition def)
    throws WSDLException
  {
    QName elementType = QNameUtils.newQName(el);

    try
    {
      ExtensionRegistry extReg = def.getExtensionRegistry();

      if (extReg == null)
      {
        throw new WSDLException(
          WSDLException.CONFIGURATION_ERROR,
          "No ExtensionRegistry set for this "
            + "Definition, so unable to deserialize "
            + "a '"
            + elementType
            + "' element in the "
            + "context of a '"
            + parentType.getName()
            + "'.");
      }

      ExtensionDeserializer extDS = extReg.queryDeserializer(parentType, elementType);

      // asign the ExtensibilityElement to a var so we can add it to the locations
      ExtensibilityElement extElem = extDS.unmarshall(parentType, elementType, el, def, extReg);
      // add the location of this element to elementLocations 
      // this might not work properly
      setLocation(extElem, el);

      // register all of the child Elements so we can find them later
      // used for inline schema validation
      registerChildElements(extElem);

      return extElem;
    }
    catch (WSDLException e)
    {
      if (e.getLocation() == null)
      {
        e.setLocation(XPathUtils.getXPathExprFromNode(el));
      }
      throw e;
    }
  }

  /**
   * Parse a specific input element.
   * 
   * @param inputEl The input element.
   * @param def The defintions element.
   * @return A WSDL input element.
   * @throws WSDLException
   */
  protected Input parseInput(Element inputEl, Definition def) throws WSDLException
  {

    Input input = def.createInput();
    String name = DOMUtils.getAttribute(inputEl, Constants.ATTR_NAME);
    QName messageName = null;
    try
    {
      messageName = DOMUtils.getQualifiedAttributeValue(inputEl, Constants.ATTR_MESSAGE, Constants.ELEM_INPUT, false);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the message name
      messageName = new QName(null, DOMUtils.getAttribute(inputEl, "message"));
    }

    if (name != null)
    {
      input.setName(name);
    }

    if (messageName != null)
    {
      Message message = def.getMessage(messageName);

      if (message == null)
      {
        message = def.createMessage();
        message.setQName(messageName);
        def.addMessage(message);
      }

      input.setMessage(message);
    }

    Element tempEl = DOMUtils.getFirstChildElement(inputEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        input.setDocumentationElement(tempEl);
      }
      else
      {
        // XML Validation will catch this
        DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(input, inputEl);

    return input;
  }

  /**
   * Parse a specific output element.
   * 
   * @param outputEl The output element.
   * @param def The defintions element.
   * @return A WSDL output element.
   * @throws WSDLException
   */
  protected Output parseOutput(Element outputEl, Definition def) throws WSDLException
  {
    Output output = def.createOutput();
    String name = DOMUtils.getAttribute(outputEl, Constants.ATTR_NAME);
    QName messageName = null;
    try
    {
      messageName = DOMUtils.getQualifiedAttributeValue(outputEl, Constants.ATTR_MESSAGE, Constants.ELEM_OUTPUT, false);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the message name
      messageName = new QName(null, DOMUtils.getAttribute(outputEl, "message"));
    }

    if (name != null)
    {
      output.setName(name);
    }

    if (messageName != null)
    {
      Message message = def.getMessage(messageName);

      if (message == null)
      {
        message = def.createMessage();
        message.setQName(messageName);
        def.addMessage(message);
      }

      output.setMessage(message);
    }

    Element tempEl = DOMUtils.getFirstChildElement(outputEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        output.setDocumentationElement(tempEl);
      }
      else
      {
        // XML Validation will catch this
        DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(output, outputEl);

    return output;
  }

  /**
   * Parse a specific fault element.
   * 
   * @param faultEl The fault element to parse.
   * @param def The definitions element.
   * @return A WSDL fault element.
   * @throws WSDLException
   */
  protected Fault parseFault(Element faultEl, Definition def) throws WSDLException
  {
    Fault fault = def.createFault();
    String name = DOMUtils.getAttribute(faultEl, Constants.ATTR_NAME);
    QName messageName = null;
    try
    {
      messageName = DOMUtils.getQualifiedAttributeValue(faultEl, Constants.ATTR_MESSAGE, Constants.ELEM_INPUT, false);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the message name
      messageName = new QName(null, DOMUtils.getAttribute(faultEl, "message"));
    }

    if (name != null)
    {
      fault.setName(name);
    }

    if (messageName != null)
    {
      Message message = def.getMessage(messageName);

      if (message == null)
      {
        message = def.createMessage();
        message.setQName(messageName);
        def.addMessage(message);
      }

      fault.setMessage(message);
    }

    Element tempEl = DOMUtils.getFirstChildElement(faultEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        fault.setDocumentationElement(tempEl);
      }
      else
      {
        // XML Validation will catch this
        DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    // add the location of this element to elementLocations 
    setLocation(fault, faultEl);

    return fault;
  }
  
  /**
   * Set the messagegenerator for the reader.
   * 
   * @param mg The message generator to set.
   */
  public void setMessageGenerator(MessageGenerator mg)
  {
    messagegenerator = mg;
  }

  /**
   * Add the refObject to the elementLocation hashtable with the location defined in element.
   * 
   * @param refObject The object to add.
   * @param element The element that contains the location information.
   */
  protected void setLocation(Object refObject, Element element)
  {
    try
    {
      ElementImpl elementImpl = (ElementImpl)element;
      ElementLocation elementLocation = (ElementLocation)elementImpl.getUserData();
      if (elementLocation != null)
      {

        elementLocations.put(
          refObject,
          new LocationHolder(elementLocation.getLineNumber(), elementLocation.getColumnNumber(), def.getDocumentBaseURI()));
      }
    }
    catch (ClassCastException e)
    {
    }
  }
  /**
   * Add a reader error to the list.
   * 
   * @param parentobject The parent object of the object with the error.
   * @param object The object with the error.
   * @param error The error message.
   */
  protected void addReaderError(Object parentobject, Object object, String error)
  {
    readerErrors.add(new ReaderError(parentobject, object, error));
  }
  
  /**
   * Add a reader warning to the list.
   * 
   * @param parentobject The parent object of the object with the error.
   * @param object The object with the error.
   * @param warning The warning message.
   */
  protected void addReaderWarning(Object parentobject, Object object, String warning)
  {
    readerWarnings.add(new ReaderError(parentobject, object, warning));
  }
  
  /**
   * Register all of the locations of the child elements of the extensibility
   * element given.
   * 
   * @param extElem The extensibility element whose child elements will be registered.
   */

  protected void registerChildElements(ExtensibilityElement extElem)
  {
    // only add those that are of type unknown. if they're known they 
    // will take care of themselves
    if (extElem instanceof UnknownExtensibilityElement)
    {
      Element elem = ((UnknownExtensibilityElement)extElem).getElement();
      registerChildElementsRecursively(elem);
    }
  }

  /**
   * Register the location of all of the child elements of elem.
   * 
   * @param elem The element whose child elements will be registered.
   */
  protected void registerChildElementsRecursively(Element elem)
  {
    if (elem instanceof ElementNSImpl)
    {
      setLocation(elem, elem);

      // call the method recursively for each child element
      NodeList childNodes = elem.getChildNodes();

      for (int i = 0; i < childNodes.getLength() || i < 5; i++)
      {
        Node n = childNodes.item(i);
        // we only want nodes that are Elements
        if (n instanceof Element)
        {
          Element child = (Element)n;
          registerChildElementsRecursively(child);
        }
      }
    }
  }
  /**
   * Check that an element name matches the expected name.
   * 
   * @param el The element with the name to check.
   * @param qname The name to check against.
   * @throws WSDLException
   */
  private static void checkElementName(Element el, QName qname) throws WSDLException
  {
    if (!QNameUtils.matches(qname, el))
    {
      WSDLException wsdlExc = new WSDLException(WSDLException.INVALID_WSDL, "Expected element '" + qname + "'.");

      wsdlExc.setLocation(XPathUtils.getXPathExprFromNode(el));

      throw wsdlExc;
    }
  }
  
  /**
   * Get the element locations hashtable.
   * 
   * @return The element locations hashtable.
   */
  public Hashtable getElementLocations()
  {
    return elementLocations;
  }
  
  /**
   * Get the reader errors.
   * 
   * @return The reader errors.
   */
  public List getReaderErrors()
  {
    return readerErrors;
  }
  
  /**
   * Get reader warnings.
   * 
   * @return The reader warnings.
   */
  public List getReaderWarnings()
  {
    return readerWarnings;
  }
}