/*******************************************************************************
 * Copyright (c) 2001, 2010 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.ui.internal.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import org.eclipse.core.resources.IFile;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
import org.eclipse.wst.wsdl.Binding;
import org.eclipse.wst.wsdl.BindingFault;
import org.eclipse.wst.wsdl.BindingInput;
import org.eclipse.wst.wsdl.BindingOperation;
import org.eclipse.wst.wsdl.BindingOutput;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.Fault;
import org.eclipse.wst.wsdl.Input;
import org.eclipse.wst.wsdl.Message;
import org.eclipse.wst.wsdl.Operation;
import org.eclipse.wst.wsdl.Output;
import org.eclipse.wst.wsdl.Part;
import org.eclipse.wst.wsdl.Port;
import org.eclipse.wst.wsdl.PortType;
import org.eclipse.wst.wsdl.Service;
import org.eclipse.wst.wsdl.WSDLElement;
import org.eclipse.wst.wsdl.internal.impl.ImportImpl;
import org.eclipse.wst.wsdl.internal.impl.WSDLElementImpl;
import org.eclipse.wst.wsdl.ui.internal.extensions.ITypeSystemProvider;
import org.eclipse.wst.wsdl.util.WSDLConstants;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


public class ComponentReferenceUtil
{
  protected Definition rootDefinition;

  public ComponentReferenceUtil(Definition rootDefinition)
  {
    this.rootDefinition = rootDefinition;
  }

  protected static boolean isEqual(String a, String b)
  {
    boolean result = false;
    if (a != null)
    {
      result = a.equals(b) || (a.length() == 0 && b == null);
    }
    else
    {
      result = (b == null || b.length() == 0);
    }
    return result;
  }

  protected static boolean isEqualInputName(Operation operation, BindingOperation bindingOperation)
  {
    boolean result = false;
    Input operationInput = operation.getEInput();
    BindingInput bindingOperationInput = bindingOperation.getEBindingInput();

    if (operationInput != null && bindingOperationInput != null)
    {
      result = isEqual(operationInput.getName(), bindingOperationInput.getName());
    }
    else if (operationInput == null && bindingOperationInput == null)
    {
      result = true;
    }
    return result;
  }

  protected static boolean isEqualOutputName(Operation operation, BindingOperation bindingOperation)
  {
    boolean result = false;
    Output operationOutput = operation.getEOutput();
    BindingOutput bindingOperationOutput = bindingOperation.getEBindingOutput();

    if (operationOutput != null && bindingOperationOutput != null)
    {
      result = isEqual(operationOutput.getName(), bindingOperationOutput.getName());
    }
    else if (operationOutput == null && bindingOperationOutput == null)
    {
      result = true;
    }
    return result;
  }

  protected static boolean isMatchingBinding(Operation operation, BindingOperation bindingOperation)
  {
    return isEqual(operation.getName(), bindingOperation.getName()); /* &&
    			   isEqualInputName(operation, bindingOperation) &&
    			   isEqualOutputName(operation, bindingOperation);*/
  }

  public List getPortsForPortType(PortType portType)
  {
    List list = new ArrayList();
    for (Iterator i = getServices().iterator(); i.hasNext();)
    {
      Service service = (Service) i.next();
      for (Iterator j = service.getEPorts().iterator(); j.hasNext();)
      {
        Port port = (Port) j.next();
        Binding binding = port.getEBinding();
        if (binding != null && binding.getEPortType() == portType)
        {
          list.add(port);
        }
      }
    }
    return list;
  }

  public List getPortsForBinding(Binding binding)
  {
    List list = new ArrayList();
    for (Iterator i = getServices().iterator(); i.hasNext();)
    {
      Service service = (Service) i.next();
      for (Iterator j = service.getEPorts().iterator(); j.hasNext();)
      {
        Port port = (Port) j.next();
        if (port.getEBinding() == binding)
        {
          list.add(port);
        }
      }
    }
    return list;
  }

  public List getBindingOperations(Operation operation)
  {
    List list = new ArrayList();
    String operationName = operation.getName();

    if (operationName != null)
    {
      PortType portType = getEnclosingPortType(operation);
      for (Iterator i = getBindings(portType).iterator(); i.hasNext();)
      {
        Binding binding = (Binding) i.next();
        BindingOperation bindingOperation = getBindingOperation(operation, binding);
        if (bindingOperation != null)
        {
          list.add(bindingOperation);
        }
      }
    }
    return list;
  }

  public BindingOperation getBindingOperation(Operation operation, Binding binding)
  {
    BindingOperation result = null;
    for (Iterator j = binding.getBindingOperations().iterator(); j.hasNext();)
    {
      BindingOperation bindingOperation = (BindingOperation) j.next();
      if (isMatchingBinding(operation, bindingOperation))
      {
        result = bindingOperation;
        break;
      }
    }
    return result;
  }

  public BindingInput getBindingInput(Input input, Binding binding)
  {
    BindingOperation bindingOperation = getBindingOperation((Operation) input.eContainer(), binding);
    return bindingOperation != null ? bindingOperation.getEBindingInput() : null;
  }

  public BindingOutput getBindingOutput(Output output, Binding binding)
  {
    BindingOperation bindingOperation = getBindingOperation((Operation) output.eContainer(), binding);
    return bindingOperation != null ? bindingOperation.getEBindingOutput() : null;
  }

  public BindingFault getBindingFault(Fault fault, Binding binding)
  {
    BindingFault result = null;
    String faultName = fault.getName();
    if (faultName != null)
    {
      BindingOperation bindingOperation = getBindingOperation((Operation) fault.eContainer(), binding);
      if (bindingOperation != null)
      {
        result = (BindingFault) bindingOperation.getBindingFault(faultName);
      }
    }
    return result;
  }

  public EObject getBindingObject(EObject interfaceObject, Binding binding)
  {
    EObject result = null;
    if (interfaceObject instanceof Input)
    {
      result = getBindingInput((Input) interfaceObject, binding);
    }
    else if (interfaceObject instanceof Output)
    {
      result = getBindingOutput((Output) interfaceObject, binding);
    }
    else if (interfaceObject instanceof Fault)
    {
      result = getBindingFault((Fault) interfaceObject, binding);
    }
    else if (interfaceObject instanceof Operation)
    {
      result = getBindingOperation((Operation) interfaceObject, binding);
    }
    else if (interfaceObject instanceof PortType)
    {
      result = binding;
    }
    return result;
  }

  public List getBindingInputs(Input input)
  {
    List list = new ArrayList();
    List operations = getBindingOperations((Operation) input.eContainer());
    for (Iterator i = operations.iterator(); i.hasNext();)
    {
      BindingOperation bindingOperation = (BindingOperation) i.next();
      if (bindingOperation.getBindingInput() != null)
      {
        list.add(bindingOperation.getBindingInput());
      }
    }
    return list;
  }

  public List getBindingOutputs(Output output)
  {
    List list = new ArrayList();
    Operation operation = (Operation) output.eContainer();
    if (operation != null)
    {
      List operations = getBindingOperations(operation);
      for (Iterator i = operations.iterator(); i.hasNext();)
      {
        BindingOperation bindingOperation = (BindingOperation) i.next();
        if (bindingOperation.getBindingOutput() != null)
        {
          list.add(bindingOperation.getBindingOutput());
        }
      }
    }
    return list;
  }

  public List getBindingFaults(Fault fault)
  {
    List list = new ArrayList();
    String faultName = fault.getName();
    if (faultName != null)
    {
      Operation operation = (Operation) fault.eContainer();
      if (operation != null)
      {
        List operations = getBindingOperations(operation);
        for (Iterator i = operations.iterator(); i.hasNext();)
        {
          BindingOperation bindingOperation = (BindingOperation) i.next();
          BindingFault bindingFault = (BindingFault) bindingOperation.getBindingFault(faultName);
          if (bindingFault != null)
          {
            list.add(bindingFault);
          }
        }
      }
    }
    return list;
  }

  protected PortType getEnclosingPortType(Operation operation)
  {
    return (PortType) operation.eContainer();
  }

  public List getBindings(Operation operation)
  {
    return getBindings(getEnclosingPortType(operation));
  }

  public List getBindings(PortType portType)
  {
    List list = new ArrayList();
    for (Iterator i = getDefinitions().iterator(); i.hasNext();)
    {
      Definition definition = (Definition) i.next();
      for (Iterator j = definition.getBindings().values().iterator(); j.hasNext();)
      {
        Binding binding = (Binding) j.next();
        if (portType == null || binding.getPortType() == portType)
        {
          list.add(binding);
        }
      }
    }
    return list;
  }

  public List getBindingsWithoutOperation(PortType portType, String operationName)
  {
    List result = new ArrayList();
    if (operationName != null)
    {
      List bindings = getBindings(portType);
      for (Iterator i = bindings.iterator(); i.hasNext();)
      {
        Binding binding = (Binding) i.next();
        boolean hasName = false;
        for (Iterator j = binding.getBindingOperations().iterator(); j.hasNext();)
        {
          BindingOperation bindingOperation = (BindingOperation) j.next();
          if (operationName.equals(bindingOperation.getName()))
          {
            hasName = true;
            break;
          }
        }
        if (!hasName)
        {
          result.add(binding);
        }
      }
    }
    return result;
  }

  public List getBindings()
  {
    return getBindings((PortType) null);
  }

  public List getBindingNames()
  {
    List list = new ArrayList();
    for (Iterator i = getBindings().iterator(); i.hasNext();)
    {
      Binding binding = (Binding) i.next();
      list.addAll(getPrefixedNames(binding.getQName()));
    }
    return list;
  }

  public List getPortTypeNames()
  {
    List list = new ArrayList();
    for (Iterator i = getDefinitions().iterator(); i.hasNext();)
    {
      Definition definition = (Definition) i.next();
      for (Iterator j = definition.getPortTypes().values().iterator(); j.hasNext();)
      {
        PortType portType = (PortType) j.next();
        list.addAll(getPrefixedNames(portType.getQName()));
      }
    }
    return list;
  }

  public List getServices()
  {
    List list = new ArrayList();
    for (Iterator i = getDefinitions().iterator(); i.hasNext();)
    {
      Definition definition = (Definition) i.next();
      list.addAll(definition.getEServices());
    }
    return list;
  }

  public List getPortTypes()
  {
    List list = new ArrayList();
    for (Iterator i = getDefinitions().iterator(); i.hasNext();)
    {
      Definition definition = (Definition) i.next();
      list.addAll(definition.getEPortTypes());
    }
    return list;
  }

  public List getMessages()
  {
    List list = new ArrayList();
    for (Iterator i = getDefinitions().iterator(); i.hasNext();)
    {
      Definition definition = (Definition) i.next();
      list.addAll(definition.getEMessages());
    }
    return list;
  }

  public List getTypes()
  {
    List list = new ArrayList();
    for (Iterator i = getDefinitions().iterator(); i.hasNext();)
    {
      Definition definition = (Definition) i.next();
      if (definition.getETypes() != null)
      {
        list.add(definition.getETypes());
      }
    }
    return list;
  }

  public List getMessageNames()
  {
    List list = new ArrayList();
    for (Iterator i = getDefinitions().iterator(); i.hasNext();)
    {
      Definition definition = (Definition) i.next();
      for (Iterator j = definition.getMessages().values().iterator(); j.hasNext();)
      {
        Message message = (Message) j.next();
        list.addAll(getPrefixedNames(message.getQName()));
      }
    }
    return list;
  }

  public List getDefinitions()
  {
    List list = new ArrayList();
    addDefinition(rootDefinition, list);
    return list;
  }

  /**
   * @deprecated -- we should always use getPrefixedNames
   */
  public String getPrefixedName(QName qname)
  {
    String name = null;
    if (qname != null)
    {
      String prefix = rootDefinition.getPrefix(qname.getNamespaceURI());
      if (prefix != null)
      {
        name = prefix + ":" + qname.getLocalPart(); //$NON-NLS-1$
      }
    }
    return name;
  }

  public List getPrefixedNames(QName qname)
  {
    List list = new ArrayList();
    if (qname != null)
    {
      Map map = rootDefinition.getNamespaces();
      for (Iterator i = map.keySet().iterator(); i.hasNext();)
      {
        String prefix = (String) i.next();
        String namespace = (String) map.get(prefix);
        if (namespace != null && namespace.equals(qname.getNamespaceURI()))
        {
          String name = prefix.length() > 0 ? prefix + ":" + qname.getLocalPart() :  //$NON-NLS-1$
                        qname.getLocalPart();
          list.add(name);
        }
      }
    }
    return list;
  }

  protected void addDefinition(Definition definition, List list)
  {
    if (definition != null)
    {
      list.add(definition);
      for (Iterator i = definition.getEImports().iterator(); i.hasNext();)
      {
        ImportImpl theImport = (ImportImpl) i.next();
        if (theImport.getLocationURI() != null && !theImport.getLocationURI().endsWith("xsd")) //$NON-NLS-1$
        {
          theImport.importDefinitionOrSchema();	 
          Definition importedDefinition = (Definition) theImport.getEDefinition();
          if (importedDefinition != null && !list.contains(importedDefinition))
          {
            addDefinition(importedDefinition, list);
          }
        }
      }
    }
  }

  public static String getPortTypeReference(Binding binding)
  {
    String result = null;
    Element element = WSDLEditorUtil.getInstance().getElementForObject(binding);
    if (element != null)
    {
      result = element.getAttribute(WSDLConstants.TYPE_ATTRIBUTE);
    }
    return result;
  }

  public static void setPortTypeReference(Binding binding, String portType)
  {
    Element element = WSDLEditorUtil.getInstance().getElementForObject(binding);
    if (element != null)
    {
      element.setAttribute(WSDLConstants.TYPE_ATTRIBUTE, portType);
    }
  }

  public static String getBindingReference(Port port)
  {
    String result = null;
    Element element = WSDLEditorUtil.getInstance().getElementForObject(port);
    if (element != null)
    {
      result = element.getAttribute(WSDLConstants.BINDING_ATTRIBUTE);
    }
    return result;
  }

  public static String getName(Binding binding)
  {
    String result = null;
    Element element = WSDLEditorUtil.getInstance().getElementForObject(binding);
    if (element != null)
    {
      result = element.getAttribute(WSDLConstants.NAME_ATTRIBUTE);
    }
    return result;
  }

  public static QName getPortTypeReferenceQName(Binding binding)
  {
    QName result = null;
    Definition definition = binding.getEnclosingDefinition();
    String prefixedName = getPortTypeReference(binding);
    if (prefixedName != null)
    {
      result = WSDLEditorUtil.createQName(definition, prefixedName);
    }
    return result;
  }

  public static QName getBindingReferenceQName(Port port)
  {
    QName result = null;
    Definition definition = port.getEnclosingDefinition();
    String prefixedName = getBindingReference(port);
    if (prefixedName != null)
    {
      result = WSDLEditorUtil.createQName(definition, prefixedName);
    }
    return result;
  }

  public static String getMessageReference(Input input)
  {
    return getMessageReferenceHelper(input);
  }

  public static String getMessageReference(Output output)
  {
    return getMessageReferenceHelper(output);
  }

  public static String getMessageReference(Fault fault)
  {
    return getMessageReferenceHelper(fault);
  }

  public static QName getMessageReferenceQName(Input input)
  {
    return getMessageReferenceQNameHelper(input);
  }

  public static QName getMessageReferenceQName(Output output)
  {
    return getMessageReferenceQNameHelper(output);
  }

  public static QName getMessageReferenceQName(Fault fault)
  {
    return getMessageReferenceQNameHelper(fault);
  }

  protected static String getMessageReferenceHelper(WSDLElement o)
  {
    String result = null;
    Element element = WSDLEditorUtil.getInstance().getElementForObject(o);
    if (element != null)
    {
      result = element.getAttribute(WSDLConstants.MESSAGE_ATTRIBUTE);
    }
    return result;
  }

  public static QName getMessageReferenceQNameHelper(WSDLElement o)
  {
    QName result = null;
    Definition definition = o.getEnclosingDefinition();
    String prefixedName = getMessageReferenceHelper(o);
    if (prefixedName != null)
    {
      result = WSDLEditorUtil.createQName(definition, prefixedName);
    }
    return result;
  }

  public static void updatePortTypeReferences(Definition definition)
  {
    for (Iterator i = definition.getBindings().values().iterator(); i.hasNext();)
    {
      Binding binding = (Binding) i.next();
      QName qname = ComponentReferenceUtil.getPortTypeReferenceQName(binding);

      PortType portType = (qname != null) ? (PortType) definition.getPortType(qname) : null;

      if (binding.getPortType() != portType)
      {
        binding.setPortType(portType);
      }
    }
  }

  public static void updateBindingReferences(Definition definition)
  {
    for (Iterator i = definition.getServices().values().iterator(); i.hasNext();)
    {
      Service service = (Service) i.next();
      for (Iterator j = service.getEPorts().iterator(); j.hasNext();)
      {
        Port port = (Port) j.next();
        QName qname = ComponentReferenceUtil.getBindingReferenceQName(port);

        Binding binding = (qname != null) ? (Binding) definition.getBinding(qname) : null;

        if (port.getBinding() != binding)
        {
          port.setBinding(binding);
        }
      }
    }
  }

  public static void updateMessageReferences(Definition definition)
  {
    // for each port type
    //
    for (Iterator i = definition.getPortTypes().values().iterator(); i.hasNext();)
    {
      PortType portType = (PortType) i.next();

      // for each operation
      //
      for (Iterator j = portType.getEOperations().iterator(); j.hasNext();)
      {
        Operation operation = (Operation) j.next();

        // handle Input
        //
        Input input = (Input) operation.getInput();
        if (input != null)
        {
          QName qname = ComponentReferenceUtil.getMessageReferenceQName(input);
          Message message = (qname != null) ? (Message) definition.getMessage(qname) : null;
          if (input.getMessage() != message)
          {
            input.setMessage(message);
          }
        }

        // handle Output
        //
        Output output = (Output) operation.getOutput();
        if (output != null)
        {
          QName qname = ComponentReferenceUtil.getMessageReferenceQName(output);
          Message message = (qname != null) ? (Message) definition.getMessage(qname) : null;
          if (output.getMessage() != message)
          {
            output.setMessage(message);
          }
        }

        // handle Faults
        //
        for (Iterator k = operation.getEFaults().iterator(); k.hasNext();)
        {
          Fault fault = (Fault) k.next();

          QName qname = ComponentReferenceUtil.getMessageReferenceQName(fault);
          Message message = (qname != null) ? (Message) definition.getMessage(qname) : null;
          if (fault.getMessage() != message)
          {
            fault.setMessage(message);
          }
        }
      }
    }
  }

  public static void updateSchemaReferences(Definition definition)
  {
    for (Iterator i = definition.getEMessages().iterator(); i.hasNext();)
    {
      Message message = (Message) i.next();
      for (Iterator j = message.getEParts().iterator(); j.hasNext();)
      {
        Part part = (Part) j.next();
        Element element = WSDLEditorUtil.getInstance().getElementForObject(part);
        if (element != null)
        {
          ((WSDLElementImpl)part).elementChanged(element);
        }
      }
    }
  }

  public static Operation getOperation(PortType portType, BindingOperation bindingOperation)
  {
    Operation result = null;
    for (Iterator i = portType.getEOperations().iterator(); i.hasNext();)
    {
      Operation operation = (Operation) i.next();
      if (isMatchingBinding(operation, bindingOperation))
      {
        result = operation;
        break;
      }
    }
    return result;
  }

  public static void updateOperationReference(BindingOperation bindingOperation)
  {
    Operation operation = computeOperation(bindingOperation);
    if (operation != bindingOperation.getOperation())
    {
      bindingOperation.setOperation(operation);
    }
  }

  public List getComponentNameList(boolean isType)
  {
    List result = Collections.EMPTY_LIST;
    ITypeSystemProvider typeSystemProvider = WSDLEditorUtil.getInstance().getTypeSystemProvider(rootDefinition);
    if (typeSystemProvider != null)
    {
      result = isType ? typeSystemProvider.getAvailableTypeNames(rootDefinition, 0) : typeSystemProvider.getAvailableElementNames(rootDefinition);
    }
    return result;
  }

  public static List getComponentNameList(Part part, boolean isType)
  {
    List result = Collections.EMPTY_LIST;
    Definition definition = part.getEnclosingDefinition();
    ITypeSystemProvider typeSystemProvider = WSDLEditorUtil.getInstance().getTypeSystemProvider(definition);
    if (typeSystemProvider != null)
    {
      result = isType ? typeSystemProvider.getAvailableTypeNames(definition, 0) : typeSystemProvider.getAvailableElementNames(definition);
    }
    return result;
  }

  public static boolean isType(Part part)
  {
    Element element = part.getElement();
    return !element.hasAttribute(WSDLConstants.ELEMENT_ATTRIBUTE);
  }

  public static String getPartComponentReference(Part part)
  {
    Element element = part.getElement();
    String result = null;
    if (element.hasAttribute(WSDLConstants.TYPE_ATTRIBUTE))
    {
      result = element.getAttribute(WSDLConstants.TYPE_ATTRIBUTE);
    }
    else if (element.hasAttribute(WSDLConstants.ELEMENT_ATTRIBUTE))
    {
      result = element.getAttribute(WSDLConstants.ELEMENT_ATTRIBUTE);
    }
    return result;
  }

  public static void setComponentReference(Part part, boolean isType, String componentName)
  {
    Element element = WSDLEditorUtil.getInstance().getElementForObject(part);
    String newAttribute = isType ? WSDLConstants.TYPE_ATTRIBUTE : WSDLConstants.ELEMENT_ATTRIBUTE;
    String oldAttribute = isType ? WSDLConstants.ELEMENT_ATTRIBUTE : WSDLConstants.TYPE_ATTRIBUTE;
    element.removeAttribute(oldAttribute);

    String value = componentName != null ? componentName : element.getAttribute(newAttribute);

    if (value == null)
    {
      if (isType)
      {
        String xsdPrefix = part.getEnclosingDefinition().getPrefix(WSDLConstants.XSD_NAMESPACE_URI);
        value = "string"; //$NON-NLS-1$
        if (xsdPrefix != null && xsdPrefix.length() > 0)
        {
          value = xsdPrefix + ":" + value; //$NON-NLS-1$
        }
      }
      else
      {
        List list = getComponentNameList(part, isType);
        value = list.size() > 0 ? (String) list.get(0) : "some-element-name"; //$NON-NLS-1$
      }
    }
    element.setAttribute(newAttribute, value);
  }

  public static Operation computeOperation(BindingOperation bindingOperation)
  {
    Operation result = null;
    Binding binding = (Binding) bindingOperation.eContainer();
    PortType portType = (PortType) binding.getPortType();
    if (portType != null)
    {
      result = getOperation(portType, bindingOperation);
    }
    return result;
  }

  public static Input computeInput(BindingInput bindingInput)
  {
    Operation operation = computeOperation((BindingOperation) bindingInput.eContainer());
    return operation != null ? operation.getEInput() : null;
  }

  public static Output computeOutput(BindingOutput bindingOutput)
  {
    Operation operation = computeOperation((BindingOperation) bindingOutput.eContainer());
    return operation != null ? operation.getEOutput() : null;
  }

  public static Fault computeFault(BindingFault bindingFault)
  {
    Fault result = null;
    Operation operation = computeOperation((BindingOperation) bindingFault.eContainer());
    if (operation != null)
    {
      for (Iterator i = operation.getEFaults().iterator(); i.hasNext();)
      {
        Fault fault = (Fault) i.next();
        String faultName = fault.getName();
        if (faultName != null && faultName.equals(bindingFault.getName()))
        {
          result = fault;
          break;
        }
      }
    }
    return result;
  }

  public static String getPartReferenceValue(Part part)
  {
    Element element = WSDLEditorUtil.getInstance().getElementForObject(part);
    String value = null;
    if (element != null)
    {
      if (element.hasAttribute(WSDLConstants.TYPE_ATTRIBUTE))
      {      		
        value = element.getAttribute(WSDLConstants.TYPE_ATTRIBUTE);
      }
      else if (element.hasAttribute(WSDLConstants.ELEMENT_ATTRIBUTE))
      {  
        value = element.getAttribute(WSDLConstants.ELEMENT_ATTRIBUTE);
      }         
    }  
    return value != null ? value : ""; //$NON-NLS-1$
  }

  public Operation getBindingOperation(Element bindingOperationContent)
  {
    Operation operation = null;
    Node parent = bindingOperationContent.getParentNode();
    if (parent instanceof Element)
    {
      Object object = WSDLEditorUtil.getInstance().findModelObjectForElement(rootDefinition, (Element) parent);
      if (object instanceof BindingOperation)
      {
        operation = ComponentReferenceUtil.computeOperation((BindingOperation) object);
      }
    }
    return operation;
  }

  public Message getBindingOperationInputMessage(Element bindingOperationContent)
  {
    Message message = null;
    Operation operation = getBindingOperation(bindingOperationContent);
    if (operation != null)
    {
      Input input = operation.getEInput();
      if (input != null)
      {
        message = input.getEMessage();
      }
    }
    return message;
  }

  public Message getBindingOperationOutputMessage(Element bindingOperationContent)
  {
    Message message = null;
    Operation operation = getBindingOperation(bindingOperationContent);
    if (operation != null)
    {
      Output output = operation.getEOutput();
      if (output != null)
      {
        message = output.getEMessage();
      }
    }
    return message;
  }

  public static String computeRelativeURI(IFile referencedLocation, IFile baseLocation, boolean enableIEStyleReferences)
  {
    // TODO... we need some extension to allow IE folks to plugin logic to create an 'IE' style path
    // TODO... consider using URI class in EMF 
    return URIHelper.getRelativeURI(referencedLocation.getLocation(), baseLocation.getLocation());
  }
  
  public static String computeRelativeURI(String referencedLocation, String baseLocation, boolean enableIEStyleReferences)
  {
    // TODO... we need some extension to allow IE folks to plugin logic to create an 'IE' style path
    // TODO... consider using URI class in EMF 
    return URIHelper.getRelativeURI(referencedLocation, baseLocation);
  }
}
