/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ide.eclipse.adt.internal.editors.uimodel;

import static com.android.SdkConstants.ANDROID_PKG_PREFIX;
import static com.android.SdkConstants.ANDROID_SUPPORT_PKG_PREFIX;
import static com.android.SdkConstants.ATTR_CLASS;
import static com.android.SdkConstants.ID_PREFIX;
import static com.android.SdkConstants.NEW_ID_PREFIX;

import com.android.SdkConstants;
import com.android.annotations.VisibleForTesting;
import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.common.resources.platform.AttributeInfo;
import com.android.ide.common.xml.XmlAttributeSortOrder;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor.Mandatory;
import com.android.ide.eclipse.adt.internal.editors.descriptors.IUnknownDescriptorProvider;
import com.android.ide.eclipse.adt.internal.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.CustomViewDescriptorService;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.adt.internal.editors.otherxml.descriptors.OtherXmlDescriptors;
import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener.UiUpdateState;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.utils.SdkUtils;
import com.android.utils.XmlUtils;

import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.xml.core.internal.document.ElementImpl;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Represents an XML node that can be modified by the user interface in the XML editor.
 * <p/>
 * Each tree viewer used in the application page's parts needs to keep a model representing
 * each underlying node in the tree. This interface represents the base type for such a node.
 * <p/>
 * Each node acts as an intermediary model between the actual XML model (the real data support)
 * and the tree viewers or the corresponding page parts.
 * <p/>
 * Element nodes don't contain data per se. Their data is contained in their attributes
 * as well as their children's attributes, see {@link UiAttributeNode}.
 * <p/>
 * The structure of a given {@link UiElementNode} is declared by a corresponding
 * {@link ElementDescriptor}.
 * <p/>
 * The class implements {@link IPropertySource}, in order to fill the Eclipse property tab when
 * an element is selected. The {@link AttributeDescriptor} are used property descriptors.
 */
@SuppressWarnings("restriction") // XML model
public class UiElementNode implements IPropertySource {

    /** List of prefixes removed from android:id strings when creating short descriptions. */
    private static String[] ID_PREFIXES = {
        "@android:id/", //$NON-NLS-1$
        NEW_ID_PREFIX, ID_PREFIX, "@+", "@" }; //$NON-NLS-1$ //$NON-NLS-2$

    /** The element descriptor for the node. Always present, never null. */
    private ElementDescriptor mDescriptor;
    /** The parent element node in the UI model. It is null for a root element or until
     *  the node is attached to its parent. */
    private UiElementNode mUiParent;
    /** The {@link AndroidXmlEditor} handling the UI hierarchy. This is defined only for the
     *  root node. All children have the value set to null and query their parent. */
    private AndroidXmlEditor mEditor;
    /** The XML {@link Document} model that is being mirror by the UI model. This is defined
     *  only for the root node. All children have the value set to null and query their parent. */
    private Document mXmlDocument;
    /** The XML {@link Node} mirror by this UI node. This can be null for mandatory UI node which
     *  have no corresponding XML node or for new UI nodes before their XML node is set. */
    private Node mXmlNode;
    /** The list of all UI children nodes. Can be empty but never null. There's one UI children
     *  node per existing XML children node. */
    private ArrayList<UiElementNode> mUiChildren;
    /** The list of <em>all</em> UI attributes, as declared in the {@link ElementDescriptor}.
     *  The list is always defined and never null. Unlike the UiElementNode children list, this
     *  is always defined, even for attributes that do not exist in the XML model - that's because
     *  "missing" attributes in the XML model simply mean a default value is used. Also note that
     *  the underlying collection is a map, so order is not respected. To get the desired attribute
     *  order, iterate through the {@link ElementDescriptor}'s attribute list. */
    private HashMap<AttributeDescriptor, UiAttributeNode> mUiAttributes;
    private HashSet<UiAttributeNode> mUnknownUiAttributes;
    /** A read-only view of the UI children node collection. */
    private List<UiElementNode> mReadOnlyUiChildren;
    /** A read-only view of the UI attributes collection. */
    private Collection<UiAttributeNode> mCachedAllUiAttributes;
    /** A map of hidden attribute descriptors. Key is the XML name. */
    private Map<String, AttributeDescriptor> mCachedHiddenAttributes;
    /** An optional list of {@link IUiUpdateListener}. Most element nodes will not have any
     *  listeners attached, so the list is only created on demand and can be null. */
    private List<IUiUpdateListener> mUiUpdateListeners;
    /** A provider that knows how to create {@link ElementDescriptor} from unmapped XML names.
     *  The default is to have one that creates new {@link ElementDescriptor}. */
    private IUnknownDescriptorProvider mUnknownDescProvider;
    /** Error Flag */
    private boolean mHasError;

    /**
     * Creates a new {@link UiElementNode} described by a given {@link ElementDescriptor}.
     *
     * @param elementDescriptor The {@link ElementDescriptor} for the XML node. Cannot be null.
     */
    public UiElementNode(ElementDescriptor elementDescriptor) {
        mDescriptor = elementDescriptor;
        clearContent();
    }

    @Override
    public String toString() {
      return String.format("%s [desc: %s, parent: %s, children: %d]",         //$NON-NLS-1$
              this.getClass().getSimpleName(),
              mDescriptor,
              mUiParent != null ? mUiParent.toString() : "none",              //$NON-NLS-1$
                      mUiChildren != null ? mUiChildren.size() : 0
      );
    }

    /**
     * Clears the {@link UiElementNode} by resetting the children list and
     * the {@link UiAttributeNode}s list.
     * Also resets the attached XML node, document, editor if any.
     * <p/>
     * The parent {@link UiElementNode} node is not reset so that it's position
     * in the hierarchy be left intact, if any.
     */
    /* package */ void clearContent() {
        mXmlNode = null;
        mXmlDocument = null;
        mEditor = null;
        clearAttributes();
        mReadOnlyUiChildren = null;
        if (mUiChildren == null) {
            mUiChildren = new ArrayList<UiElementNode>();
        } else {
            // We can't remove mandatory nodes, we just clear them.
            for (int i = mUiChildren.size() - 1; i >= 0; --i) {
                removeUiChildAtIndex(i);
            }
        }
    }

    /**
     * Clears the internal list of attributes, the read-only cached version of it
     * and the read-only cached hidden attribute list.
     */
    private void clearAttributes() {
        mUiAttributes = null;
        mCachedAllUiAttributes = null;
        mCachedHiddenAttributes = null;
        mUnknownUiAttributes = new HashSet<UiAttributeNode>();
    }

    /**
     * Gets or creates the internal UiAttributes list.
     * <p/>
     * When the descriptor derives from ViewElementDescriptor, this list depends on the
     * current UiParent node.
     *
     * @return A new set of {@link UiAttributeNode} that matches the expected
     *         attributes for this node.
     */
    private HashMap<AttributeDescriptor, UiAttributeNode> getInternalUiAttributes() {
        if (mUiAttributes == null) {
            AttributeDescriptor[] attrList = getAttributeDescriptors();
            mUiAttributes = new HashMap<AttributeDescriptor, UiAttributeNode>(attrList.length);
            for (AttributeDescriptor desc : attrList) {
                UiAttributeNode uiNode = desc.createUiNode(this);
                if (uiNode != null) {  // Some AttributeDescriptors do not have UI associated
                    mUiAttributes.put(desc, uiNode);
                }
            }
        }
        return mUiAttributes;
    }

    /**
     * Computes a short string describing the UI node suitable for tree views.
     * Uses the element's attribute "android:name" if present, or the "android:label" one
     * followed by the element's name if not repeated.
     *
     * @return A short string describing the UI node suitable for tree views.
     */
    public String getShortDescription() {
        String name = mDescriptor.getUiName();
        String attr = getDescAttribute();
        if (attr != null) {
            // If the ui name is repeated in the attribute value, don't use it.
            // Typical case is to avoid ".pkg.MyActivity (Activity)".
            if (attr.contains(name)) {
                return attr;
            } else {
                return String.format("%1$s (%2$s)", attr, name);
            }
        }

        return name;
    }

    /** Returns the key attribute that can be used to describe this node, or null */
    private String getDescAttribute() {
        if (mXmlNode != null && mXmlNode instanceof Element && mXmlNode.hasAttributes()) {
            // Application and Manifest nodes have a special treatment: they are unique nodes
            // so we don't bother trying to differentiate their strings and we fall back to
            // just using the UI name below.
            Element elem = (Element) mXmlNode;

            String attr = _Element_getAttributeNS(elem,
                                SdkConstants.NS_RESOURCES,
                                AndroidManifestDescriptors.ANDROID_NAME_ATTR);
            if (attr == null || attr.length() == 0) {
                attr = _Element_getAttributeNS(elem,
                                SdkConstants.NS_RESOURCES,
                                AndroidManifestDescriptors.ANDROID_LABEL_ATTR);
            } else if (mXmlNode.getNodeName().equals(SdkConstants.VIEW_FRAGMENT)) {
                attr = attr.substring(attr.lastIndexOf('.') + 1);
            }
            if (attr == null || attr.length() == 0) {
                attr = _Element_getAttributeNS(elem,
                                SdkConstants.NS_RESOURCES,
                                OtherXmlDescriptors.PREF_KEY_ATTR);
            }
            if (attr == null || attr.length() == 0) {
                attr = _Element_getAttributeNS(elem,
                                null, // no namespace
                                SdkConstants.ATTR_NAME);
            }
            if (attr == null || attr.length() == 0) {
                attr = _Element_getAttributeNS(elem,
                                SdkConstants.NS_RESOURCES,
                                SdkConstants.ATTR_ID);

                if (attr != null && attr.length() > 0) {
                    for (String prefix : ID_PREFIXES) {
                        if (attr.startsWith(prefix)) {
                            attr = attr.substring(prefix.length());
                            break;
                        }
                    }
                }
            }
            if (attr != null && attr.length() > 0) {
                return attr;
            }
        }

        return null;
    }

