/*******************************************************************************
 * 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.internal.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import com.ibm.icu.util.StringTokenizer;

import javax.xml.namespace.QName;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.Namespace;
import org.eclipse.wst.wsdl.WSDLElement;
import org.eclipse.wst.wsdl.WSDLPackage;
import org.eclipse.wst.wsdl.util.WSDLConstants;
import org.eclipse.xsd.util.XSDConstants;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;


/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Element</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link org.eclipse.wsdl.impl.WSDLElementImpl#getDocumentationElement <em>Documentation Element</em>}</li>
 *   <li>{@link org.eclipse.wsdl.impl.WSDLElementImpl#getElement <em>Element</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public abstract class WSDLElementImpl extends EObjectImpl implements WSDLElement
{
  /**
   * The default value of the '{@link #getDocumentationElement() <em>Documentation Element</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getDocumentationElement()
   * @generated
   * @ordered
   */
  protected static final Element DOCUMENTATION_ELEMENT_EDEFAULT = null;

  /**
   * The cached value of the '{@link #getDocumentationElement() <em>Documentation Element</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getDocumentationElement()
   * @generated
   * @ordered
   */
  protected Element documentationElement = DOCUMENTATION_ELEMENT_EDEFAULT;

  /**
   * The default value of the '{@link #getElement() <em>Element</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getElement()
   * @generated
   * @ordered
   */
  protected static final Element ELEMENT_EDEFAULT = null;

  /**
   * The cached value of the '{@link #getElement() <em>Element</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getElement()
   * @generated
   * @ordered
   */
  protected Element element = ELEMENT_EDEFAULT;

  protected boolean isReconciling = false;
  protected boolean updatingDOM = false;
  protected EList wsdlContents;

  private Definition enclosingDefinition;

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  protected WSDLElementImpl()
  {
    super();
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  protected EClass eStaticClass()
  {
    return WSDLPackage.eINSTANCE.getWSDLElement();
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public Element getDocumentationElement()
  {
    return documentationElement;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public void setDocumentationElement(Element newDocumentationElement)
  {
    Element oldDocumentationElement = documentationElement;
    documentationElement = newDocumentationElement;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET, WSDLPackage.WSDL_ELEMENT__DOCUMENTATION_ELEMENT, oldDocumentationElement, documentationElement));
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public Element getElement()
  {
    return element;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public void setElementGen(Element newElement)
  {
    Element oldElement = element;
    element = newElement;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET, WSDLPackage.WSDL_ELEMENT__ELEMENT, oldElement, element));
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated NOT
   */
  public void setEnclosingDefinition(Definition definition)
  {
    enclosingDefinition = definition;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public Object eGet(EStructuralFeature eFeature, boolean resolve)
  {
    switch (eDerivedStructuralFeatureID(eFeature))
    {
      case WSDLPackage.WSDL_ELEMENT__DOCUMENTATION_ELEMENT:
        return getDocumentationElement();
      case WSDLPackage.WSDL_ELEMENT__ELEMENT:
        return getElement();
    }
    return eDynamicGet(eFeature, resolve);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public void eSet(EStructuralFeature eFeature, Object newValue)
  {
    switch (eDerivedStructuralFeatureID(eFeature))
    {
      case WSDLPackage.WSDL_ELEMENT__DOCUMENTATION_ELEMENT:
        setDocumentationElement((Element)newValue);
        return;
      case WSDLPackage.WSDL_ELEMENT__ELEMENT:
        setElement((Element)newValue);
        return;
    }
    eDynamicSet(eFeature, newValue);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public void eUnset(EStructuralFeature eFeature)
  {
    switch (eDerivedStructuralFeatureID(eFeature))
    {
      case WSDLPackage.WSDL_ELEMENT__DOCUMENTATION_ELEMENT:
        setDocumentationElement(DOCUMENTATION_ELEMENT_EDEFAULT);
        return;
      case WSDLPackage.WSDL_ELEMENT__ELEMENT:
        setElement(ELEMENT_EDEFAULT);
        return;
    }
    eDynamicUnset(eFeature);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public boolean eIsSet(EStructuralFeature eFeature)
  {
    switch (eDerivedStructuralFeatureID(eFeature))
    {
      case WSDLPackage.WSDL_ELEMENT__DOCUMENTATION_ELEMENT:
        return DOCUMENTATION_ELEMENT_EDEFAULT == null ? documentationElement != null : !DOCUMENTATION_ELEMENT_EDEFAULT.equals(documentationElement);
      case WSDLPackage.WSDL_ELEMENT__ELEMENT:
        return ELEMENT_EDEFAULT == null ? element != null : !ELEMENT_EDEFAULT.equals(element);
    }
    return eDynamicIsSet(eFeature);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public String toString()
  {
    if (eIsProxy()) return super.toString();

    StringBuffer result = new StringBuffer(super.toString());
    result.append(" (documentationElement: ");
    result.append(documentationElement);
    result.append(", element: ");
    result.append(element);
    result.append(')');
    return result.toString();
  }

  //
  // Reconcilation methods: DOM -> Model
  //

  public static class WSDLContentsEList extends EContentsEList
  {
    WSDLContentsEList(EObject eObject, EStructuralFeature[] eStructuralFeatures)
    {
      super(eObject, eStructuralFeatures);
    }

    protected ListIterator newListIterator()
    {
      return new FeatureIteratorImpl(eObject, eStructuralFeatures);
    }

    protected boolean isIncluded(EStructuralFeature eStructuralFeature)
    {
      EReference eReference = (EReference) eStructuralFeature;
      return !eReference.isTransient();
    }

    public List basicList()
    {
      return new WSDLContentsEList(eObject, eStructuralFeatures);
    }

    public Iterator basicIterator()
    {
      return new FeatureIteratorImpl(eObject, eStructuralFeatures);
    }

    public static class FeatureIteratorImpl extends EContentsEList.FeatureIteratorImpl
    {
      public FeatureIteratorImpl(EObject eObject)
      {
        super(eObject, (EStructuralFeature[]) ((BasicEList) eObject.eClass().getEAllReferences()).data());
      }

      public FeatureIteratorImpl(EObject eObject, EStructuralFeature[] eStructuralFeatures)
      {
        super(eObject, eStructuralFeatures);
      }

      protected boolean isIncluded(EStructuralFeature eStructuralFeature)
      {
        EReference eReference = (EReference) eStructuralFeature;
        return !eReference.isTransient();
      }
    }
  }

  public EList getWSDLContents()
  {
    if (wsdlContents == null)
    {
      wsdlContents = new WSDLContentsEList(this, (EStructuralFeature[]) ((BasicEList) eClass().getEAllContainments()).data());
    }

    return wsdlContents;
  }

  public void setElement(Element element)
  {
    if (element == null)
    {
      isReconciling = true;
      setElementGen(null);
      for (Iterator contents = getWSDLContents().iterator(); contents.hasNext();)
      {
        Object obj = contents.next();
        if (obj instanceof WSDLElementImpl)
        {
          WSDLElementImpl content = (WSDLElementImpl) obj;
          content.setElement(null);
        }
      }
      isReconciling = false;
    }
    else
    {
      setElementGen(element);
    }
  }

  public boolean eNotificationRequired()
  {
    return true;
  }

  public void eNotify(Notification msg)
  {
    int eventType = msg.getEventType();
    Object feature = msg.getFeature();
    Object oldValue = msg.getOldValue();
    Object newValue = msg.getNewValue();

    if (eClass().getEAllReferences().contains(feature))
    {
      EReference eReference = (EReference) feature;
      if (eReference.isContainment() && !eReference.isTransient())
      {
        switch (eventType)
        {
          case Notification.ADD :
          {
              adoptContent(eReference,newValue);
            break;
          }
          case Notification.ADD_MANY :
          {
            for (Iterator newValues = ((Collection) newValue).iterator(); newValues.hasNext();)
            {
              WSDLElement wsdlElement = (WSDLElement) newValues.next();
              adoptContent(eReference, wsdlElement);
            }
            break;
          }
          case Notification.REMOVE :
          {
            if (oldValue != null)
            {
              orphanContent(eReference, /*(WSDLElement)*/ oldValue);
            }
            break;
          }
          case Notification.REMOVE_MANY :
          {
            for (Iterator oldValues = ((Collection) oldValue).iterator(); oldValues.hasNext();)
            {
              EObject object = (EObject) oldValues.next();
              orphanContent(eReference, object);
            }
            break;
          }
          case Notification.MOVE :
          {
            moveContent(eReference, (WSDLElement) newValue);
            break;
          }
          case Notification.SET :
          case Notification.UNSET :
          {
            if (oldValue != null)
            {
              orphanContent(eReference, oldValue);
            }
            if (newValue != null)
            {
              adoptContent(eReference, newValue);
            }
            break;
          }
        }
      }
      else
      {
        switch (eventType)
        {
          case Notification.ADD :
          case Notification.ADD_MANY :
          case Notification.REMOVE :
          case Notification.REMOVE_MANY :
          case Notification.MOVE :
          case Notification.SET :
          case Notification.UNSET :
          {
            changeReference(eReference);
            break;
          }
        }
      }
    }
    else if (eClass().getEAllAttributes().contains(feature))
    {
      EAttribute eAttribute = (EAttribute) feature;
      switch (eventType)
      {
        case Notification.ADD :
        case Notification.ADD_MANY :
        case Notification.REMOVE :
        case Notification.REMOVE_MANY :
        case Notification.MOVE :
        case Notification.SET :
        case Notification.UNSET :
        {
          changeAttribute(eAttribute);
          break;
        }
      }
    }
    super.eNotify(msg);
  }

  protected void orphanContent(EReference eReference, Object obj)
  {
    if (!isReconciling)
    {
      Element parent = getElement();
      if (parent != null && obj != null && obj instanceof WSDLElement)
      {
      	WSDLElement wsdlElement = (WSDLElement)obj;
        Element contentElement = wsdlElement.getElement();
        if (contentElement != null)
          niceRemoveChild(contentElement.getParentNode(), contentElement);
      }
      else
      	;//System.out.println("WSDLElement.orphanContent(), Object is: " + obj);
    }
  }
  
  protected void niceRemoveChild(Node parent, Node child)
  {
    if (isReconciling)
    {
      // System.out.println("**** cyclic dom writeback avoided " + eClass().getName());
      return;
    }
    forceNiceRemoveChild(parent, child);
  }
  
  public void forceNiceRemoveChild(Node parent, Node child)
  {
    updatingDOM = true;

    boolean done = false;

// System.out.println("?*");
    Node previous = child.getPreviousSibling();
    if (previous != null && previous.getNodeType() == Node.TEXT_NODE)
    {
      Text text = (Text)previous;
      String data = text.getData();
      int index = data.lastIndexOf('\n');
      if (index != -1)
      {
        if (index - 1 > 0 && data.charAt(index - 1) == '\r')
        {
//System.out.println("1*");
          text.deleteData(index - 1, data.length() - index + 1);
        }
        else
        {
//System.out.println("2*");
          text.deleteData(index, data.length() - index);
        }
        done = true;
      }
      else
      {
        //System.out.println("No return before!");
      }
    }
    else
    {
      // System.out.println("No text node before!");
    }


    if (!done)
    {
      for (Node next = child.getNextSibling(); next != null; next = next.getNextSibling())
      {
        if (next.getNodeType() == Node.TEXT_NODE)
        {
          Text text = (Text)next;
          String data = text.getData();
/*
           System.out.print("xx " + data.length() + ":: ");
          for (int i = 0; i < data.length(); ++i)
          {
             System.out.print(" " + Integer.toHexString((int)data.charAt(i)));
          }
          System.out.println();
*/

          int index = data.indexOf('\n');
          if (index != -1)
          {
            if (index + 1 < data.length() && data.charAt(index + 1) == '\r')
            {
    // System.out.println("3*");
              text.deleteData(0, index + 2);
            }
            else
            {
    //System.out.println("4*");
              text.deleteData(0, index + 1);
            }
            break;
          }
          else
          {
            // System.out.println("No return after!");
          }
        }
        else if (next.getNodeType() == Node.ELEMENT_NODE)
        {
          break;
        }
      }
    }

// System.out.println("Removing from--------\n     " + parent);
// System.out.println("Removing--------\n     " + child);
    if (parent != null)
    	parent.removeChild(child);

    updatingDOM=false;
  }
 
  protected void moveContent(EReference eReference, WSDLElement wsdlElement)
  {
    if (isReconciling)
    {
      // System.out.println("**** cyclic dom writeback avoided " + eClass().getName());
      return;
    }
    //System.out.println("moving " + xsdConcreteComponent);
    Node parent = getAdoptionParentNode(eReference);
    if (parent != null)
    {
      Element child = wsdlElement.getElement();
      if (child != null)
      {
        List contents = getWSDLContents();
        int index = contents.indexOf(wsdlElement);
        niceRemoveChild(parent, child);
        niceInsertBefore
          (parent, 
            child, 
            ++index == contents.size() ?  
              null : 
              ((WSDLElement)contents.get(index)).getElement());
      }
    }
    //System.out.println("moved " + xsdConcreteComponent);

  }

  protected void adoptContent(EReference eReference, Object object)
  {
    if (object instanceof WSDLElement)
    {
      WSDLElement wsdlElement = (WSDLElement) object;
      if (isReconciling)
      {
        if (wsdlElement.getElement() != null)
        {
          ((WSDLElementImpl) wsdlElement).elementChanged(wsdlElement.getElement());
        }
      }
      else
      {
        Element childElement = wsdlElement.getElement();
        if (getElement() != null && (childElement == null || childElement.getParentNode() == null))
        {
          if (childElement != null && childElement.getOwnerDocument() != getElement().getOwnerDocument())
          {
            wsdlElement.setElement(null);
            childElement = null;
          }

          handleElementForAdopt(eReference, wsdlElement);
          ((WSDLElementImpl) wsdlElement).updateElement();
        }
      }

      Definition definition = getEnclosingDefinition();
      if (definition != null)
      {
        ((WSDLElementImpl) wsdlElement).adoptBy(definition);
      }
    }
    else if (object instanceof Namespace)
    {
      // Add a namespace attribute to the Definitions element.
      Namespace ns = (Namespace)object;
      Node adoptionParent = getAdoptionParentNode(eReference); // Definitions node
      // KB: Assumption - The prefix is unique if we are here (by the Definitions model). 
	  if (adoptionParent != null) {
		  ((Element)adoptionParent).setAttribute("xmlns:"+ns.getPrefix(),ns.getURI());
	  }
    }
  }

  protected Node getAdoptionParentNode(EReference eReference)
  {
    return getElement();
  }
  
  protected void handleElementForAdopt(EReference eReference, WSDLElement wsdlElement)
  { 
    // Establish DOM parent-child relationship
    
    Node adoptionParent = getAdoptionParentNode(eReference);
    Element childElement = wsdlElement.getElement();
    Element referencedElement = null;
    
    for (Iterator contents = getWSDLContents().iterator(); contents.hasNext(); )
    {
      if (contents.next() == wsdlElement)
      {
        if (contents.hasNext())
        {
          Object next = contents.next();
          if (next instanceof WSDLElement)
          {
            referencedElement = ((WSDLElement)next).getElement();
            while (referencedElement != null)
            {
              Node parent = referencedElement.getParentNode(); 
              if (parent == null )
              {
                referencedElement = null;
                break;
              }
              else if (parent == adoptionParent)
              {
                break;
              }
              else if (parent.getNodeType() == Node.ELEMENT_NODE)
              {
                referencedElement = (Element)parent;
              }
              else
              {
                break;
              }
            }
          }
        }
        break;
      }
    }
   
    if (childElement == null)
    {
      ((WSDLElementImpl)wsdlElement).isReconciling = true;
      childElement = ((WSDLElementImpl)wsdlElement).createElement();
      ((WSDLElementImpl)wsdlElement).isReconciling = false;
      if (childElement == null)
      {
         //System.out.println("not created! " + wsdlElement);
         return;
      }
    }

    boolean isAttached = false;
    for (Node rootDocument = childElement; rootDocument != null; rootDocument = rootDocument.getParentNode())
    {
      if (WSDLConstants.nodeType(rootDocument) == WSDLConstants.DEFINITION)
      {
        isAttached = true;
        break;
      }
    }
    
    if (!isAttached)
    {
      if (referencedElement == null && 
          !eReference.isMany())
    {
      for (Node child = adoptionParent.getFirstChild(); child != null; child = child.getNextSibling())
      {
        if (child.getNodeType() == Node.ELEMENT_NODE)
        {
          referencedElement = (Element)child;
          break;
        }
      }
    }
      //referencedElement = computeTopLevelRefChild(adoptionParent,childElement);     
      niceInsertBefore(adoptionParent, childElement, referencedElement);
    }
  }

  public void niceInsertBefore(Node parent, Node newChild, Node referenceChild)
  {
    if (isReconciling)
    {
      // System.out.println("**** cyclic dom writeback avoided " + eClass().getName());
      return;
    }

    forceNiceInsertBefore(parent, newChild, referenceChild);
  }

  public void forceNiceInsertBefore(Node parent, Node newChild, Node referenceChild)
  {
    updatingDOM = true;

    LOOP:
    for (Node child = referenceChild == null ? parent.getLastChild() : referenceChild.getPreviousSibling(); 
         child != null; 
         child = child.getPreviousSibling())
    {
      switch (child.getNodeType())
      {
        case Node.TEXT_NODE:
        {
          Text text = (Text)child;
          String data = text.getData();

/*
          System.out.print("xx " + data.length() + ":: ");
          for (int i = 0; i < data.length(); ++i)
          {
            System.out.print(" " + Integer.toHexString((int)data.charAt(i)));
          }
          System.out.println();
*/

          int index = data.lastIndexOf('\n');
          if (index != -1)
          {
// System.out.println("In here");

            StringBuffer indent = new StringBuffer();
            for (Node ancestor = parent.getParentNode(); 
                 ancestor != null && ancestor.getNodeType() != Node.DOCUMENT_NODE; 
                 ancestor = ancestor.getParentNode())
            {
              indent.append("    ");
            }

            if (index + 1 < data.length() && data.charAt(index + 1) == '\r')
            {
              ++index;
            }
            text.replaceData(index + 1, data.length() - index - 1, indent + "    ");

            // setCorrectIndentation(indent, newText);
            if (referenceChild != null)
            {
              indent.append("    ");
            }
            Text newText = parent.getOwnerDocument().createTextNode("\n" + indent);
// System.out.println("Inserted..." + newText);
            parent.insertBefore(newText, referenceChild);
            referenceChild = newText;
            break LOOP;
          }

          break;
        } 
        case Node.ELEMENT_NODE:
        {
          break LOOP;
        }
      }
    }

// System.out.println("Inserted..." + newChild);
    parent.insertBefore(newChild, referenceChild);

    updatingDOM = false;
  }

  protected Element computeTopLevelRefChild(Node parentNode, Node nodeToAdd)
  {
  	Element result = null;
    int a = getPrecedence(nodeToAdd);
      	
    for (Node node = parentNode.getFirstChild(); node != null; node = node.getNextSibling())
    {
      if (node.getNodeType() == Node.ELEMENT_NODE)
      {
		    int b = getPrecedence(node);
		    if (b >= a)
		    {
		      result = (Element)node;	
	        break;	    
		    }        
      } 
    }
    return result;
  }
  
  private HashMap precedenceMap = createPrecedenceMap();

  private int getPrecedence(Node node)
  {
  	int result = 2;
  	String localName = node.getLocalName();
  	if (localName != null)
  	{  	
      Integer integer = (Integer)precedenceMap.get(localName);
      if (integer != null)
      {      
        result = integer.intValue();
      }
  	}
  	return result;
  }
    
  private HashMap createPrecedenceMap()
	{
		HashMap hashMap = new HashMap();
		hashMap.put(WSDLConstants.DOCUMENTATION_ELEMENT_TAG, new Integer(1));
		hashMap.put(WSDLConstants.IMPORT_ELEMENT_TAG, new Integer(3));
		hashMap.put(WSDLConstants.TYPES_ELEMENT_TAG, new Integer(4));
		hashMap.put(WSDLConstants.MESSAGE_ELEMENT_TAG, new Integer(5));
		hashMap.put(WSDLConstants.PORT_TYPE_ELEMENT_TAG, new Integer(6));
		hashMap.put(WSDLConstants.BINDING_ELEMENT_TAG, new Integer(7));
		hashMap.put(WSDLConstants.SERVICE_ELEMENT_TAG, new Integer(8));
		return hashMap;
	}

  protected void adoptBy(Definition definition)
  {
    for (Iterator components = getWSDLContents().iterator(); components.hasNext();)
    {
      Object child = components.next();
      if (child instanceof WSDLElementImpl)
      {
        ((WSDLElementImpl) child).adoptBy(definition);
      }
    }
  }

  protected boolean isUpdatingDOM()
  {
    return updatingDOM;
  }

  public void elementChanged(Element changedElement)
  {
    if (!isUpdatingDOM())
    {
      if (!isReconciling)
      {
        //System.out.println("**** changeFor " + eClass().getName());
        isReconciling = true;
        reconcile(changedElement);

        WSDLElement theContainer = getContainer();
        if (theContainer != null && theContainer.getElement() == changedElement)
        {
          ((WSDLElementImpl) theContainer).elementChanged(changedElement);
        }

        isReconciling = false;
        traverseToRootForPatching();
      }
      else
      {
        ; //System.out.println("**** cyclic internal reconcile avoided " + eClass().getName());
      }
    }
    else
    {
      ; //System.out.println("**** cyclic DOM reconcile avoided " + eClass().getName());
    }
  }

  protected void handleUnreconciledElement(Element child, Collection remainingModelObjects)
  {
  }

  protected void handleReconciliation(Collection remainingModelObjects)
  {
  }

  /**
   * @deprecated
   * TODO... remove this method!
   */
  public Collection getModelObjects(Object component)
  {
    return getWSDLContents();
  }

  /*
  protected Element getElementForModelObject(Object modelObject)
  {
    Element result = null;
    if (modelObject instanceof Element)
    {
      result = (Element) modelObject;
    }
    else if (modelObject instanceof WSDLElement)
    {
      result = ((WSDLElement) modelObject).getElement();
    }
    return result;
  }
  */

  private Collection getContentNodes(Element changedElement)
  {
    Collection result = new ArrayList();
    for (Node child = changedElement.getFirstChild(); child != null; child = child.getNextSibling())
    {
      if (child.getNodeType() == Node.ELEMENT_NODE)
      {
        result.add(child);
      }
    }
    return result;
  }

  // Some subclasses use this method
  protected QName createQName(Definition definition, String prefixedName)
  {
    // Delegate to the new form to preserve backward compatibility in case someone
    // else calls this method.
    
    return createQName(definition, prefixedName, null);
  }

  /**
   * Creates a QName from a prefixed name. Takes into account locally defined
   * namespace prefixes.
   * 
   * @param definition
   *          the enclosing definition. Must not be null.
   * @param prefixedName
   *          the prefixed name to convert to QName
   * @param element
   *          the enclosing element. May be null in which case the prefix is
   *          only looked up among the ones defined at the definition level.
   * @return the QName equivalent for the given prefixed name, or null if a
   *         namespace prefix cannot be found for the given namespace URI or if
   *         the prefixed name is null.
   */
  protected QName createQName(Definition definition, String prefixedName, Element element)
  {
    QName qname = null;
    if (prefixedName != null)
    {
      int index = prefixedName.indexOf(":"); ////$NON-NLS-1$
      String prefix = (index == -1) ? "" : prefixedName.substring(0, index); //$NON-NLS-1$
      String namespace = definition.getNamespace(prefix);
      
      if (namespace == null && element != null)
      {
        // Try to find a locally defined namespace prefix.
        
        namespace = getNamespaceURIFromPrefix(element, prefix);
      }
      
      if (namespace != null)
      {
        String localPart = prefixedName.substring(index + 1);
        qname = new QName(namespace, localPart);       
      }
    }
    return qname;
  }

  /**
   * Given a prefix and a node, finds the namespace URI pointed to by the
   * prefix. Walks the element containment hierarchy until it finds one or it
   * reaches the document root.
   * 
   * @param node
   *          the starting node
   * @param prefix
   *          the prefix to find an xmlns:prefix=uri for
   * 
   * @return the namespace URI or null if not found
   */
  private static String getNamespaceURIFromPrefix(Node node, String prefix)
  {
    if (node == null || prefix == null)
    {
      return null;
    }

    Node currentNode = node;

    while (currentNode != null && currentNode.getNodeType() == Node.ELEMENT_NODE)
    {
      String namespaceURI = getAttributeNS((Element) currentNode, XSDConstants.XMLNS_URI_2000, prefix);

      if (namespaceURI != null)
      {
        return namespaceURI;
      }
      else
      {
        currentNode = currentNode.getParentNode();
      }
    }

    return null;
  }
  
  /**
   * Retrieves an attribute's value.
   * @param element the containing element.
   * @param namespaceURI the namespace URI.
   * @param localPart the local name.
   * @return the attribute's value if present, or null if not. 
   */
  private static String getAttributeNS(Element element, String namespaceURI, String localPart)
  {
    String attributeValue = null;
    Attr attribute = element.getAttributeNodeNS(namespaceURI, localPart);

    if (attribute != null)
    {
      attributeValue = attribute.getValue();
    }

    return attributeValue;
  }  

  //
  // For reconciliation: Model -> DOM
  //

  public void updateElement(boolean deep)
  {
    if (deep || getElement() == null)
    {
      updateElement();
    }
    else
    {
      changeAttribute(null);
      changeReference(null);
    }
  }

  public void updateElement()
  {
    if (getElement() == null)
    {
      isReconciling = true;
      createElement();
      isReconciling = false;
    }

    changeAttribute(null);
    changeReference(null);

    Object obj = null;
    for (Iterator containments = eClass().getEAllContainments().iterator(); containments.hasNext();)
    {
      EReference eReference = (EReference) containments.next();
      if (eReference == WSDLPackage.eINSTANCE.getXSDSchemaExtensibilityElement_Schema())
      {
        // TBD - This is an instance of XSDSchemaExtensibilityElement and
        // eRefernce is XSDSchema. What do we want to do for update?
      }
      else if (!eReference.isTransient())
      {
        if (eReference.isMany())
        {
          for (Iterator objects = ((Collection) eGet(eReference)).iterator(); objects.hasNext();)
          {
            obj = objects.next();
            if (!(obj instanceof WSDLElement) || obj == null)
            {
              // Skip it. Probably this is Namespace.
            }
            else
            {
              WSDLElement wsdlElement = (WSDLElement) obj;
              //handleElementForAdopt(eReference, wsdlElement);
               ((WSDLElementImpl) wsdlElement).updateElement();
            }
          }
        }
        else
        {
          WSDLElement wsdlElement = (WSDLElement) eGet(eReference);
          if (wsdlElement != null)
          {
            //handleElementForAdopt(eReference,  wsdlElement);
             ((WSDLElementImpl) wsdlElement).updateElement();
          }
        }
      } // end else if
    } // end for
  }

  protected void changeAttribute(EAttribute eAttribute)
  {
    if (eAttribute == WSDLPackage.eINSTANCE.getWSDLElement_Element())
    {
      Element theElement = getElement();
      if (theElement != null && !isReconciling)
      {
        for (Node rootDocument = theElement.getParentNode(); rootDocument != null; rootDocument = rootDocument.getParentNode())
        {
          if (rootDocument.getNodeType() == Node.DOCUMENT_NODE)
          {
            isReconciling = true;
            if (getEnclosingDefinition() == null)
            {
              reconcileAttributes(getElement());
              isReconciling = false;
            }
            else
            {
              reconcile(getElement());
              isReconciling = false;
              traverseToRootForPatching();
            }
            break;
          }
        }
      }
    }

  }

  protected void traverseToRootForPatching()
  {
    if (!isReconciling)
    {
      WSDLElementImpl container = (WSDLElementImpl)getContainer();
      if (container != null)
      {
        container.traverseToRootForPatching();
      }
    }
  }

  protected void reconcile(Element changedElement)
  {
    reconcileAttributes(changedElement);
    reconcileContents(changedElement);
  }

  protected void reconcileAttributes(Element changedElement)
  {
  }

  protected void reconcileContents(Element changedElement)
  {
    List remainingModelObjects = new ArrayList(getWSDLContents());

    Collection contentNodes = getContentNodes(changedElement);

    Element theDocumentationElement = null;
    
    // for each applicable child node of changedElement
    LOOP : for (Iterator i = contentNodes.iterator(); i.hasNext();)
    {
      Element child = (Element) i.next();
      // Set Documentation element if exists
      if (WSDLConstants.DOCUMENTATION_ELEMENT_TAG.equals(child.getLocalName()) &&
          WSDLConstants.isMatchingNamespace(child.getNamespaceURI(), WSDLConstants.WSDL_NAMESPACE_URI))
      {
        // assume the first 'documentation' element is 'the' documentation element
        // 'there can be only one!'
        if (theDocumentationElement == null)
        {  
          theDocumentationElement = child;
        }   
      } 
      // go thru the model objects to collect matching object for reuse
      for (Iterator contents = remainingModelObjects.iterator(); contents.hasNext();)
      {
        Object modelObject = (Object) contents.next();
        if (((WSDLElement) modelObject).getElement() == child)
        {
          contents.remove(); // removes the 'child' Node from the remainingModelObjects list
          continue LOOP;
        }
      }

      // if the documentation element has changed... update it
      //
      if (theDocumentationElement != getDocumentationElement())
      {
        setDocumentationElement(theDocumentationElement);  
      }  
      
      // we haven't found a matching model object for the Node, se we may need to
      // create a new model object
      handleUnreconciledElement(child, remainingModelObjects);
    }

    // now we can remove the remaining model objects
    handleReconciliation(remainingModelObjects);

  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated NOT
   */
  public Definition getEnclosingDefinition()
  {
    if (enclosingDefinition != null)
      return enclosingDefinition;

    // TBD - Revisit
    //EObject c = eContaier(); c != null; c = c.eContainter())
    //{

    for (WSDLElement container = this; container != null; container = ((WSDLElementImpl) container).getContainer())
    {
      if (container instanceof Definition)
      {
        enclosingDefinition = (Definition) container;
        return enclosingDefinition;
      }
    }

    return null;
  }

  /*
  public Definition getRootEnclosingDefinition()
  {
    if (enclosingDefinition == null)
     {
      Resource resource = eResource();
      List contents = resource.getContents();
      if (contents.size() == 1 
          && contents.get(0) instanceof Definition)
        enclosingDefinition = (Definition)contents.get(0);
    } 
    return enclosingDefinition;
  }
  */

  public WSDLElement getContainer()
  {
    return eContainer() instanceof WSDLElement ? (WSDLElement) eContainer() : null;
  }

  protected void niceSetAttribute(Element element, String attribute, String value)
  {
    if (isReconciling)
    {
      //System.out.println("**** cyclic dom attribute writeback avoided " + eClass().getName());
      return;
    }

    if (value == null)
    {
      if (element.hasAttributeNS(null, attribute))
      {
        updatingDOM = true;
        element.removeAttribute(attribute);
        updatingDOM = false;
      }
    }
    else if (!element.hasAttributeNS(null, attribute) || !element.getAttributeNS(null, attribute).equals(value))
    {
      updatingDOM = true;
      element.setAttributeNS(null, attribute, value);
      updatingDOM = false;
    }
  }

  protected String niceCreateNamespaceAttribute(String namespace)
  {
    // Create and return a unique prefix for "namespace."
    return null;
  }

  protected void niceSetAttributeURIValue(Element element, String attribute, String uriList)
  {
    if (isReconciling)
    {
      // System.out.println("**** cyclic dom attribute writeback avoided " + eClass().getName());
      return;
    }

    if (uriList == null)
    {
      updatingDOM = true;
      element.removeAttribute(attribute);
      updatingDOM = false;
    }
    else
    {
      StringBuffer value = new StringBuffer();
      for (StringTokenizer stringTokenizer = new StringTokenizer(uriList, " "); stringTokenizer.hasMoreElements();)
      {
        String uri = stringTokenizer.nextToken();
        String namespace = null;
        String localName = uri;
        int index = uri.lastIndexOf("#");
        if (index != -1)
        {
          if (index > 0)
          {
            namespace = uri.substring(0, index);
          }
          localName = uri.substring(index + 1);
        }
        String qualifier = XSDConstants.lookupQualifier(element, namespace);
        if (qualifier == null)
        {
          qualifier = niceCreateNamespaceAttribute(namespace);
        }

        String qName = qualifier == null || qualifier.length() == 0 ? localName : qualifier + ":" + localName;

        if (value.length() != 0)
        {
          value.append(' ');
        }
        value.append(qName);
      }

      if (!element.hasAttributeNS(null, attribute) || !element.getAttributeNS(null, attribute).equals(value.toString()))
      {
        updatingDOM = true;
        element.setAttributeNS(null, attribute, value.toString());
        updatingDOM = false;
      }
    }
  }

  protected void changeReference(EReference eReference)
  {
  }

  protected Element createElement() // Should I make this abstract?
  {
    return null;
  }

  protected final Element createElement(int nodeType)
  {
    Definition definition = null;
    if (this instanceof Definition)
      definition = (Definition) this;
    else
      definition = getEnclosingDefinition();

    if (definition == null)
      return null;

    Document document = definition.getDocument();
    if (document == null)
      document = ((DefinitionImpl) definition).updateDocument();

    // Retrieve the namespace prefix for the WSDL namespace
    String wsdlNamespace = WSDLConstants.WSDL_NAMESPACE_URI;
    String qualifier = definition.getPrefix(wsdlNamespace);

    Element newElement = document.createElementNS(wsdlNamespace, (qualifier == null ? "" : qualifier + ":") + WSDLConstants.getElementTag(nodeType));

    if (document.getDocumentElement() == null)
      document.appendChild(newElement);

    if (getDocumentationElement() != null)
      newElement.appendChild(document.importNode(getDocumentationElement(), true));

    return newElement;
  }

  public void reconcileReferences(boolean deep)
  {
    if (deep)
    {
      for (Iterator contents = getWSDLContents().iterator(); contents.hasNext();)
      {
        Object content = contents.next();
        if (content instanceof WSDLElementImpl)
        {
          WSDLElementImpl element = (WSDLElementImpl) content;
          element.isReconciling = true;
          element.reconcileReferences(true);
          element.isReconciling = false;
        }
      }
    }
  }
  
  public WSDLElement getBestWSDLElement(List elementPath)
  {
	  WSDLElement result = this;
	  for (Iterator components = getWSDLContents().iterator(); components.hasNext(); )
	  {
		  Object object = components.next();
		  if (object instanceof WSDLElementImpl) {
			  WSDLElementImpl childWSDLElement = (WSDLElementImpl) object;

			  if (elementPath.contains(childWSDLElement.getElement()))
			  {
				  result = childWSDLElement;
				  WSDLElement betterWSDLElement = childWSDLElement.getBestWSDLElement(elementPath);
				  if (betterWSDLElement != null)
				  {
					  result = betterWSDLElement;
				  }

				  if (!considerAllContainsForBestWSDLElement())
				  {
					  break;
				  }
			  }
		  }
	  }

	  return result;
  }

  protected boolean considerAllContainsForBestWSDLElement()
  {
    return false;
  }
  
    public void elementAttributesChanged(Element changedElement)
  {
    if (!isUpdatingDOM())
    {
      if (!isReconciling)
      {
        // System.out.println("**** changeFor " + eClass().getName());
    
        isReconciling = true;
        reconcileAttributes(changedElement);

        WSDLElementImpl theContainer = (WSDLElementImpl)getContainer();
        if (theContainer != null && theContainer.getElement() == changedElement)
        {
          theContainer.elementAttributesChanged(changedElement);
        }

        isReconciling = false;
        traverseToRootForPatching();
      }
      else
      {
        // System.out.println("**** cyclic internal reconcile avoided " + eClass().getName());
      }
    }
    else
    {
      // System.out.println("**** cyclic DOM reconcile avoided " + eClass().getName());
    }
  }

  public void elementContentsChanged(Element changedElement)
  {
    if (!isUpdatingDOM())
    {
      if (!isReconciling)
      {
        // System.out.println("**** changeFor " + eClass().getName());
    
        isReconciling = true;
        reconcileContents(changedElement);

        WSDLElementImpl theContainer = (WSDLElementImpl)getContainer();
        if (theContainer != null && theContainer.getElement() == changedElement)
        {
          theContainer.elementContentsChanged(changedElement);
        }

        isReconciling = false;
        traverseToRootForPatching();
      }
      else
      {
        // System.out.println("**** cyclic internal reconcile avoided " + eClass().getName());
      }
    }
    else
    {
      // System.out.println("**** cyclic DOM reconcile avoided " + eClass().getName());
    }
  }
  
  protected void updatePrefix(Node node, String namespace, String oldPrefix, String newPrefix)
  {
    if ((namespace == null ? node.getNamespaceURI() == null : namespace.equals(node.getNamespaceURI())) &&
          (oldPrefix == null ? node.getPrefix() == null : oldPrefix.equals(node.getPrefix())))
    {
      node.setPrefix(newPrefix);
    }

    for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling())
    {
      updatePrefix(child, namespace, oldPrefix, newPrefix);
    }
  } 

  protected String getNamespace(Element element)
  {
    String name = element.getTagName();
    int index = name.indexOf(":");
    if (index == -1)
      return null;
    else if (getEnclosingDefinition() != null)
      return getEnclosingDefinition().getNamespace(name.substring(0,index));
    else
      return null;
  }
  
  protected String getLocalName(Element element)
  {
    String name = element.getTagName();
    int index = name.indexOf(":");
    if ( index == -1)
      return name;
    else
      return name.substring(index+1);
  }

} //WSDLElementImpl
