/*******************************************************************************
 * 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.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 we're dealing with a documentation element we need to put it first in the list

      if (referencedElement == null && WSDLConstants.nodeType(childElement) == WSDLConstants.DOCUMENTATION && !eReference.isMany())
      {
        // Here we find the first element node in the list, the documentation element needs to go before this element

        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, true);
  }

  /**
   * 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 = null;

      if (element == null)
      {
        namespace = definition.getNamespace(prefix);
      }
      else
      {
        // 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;
    }
    
    if (prefix.length() == 0)
    {
      prefix = "xmlns"; //$NON-NLS-1$
    }

    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.Literals.XSD_SCHEMA_EXTENSIBILITY_ELEMENT__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.Literals.WSDL_ELEMENT__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 (modelObject instanceof WSDLElement)
        {
          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(":"); //$NON-NLS-1$
    String nsPrefix = null;
    if (index != -1)
    {
      nsPrefix = name.substring(0, index);
    }
    else
    {
      nsPrefix = "xmlns"; //$NON-NLS-1$
    }

    String namespaceURI = null;

    // First try to locate the namespace URI in the definition's prefix to namespace map.
    // This will provide backward compatibility for existing clients.

    Definition enclosingDefinition = getEnclosingDefinition();
    if (enclosingDefinition != null)
    {
      namespaceURI = enclosingDefinition.getNamespace(nsPrefix);
    }

    // We did not find it at the top level, try to find a locally defined namespace prefix.

    if (namespaceURI == null)
    {
      namespaceURI = getNamespaceURIFromPrefix(element, nsPrefix);
    }

    return namespaceURI;
  }

  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