    /**
     * Computes a styled string describing the UI node suitable for tree views.
     * Similar to {@link #getShortDescription()} but styles the Strings.
     *
     * @return A styled string describing the UI node suitable for tree views.
     */
    public StyledString getStyledDescription() {
        String uiName = mDescriptor.getUiName();

        // Special case: for <view>, show the class attribute value instead.
        // This is done here rather than in the descriptor since this depends on
        // node instance data.
        if (SdkConstants.VIEW_TAG.equals(uiName) && mXmlNode instanceof Element) {
            Element element = (Element) mXmlNode;
            String cls = element.getAttribute(ATTR_CLASS);
            if (cls != null) {
                uiName = cls.substring(cls.lastIndexOf('.') + 1);
            }
        }

        StyledString styledString = new StyledString();
        String attr = getDescAttribute();
        if (attr != null) {
            // Don't append the two when it's a repeat, e.g. Button01 (Button),
            // only when the ui name is not part of the attribute
            if (attr.toLowerCase(Locale.US).indexOf(uiName.toLowerCase(Locale.US)) == -1) {
                styledString.append(attr);
                styledString.append(String.format(" (%1$s)", uiName),
                        StyledString.DECORATIONS_STYLER);
            } else {
                styledString.append(attr);
            }
        }

        if (styledString.length() == 0) {
            styledString.append(uiName);
        }

        return styledString;
    }

    /**
     * Retrieves an attribute value by local name and namespace URI.
     * <br>Per [<a href='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
     * , applications must use the value <code>null</code> as the
     * <code>namespaceURI</code> parameter for methods if they wish to have
     * no namespace.
     * <p/>
     * Note: This is a wrapper around {@link Element#getAttributeNS(String, String)}.
     * In some versions of webtools, the getAttributeNS implementation crashes with an NPE.
     * This wrapper will return an empty string instead.
     *
     * @see Element#getAttributeNS(String, String)
     * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=318108">https://bugs.eclipse.org/bugs/show_bug.cgi?id=318108</a>
     * @return The result from {@link Element#getAttributeNS(String, String)} or an empty string.
     */
    private String _Element_getAttributeNS(Element element,
            String namespaceURI,
            String localName) {
        try {
            return element.getAttributeNS(namespaceURI, localName);
        } catch (Exception ignore) {
            return "";
        }
    }

    /**
     * Computes a "breadcrumb trail" description for this node.
     * It will look something like "Manifest > Application > .myactivity (Activity) > Intent-Filter"
     *
     * @param includeRoot Whether to include the root (e.g. "Manifest") or not. Has no effect
     *                     when called on the root node itself.
     * @return The "breadcrumb trail" description for this node.
     */
    public String getBreadcrumbTrailDescription(boolean includeRoot) {
        StringBuilder sb = new StringBuilder(getShortDescription());

        for (UiElementNode uiNode = getUiParent();
                uiNode != null;
                uiNode = uiNode.getUiParent()) {
            if (!includeRoot && uiNode.getUiParent() == null) {
                break;
            }
            sb.insert(0, String.format("%1$s > ", uiNode.getShortDescription())); //$NON-NLS-1$
        }

        return sb.toString();
    }

    /**
     * Sets the XML {@link Document}.
     * <p/>
     * The XML {@link Document} is initially null. The XML {@link Document} must be set only on the
     * UI root element node (this method takes care of that.)
     * @param xmlDoc The new XML document to associate this node with.
     */
    public void setXmlDocument(Document xmlDoc) {
        if (mUiParent == null) {
            mXmlDocument = xmlDoc;
        } else {
            mUiParent.setXmlDocument(xmlDoc);
        }
    }

    /**
     * Returns the XML {@link Document}.
     * <p/>
     * The value is initially null until the UI node is attached to its UI parent -- the value
     * of the document is then propagated.
     *
     * @return the XML {@link Document} or the parent's XML {@link Document} or null.
     */
    public Document getXmlDocument() {
        if (mXmlDocument != null) {
            return mXmlDocument;
        } else if (mUiParent != null) {
            return mUiParent.getXmlDocument();
        }
        return null;
    }

    /**
     * Returns the XML node associated with this UI node.
     * <p/>
     * Some {@link ElementDescriptor} are declared as being "mandatory". This means the
     * corresponding UI node will exist even if there is no corresponding XML node. Such structure
     * is created and enforced by the parent of the tree, not the element themselves. However
     * such nodes will likely not have an XML node associated, so getXmlNode() can return null.
     *
     * @return The associated XML node. Can be null for mandatory nodes.
     */
    public Node getXmlNode() {
        return mXmlNode;
    }

    /**
     * Returns the {@link ElementDescriptor} for this node. This is never null.
     * <p/>
     * Do not use this to call getDescriptor().getAttributes(), instead call
     * getAttributeDescriptors() which can be overridden by derived classes.
     * @return The {@link ElementDescriptor} for this node. This is never null.
     */
    public ElementDescriptor getDescriptor() {
        return mDescriptor;
    }

    /**
     * Returns the {@link AttributeDescriptor} array for the descriptor of this node.
     * <p/>
     * Use this instead of getDescriptor().getAttributes() -- derived classes can override
     * this to manipulate the attribute descriptor list depending on the current UI node.
     * @return The {@link AttributeDescriptor} array for the descriptor of this node.
     */
    public AttributeDescriptor[] getAttributeDescriptors() {
        return mDescriptor.getAttributes();
    }

    /**
     * Returns the hidden {@link AttributeDescriptor} array for the descriptor of this node.
     * This is a subset of the getAttributeDescriptors() list.
     * <p/>
     * Use this instead of getDescriptor().getHiddenAttributes() -- potentially derived classes
     * could override this to manipulate the attribute descriptor list depending on the current
     * UI node. There's no need for it right now so keep it private.
     */
    private Map<String, AttributeDescriptor> getHiddenAttributeDescriptors() {
        if (mCachedHiddenAttributes == null) {
            mCachedHiddenAttributes = new HashMap<String, AttributeDescriptor>();
            for (AttributeDescriptor attrDesc : getAttributeDescriptors()) {
                if (attrDesc instanceof XmlnsAttributeDescriptor) {
                    mCachedHiddenAttributes.put(
                            ((XmlnsAttributeDescriptor) attrDesc).getXmlNsName(),
                            attrDesc);
                }
            }
        }
        return mCachedHiddenAttributes;
    }

    /**
     * Sets the parent of this UiElementNode.
     * <p/>
     * The root node has no parent.
     */
    protected void setUiParent(UiElementNode parent) {
        mUiParent = parent;
        // Invalidate the internal UiAttributes list, as it may depend on the actual UiParent.
        clearAttributes();
    }

    /**
     * @return The parent {@link UiElementNode} or null if this is the root node.
     */
    public UiElementNode getUiParent() {
        return mUiParent;
    }

    /**
     * Returns the root {@link UiElementNode}.
     *
     * @return The root {@link UiElementNode}.
     */
    public UiElementNode getUiRoot() {
        UiElementNode root = this;
        while (root.mUiParent != null) {
            root = root.mUiParent;
        }

        return root;
    }

    /**
     * Returns the index of this sibling (where the first child has index 0, the second child
     * has index 1, and so on.)
     *
     * @return The sibling index of this node
     */
    public int getUiSiblingIndex() {
        if (mUiParent != null) {
            int index = 0;
            for (UiElementNode node : mUiParent.getUiChildren()) {
                if (node == this) {
                    break;
                }
                index++;
            }
            return index;
        }

        return 0;
    }

    /**
     * Returns the previous UI sibling of this UI node. If the node does not have a previous
     * sibling, returns null.
     *
     * @return The previous UI sibling of this UI node, or null if not applicable.
     */
    public UiElementNode getUiPreviousSibling() {
        if (mUiParent != null) {
            List<UiElementNode> childlist = mUiParent.getUiChildren();
            if (childlist != null && childlist.size() > 1 && childlist.get(0) != this) {
                int index = childlist.indexOf(this);
                return index > 0 ? childlist.get(index - 1) : null;
            }
        }
        return null;
    }

