/*******************************************************************************
 * 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();

    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);
          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().equalsIgnoreCase(name))
            {
              Input opInput = oper.getInput();
              if (opInput != null && input != null)
              {
                String opInputName = opInput.getName();
                if (opInputName != null && inputName != null && opInputName.equalsIgnoreCase(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.equalsIgnoreCase(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(ElementLocation.ID);
      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;
  }
}