/*******************************************************************************
 * 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, 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 = 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
