/*******************************************************************************
 * Copyright (c) 2001, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.xsd.ui.internal.util;

import java.util.ArrayList;

import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
import org.eclipse.xsd.util.XSDConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

public class XSDDOMHelper
{
  public static final int LENGTH_FACET        =  1;
  public static final int MIN_LENGTH_FACET    =  2;
  public static final int MAX_LENGTH_FACET    =  3;
  public static final int PATTERN_FACET       =  4;
  public static final int ENUM_FACET          =  5;
  public static final int WHITE_SPACE_FACET   =  6;

  public static final int MAX_INCLUSIVE_FACET =  7;
  public static final int MAX_EXCLUSIVE_FACET =  8;
  public static final int MIN_INCLUSIVE_FACET =  9;
  public static final int MIN_EXCLUSIVE_FACET =  10;

  public static final int TOTAL_DIGITS_FACET     = 11;
  public static final int FRACTION_DIGITS_FACET  = 12;

  public static final int N_FACETS            = 13;

  public static String[][] dataType =
  {
    //
    // Table format:
    // Type
    //  Length, MinLength, MaxLength, Pattern, Enumeration,whiteSpace
    //  MaxInclusive, MaxExclusive, MinInclusive, MinExclusive, TotalDigits, FractionDigits
    //

    // 0
    { "anySimpleType",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 1
    { "anyType",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },


    // 2
    { "anyURI",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 3
    { "base64Binary",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 4
    { "boolean",
        "N", "N", "N", "Y", "N", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 5
    { "byte",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 6
    { "date",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 7
    { "dateTime",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 8
    { "decimal",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },


    // 9
    { "double",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 10
    { "duration",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 11
    { "ENTITY",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 12
    { "ENTITIES",
        "Y", "Y", "Y", "N", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 13
    { "float",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 14
    { "gDay",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 15
    { "gMonth",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 16
    { "gMonthDay",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 17
    { "gYear",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 18
    { "gYearMonth",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 19
    { "hexBinary",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 20
    { "ID",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 21
    { "IDREF",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 22
    { "IDREFS",
        "Y", "Y", "Y", "N", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 23
    { "int",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 24
    { "integer",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 25
    { "language",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 26
    { "long",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 27
    { "Name",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },


    // 28
    { "NCName",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 29
    { "negativeInteger",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 30
    { "NMTOKEN",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 31
    { "NMTOKENS",
        "Y", "Y", "Y", "N", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 32
    { "nonNegativeInteger",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 33
    { "nonPositiveInteger",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 34
    { "normalizedString",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",

    },

    // 35
    { "NOTATION",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",

    },

    // 36
    { "positiveInteger",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 37
    { "QName",
        "N", "N", "N", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 38
    { "short",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 39
    { "string",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 40
    { "time",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "N", "N",
    },

    // 41
    { "token",
        "Y", "Y", "Y", "Y", "Y", "Y",
        "N", "N", "N", "N", "N", "N",
    },

    // 42
    { "unsignedByte",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 43
    { "unsignedInt",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 44
    { "unsignedLong",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

    // 45
    { "unsignedShort",
        "N", "N", "N", "Y", "Y", "Y",
        "Y", "Y", "Y", "Y", "Y", "Y",
    },

  };

  public static String XMLSchemaURI = "http://www.w3.org/2001/XMLSchema";

  /**
   * Constructor for XSDDOMHelper.
   */
  public XSDDOMHelper()
  {
    super();
  }

  public Node getChildNode(Element parent, String childName)
  {
/*    NodeList nodeList = parent.getElementsByTagNameNS(XMLSchemaURI, childName);
    if (nodeList.getLength() > 0)
      return nodeList.item(0);
    return null;
*/
    NodeList list = null;
    if (parent != null)
    {
      list = parent.getChildNodes();
    }
   
    String name = null;
    if (list != null)
    {
      // Performance issue perhaps?
      for (int i = 0; i < list.getLength(); i++)
      {
        if (list.item(i) instanceof Element)
        {
          if (list.item(i).getLocalName().equals(childName))
          {
            return list.item(i);
          }
        }
      }
    }
    return null;
  }

  public static String SIMPLE_TYPE = "Simple";
  public static String USER_SIMPLE_TYPE = "simpleType";
  public static String USER_COMPLEX_TYPE = "complexType";
