/*******************************************************************************
 * Copyright (c) 2001, 2007 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 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;

import com.ibm.icu.util.StringTokenizer;


/**
 * <!-- 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.wst.wsdl.internal.impl.WSDLElementImpl#getDocumentationElement <em>Documentation Element</em>}</li>
 *   <li>{@link org.eclipse.wst.wsdl.internal.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.Literals.WSDL_ELEMENT;
  }

  /**
   * <!-- 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(int featureID, boolean resolve, boolean coreType)
  {
    switch (featureID)
    {
      case WSDLPackage.WSDL_ELEMENT__DOCUMENTATION_ELEMENT:
      return getDocumentationElement();
      case WSDLPackage.WSDL_ELEMENT__ELEMENT:
      return getElement();
    }
    return super.eGet(featureID, resolve, coreType);
  }

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

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

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public boolean eIsSet(int featureID)
  {
    switch (featureID)
    {
      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 super.eIsSet(featureID);
  }

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

    StringBuffer result = new StringBuffer(super.toString());
    result.append(" (documentationElement: "); //$NON-NLS-1$
    result.append(documentationElement);
    result.append(", element: "); //$NON-NLS-1$
    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)
  {
    return createQName(definition, prefixedName, element, false);
  }
  
  /**
   * Creates a QName from a prefixed name. Takes into account locally defined
   * namespace prefixes. Selectively allows null namespace URIs.
   * 
   * @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.
   * @param allowNullNamespaceURI if true and the prefixed name does not have 
   *          a prefix a QName is constructed and returned using 
   *          {@link XMLConstants#NULL_NS_URI} for the namespace URI          
   * @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, boolean allowNullNamespaceURI)
  {
    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 || (allowNullNamespaceURI && prefix.length() == 0))
      {
        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
