Package org.eclipse.wst.wsdl.validation.internal.wsdl11

Source Code of org.eclipse.wst.wsdl.validation.internal.wsdl11.WSDLDocument

/*******************************************************************************
* Copyright (c) 2001, 2009 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.extensions.schema.Schema;
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, def);
    }
    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();
        if (name != null) {
          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
      {
        // message allows extensibility elements
        msg.addExtensibilityElement(parseExtensibilityElement(Message.class, tempEl, def));
      }

      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, def);
    }
    catch (Exception e)
    {
      //the call above fails if there is no qualified namespace for the element name
      elementName = new QName(null, DOMUtils.getAttribute(partEl, Constants.ATTR_ELEMENT));
    }

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

    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, def);
          }
          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();
    List extElements = new ArrayList();

    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
      {
        // operation allows extensibility elements
        extElements.add(parseExtensibilityElement(Operation.class, tempEl, def));
      }

      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});
        }
      }
    }
   
    if (extElements.size() > 0)
    {
      Iterator extElementsIterator = extElements.iterator();
      while (extElementsIterator.hasNext())
      {
          op.addExtensibilityElement((ExtensibilityElement)extElementsIterator.next());
      }
    }

    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, def);
    }
    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, def);
    }
    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, def);
    }
    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, def);
    }
    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);
    } else if (extElem instanceof Schema)
    {
        Element elem = ((Schema)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;
  }
}
TOP

Related Classes of org.eclipse.wst.wsdl.validation.internal.wsdl11.WSDLDocument

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.