/*
  public void setElementType(Element element, String type)
  {
    Document doc = element.getOwnerDocument();
    if (type.equals(SIMPLE_TYPE))
    {
      removeChild(element, USER_SIMPLE_TYPE);
      removeChild(element, USER_COMPLEX_TYPE);
      element.setAttribute("type","xsd:string");
      return;
    }
    else if (type.equals(USER_SIMPLE_TYPE))
    {
      removeChild(element, USER_COMPLEX_TYPE);
    }
    else
    {
      removeChild(element, USER_SIMPLE_TYPE);
    }
    element.removeAttribute("type");
    element.appendChild(doc.createElement("xsd:"+type));
  }

  public String getElementType(Element element)
  {
    String tagName = element.getLocalName();

    if (tagName.equals(XSDConstants.ELEMENT_ELEMENT_TAG) ||
        tagName.equals(XSDConstants.ATTRIBUTE_ELEMENT_TAG))
    {
      if (element.hasAttribute("type"))
      {
        return SIMPLE_TYPE;
      }
      NodeList nodes = element.getElementsByTagNameNS(XMLSchemaURI, USER_SIMPLE_TYPE);
      if (nodes.getLength() > 0)
      {
        return USER_SIMPLE_TYPE;
      }
      nodes = element.getElementsByTagNameNS(XMLSchemaURI, USER_COMPLEX_TYPE);
      if (nodes.getLength() > 0)
      {
        return USER_COMPLEX_TYPE;
      }
    }
    return "";
  }
*/
  public void removeDerivedByElement(Element element)
  {
    removeChild(element, XSDConstants.RESTRICTION_ELEMENT_TAG);
    removeChild(element, XSDConstants.EXTENSION_ELEMENT_TAG);
  }

  public String getBaseType(Element element) // for SimpleContent and ComplexContent
  {
    Node restrictionChild = getChildNode(element, "restriction");
    Node extensionChild = getChildNode(element, "extension");
    String baseType = "";
    if (restrictionChild != null)
    {
      if (restrictionChild instanceof Element)
      {
        baseType = ((Element)restrictionChild).getAttribute("base");
//        String prefix = element.getPrefix();
//        if (prefix != null && prefix.length() > 0)
//        {
//          baseType = baseType.substring(baseType.indexOf(prefix) + prefix.length() + 1);
//        }
      }
    }
    else if (extensionChild != null) // should be one or the other
    {
      if (extensionChild instanceof Element)
      {
        baseType = ((Element)extensionChild).getAttribute("base");
//        String prefix = element.getPrefix();
//        if (prefix != null && prefix.length() > 0)
//        {
//          baseType = baseType.substring(baseType.indexOf(prefix) + prefix.length() + 1);
//        }
      }
    }
    return baseType;
  }

  public void setDerivedByBaseType(Element element, String derivedByType, String type)
  {
    Document doc = element.getOwnerDocument();

    Element derivedByElement = getDerivedByElement(element);
    if (derivedByElement != null)
    {
      derivedByElement.setAttribute("base", type);
    }
    else  // there really should be one already...base is required.
    {
      Element newElement = doc.createElement(derivedByType);
      newElement.setAttribute("base", type);
      element.appendChild(newElement);
    }
  }

  public void changeDerivedByType(Element element, String derivedByType, String type)
  {
    Document doc = element.getOwnerDocument();

    String prefix = element.getPrefix();
    prefix = prefix == null ? "" : prefix + ":";

    Element derivedByElement = getDerivedByElement(element);
    
    if (derivedByElement != null && derivedByElement.getLocalName().equals(derivedByType))
    {
    	return; // it's already the derived by type
    }
    Element newNode;
  	if (derivedByType.equals("restriction"))
  	{
    	newNode = doc.createElementNS(XSDDOMHelper.XMLSchemaURI, prefix + XSDConstants.RESTRICTION_ELEMENT_TAG);
    }
    else
    {
    	newNode = doc.createElementNS(XSDDOMHelper.XMLSchemaURI, prefix + XSDConstants.EXTENSION_ELEMENT_TAG);
    }
	
    newNode.setAttribute("base", type);

    if (derivedByElement != null)
    {
      if (derivedByElement.hasChildNodes())
      {        
        NodeList nodes = derivedByElement.getChildNodes();
        // use clones so we don't have a refresh problem
        for (int i = 0; i < nodes.getLength(); i++)
        {
          Node node = nodes.item(i);       
          newNode.appendChild(node.cloneNode(true));
        }
      }
	  element.replaceChild(newNode, derivedByElement);
    }
    else 
	{
		Element parent = (Element) element.getParentNode();				// get back to complexType
        NodeList nodes = parent.getChildNodes();
		ArrayList nodeSaveList = new ArrayList();
		
		// save children. (nodes turns out to be the same object as parent;
		// deleting them from parent will delete them from nodes.)
        for (int i = 0; i < nodes.getLength(); i++)			
        {
          Node node = nodes.item(i);      
		  nodeSaveList.add(node);
        }

        // remove children so we can surround them by complexContent
        for (int i = 0; i < nodeSaveList.size(); i++)			
        {
          Node node = (Node) nodeSaveList.get(i);      
          parent.removeChild(node);
        }
		
		// build a complexContent element
		Element complexContent = doc.createElementNS(XSDDOMHelper.XMLSchemaURI, prefix + XSDConstants.COMPLEXCONTENT_ELEMENT_TAG);
		parent.appendChild(complexContent);					// insert into complexType
		complexContent.appendChild(newNode);				// insert derivation type
        for (int i = 0; i < nodeSaveList.size(); i++)			// insert children previously of complexType
        {
          Node node = (Node) nodeSaveList.get(i);       
          newNode.appendChild(node.cloneNode(true));
        }
		
		parent.appendChild(complexContent);
		formatChild(complexContent);
    }
  }

  public void setSimpleContentType(Element element, String type)
  {
    String contentTypeName = element.getLocalName();

    if (contentTypeName.equals(XSDConstants.UNION_ELEMENT_TAG))
    {
      element.setAttribute(XSDConstants.MEMBERTYPES_ATTRIBUTE, type);
    }
    else if (contentTypeName.equals(XSDConstants.LIST_ELEMENT_TAG))
    {
      element.setAttribute(XSDConstants.ITEMTYPE_ATTRIBUTE, type);
    }
    else if (contentTypeName.equals(XSDConstants.RESTRICTION_ELEMENT_TAG))
    {
      element.setAttribute(XSDConstants.BASE_ATTRIBUTE, type);
    }
  }

  public void removeSimpleTypeContent(Element element)
  {
    String contentTypeName = element.getLocalName();
    if (contentTypeName.equals(XSDConstants.UNION_ELEMENT_TAG))
    {
      element.removeAttribute(XSDConstants.MEMBERTYPES_ATTRIBUTE);
    }
    else if (contentTypeName.equals(XSDConstants.LIST_ELEMENT_TAG))
    {
      element.removeAttribute(XSDConstants.ITEMTYPE_ATTRIBUTE);
    }
    else if (contentTypeName.equals(XSDConstants.RESTRICTION_ELEMENT_TAG))
    {
      element.removeAttribute(XSDConstants.BASE_ATTRIBUTE);
    }
  }

  public String getDerivedByName(Element element)
  {
    Node restrictionChild = getChildNode(element, "restriction");
    Node extensionChild = getChildNode(element, "extension");
    if (restrictionChild != null)
    {
      return "restriction";
    }
    if (extensionChild != null)
    {
      return "extension";
    }
    return "";
  }

  /**
   * Get the derived by node given the complexContent or simpleContent node
   */
  public Element getDerivedByElement(Element element)
  {
    Node restrictionChild = getChildNode(element, "restriction");
    Node extensionChild = getChildNode(element, "extension");
    if (restrictionChild != null)
    {
      if (restrictionChild instanceof Element)
      {
        return (Element)restrictionChild;
      }
    }
    
    if (extensionChild != null)
    {
      if (extensionChild instanceof Element)
      {
        return (Element)extensionChild;
      }
    }
    return null;
  }

  /**
   * Get the derived by node given the ComplexType node
   * Returns the first one, if say, the INVALID schema has more than one
   */
  public Element getDerivedByElementFromComplexType(Element element)
  {
    NodeList nl = element.getChildNodes();
    int childNumber = 0;
    int j = 0;
    for (j = 0; j < nl.getLength(); j++)
    {
      Node aNode = nl.item(j);
      if (inputEquals(aNode, XSDConstants.COMPLEXCONTENT_ELEMENT_TAG, false))
      {
        break; 
      }
      else if (inputEquals(aNode, XSDConstants.SIMPLECONTENT_ELEMENT_TAG, false))
      {
        break;
      }
    }
    Element derivedByNode = getDerivedByElement((Element)nl.item(j));
    return derivedByNode;
  }

  /**
   * Get the content model given the ComplexType node
   * Returns the first one, if say, the INVALID schema has more than one
   */
  public Element getContentModelFromParent(Element element)
  {
    NodeList nl = element.getChildNodes();
    int childNumber = 0;
    int j = 0;
    boolean modelExists = false;
    int length = nl.getLength();
    for (j = 0; j < length; j++)
    {
      Node aNode = nl.item(j);
      if (inputEquals(aNode, XSDConstants.COMPLEXCONTENT_ELEMENT_TAG, false))
      {
        modelExists = true;
        break; 
      }
      else if (inputEquals(aNode, XSDConstants.SIMPLECONTENT_ELEMENT_TAG, false))
      {
        modelExists = true;
        break;
      }
      else if (inputEquals(aNode, XSDConstants.SEQUENCE_ELEMENT_TAG, false))
      {
        modelExists = true;
        break;
      }
      else if (inputEquals(aNode, XSDConstants.CHOICE_ELEMENT_TAG, false))
      {
        modelExists = true;
        break;
      }
      else if (inputEquals(aNode, XSDConstants.ALL_ELEMENT_TAG, false))
      {
        modelExists = true;
        break;
      }
    }
    if (!modelExists)
    {
      return null;
    }

    Element derivedByNode = (Element)nl.item(j);
    return derivedByNode;
  }

  /**
   * 
   */
  public void changeContentModel(Element complexTypeElement, String contentModel, Element sequenceChoiceOrAllElement)
  {
    Document doc = complexTypeElement.getOwnerDocument();

    String prefix = complexTypeElement.getPrefix();
    prefix = prefix == null ? "" : prefix + ":";
    
    Element contentModelElement = getContentModelFromParent(complexTypeElement);

    if (contentModelElement.getLocalName().equals(contentModel))
    {
      return; // it's already the content model 
    }
    Element newNode;
    newNode = doc.createElementNS(XSDDOMHelper.XMLSchemaURI, prefix + contentModel);

    if (contentModelElement.hasChildNodes())
    {        
      NodeList nodes = contentModelElement.getChildNodes();
      // use clones so we don't have a refresh problem
      for (int i = 0; i < nodes.getLength(); i++)
      {
        Node node = nodes.item(i);
        if (node instanceof Element)
        {
          if (node.getLocalName().equals(XSDConstants.ANNOTATION_ELEMENT_TAG))
          {
            if (!(XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.SEQUENCE_ELEMENT_TAG, false) ||
                XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.CHOICE_ELEMENT_TAG, false) ||
                XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.ALL_ELEMENT_TAG, false)))
            {
              newNode.appendChild(node.cloneNode(true));
            }
          }
          else if (node.getLocalName().equals(XSDConstants.RESTRICTION_ELEMENT_TAG) ||
                    node.getLocalName().equals(XSDConstants.EXTENSION_ELEMENT_TAG))
          {
            newNode.appendChild(node.cloneNode(true));
            if (sequenceChoiceOrAllElement != null)
            {
              node.appendChild(sequenceChoiceOrAllElement);
            }
          }
          else
          {
            removeNodeAndWhitespace(node);
          }
        }
        else
        {
          newNode.appendChild(node.cloneNode(true)); 
        }
      }
    }
    complexTypeElement.replaceChild(newNode, contentModelElement);
  }

  public Element cloneElement(Element parent, Element sourceNode)
  {
    Document doc = parent.getOwnerDocument();
    String prefix = parent.getPrefix();
    prefix = prefix == null ? "" : prefix + ":";
    
    Element newNode = doc.createElementNS(XSDDOMHelper.XMLSchemaURI, prefix + sourceNode.getLocalName());

    if (sourceNode.hasChildNodes())
    {        
      NodeList nodes = sourceNode.getChildNodes();
      // use clones so we don't have a refresh problem
      for (int i = 0; i < nodes.getLength(); i++)
      {
        Node node = nodes.item(i);
        newNode.appendChild(node.cloneNode(true));
      }
    }
    return newNode;
//    parent.replaceChild(newNode, sourceNode);
  }

  public boolean hasElementChildren(Element parentNode)
  {
    boolean hasChildrenElements = false;
    if (parentNode != null && parentNode.hasChildNodes())
    {
      NodeList nodes = parentNode.getChildNodes();
      for (int i = 0; i < nodes.getLength(); i++)
      {
        if (nodes.item(i) instanceof Element)
        {
          hasChildrenElements = true;
          break;
        }
      }
    }
    return hasChildrenElements;
  }

  public void removeChild(Element node, String childName)
  {
    Node child = getChildNode(node,childName);
    if (child != null)
    {
      node.removeChild(child);
    }
  }

  public static boolean isFacet(Object obj)
  {
    if (XSDDOMHelper.inputEquals(obj, XSDConstants.LENGTH_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.MINLENGTH_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.MAXLENGTH_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.WHITESPACE_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.MAXINCLUSIVE_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.MAXEXCLUSIVE_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.MININCLUSIVE_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.MINEXCLUSIVE_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.TOTALDIGITS_ELEMENT_TAG, false) ||
        XSDDOMHelper.inputEquals(obj, XSDConstants.FRACTIONDIGITS_ELEMENT_TAG, false))
    {
      return true;
    }
    return false;
  }

  public static void removeNodeAndWhitespace(Node node)
  {
    Node parentNode = node.getParentNode();
    
    Node nextElement = getNextElementNode(node);
    Node previousElement = getPreviousElementNode(node);

    Node nextSibling = node.getNextSibling();
    if (nextSibling instanceof Text)
    {
      parentNode.removeChild(nextSibling);
    }
    Node previousSibling = node.getPreviousSibling();

		parentNode.removeChild(node);

    if (nextElement != null)
    {
			formatChild(nextElement);
    }

		if (previousElement != null)
		{
			formatChild(previousElement);
		}
  }

	public static void formatChild(Node child)
	{
    if (child instanceof IDOMNode)
    {
      IDOMModel model = ((IDOMNode)child).getModel();
      try
      {
        // tell the model that we are about to make a big model change
        model.aboutToChangeModel();
        
	      IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
		    formatProcessor.formatNode(child);
      }
      finally
      {
        // tell the model that we are done with the big model change
        model.changedModel(); 
      }
    }
  }
  
  public static Node getLastElementNode(Node parent)
  {
    Node lastChild = parent.getLastChild();
    
    while (!(lastChild instanceof Element) && lastChild != null)
    {
      lastChild = lastChild.getPreviousSibling();
    }
    return lastChild;
  }

  public static Node getNextElementNode(Node node)
  {
    Node next = node.getNextSibling();
    
    while (!(next instanceof Element) && next != null)
    {
      next = next.getNextSibling();
    }
    if (next instanceof Text)
    {
    	return null;
    }
    return next;
  }

	public static Node getPreviousElementNode(Node node)
	{
		Node previous = node.getPreviousSibling();
    
		while (!(previous instanceof Element) && previous != null)
		{
			previous = previous.getPreviousSibling();
		}
    if (previous instanceof Text)
    {
      return null;
    }
    return previous;
	}

  public static void moveNode(Node referenceNode, Node nodeToMove, boolean isBefore)
  {
    // this assumes that the referenceNode and node to move have the same parent
    Node parent = referenceNode.getParentNode();

    // Get reference nodes next and previous text strings
    String referenceNodeNextString = "";
    String referenceNodePreviousString = "";
    if (referenceNode != null)
    {
      Node referenceNodeNextSibling = referenceNode.getNextSibling();
      Node referenceNodePreviousSibling = referenceNode.getPreviousSibling();
      if (referenceNodeNextSibling instanceof Text)
      {
        referenceNodeNextString = ((Text)referenceNodeNextSibling).getData();
      }
      if (referenceNodePreviousSibling instanceof Text)
      {
        referenceNodePreviousString = ((Text)referenceNodePreviousSibling).getData();
      }
    }
    // Get the dragged node's next and previous text strings
    Node nodeToMoveNextSibling = nodeToMove.getNextSibling();
    Node nodeToMovePreviousSibling = nodeToMove.getPreviousSibling();
    Node nodeToMoveNextText = null;
    String nodeToMoveNextString = "";
    String nodeToMovePreviousString = "";
    if (nodeToMoveNextSibling instanceof Text)
    {
      nodeToMoveNextText = (Text)nodeToMoveNextSibling;
      nodeToMoveNextString = ((Text)nodeToMoveNextSibling).getData();
    }
    if (nodeToMovePreviousSibling instanceof Text)
    {
      nodeToMovePreviousString = ((Text)nodeToMovePreviousSibling).getData();
    }

    // Get the last element's next and previous text strings
    Node lastElement = getLastElementNode(parent);
    Node lastElementNextSibling = lastElement.getNextSibling();
    Node lastElementPreviousSibling = lastElement.getPreviousSibling();
    String lastElementNextString = "";
    String lastElementPreviousString = "";		
    if (lastElementNextSibling instanceof Text)
    {
      lastElementNextString = ((Text)lastElementNextSibling).getData();
    }
    if (lastElementPreviousSibling instanceof Text)
    {
      lastElementPreviousString = ((Text)lastElementPreviousSibling).getData();
    }

    boolean isLastElement = false; // whether the last element is dragged/moved
    if (lastElement == nodeToMove)
    {
      isLastElement = true;
    }
		
    // defect 221056 this test is required or else the node will
    // be removed from the tree and the insert will fail
    if (referenceNode != nodeToMove)
    {
      parent.removeChild(nodeToMove);
      if (referenceNode != null)
      {
        if (!isBefore)
        {
          referenceNode = getNextElementNode(referenceNode);
//        referenceNode = referenceNode.getNextSibling();
        }
      }

      if (referenceNode != null)
      {
        insertBefore(nodeToMove, referenceNode);
      }
      else
      {
        parent.appendChild(nodeToMove);
      }

      Node newLastElement = getLastElementNode(parent);
      if (referenceNode != null)
      {
        if (referenceNode != newLastElement) 
        {
          if (!isLastElement)
          {
            setTextData(referenceNode, nodeToMoveNextString, nodeToMovePreviousString);
          }
        }
        setTextData(nodeToMove, referenceNodeNextString, referenceNodePreviousString);
      }
      // Remove the empty space left by the dragged node
      if (nodeToMoveNextText != null)
      {
    	  parent.removeChild(nodeToMoveNextText);
      }
      // special case for the last element
      if ((newLastElement == nodeToMove) || isLastElement)
      {
        setTextData(newLastElement, lastElementNextString, lastElementPreviousString);
      }
    }
  }

  public static void setTextData(Node target, String nextText, String previousText)
  {
    Node parent = target.getParentNode();
    Node nextSibling = target.getNextSibling();
    Node previousSibling = target.getPreviousSibling();
    if (nextSibling instanceof Text)
    {
      ((Text)nextSibling).setData(nextText);	
    }
    if (nextSibling == null || nextSibling instanceof Element)
    {
      Text textNode = parent.getOwnerDocument().createTextNode("");
      textNode.setData(nextText);
      if (nextSibling != null)
      {
        parent.insertBefore(textNode, nextSibling);
      }
      else
      {
        parent.insertBefore(textNode, getNextElementNode(target));
      }
    }				

    if (previousSibling instanceof Text)
    {
      ((Text)previousSibling).setData(previousText);
    }
    if (previousSibling == null || previousSibling instanceof Element)
    {
      Text textNode = parent.getOwnerDocument().createTextNode("");
      textNode.setData(previousText);
      parent.insertBefore(textNode, target);
    }				
  }

  public static void insertBefore(Node nodeToInsert, Node referenceNode)
  {
    // this assumes that the referenceNode and node to move have the same parent
    Node parent = referenceNode.getParentNode();

    Node previousSibling = referenceNode.getPreviousSibling();
    parent.insertBefore(nodeToInsert, referenceNode);
  }

  public static boolean inputEquals(Object input, String tagname, boolean isRef)
  {
    if (input instanceof Element)
    {
      Element element = (Element) input;
      if (element.getLocalName().equals(tagname))
      {
        boolean refPresent = element.hasAttribute("ref");

        return refPresent == isRef;
      }
    }
    return false;
  }

  public static void updateElementToNotAnonymous(Element element)
  {
    if (element != null)
    {
      NodeList children = element.getChildNodes();
      if (children != null)
      {
        for (int i = 0; i < children.getLength(); i++)
        {
          Node node = (Node)children.item(i);
          if (node instanceof Element)
          {
            if (node.getLocalName().equals(XSDConstants.SIMPLETYPE_ELEMENT_TAG) ||
                node.getLocalName().equals(XSDConstants.COMPLEXTYPE_ELEMENT_TAG))
            {
              XSDDOMHelper.removeNodeAndWhitespace(node);
              i=0;
            }
          }
        }
      }
    }
  }
  
  public static boolean isAttributeRef(Element ct, String attrName, String ns)
  {
    NodeList list = ct.getChildNodes();
    int length = list.getLength();
    for (int i = 0; i < length; i++)
    {
      if (list.item(i) instanceof Element)
      {
        Element aChild = (Element)list.item(i);
        if (aChild.getLocalName().equals(XSDConstants.ATTRIBUTE_ELEMENT_TAG))
        {
          if (aChild.hasAttribute(XSDConstants.REF_ATTRIBUTE))
          {
            String refValue = aChild.getAttribute(XSDConstants.REF_ATTRIBUTE);
            if (refValue.equals(attrName))
            {
              return true;
            }
          }
        }
      }
      
    }
    
    return false;
  }
}