    /**
     * Returns the next UI sibling of this UI node.
     * If the node does not have a next sibling, returns null.
     *
     * @return The next UI sibling of this UI node, or null.
     */
    public UiElementNode getUiNextSibling() {
        if (mUiParent != null) {
            List<UiElementNode> childlist = mUiParent.getUiChildren();
            if (childlist != null) {
                int size = childlist.size();
                if (size > 1 && childlist.get(size - 1) != this) {
                    int index = childlist.indexOf(this);
                    return index >= 0 && index < size - 1 ? childlist.get(index + 1) : null;
                }
            }
        }
        return null;
    }

    /**
     * Sets the {@link AndroidXmlEditor} handling this {@link UiElementNode} hierarchy.
     * <p/>
     * The editor must always be set on the root node. This method takes care of that.
     *
     * @param editor The editor to associate this node with.
     */
    public void setEditor(AndroidXmlEditor editor) {
        if (mUiParent == null) {
            mEditor = editor;
        } else {
            mUiParent.setEditor(editor);
        }
    }

    /**
     * Returns the {@link AndroidXmlEditor} that embeds this {@link UiElementNode}.
     * <p/>
     * The value is initially null until the node is attached to its parent -- the value
     * of the root node is then propagated.
     *
     * @return The embedding {@link AndroidXmlEditor} or null.
     */
    public AndroidXmlEditor getEditor() {
        return mUiParent == null ? mEditor : mUiParent.getEditor();
    }

    /**
     * Returns the Android target data for the file being edited.
     *
     * @return The Android target data for the file being edited.
     */
    public AndroidTargetData getAndroidTarget() {
        return getEditor().getTargetData();
    }

    /**
     * @return A read-only version of the children collection.
     */
    public List<UiElementNode> getUiChildren() {
        if (mReadOnlyUiChildren == null) {
            mReadOnlyUiChildren = Collections.unmodifiableList(mUiChildren);
        }
        return mReadOnlyUiChildren;
    }

    /**
     * Returns a collection containing all the known attributes as well as
     * all the unknown ui attributes.
     *
     * @return A read-only version of the attributes collection.
     */
    public Collection<UiAttributeNode> getAllUiAttributes() {
        if (mCachedAllUiAttributes == null) {

            List<UiAttributeNode> allValues =
                new ArrayList<UiAttributeNode>(getInternalUiAttributes().values());
            allValues.addAll(mUnknownUiAttributes);

            mCachedAllUiAttributes = Collections.unmodifiableCollection(allValues);
        }
        return mCachedAllUiAttributes;
    }

    /**
     * Returns all the unknown ui attributes, that is those we found defined in the
     * actual XML but that we don't have descriptors for.
     *
     * @return A read-only version of the unknown attributes collection.
     */
    public Collection<UiAttributeNode> getUnknownUiAttributes() {
        return Collections.unmodifiableCollection(mUnknownUiAttributes);
    }

    /**
     * Sets the error flag value.
     *
     * @param errorFlag the error flag
     */
    public final void setHasError(boolean errorFlag) {
        mHasError = errorFlag;
    }

    /**
     * Returns whether this node, its attributes, or one of the children nodes (and attributes)
     * has errors.
     *
     * @return True if this node, its attributes, or one of the children nodes (and attributes)
     * has errors.
     */
    public final boolean hasError() {
        if (mHasError) {
            return true;
        }

        // get the error value from the attributes.
        for (UiAttributeNode attribute : getAllUiAttributes()) {
            if (attribute.hasError()) {
                return true;
            }
        }

        // and now from the children.
        for (UiElementNode child : mUiChildren) {
            if (child.hasError()) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns the provider that knows how to create {@link ElementDescriptor} from unmapped
     * XML names.
     * <p/>
     * The default is to have one that creates new {@link ElementDescriptor}.
     * <p/>
     * There is only one such provider in any UI model tree, attached to the root node.
     *
     * @return An instance of {@link IUnknownDescriptorProvider}. Can never be null.
     */
    public IUnknownDescriptorProvider getUnknownDescriptorProvider() {
        if (mUiParent != null) {
            return mUiParent.getUnknownDescriptorProvider();
        }
        if (mUnknownDescProvider == null) {
            // Create the default one on demand.
            mUnknownDescProvider = new IUnknownDescriptorProvider() {

                private final HashMap<String, ElementDescriptor> mMap =
                    new HashMap<String, ElementDescriptor>();

                /**
                 * The default is to create a new ElementDescriptor wrapping
                 * the unknown XML local name and reuse previously created descriptors.
                 */
                @Override
                public ElementDescriptor getDescriptor(String xmlLocalName) {

                    ElementDescriptor desc = mMap.get(xmlLocalName);

                    if (desc == null) {
                        desc = new ElementDescriptor(xmlLocalName);
                        mMap.put(xmlLocalName, desc);
                    }

                    return desc;
                }
            };
        }
        return mUnknownDescProvider;
    }

    /**
     * Sets the provider that knows how to create {@link ElementDescriptor} from unmapped
     * XML names.
     * <p/>
     * The default is to have one that creates new {@link ElementDescriptor}.
     * <p/>
     * There is only one such provider in any UI model tree, attached to the root node.
     *
     * @param unknownDescProvider The new provider to use. Must not be null.
     */
    public void setUnknownDescriptorProvider(IUnknownDescriptorProvider unknownDescProvider) {
        if (mUiParent == null) {
            mUnknownDescProvider = unknownDescProvider;
        } else {
            mUiParent.setUnknownDescriptorProvider(unknownDescProvider);
        }
    }

    /**
     * Adds a new {@link IUiUpdateListener} to the internal update listener list.
     *
     * @param listener The listener to add.
     */
    public void addUpdateListener(IUiUpdateListener listener) {
       if (mUiUpdateListeners == null) {
           mUiUpdateListeners = new ArrayList<IUiUpdateListener>();
       }
       if (!mUiUpdateListeners.contains(listener)) {
           mUiUpdateListeners.add(listener);
       }
    }

    /**
     * Removes an existing {@link IUiUpdateListener} from the internal update listener list.
     * Does nothing if the list is empty or the listener is not registered.
     *
     * @param listener The listener to remove.
     */
    public void removeUpdateListener(IUiUpdateListener listener) {
       if (mUiUpdateListeners != null) {
           mUiUpdateListeners.remove(listener);
       }
    }

    /**
     * Finds a child node relative to this node using a path-like expression.
     * F.ex. "node1/node2" would find a child "node1" that contains a child "node2" and
     * returns the latter. If there are multiple nodes with the same name at the same
     * level, always uses the first one found.
     *
     * @param path The path like expression to select a child node.
     * @return The ui node found or null.
     */
    public UiElementNode findUiChildNode(String path) {
        String[] items = path.split("/");  //$NON-NLS-1$
        UiElementNode uiNode = this;
        for (String item : items) {
            boolean nextSegment = false;
            for (UiElementNode c : uiNode.mUiChildren) {
                if (c.getDescriptor().getXmlName().equals(item)) {
                    uiNode = c;
                    nextSegment = true;
                    break;
                }
            }
            if (!nextSegment) {
                return null;
            }
        }
        return uiNode;
    }

    /**
     * Finds an {@link UiElementNode} which contains the give XML {@link Node}.
     * Looks recursively in all children UI nodes.
     *
     * @param xmlNode The XML node to look for.
     * @return The {@link UiElementNode} that contains xmlNode or null if not found,
     */
    public UiElementNode findXmlNode(Node xmlNode) {
        if (xmlNode == null) {
            return null;
        }
        if (getXmlNode() == xmlNode) {
            return this;
        }

        for (UiElementNode uiChild : mUiChildren) {
            UiElementNode found = uiChild.findXmlNode(xmlNode);
            if (found != null) {
                return found;
            }
        }

        return null;
    }

    /**
     * Returns the {@link UiAttributeNode} matching this attribute descriptor or
     * null if not found.
     *
     * @param attrDesc The {@link AttributeDescriptor} to match.
     * @return the {@link UiAttributeNode} matching this attribute descriptor or null
     *         if not found.
     */
    public UiAttributeNode findUiAttribute(AttributeDescriptor attrDesc) {
        return getInternalUiAttributes().get(attrDesc);
    }

    /**
     * Populate this element node with all values from the given XML node.
     *
     * This fails if the given XML node has a different element name -- it won't change the
     * type of this ui node.
     *
     * This method can be both used for populating values the first time and updating values
     * after the XML model changed.
     *
     * @param xmlNode The XML node to mirror
     * @return Returns true if the XML structure has changed (nodes added, removed or replaced)
     */
    public boolean loadFromXmlNode(Node xmlNode) {
        boolean structureChanged = (mXmlNode != xmlNode);
        mXmlNode = xmlNode;
        if (xmlNode != null) {
            updateAttributeList(xmlNode);
            structureChanged |= updateElementList(xmlNode);
            invokeUiUpdateListeners(structureChanged ? UiUpdateState.CHILDREN_CHANGED
                                                      : UiUpdateState.ATTR_UPDATED);
        }
        return structureChanged;
    }

    /**
     * Clears the UI node and reload it from the given XML node.
     * <p/>
     * This works by clearing all references to any previous XML or UI nodes and
     * then reloads the XML document from scratch. The editor reference is kept.
     * <p/>
     * This is used in the special case where the ElementDescriptor structure has changed.
     * Rather than try to diff inflated UI nodes (as loadFromXmlNode does), we don't bother
     * and reload everything. This is not subtle and should be used very rarely.
     *
     * @param xmlNode The XML node or document to reload. Can be null.
     */
    public void reloadFromXmlNode(Node xmlNode) {
        // The editor needs to be preserved, it is not affected by an XML change.
        AndroidXmlEditor editor = getEditor();
        clearContent();
        setEditor(editor);
        if (xmlNode != null) {
            setXmlDocument(xmlNode.getOwnerDocument());
        }
        // This will reload all the XML and recreate the UI structure from scratch.
        loadFromXmlNode(xmlNode);
    }

    /**
     * Called by attributes when they want to commit their value
     * to an XML node.
     * <p/>
     * For mandatory nodes, this makes sure the underlying XML element node
     * exists in the model. If not, it is created and assigned as the underlying
     * XML node.
     * </br>
     * For non-mandatory nodes, simply return the underlying XML node, which
     * must always exists.
     *
     * @return The XML node matching this {@link UiElementNode} or null.
     */
    public Node prepareCommit() {
        if (getDescriptor().getMandatory() != Mandatory.NOT_MANDATORY) {
            createXmlNode();
            // The new XML node has been created.
            // We don't need to refresh using loadFromXmlNode() since there are
            // no attributes or elements that need to be loading into this node.
        }
        return getXmlNode();
    }

    /**
     * Commits the attributes (all internal, inherited from UI parent & unknown attributes).
     * This is called by the UI when the embedding part needs to be committed.
     */
    public void commit() {
        for (UiAttributeNode uiAttr : getAllUiAttributes()) {
            uiAttr.commit();
        }
    }

    /**
     * Returns true if the part has been modified with respect to the data
     * loaded from the model.
     * @return True if the part has been modified with respect to the data
     * loaded from the model.
     */
    public boolean isDirty() {
        for (UiAttributeNode uiAttr : getAllUiAttributes()) {
            if (uiAttr.isDirty()) {
                return true;
            }
        }

        return false;
    }

    /**
     * Creates the underlying XML element node for this UI node if it doesn't already
     * exists.
     *
     * @return The new value of getXmlNode() (can be null if creation failed)
     */
    public Node createXmlNode() {
        if (mXmlNode != null) {
            return null;
        }
        Node parentXmlNode = null;
        if (mUiParent != null) {
            parentXmlNode = mUiParent.prepareCommit();
            if (parentXmlNode == null) {
                // The parent failed to create its own backing XML node. Abort.
                // No need to throw an exception, the parent will most likely
                // have done so itself.
                return null;
            }
        }

        String elementName = getDescriptor().getXmlName();
        Document doc = getXmlDocument();

        // We *must* have a root node. If not, we need to abort.
        if (doc == null) {
            throw new RuntimeException(
                    String.format("Missing XML document for %1$s XML node.", elementName));
        }

        // If we get here and parentXmlNode is null, the node is to be created
        // as the root node of the document (which can't be null, cf. check above).
        if (parentXmlNode == null) {
            parentXmlNode = doc;
        }

        mXmlNode = doc.createElement(elementName);

        // If this element does not have children, mark it as an empty tag
        // such that the XML looks like <tag/> instead of <tag></tag>
        if (!mDescriptor.hasChildren()) {
            if (mXmlNode instanceof ElementImpl) {
                ElementImpl element = (ElementImpl) mXmlNode;
                element.setEmptyTag(true);
            }
        }

        Node xmlNextSibling = null;

        UiElementNode uiNextSibling = getUiNextSibling();
        if (uiNextSibling != null) {
            xmlNextSibling = uiNextSibling.getXmlNode();
        }

        Node previousTextNode = null;
        if (xmlNextSibling != null) {
            Node previousNode = xmlNextSibling.getPreviousSibling();
            if (previousNode != null && previousNode.getNodeType() == Node.TEXT_NODE) {
                previousTextNode = previousNode;
            }
        } else {
            Node lastChild = parentXmlNode.getLastChild();
            if (lastChild != null && lastChild.getNodeType() == Node.TEXT_NODE) {
                previousTextNode = lastChild;
            }
        }

        String insertAfter = null;

        // Try to figure out the indentation node to insert. Even in auto-formatting
        // we need to do this, because it turns out the XML editor's formatter does
        // not do a very good job with completely botched up XML; it does a much better
        // job if the new XML is already mostly well formatted. Thus, the main purpose
        // of applying the real XML formatter after our own indentation attempts here is
        // to make it apply its own tab-versus-spaces indentation properties, have it
        // insert line breaks before attributes (if the user has configured that), etc.

        // First figure out the indentation level of the newly inserted element;
        // this is either the same as the previous sibling, or if there is no sibling,
        // it's the indentation of the parent plus one indentation level.
        boolean isFirstChild = getUiPreviousSibling() == null
                || parentXmlNode.getFirstChild() == null;
        AndroidXmlEditor editor = getEditor();
        String indent;
        String parentIndent = ""; //$NON-NLS-1$
        if (isFirstChild) {
            indent = parentIndent = editor.getIndent(parentXmlNode);
            // We need to add one level of indentation. Are we using tabs?
            // Can't get to formatting settings so let's just look at the
            // parent indentation and see if we can guess
            if (indent.length() > 0 && indent.charAt(indent.length()-1) == '\t') {
                indent = indent + '\t';
            } else {
                // Not using tabs, or we can't figure it out (because parent had no
                // indentation). In that case, indent with 4 spaces, as seems to
                // be the Android default.
                indent = indent + "    "; //$NON-NLS-1$
            }
        } else {
            // Find out the indent of the previous sibling
            indent = editor.getIndent(getUiPreviousSibling().getXmlNode());
        }

        // We want to insert the new element BEFORE the text node which precedes
        // the next element, since that text node is the next element's indentation!
        if (previousTextNode != null) {
            xmlNextSibling = previousTextNode;
        } else {
            // If there's no previous text node, we are probably inside an
            // empty element (<LinearLayout>|</LinearLayout>) and in that case we need
            // to not only insert a newline and indentation before the new element, but
            // after it as well.
            insertAfter = parentIndent;
        }

        // Insert indent text node before the new element
        IStructuredDocument document = editor.getStructuredDocument();
        String newLine;
        if (document != null) {
            newLine = TextUtilities.getDefaultLineDelimiter(document);
        } else {
            newLine = SdkUtils.getLineSeparator();
        }
        Text indentNode = doc.createTextNode(newLine + indent);
        parentXmlNode.insertBefore(indentNode, xmlNextSibling);

        // Insert the element itself
        parentXmlNode.insertBefore(mXmlNode, xmlNextSibling);

        // Insert a separator after the tag. We only do this when we've inserted
        // a tag into an area where there was no whitespace before
        // (e.g. a new child of <LinearLayout></LinearLayout>).
        if (insertAfter != null) {
            Text sep = doc.createTextNode(newLine + insertAfter);
            parentXmlNode.insertBefore(sep, xmlNextSibling);
        }

        // Set all initial attributes in the XML node if they are not empty.
        // Iterate on the descriptor list to get the desired order and then use the
        // internal values, if any.
        List<UiAttributeNode> addAttributes = new ArrayList<UiAttributeNode>();

        for (AttributeDescriptor attrDesc : getAttributeDescriptors()) {
            if (attrDesc instanceof XmlnsAttributeDescriptor) {
                XmlnsAttributeDescriptor desc = (XmlnsAttributeDescriptor) attrDesc;
                Attr attr = doc.createAttributeNS(SdkConstants.XMLNS_URI,
                        desc.getXmlNsName());
                attr.setValue(desc.getValue());
                attr.setPrefix(desc.getXmlNsPrefix());
                mXmlNode.getAttributes().setNamedItemNS(attr);
            } else {
                UiAttributeNode uiAttr = getInternalUiAttributes().get(attrDesc);

                // Don't apply the attribute immediately, instead record this attribute
                // such that we can gather all attributes and sort them first.
                // This is necessary because the XML model will *append* all attributes
                // so we want to add them in a particular order.
                // (Note that we only have to worry about UiAttributeNodes with non null
                // values, since this is a new node and we therefore don't need to attempt
                // to remove existing attributes)
                String value = uiAttr.getCurrentValue();
                if (value != null && value.length() > 0) {
                    addAttributes.add(uiAttr);
                }
            }
        }

        // Sort and apply the attributes in order, because the Eclipse XML model will always
        // append the XML attributes, so by inserting them in our desired order they will
        // appear that way in the XML
        Collections.sort(addAttributes);

        for (UiAttributeNode node : addAttributes) {
            commitAttributeToXml(node, node.getCurrentValue());
            node.setDirty(false);
        }

        getEditor().scheduleNodeReformat(this, false);

        // Notify per-node listeners
        invokeUiUpdateListeners(UiUpdateState.CREATED);
        // Notify global listeners
        fireNodeCreated(this, getUiSiblingIndex());

        return mXmlNode;
    }

    /**
     * Removes the XML node corresponding to this UI node if it exists
     * and also removes all mirrored information in this UI node (i.e. children, attributes)
     *
     * @return The removed node or null if it didn't exist in the first place.
     */
    public Node deleteXmlNode() {
        if (mXmlNode == null) {
            return null;
        }

        int previousIndex = getUiSiblingIndex();

        // First clear the internals of the node and *then* actually deletes the XML
        // node (because doing so will generate an update even and this node may be
        // revisited via loadFromXmlNode).
        Node oldXmlNode = mXmlNode;
        clearContent();

        Node xmlParent = oldXmlNode.getParentNode();
        if (xmlParent == null) {
            xmlParent = getXmlDocument();
        }
        Node previousSibling = oldXmlNode.getPreviousSibling();
        oldXmlNode = xmlParent.removeChild(oldXmlNode);

        // We need to remove the text node BEFORE the removed element, since THAT's the
        // indentation node for the removed element.
        if (previousSibling != null && previousSibling.getNodeType() == Node.TEXT_NODE
                && previousSibling.getNodeValue().trim().length() == 0) {
            xmlParent.removeChild(previousSibling);
        }

        invokeUiUpdateListeners(UiUpdateState.DELETED);
        fireNodeDeleted(this, previousIndex);

        return oldXmlNode;
    }

    /**
     * Updates the element list for this UiElementNode.
     * At the end, the list of children UiElementNode here will match the one from the
     * provided XML {@link Node}:
     * <ul>
     * <li> Walk both the current ui children list and the xml children list at the same time.
     * <li> If we have a new xml child but already reached the end of the ui child list, add the
     *      new xml node.
     * <li> Otherwise, check if the xml node is referenced later in the ui child list and if so,
     *      move it here. It means the XML child list has been reordered.
     * <li> Otherwise, this is a new XML node that we add in the middle of the ui child list.
     * <li> At the end, we may have finished walking the xml child list but still have remaining
     *      ui children, simply delete them as they matching trailing xml nodes that have been
     *      removed unless they are mandatory ui nodes.
     * </ul>
     * Note that only the first case is used when populating the ui list the first time.
     *
     * @param xmlNode The XML node to mirror
     * @return True when the XML structure has changed.
     */
    protected boolean updateElementList(Node xmlNode) {
        boolean structureChanged = false;
        boolean hasMandatoryLast = false;
        int uiIndex = 0;
        Node xmlChild = xmlNode.getFirstChild();
        while (xmlChild != null) {
            if (xmlChild.getNodeType() == Node.ELEMENT_NODE) {
                String elementName = xmlChild.getNodeName();
                UiElementNode uiNode = null;
                CustomViewDescriptorService service = CustomViewDescriptorService.getInstance();
                if (mUiChildren.size() <= uiIndex) {
                    // A new node is being added at the end of the list
                    ElementDescriptor desc = mDescriptor.findChildrenDescriptor(elementName,
                            false /* recursive */);
                    if (desc == null && elementName.indexOf('.') != -1 &&
                            (!elementName.startsWith(ANDROID_PKG_PREFIX)
                                    || elementName.startsWith(ANDROID_SUPPORT_PKG_PREFIX))) {
                        AndroidXmlEditor editor = getEditor();
                        if (editor != null && editor.getProject() != null) {
                            desc = service.getDescriptor(editor.getProject(), elementName);
                        }
                    }
                    if (desc == null) {
                        // Unknown node. Create a temporary descriptor for it.
                        // We'll add unknown attributes to it later.
                        IUnknownDescriptorProvider p = getUnknownDescriptorProvider();
                        desc = p.getDescriptor(elementName);
                    }
                    structureChanged = true;
                    uiNode = appendNewUiChild(desc);
                    uiIndex++;
                } else {
                    // A new node is being inserted or moved.
                    // Note: mandatory nodes can be created without an XML node in which case
                    // getXmlNode() is null.
                    UiElementNode uiChild;
                    int n = mUiChildren.size();
                    for (int j = uiIndex; j < n; j++) {
                        uiChild = mUiChildren.get(j);
                        if (uiChild.getXmlNode() != null && uiChild.getXmlNode() == xmlChild) {
                            if (j > uiIndex) {
                                // Found the same XML node at some later index, now move it here.
                                mUiChildren.remove(j);
                                mUiChildren.add(uiIndex, uiChild);
                                structureChanged = true;
                            }
                            uiNode = uiChild;
                            uiIndex++;
                            break;
                        }
                    }

                    if (uiNode == null) {
                        // Look for an unused mandatory node with no XML node attached
                        // referencing the same XML element name
                        for (int j = uiIndex; j < n; j++) {
                            uiChild = mUiChildren.get(j);
                            if (uiChild.getXmlNode() == null &&
                                    uiChild.getDescriptor().getMandatory() !=
                                                                Mandatory.NOT_MANDATORY &&
                                    uiChild.getDescriptor().getXmlName().equals(elementName)) {

                                if (j > uiIndex) {
                                    // Found it, now move it here
                                    mUiChildren.remove(j);
                                    mUiChildren.add(uiIndex, uiChild);
                                }
                                // Assign the XML node to this empty mandatory element.
                                uiChild.mXmlNode = xmlChild;
                                structureChanged = true;
                                uiNode = uiChild;
                                uiIndex++;
                            }
                        }
                    }

                    if (uiNode == null) {
                        // Inserting new node
                        ElementDescriptor desc = mDescriptor.findChildrenDescriptor(elementName,
                                false /* recursive */);
                        if (desc == null && elementName.indexOf('.') != -1 &&
                                (!elementName.startsWith(ANDROID_PKG_PREFIX)
                                        || elementName.startsWith(ANDROID_SUPPORT_PKG_PREFIX))) {
                            AndroidXmlEditor editor = getEditor();
                            if (editor != null && editor.getProject() != null) {
                                desc = service.getDescriptor(editor.getProject(), elementName);
                            }
                        }
                        if (desc == null) {
                            // Unknown node. Create a temporary descriptor for it.
                            // We'll add unknown attributes to it later.
                            IUnknownDescriptorProvider p = getUnknownDescriptorProvider();
                            desc = p.getDescriptor(elementName);
                        } else {
                            structureChanged = true;
                            uiNode = insertNewUiChild(uiIndex, desc);
                            uiIndex++;
                        }
                    }
                }
                if (uiNode != null) {
                    // If we touched an UI Node, even an existing one, refresh its content.
                    // For new nodes, this will populate them recursively.
                    structureChanged |= uiNode.loadFromXmlNode(xmlChild);

                    // Remember if there are any mandatory-last nodes to reorder.
                    hasMandatoryLast |=
                        uiNode.getDescriptor().getMandatory() == Mandatory.MANDATORY_LAST;
                }
            }
            xmlChild = xmlChild.getNextSibling();
        }

        // There might be extra UI nodes at the end if the XML node list got shorter.
        for (int index = mUiChildren.size() - 1; index >= uiIndex; --index) {
             structureChanged |= removeUiChildAtIndex(index);
        }

        if (hasMandatoryLast) {
            // At least one mandatory-last uiNode was moved. Let's see if we can
            // move them back to the last position. That's possible if the only
            // thing between these and the end are other mandatory empty uiNodes
            // (mandatory uiNodes with no XML attached are pure "virtual" reserved
            // slots and it's ok to reorganize them but other can't.)
            int n = mUiChildren.size() - 1;
            for (int index = n; index >= 0; index--) {
                UiElementNode uiChild = mUiChildren.get(index);
                Mandatory mand = uiChild.getDescriptor().getMandatory();
                if (mand == Mandatory.MANDATORY_LAST && index < n) {
                    // Remove it from index and move it back at the end of the list.
                    mUiChildren.remove(index);
                    mUiChildren.add(uiChild);
                } else if (mand == Mandatory.NOT_MANDATORY || uiChild.getXmlNode() != null) {
                    // We found at least one non-mandatory or a mandatory node with an actual
                    // XML attached, so there's nothing we can reorganize past this point.
                    break;
                }
            }
        }

        return structureChanged;
    }

    /**
     * Internal helper to remove an UI child node given by its index in the
     * internal child list.
     *
     * Also invokes the update listener on the node to be deleted *after* the node has
     * been removed.
     *
     * @param uiIndex The index of the UI child to remove, range 0 .. mUiChildren.size()-1
     * @return True if the structure has changed
     * @throws IndexOutOfBoundsException if index is out of mUiChildren's bounds. Of course you
     *         know that could never happen unless the computer is on fire or something.
     */
    private boolean removeUiChildAtIndex(int uiIndex) {
        UiElementNode uiNode = mUiChildren.get(uiIndex);
        ElementDescriptor desc = uiNode.getDescriptor();

        try {
            if (uiNode.getDescriptor().getMandatory() != Mandatory.NOT_MANDATORY) {
                // This is a mandatory node. Such a node must exist in the UiNode hierarchy
                // even if there's no XML counterpart. However we only need to keep one.

                // Check if the parent (e.g. this node) has another similar ui child node.
                boolean keepNode = true;
                for (UiElementNode child : mUiChildren) {
                    if (child != uiNode && child.getDescriptor() == desc) {
                        // We found another child with the same descriptor that is not
                        // the node we want to remove. This means we have one mandatory
                        // node so we can safely remove uiNode.
                        keepNode = false;
                        break;
                    }
                }

                if (keepNode) {
                    // We can't remove a mandatory node as we need to keep at least one
                    // mandatory node in the parent. Instead we just clear its content
                    // (including its XML Node reference).

                    // A mandatory node with no XML means it doesn't really exist, so it can't be
                    // deleted. So the structure will change only if the ui node is actually
                    // associated to an XML node.
                    boolean xmlExists = (uiNode.getXmlNode() != null);

                    uiNode.clearContent();
                    return xmlExists;
                }
            }

            mUiChildren.remove(uiIndex);

            return true;
        } finally {
            // Tell listeners that a node has been removed.
            // The model has already been modified.
            invokeUiUpdateListeners(UiUpdateState.DELETED);
        }
    }

    /**
     * Creates a new {@link UiElementNode} from the given {@link ElementDescriptor}
     * and appends it to the end of the element children list.
     *
     * @param descriptor The {@link ElementDescriptor} that knows how to create the UI node.
     * @return The new UI node that has been appended
     */
    public UiElementNode appendNewUiChild(ElementDescriptor descriptor) {
        UiElementNode uiNode;
        uiNode = descriptor.createUiNode();
        mUiChildren.add(uiNode);
        uiNode.setUiParent(this);
        uiNode.invokeUiUpdateListeners(UiUpdateState.CREATED);
        return uiNode;
    }

    /**
     * Creates a new {@link UiElementNode} from the given {@link ElementDescriptor}
     * and inserts it in the element children list at the specified position.
     *
     * @param index The position where to insert in the element children list.
     *              Shifts the element currently at that position (if any) and any
     *              subsequent elements to the right (adds one to their indices).
     *              Index must >= 0 and <= getUiChildren.size().
     *              Using size() means to append to the end of the list.
     * @param descriptor The {@link ElementDescriptor} that knows how to create the UI node.
     * @return The new UI node.
     */
    public UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) {
        UiElementNode uiNode;
        uiNode = descriptor.createUiNode();
        mUiChildren.add(index, uiNode);
        uiNode.setUiParent(this);
        uiNode.invokeUiUpdateListeners(UiUpdateState.CREATED);
        return uiNode;
    }

    /**
     * Updates the {@link UiAttributeNode} list for this {@link UiElementNode}
     * using the values from the XML element.
     * <p/>
     * For a given {@link UiElementNode}, the attribute list always exists in
     * full and is totally independent of whether the XML model actually
     * has the corresponding attributes.
     * <p/>
     * For each attribute declared in this {@link UiElementNode}, get
     * the corresponding XML attribute. It may not exist, in which case the
     * value will be null. We don't really know if a value has changed, so
     * the updateValue() is called on the UI attribute in all cases.
     *
     * @param xmlNode The XML node to mirror
     */
    protected void updateAttributeList(Node xmlNode) {
        NamedNodeMap xmlAttrMap = xmlNode.getAttributes();
        HashSet<Node> visited = new HashSet<Node>();

        // For all known (i.e. expected) UI attributes, find an existing XML attribute of
        // same (uri, local name) and update the internal Ui attribute value.
        for (UiAttributeNode uiAttr : getInternalUiAttributes().values()) {
            AttributeDescriptor desc = uiAttr.getDescriptor();
            if (!(desc instanceof SeparatorAttributeDescriptor)) {
                Node xmlAttr = xmlAttrMap == null ? null :
                    xmlAttrMap.getNamedItemNS(desc.getNamespaceUri(), desc.getXmlLocalName());
                uiAttr.updateValue(xmlAttr);
                visited.add(xmlAttr);
            }
        }

        // Clone the current list of unknown attributes. We'll then remove from this list when
        // we find attributes which are still unknown. What will be left are the old unknown
        // attributes that have been deleted in the current XML attribute list.
        @SuppressWarnings("unchecked")
        HashSet<UiAttributeNode> deleted = (HashSet<UiAttributeNode>) mUnknownUiAttributes.clone();

        // We need to ignore hidden attributes.
        Map<String, AttributeDescriptor> hiddenAttrDesc = getHiddenAttributeDescriptors();

        // Traverse the actual XML attribute list to find unknown attributes
        if (xmlAttrMap != null) {
            for (int i = 0; i < xmlAttrMap.getLength(); i++) {
                Node xmlAttr = xmlAttrMap.item(i);
                // Ignore attributes which have actual descriptors
                if (visited.contains(xmlAttr)) {
                    continue;
                }

                String xmlFullName = xmlAttr.getNodeName();

                // Ignore attributes which are hidden (based on the prefix:localName key)
                if (hiddenAttrDesc.containsKey(xmlFullName)) {
                    continue;
                }

                String xmlAttrLocalName = xmlAttr.getLocalName();
                String xmlNsUri = xmlAttr.getNamespaceURI();

                UiAttributeNode uiAttr = null;
                for (UiAttributeNode a : mUnknownUiAttributes) {
                    String aLocalName = a.getDescriptor().getXmlLocalName();
                    String aNsUri = a.getDescriptor().getNamespaceUri();
                    if (aLocalName.equals(xmlAttrLocalName) &&
                            (aNsUri == xmlNsUri || (aNsUri != null && aNsUri.equals(xmlNsUri)))) {
                        // This attribute is still present in the unknown list
                        uiAttr = a;
                        // It has not been deleted
                        deleted.remove(a);
                        break;
                    }
                }
                if (uiAttr == null) {
                    uiAttr = addUnknownAttribute(xmlFullName, xmlAttrLocalName, xmlNsUri);
                }

                uiAttr.updateValue(xmlAttr);
            }

            // Remove from the internal list unknown attributes that have been deleted from the xml
            for (UiAttributeNode a : deleted) {
                mUnknownUiAttributes.remove(a);
                mCachedAllUiAttributes = null;
            }
        }
    }

    /**
     * Create a new temporary text attribute descriptor for the unknown attribute
     * and returns a new {@link UiAttributeNode} associated to this descriptor.
     * <p/>
     * The attribute is not marked as dirty, doing so is up to the caller.
     */
    private UiAttributeNode addUnknownAttribute(String xmlFullName,
            String xmlAttrLocalName, String xmlNsUri) {
        // Create a new unknown attribute of format string
        TextAttributeDescriptor desc = new TextAttributeDescriptor(
                xmlAttrLocalName,           // xml name
                xmlNsUri,                // ui name
                new AttributeInfo(xmlAttrLocalName, Format.STRING_SET)
                );
        UiAttributeNode uiAttr = desc.createUiNode(this);
        mUnknownUiAttributes.add(uiAttr);
        mCachedAllUiAttributes = null;
        return uiAttr;
    }

    /**
     * Invoke all registered {@link IUiUpdateListener} listening on this UI update for this node.
     */
    protected void invokeUiUpdateListeners(UiUpdateState state) {
        if (mUiUpdateListeners != null) {
            for (IUiUpdateListener listener : mUiUpdateListeners) {
                try {
                    listener.uiElementNodeUpdated(this, state);
                } catch (Exception e) {
                    // prevent a crashing listener from crashing the whole invocation chain
                    AdtPlugin.log(e, "UIElement Listener failed: %s, state=%s",  //$NON-NLS-1$
                            getBreadcrumbTrailDescription(true),
                            state.toString());
                }
            }
        }
    }

    // --- for derived implementations only ---

    @VisibleForTesting
    public void setXmlNode(Node xmlNode) {
        mXmlNode = xmlNode;
    }

    public void refreshUi() {
        invokeUiUpdateListeners(UiUpdateState.ATTR_UPDATED);
    }


    // ------------- Helpers

    /**
     * Helper method to commit a single attribute value to XML.
     * <p/>
     * This method updates the XML regardless of the current XML value.
     * Callers should check first if an update is needed.
     * If the new value is empty, the XML attribute will be actually removed.
     * <p/>
     * Note that the caller MUST ensure that modifying the underlying XML model is
     * safe and must take care of marking the model as dirty if necessary.
     *
     * @see AndroidXmlEditor#wrapEditXmlModel(Runnable)
     *
     * @param uiAttr The attribute node to commit. Must be a child of this UiElementNode.
     * @param newValue The new value to set.
     * @return True if the XML attribute was modified or removed, false if nothing changed.
     */
    public boolean commitAttributeToXml(UiAttributeNode uiAttr, String newValue) {
        // Get (or create) the underlying XML element node that contains the attributes.
        Node element = prepareCommit();
        if (element != null && uiAttr != null) {
            String attrLocalName = uiAttr.getDescriptor().getXmlLocalName();
            String attrNsUri = uiAttr.getDescriptor().getNamespaceUri();

            NamedNodeMap attrMap = element.getAttributes();
            if (newValue == null || newValue.length() == 0) {
                // Remove attribute if it's empty
                if (attrMap.getNamedItemNS(attrNsUri, attrLocalName) != null) {
                    attrMap.removeNamedItemNS(attrNsUri, attrLocalName);
                    return true;
                }
            } else {
                // Add or replace an attribute
                Document doc = element.getOwnerDocument();
                if (doc != null) {
                    Attr attr;
                    if (attrNsUri != null && attrNsUri.length() > 0) {
                        attr = (Attr) attrMap.getNamedItemNS(attrNsUri, attrLocalName);
                        if (attr == null) {
                            attr = doc.createAttributeNS(attrNsUri, attrLocalName);
                            attr.setPrefix(XmlUtils.lookupNamespacePrefix(element, attrNsUri));
                            attrMap.setNamedItemNS(attr);
                        }
                    } else {
                        attr = (Attr) attrMap.getNamedItem(attrLocalName);
                        if (attr == null) {
                            attr = doc.createAttribute(attrLocalName);
                            attrMap.setNamedItem(attr);
                        }
                    }
                    attr.setValue(newValue);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Helper method to commit all dirty attributes values to XML.
     * <p/>
     * This method is useful if {@link #setAttributeValue(String, String, String, boolean)} has
     * been called more than once and all the attributes marked as dirty must be committed to
     * the XML. It calls {@link #commitAttributeToXml(UiAttributeNode, String)} on each dirty
     * attribute.
     * <p/>
     * Note that the caller MUST ensure that modifying the underlying XML model is
     * safe and must take care of marking the model as dirty if necessary.
     *
     * @see AndroidXmlEditor#wrapEditXmlModel(Runnable)
     *
     * @return True if one or more values were actually modified or removed,
     *         false if nothing changed.
     */
    @SuppressWarnings("null") // Eclipse is confused by the logic and gets it wrong
    public boolean commitDirtyAttributesToXml() {
        boolean result = false;
        List<UiAttributeNode> dirtyAttributes = new ArrayList<UiAttributeNode>();
        for (UiAttributeNode uiAttr : getAllUiAttributes()) {
            if (uiAttr.isDirty()) {
                String value = uiAttr.getCurrentValue();
                if (value != null && value.length() > 0) {
                    // Defer the new attributes: set these last and in order
                    dirtyAttributes.add(uiAttr);
                } else {
                    result |= commitAttributeToXml(uiAttr, value);
                    uiAttr.setDirty(false);
                }
            }
        }
        if (dirtyAttributes.size() > 0) {
            result = true;

            Collections.sort(dirtyAttributes);

            // The Eclipse XML model will *always* append new attributes.
            // Therefore, if any of the dirty attributes are new, they will appear
            // after any existing, clean attributes on the element. To fix this,
            // we need to first remove any of these attributes, then insert them
            // back in the right order.
            Node element = prepareCommit();
            if (element == null) {
                return result;
            }

            if (AdtPrefs.getPrefs().getFormatGuiXml() && getEditor().supportsFormatOnGuiEdit()) {
                // If auto formatting, don't bother with attribute sorting here since the
                // order will be corrected as soon as the edit is committed anyway
                for (UiAttributeNode uiAttribute : dirtyAttributes) {
                    commitAttributeToXml(uiAttribute, uiAttribute.getCurrentValue());
                    uiAttribute.setDirty(false);
                }

                return result;
            }

            AttributeDescriptor descriptor = dirtyAttributes.get(0).getDescriptor();
            String firstName = descriptor.getXmlLocalName();
            String firstNamePrefix = null;
            String namespaceUri = descriptor.getNamespaceUri();
            if (namespaceUri != null) {
                firstNamePrefix = XmlUtils.lookupNamespacePrefix(element, namespaceUri);
            }
            NamedNodeMap attributes = ((Element) element).getAttributes();
            List<Attr> move = new ArrayList<Attr>();
            for (int i = 0, n = attributes.getLength(); i < n; i++) {
                Attr attribute = (Attr) attributes.item(i);
                if (XmlAttributeSortOrder.compareAttributes(
                        attribute.getPrefix(), attribute.getLocalName(),
                        firstNamePrefix, firstName) > 0) {
                    move.add(attribute);
                }
            }

            for (Attr attribute : move) {
                if (attribute.getNamespaceURI() != null) {
                    attributes.removeNamedItemNS(attribute.getNamespaceURI(),
                            attribute.getLocalName());
                } else {
                    attributes.removeNamedItem(attribute.getName());
                }
            }

            // Merge back the removed DOM attribute nodes and the new UI attribute nodes.
            // In cases where the attribute DOM name and the UI attribute names equal,
            // skip the DOM nodes and just apply the UI attributes.
            int domAttributeIndex = 0;
            int domAttributeIndexMax = move.size();
            int uiAttributeIndex = 0;
            int uiAttributeIndexMax = dirtyAttributes.size();

            while (true) {
                Attr domAttribute;
                UiAttributeNode uiAttribute;

                int compare;
                if (uiAttributeIndex < uiAttributeIndexMax) {
                    if (domAttributeIndex < domAttributeIndexMax) {
                        domAttribute = move.get(domAttributeIndex);
                        uiAttribute = dirtyAttributes.get(uiAttributeIndex);

                        String domAttributeName = domAttribute.getLocalName();
                        String uiAttributeName = uiAttribute.getDescriptor().getXmlLocalName();
                        compare = XmlAttributeSortOrder.compareAttributes(domAttributeName,
                                uiAttributeName);
                    } else {
                        compare = 1;
                        uiAttribute = dirtyAttributes.get(uiAttributeIndex);
                        domAttribute = null;
                    }
                } else if (domAttributeIndex < domAttributeIndexMax) {
                    compare = -1;
                    domAttribute = move.get(domAttributeIndex);
                    uiAttribute = null;
                } else {
                    break;
                }

                if (compare < 0) {
                    if (domAttribute.getNamespaceURI() != null) {
                        attributes.setNamedItemNS(domAttribute);
                    } else {
                        attributes.setNamedItem(domAttribute);
                    }
                    domAttributeIndex++;
                } else {
                    assert compare >= 0;
                    if (compare == 0) {
                        domAttributeIndex++;
                    }
                    commitAttributeToXml(uiAttribute, uiAttribute.getCurrentValue());
                    uiAttribute.setDirty(false);
                    uiAttributeIndex++;
                }
            }
        }

        return result;
    }

    /**
     * Utility method to internally set the value of a text attribute for the current
     * UiElementNode.
     * <p/>
     * This method is a helper. It silently ignores the errors such as the requested
     * attribute not being present in the element or attribute not being settable.
     * It accepts inherited attributes (such as layout).
     * <p/>
     * This does not commit to the XML model. It does mark the attribute node as dirty.
     * This is up to the caller.
     *
     * @see #commitAttributeToXml(UiAttributeNode, String)
     * @see #commitDirtyAttributesToXml()
     *
     * @param attrXmlName The XML <em>local</em> name of the attribute to modify
     * @param attrNsUri The namespace URI of the attribute.
     *                  Can be null if the attribute uses the global namespace.
     * @param value The new value for the attribute. If set to null, the attribute is removed.
     * @param override True if the value must be set even if one already exists.
     * @return The {@link UiAttributeNode} that has been modified or null.
     */
    public UiAttributeNode setAttributeValue(
            String attrXmlName,
            String attrNsUri,
            String value,
            boolean override) {
        if (value == null) {
            value = ""; //$NON-NLS-1$ -- this removes an attribute
        }

        getEditor().scheduleNodeReformat(this, true);

        // Try with all internal attributes
        UiAttributeNode uiAttr = setInternalAttrValue(
                getAllUiAttributes(), attrXmlName, attrNsUri, value, override);
        if (uiAttr != null) {
            return uiAttr;
        }

        if (uiAttr == null) {
            // Failed to find the attribute. For non-android attributes that is mostly expected,
            // in which case we just create a new custom one. As a side effect, we'll find the
            // attribute descriptor via getAllUiAttributes().
            addUnknownAttribute(attrXmlName, attrXmlName, attrNsUri);

            // We've created the attribute, but not actually set the value on it, so let's do it.
            // Try with the updated internal attributes.
            // Implementation detail: we could just do a setCurrentValue + setDirty on the
            // uiAttr returned by addUnknownAttribute(); however going through setInternalAttrValue
            // means we won't duplicate the logic, at the expense of doing one more lookup.
            uiAttr = setInternalAttrValue(
                    getAllUiAttributes(), attrXmlName, attrNsUri, value, override);
        }

        return uiAttr;
    }

    private UiAttributeNode setInternalAttrValue(
            Collection<UiAttributeNode> attributes,
            String attrXmlName,
            String attrNsUri,
            String value,
            boolean override) {

        // For namespace less attributes (like the "layout" attribute of an <include> tag
        // we may be passed "" as the namespace (during an attribute copy), and it
        // should really be null instead.
        if (attrNsUri != null && attrNsUri.length() == 0) {
            attrNsUri = null;
        }

        for (UiAttributeNode uiAttr : attributes) {
            AttributeDescriptor uiDesc = uiAttr.getDescriptor();

            if (uiDesc.getXmlLocalName().equals(attrXmlName)) {
                // Both NS URI must be either null or equal.
                if ((attrNsUri == null && uiDesc.getNamespaceUri() == null) ||
                        (attrNsUri != null && attrNsUri.equals(uiDesc.getNamespaceUri()))) {

                    // Not all attributes are editable, ignore those which are not.
                    if (uiAttr instanceof IUiSettableAttributeNode) {
                        String current = uiAttr.getCurrentValue();
                        // Only update (and mark as dirty) if the attribute did not have any
                        // value or if the value was different.
                        if (override || current == null || !current.equals(value)) {
                            ((IUiSettableAttributeNode) uiAttr).setCurrentValue(value);
                            // mark the attribute as dirty since their internal content
                            // as been modified, but not the underlying XML model
                            uiAttr.setDirty(true);
                            return uiAttr;
                        }
                    }

                    // We found the attribute but it's not settable. Since attributes are
                    // not duplicated, just abandon here.
                    break;
                }
            }
        }

        return null;
    }

    /**
     * Utility method to retrieve the internal value of an attribute.
     * <p/>
     * Note that this retrieves the *field* value if the attribute has some UI, and
     * not the actual XML value. They may differ if the attribute is dirty.
     *
     * @param attrXmlName The XML name of the attribute to modify
     * @return The current internal value for the attribute or null in case of error.
     */
    public String getAttributeValue(String attrXmlName) {
        HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();

        for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) {
            AttributeDescriptor uiDesc = entry.getKey();
            if (uiDesc.getXmlLocalName().equals(attrXmlName)) {
                UiAttributeNode uiAttr = entry.getValue();
                return uiAttr.getCurrentValue();
            }
        }
        return null;
    }

    // ------ IPropertySource methods

    @Override
    public Object getEditableValue() {
        return null;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
     *
     * Returns the property descriptor for this node. Since the descriptors are not linked to the
     * data, the AttributeDescriptor are used directly.
     */
    @Override
    public IPropertyDescriptor[] getPropertyDescriptors() {
        List<IPropertyDescriptor> propDescs = new ArrayList<IPropertyDescriptor>();

        // get the standard descriptors
        HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();
        Set<AttributeDescriptor> keys = attributeMap.keySet();


        // we only want the descriptor that do implement the IPropertyDescriptor interface.
        for (AttributeDescriptor key : keys) {
            if (key instanceof IPropertyDescriptor) {
                propDescs.add((IPropertyDescriptor)key);
            }
        }

        // now get the descriptor from the unknown attributes
        for (UiAttributeNode unknownNode : mUnknownUiAttributes) {
            if (unknownNode.getDescriptor() instanceof IPropertyDescriptor) {
                propDescs.add((IPropertyDescriptor)unknownNode.getDescriptor());
            }
        }

        // TODO cache this maybe, as it's not going to change (except for unknown descriptors)
        return propDescs.toArray(new IPropertyDescriptor[propDescs.size()]);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
     *
     * Returns the value of a given property. The id is the result of IPropertyDescriptor.getId(),
     * which return the AttributeDescriptor itself.
     */
    @Override
    public Object getPropertyValue(Object id) {
        HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();

        UiAttributeNode attribute = attributeMap.get(id);

        if (attribute == null) {
            // look for the id in the unknown attributes.
            for (UiAttributeNode unknownAttr : mUnknownUiAttributes) {
                if (id == unknownAttr.getDescriptor()) {
                    return unknownAttr;
                }
            }
        }

        return attribute;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.views.properties.IPropertySource#isPropertySet(java.lang.Object)
     *
     * Returns whether the property is set. In our case this is if the string is non empty.
     */
    @Override
    public boolean isPropertySet(Object id) {
        HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();

        UiAttributeNode attribute = attributeMap.get(id);

        if (attribute != null) {
            return attribute.getCurrentValue().length() > 0;
        }

        // look for the id in the unknown attributes.
        for (UiAttributeNode unknownAttr : mUnknownUiAttributes) {
            if (id == unknownAttr.getDescriptor()) {
                return unknownAttr.getCurrentValue().length() > 0;
            }
        }

        return false;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.views.properties.IPropertySource#resetPropertyValue(java.lang.Object)
     *
     * Reset the property to its default value. For now we simply empty it.
     */
    @Override
    public void resetPropertyValue(Object id) {
        HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();

        UiAttributeNode attribute = attributeMap.get(id);
        if (attribute != null) {
            // TODO: reset the value of the attribute

            return;
        }

        // look for the id in the unknown attributes.
        for (UiAttributeNode unknownAttr : mUnknownUiAttributes) {
            if (id == unknownAttr.getDescriptor()) {
                // TODO: reset the value of the attribute

                return;
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
     *
     * Set the property value. id is the result of IPropertyDescriptor.getId(), which is the
     * AttributeDescriptor itself. Value should be a String.
     */
    @Override
    public void setPropertyValue(Object id, Object value) {
        HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();

        UiAttributeNode attribute = attributeMap.get(id);

        if (attribute == null) {
            // look for the id in the unknown attributes.
            for (UiAttributeNode unknownAttr : mUnknownUiAttributes) {
                if (id == unknownAttr.getDescriptor()) {
                    attribute = unknownAttr;
                    break;
                }
            }
        }

        if (attribute != null) {

            // get the current value and compare it to the new value
            String oldValue = attribute.getCurrentValue();
            final String newValue = (String)value;

            if (oldValue.equals(newValue)) {
                return;
            }

            final UiAttributeNode fAttribute = attribute;
            AndroidXmlEditor editor = getEditor();
            editor.wrapEditXmlModel(new Runnable() {
                @Override
                public void run() {
                    commitAttributeToXml(fAttribute, newValue);
                }
            });
        }
    }

    /**
     * Returns true if this node is an ancestor (parent, grandparent, and so on)
     * of the given node. Note that a node is not considered an ancestor of
     * itself.
     *
     * @param node the node to test
     * @return true if this node is an ancestor of the given node
     */
    public boolean isAncestorOf(UiElementNode node) {
        node = node.getUiParent();
        while (node != null) {
            if (node == this) {
                return true;
            }
            node = node.getUiParent();
        }
        return false;
    }

    /**
     * Finds the nearest common parent of the two given nodes (which could be one of the
     * two nodes as well)
     *
     * @param node1 the first node to test
     * @param node2 the second node to test
     * @return the nearest common parent of the two given nodes
     */
    public static UiElementNode getCommonAncestor(UiElementNode node1, UiElementNode node2) {
        while (node2 != null) {
            UiElementNode current = node1;
            while (current != null && current != node2) {
                current = current.getUiParent();
            }
            if (current == node2) {
                return current;
            }
            node2 = node2.getUiParent();
        }

        return null;
    }

    // ---- Global node create/delete Listeners ----

    /** List of listeners to be notified of newly created nodes, or null */
    private static List<NodeCreationListener> sListeners;

    /** Notify listeners that a new node has been created */
    private void fireNodeCreated(UiElementNode newChild, int index) {
        // Nothing to do if there aren't any listeners. We don't need to worry about
        // the case where one thread is firing node changes while another is adding a listener
        // (in that case it's still okay for this node firing not to be heard) so perform
        // the check outside of synchronization.
        if (sListeners == null) {
            return;
        }
        synchronized (UiElementNode.class) {
            if (sListeners != null) {
                UiElementNode parent = newChild.getUiParent();
                for (NodeCreationListener listener : sListeners) {
                    listener.nodeCreated(parent, newChild, index);
                }
            }
        }
    }

    /** Notify listeners that a new node has been deleted */
    private void fireNodeDeleted(UiElementNode oldChild, int index) {
        if (sListeners == null) {
            return;
        }
        synchronized (UiElementNode.class) {
            if (sListeners != null) {
                UiElementNode parent = oldChild.getUiParent();
                for (NodeCreationListener listener : sListeners) {
                    listener.nodeDeleted(parent, oldChild, index);
                }
            }
        }
    }

    /**
     * Adds a {@link NodeCreationListener} to be notified when new nodes are created
     *
     * @param listener the listener to be notified
     */
    public static void addNodeCreationListener(NodeCreationListener listener) {
        synchronized (UiElementNode.class) {
            if (sListeners == null) {
                sListeners = new ArrayList<NodeCreationListener>(1);
            }
            sListeners.add(listener);
        }
    }

    /**
     * Removes a {@link NodeCreationListener} from the set of listeners such that it is
     * no longer notified when nodes are created.
     *
     * @param listener the listener to be removed from the notification list
     */
    public static void removeNodeCreationListener(NodeCreationListener listener) {
        synchronized (UiElementNode.class) {
            sListeners.remove(listener);
            if (sListeners.size() == 0) {
                sListeners = null;
            }
        }
    }

    /** Interface implemented by listeners to be notified of newly created nodes */
    public interface NodeCreationListener {
        /**
         * Called when a new child node is created and added to the given parent
         *
         * @param parent the parent of the created node
         * @param child the newly node
         * @param index the index among the siblings of the child <b>after</b>
         *            insertion
         */
        void nodeCreated(UiElementNode parent, UiElementNode child, int index);

        /**
         * Called when a child node is removed from the given parent
         *
         * @param parent the parent of the removed node
         * @param child the removed node
         * @param previousIndex the index among the siblings of the child
         *            <b>before</b> removal
         */
        void nodeDeleted(UiElementNode parent, UiElementNode child, int previousIndex);
    }
}
