/*
 * Copyright (C) 2011 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.layout.gle2;

import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_ID;
import static com.android.SdkConstants.ID_PREFIX;
import static com.android.SdkConstants.NEW_ID_PREFIX;
import static com.android.SdkConstants.TOOLS_URI;
import static org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML.ContentTypeID_XML;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
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.DescriptorsUtils;
import com.android.utils.Pair;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.text.IDocument;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
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.NodeList;
import org.xml.sax.InputSource;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * Various utility methods for manipulating DOM nodes.
 */
@SuppressWarnings("restriction") // No replacement for restricted XML model yet
public class DomUtilities {
    /**
     * 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
     */
    @Nullable
    public static Node getCommonAncestor(@NonNull Node node1, @NonNull Node node2) {
        while (node2 != null) {
            Node current = node1;
            while (current != null && current != node2) {
                current = current.getParentNode();
            }
            if (current == node2) {
                return current;
            }
            node2 = node2.getParentNode();
        }

        return null;
    }

    /**
     * Returns all elements below the given node (which can be a document,
     * element, etc). This will include the node itself, if it is an element.
     *
     * @param node the node to search from
     * @return all elements in the subtree formed by the node parameter
     */
    @NonNull
    public static List<Element> getAllElements(@NonNull Node node) {
        List<Element> elements = new ArrayList<Element>(64);
        addElements(node, elements);
        return elements;
    }

    private static void addElements(@NonNull Node node, @NonNull List<Element> elements) {
        if (node instanceof Element) {
            elements.add((Element) node);
        }

        NodeList childNodes = node.getChildNodes();
        for (int i = 0, n = childNodes.getLength(); i < n; i++) {
            addElements(childNodes.item(i), elements);
        }
    }

    /**
     * Returns the depth of the given node (with the document node having depth 0,
     * and the document element having depth 1)
     *
     * @param node the node to test
     * @return the depth in the document
     */
    public static int getDepth(@NonNull Node node) {
        int depth = -1;
        while (node != null) {
            depth++;
            node = node.getParentNode();
        }

        return depth;
    }

    /**
     * Returns true if the given node has one or more element children
     *
     * @param node the node to test for element children
     * @return true if the node has one or more element children
     */
    public static boolean hasElementChildren(@NonNull Node node) {
        NodeList children = node.getChildNodes();
        for (int i = 0, n = children.getLength(); i < n; i++) {
            if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns the DOM document for the given file
     *
     * @param file the XML file
     * @return the document, or null if not found or not parsed properly (no
     *         errors are generated/thrown)
     */
    @Nullable
    public static Document getDocument(@NonNull IFile file) {
        IModelManager modelManager = StructuredModelManager.getModelManager();
        if (modelManager == null) {
            return null;
        }
        try {
            IStructuredModel model = modelManager.getExistingModelForRead(file);
            if (model == null) {
                model = modelManager.getModelForRead(file);
            }
            if (model != null) {
                if (model instanceof IDOMModel) {
                    IDOMModel domModel = (IDOMModel) model;
                    return domModel.getDocument();
                }
                try {
                } finally {
                    model.releaseFromRead();
                }
            }
        } catch (Exception e) {
            // Ignore exceptions.
        }

        return null;
    }

    /**
     * Returns the DOM document for the given editor
     *
     * @param editor the XML editor
     * @return the document, or null if not found or not parsed properly (no
     *         errors are generated/thrown)
     */
    @Nullable
    public static Document getDocument(@NonNull AndroidXmlEditor editor) {
        IStructuredModel model = editor.getModelForRead();
        try {
            if (model instanceof IDOMModel) {
                IDOMModel domModel = (IDOMModel) model;
                return domModel.getDocument();
            }
        } finally {
            if (model != null) {
                model.releaseFromRead();
            }
        }

        return null;
    }


    /**
     * Returns the XML DOM node corresponding to the given offset of the given
     * document.
     *
     * @param document The document to look in
     * @param offset The offset to look up the node for
     * @return The node containing the offset, or null
     */
    @Nullable
    public static Node getNode(@NonNull IDocument document, int offset) {
        Node node = null;
        IModelManager modelManager = StructuredModelManager.getModelManager();
        if (modelManager == null) {
            return null;
        }
        try {
            IStructuredModel model = modelManager.getExistingModelForRead(document);
            if (model != null) {
                try {
                    for (; offset >= 0 && node == null; --offset) {
                        node = (Node) model.getIndexedRegion(offset);
                    }
                } finally {
                    model.releaseFromRead();
                }
            }
        } catch (Exception e) {
            // Ignore exceptions.
        }

        return node;
    }

    /**
     * Returns the editing context at the given offset, as a pair of parent node and child
     * node. This is not the same as just calling {@link DomUtilities#getNode} and taking
     * its parent node, because special care has to be taken to return content element
     * positions.
     * <p>
     * For example, for the XML {@code <foo>^</foo>}, if the caret ^ is inside the foo
     * element, between the opening and closing tags, then the foo element is the parent,
     * and the child is null which represents a potential text node.
     * <p>
     * If the node is inside an element tag definition (between the opening and closing
     * bracket) then the child node will be the element and whatever parent (element or
     * document) will be its parent.
     * <p>
     * If the node is in a text node, then the text node will be the child and its parent
     * element or document node its parent.
     * <p>
     * Finally, if the caret is on a boundary of a text node, then the text node will be
     * considered the child, regardless of whether it is on the left or right of the
     * caret. For example, in the XML {@code <foo>^ </foo>} and in the XML
     * {@code <foo> ^</foo>}, in both cases the text node is preferred over the element.
     *
     * @param document the document to search in
     * @param offset the offset to look up
     * @return a pair of parent and child elements, where either the parent or the child
     *         but not both can be null, and if non null the child.getParentNode() should
     *         return the parent. Note that the method can also return null if no
     *         document or model could be obtained or if the offset is invalid.
     */
    @Nullable
    public static Pair<Node, Node> getNodeContext(@NonNull IDocument document, int offset) {
        Node node = null;
        IModelManager modelManager = StructuredModelManager.getModelManager();
        if (modelManager == null) {
            return null;
        }
        try {
            IStructuredModel model = modelManager.getExistingModelForRead(document);
            if (model != null) {
                try {
                    for (; offset >= 0 && node == null; --offset) {
                        IndexedRegion indexedRegion = model.getIndexedRegion(offset);
                        if (indexedRegion != null) {
                            node = (Node) indexedRegion;

                            if (node.getNodeType() == Node.TEXT_NODE) {
                                return Pair.of(node.getParentNode(), node);
                            }

                            // Look at the structured document to see if
                            // we have the special case where the caret is pointing at
                            // a -potential- text node, e.g. <foo>^</foo>
                            IStructuredDocument doc = model.getStructuredDocument();
                            IStructuredDocumentRegion region =
                                doc.getRegionAtCharacterOffset(offset);

                            ITextRegion subRegion = region.getRegionAtCharacterOffset(offset);
                            String type = subRegion.getType();
                            if (DOMRegionContext.XML_END_TAG_OPEN.equals(type)) {
                                // Try to return the text node if it's on the left
                                // of this element node, such that replace strings etc
                                // can be computed.
                                Node lastChild = node.getLastChild();
                                if (lastChild != null) {
                                    IndexedRegion previousRegion = (IndexedRegion) lastChild;
                                    if (previousRegion.getEndOffset() == offset) {
                                        return Pair.of(node, lastChild);
                                    }
                                }
                                return Pair.of(node, null);
                            }

                            return Pair.of(node.getParentNode(), node);
                        }
                    }
                } finally {
                    model.releaseFromRead();
                }
            }
        } catch (Exception e) {
            // Ignore exceptions.
        }

        return null;
    }

    /**
     * Like {@link #getNode(IDocument, int)}, but has a bias parameter which lets you
     * indicate whether you want the search to look forwards or backwards.
     * This is vital when trying to compute a node range. Consider the following
     * XML fragment:
     * {@code
     *    <a/><b/>[<c/><d/><e/>]<f/><g/>
     * }
     * Suppose we want to locate the nodes in the range indicated by the brackets above.
     * If we want to search for the node corresponding to the start position, should
     * we pick the node on its left or the node on its right? Similarly for the end
     * position. Clearly, we'll need to bias the search towards the right when looking
     * for the start position, and towards the left when looking for the end position.
     * The following method lets us do just that. When passed an offset which sits
     * on the edge of the computed node, it will pick the neighbor based on whether
     * "forward" is true or false, where forward means searching towards the right
     * and not forward is obviously towards the left.
     * @param document the document to search in
     * @param offset the offset to search for
     * @param forward if true, search forwards, otherwise search backwards when on node boundaries
     * @return the node which surrounds the given offset, or the node adjacent to the offset
     *    where the side depends on the forward parameter
     */
    @Nullable
    public static Node getNode(@NonNull IDocument document, int offset, boolean forward) {
        Node node = getNode(document, offset);

        if (node instanceof IndexedRegion) {
            IndexedRegion region = (IndexedRegion) node;

            if (!forward && offset <= region.getStartOffset()) {
                Node left = node.getPreviousSibling();
                if (left == null) {
                    left = node.getParentNode();
                }

                node = left;
            } else if (forward && offset >= region.getEndOffset()) {
                Node right = node.getNextSibling();
                if (right == null) {
                    right = node.getParentNode();
                }
                node = right;
            }
        }

        return node;
    }

    /**
     * Returns a range of elements for the given caret range. Note that the two elements
     * may not be at the same level so callers may want to perform additional input
     * filtering.
     *
     * @param document the document to search in
     * @param beginOffset the beginning offset of the range
     * @param endOffset the ending offset of the range
     * @return a pair of begin+end elements, or null
     */
    @Nullable
    public static Pair<Element, Element> getElementRange(@NonNull IDocument document,
            int beginOffset, int endOffset) {
        Element beginElement = null;
        Element endElement = null;
        Node beginNode = getNode(document, beginOffset, true);
        Node endNode = beginNode;
        if (endOffset > beginOffset) {
            endNode = getNode(document, endOffset, false);
        }

        if (beginNode == null || endNode == null) {
            return null;
        }

        // Adjust offsets if you're pointing at text
        if (beginNode.getNodeType() != Node.ELEMENT_NODE) {
            // <foo> <bar1/> | <bar2/> </foo> => should pick <bar2/>
            beginElement = getNextElement(beginNode);
            if (beginElement == null) {
                // Might be inside the end of a parent, e.g.
                // <foo> <bar/> | </foo> => should pick <bar/>
                beginElement = getPreviousElement(beginNode);
                if (beginElement == null) {
                    // We must be inside an empty element,
                    // <foo> | </foo>
                    // In that case just pick the parent.
                    beginElement = getParentElement(beginNode);
                }
            }
        } else {
            beginElement = (Element) beginNode;
        }

        if (endNode.getNodeType() != Node.ELEMENT_NODE) {
            // In the following, | marks the caret position:
            // <foo> <bar1/> | <bar2/> </foo> => should pick <bar1/>
            endElement = getPreviousElement(endNode);
            if (endElement == null) {
                // Might be inside the beginning of a parent, e.g.
                // <foo> | <bar/></foo> => should pick <bar/>
                endElement = getNextElement(endNode);
                if (endElement == null) {
                    // We must be inside an empty element,
                    // <foo> | </foo>
                    // In that case just pick the parent.
                    endElement = getParentElement(endNode);
                }
            }
        } else {
            endElement = (Element) endNode;
        }

        if (beginElement != null && endElement != null) {
            return Pair.of(beginElement, endElement);
        }

        return null;
    }

    /**
     * Returns the next sibling element of the node, or null if there is no such element
     *
     * @param node the starting node
     * @return the next sibling element, or null
     */
    @Nullable
    public static Element getNextElement(@NonNull Node node) {
        while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
            node = node.getNextSibling();
        }

        return (Element) node; // may be null as well
    }

    /**
     * Returns the previous sibling element of the node, or null if there is no such element
     *
     * @param node the starting node
     * @return the previous sibling element, or null
     */
    @Nullable
    public static Element getPreviousElement(@NonNull Node node) {
        while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
            node = node.getPreviousSibling();
        }

        return (Element) node; // may be null as well
    }

    /**
     * Returns the closest ancestor element, or null if none
     *
     * @param node the starting node
     * @return the closest parent element, or null
     */
    @Nullable
    public static Element getParentElement(@NonNull Node node) {
        while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
            node = node.getParentNode();
        }

        return (Element) node; // may be null as well
    }

    /** Utility used by {@link #getFreeWidgetId(Element)} */
    private static void addLowercaseIds(@NonNull Element root, @NonNull Set<String> seen) {
        if (root.hasAttributeNS(ANDROID_URI, ATTR_ID)) {
            String id = root.getAttributeNS(ANDROID_URI, ATTR_ID);
            if (id.startsWith(NEW_ID_PREFIX)) {
                // See getFreeWidgetId for details on locale
                seen.add(id.substring(NEW_ID_PREFIX.length()).toLowerCase(Locale.US));
            } else if (id.startsWith(ID_PREFIX)) {
                seen.add(id.substring(ID_PREFIX.length()).toLowerCase(Locale.US));
            } else {
                seen.add(id.toLowerCase(Locale.US));
            }
        }
    }

    /**
     * Returns a suitable new widget id (not including the {@code @id/} prefix) for the
     * given element, which is guaranteed to be unique in this document
     *
     * @param element the element to compute a new widget id for
     * @param reserved an optional set of extra, "reserved" set of ids that should be
     *            considered taken
     * @param prefix an optional prefix to use for the generated name, or null to get a
     *            default (which is currently the tag name)
     * @return a unique id, never null, which does not include the {@code @id/} prefix
     * @see DescriptorsUtils#getFreeWidgetId
     */
    public static String getFreeWidgetId(
            @NonNull Element element,
            @Nullable Set<String> reserved,
            @Nullable String prefix) {
        Set<String> ids = new HashSet<String>();
        if (reserved != null) {
            for (String id : reserved) {
                // Note that we perform locale-independent lowercase checks; in "Image" we
                // want the lowercase version to be "image", not "?mage" where ? is
                // the char LATIN SMALL LETTER DOTLESS I.

                ids.add(id.toLowerCase(Locale.US));
            }
        }
        addLowercaseIds(element.getOwnerDocument().getDocumentElement(), ids);

        if (prefix == null) {
            prefix = DescriptorsUtils.getBasename(element.getTagName());
        }
        String generated;
        int num = 1;
        do {
            generated = String.format("%1$s%2$d", prefix, num++);   //$NON-NLS-1$
        } while (ids.contains(generated.toLowerCase(Locale.US)));

        return generated;
    }

    /**
     * Returns the element children of the given element
     *
     * @param element the parent element
     * @return a list of child elements, possibly empty but never null
     */
    @NonNull
    public static List<Element> getChildren(@NonNull Element element) {
        // Convenience to avoid lots of ugly DOM access casting
        NodeList children = element.getChildNodes();
        // An iterator would have been more natural (to directly drive the child list
        // iteration) but iterators can't be used in enhanced for loops...
        List<Element> result = new ArrayList<Element>(children.getLength());
        for (int i = 0, n = children.getLength(); i < n; i++) {
            Node node = children.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element child = (Element) node;
                result.add(child);
            }
        }

        return result;
    }

    /**
     * Returns true iff the given elements are contiguous siblings
     *
     * @param elements the elements to be tested
     * @return true if the elements are contiguous siblings with no gaps
     */
    public static boolean isContiguous(@NonNull List<Element> elements) {
        if (elements.size() > 1) {
            // All elements must be siblings (e.g. same parent)
            Node parent = elements.get(0).getParentNode();
            if (!(parent instanceof Element)) {
                return false;
            }
            for (Element node : elements) {
                if (parent != node.getParentNode()) {
                    return false;
                }
            }

            // Ensure that the siblings are contiguous; no gaps.
            // If we've selected all the children of the parent then we don't need
            // to look.
            List<Element> siblings = DomUtilities.getChildren((Element) parent);
            if (siblings.size() != elements.size()) {
                Set<Element> nodeSet = new HashSet<Element>(elements);
                boolean inRange = false;
                int remaining = elements.size();
                for (Element node : siblings) {
                    boolean in = nodeSet.contains(node);
                    if (in) {
                        remaining--;
                        if (remaining == 0) {
                            break;
                        }
                        inRange = true;
                    } else if (inRange) {
                        return false;
                    }
                }
            }
        }

        return true;
    }

    /**
     * Determines whether two element trees are equivalent. Two element trees are
     * equivalent if they represent the same DOM structure (elements, attributes, and
     * children in order). This is almost the same as simply checking whether the String
     * representations of the two nodes are identical, but this allows for minor
     * variations that are not semantically significant, such as variations in formatting
     * or ordering of the element attribute declarations, and the text children are
     * ignored (this is such that in for example layout where content is only used for
     * indentation the indentation differences are ignored). Null trees are never equal.
     *
     * @param element1 the first element to compare
     * @param element2 the second element to compare
     * @return true if the two element hierarchies are logically equal
     */
    public static boolean isEquivalent(@Nullable Element element1, @Nullable Element element2) {
        if (element1 == null || element2 == null) {
            return false;
        }

        if (!element1.getTagName().equals(element2.getTagName())) {
            return false;
        }

        // Check attribute map
        NamedNodeMap attributes1 = element1.getAttributes();
        NamedNodeMap attributes2 = element2.getAttributes();

        List<Attr> attributeNodes1 = new ArrayList<Attr>();
        for (int i = 0, n = attributes1.getLength(); i < n; i++) {
            Attr attribute = (Attr) attributes1.item(i);
            // Ignore tools uri namespace attributes for equivalency test
            if (TOOLS_URI.equals(attribute.getNamespaceURI())) {
                continue;
            }
            attributeNodes1.add(attribute);
        }
        List<Attr> attributeNodes2 = new ArrayList<Attr>();
        for (int i = 0, n = attributes2.getLength(); i < n; i++) {
            Attr attribute = (Attr) attributes2.item(i);
            // Ignore tools uri namespace attributes for equivalency test
            if (TOOLS_URI.equals(attribute.getNamespaceURI())) {
                continue;
            }
            attributeNodes2.add(attribute);
        }

        if (attributeNodes1.size() != attributeNodes2.size()) {
            return false;
        }

        if (attributes1.getLength() > 0) {
            Collections.sort(attributeNodes1, ATTRIBUTE_COMPARATOR);
            Collections.sort(attributeNodes2, ATTRIBUTE_COMPARATOR);
            for (int i = 0; i < attributeNodes1.size(); i++) {
                Attr attr1 = attributeNodes1.get(i);
                Attr attr2 = attributeNodes2.get(i);
                if (attr1.getLocalName() == null || attr2.getLocalName() == null) {
                    if (!attr1.getName().equals(attr2.getName())) {
                        return false;
                    }
                } else if (!attr1.getLocalName().equals(attr2.getLocalName())) {
                    return false;
                }
                if (!attr1.getValue().equals(attr2.getValue())) {
                    return false;
                }
                if (attr1.getNamespaceURI() == null) {
                    if (attr2.getNamespaceURI() != null) {
                        return false;
                    }
                } else if (attr2.getNamespaceURI() == null) {
                    return false;
                } else if (!attr1.getNamespaceURI().equals(attr2.getNamespaceURI())) {
                    return false;
                }
            }
        }

        NodeList children1 = element1.getChildNodes();
        NodeList children2 = element2.getChildNodes();
        int nextIndex1 = 0;
        int nextIndex2 = 0;
        while (true) {
            while (nextIndex1 < children1.getLength() &&
                    children1.item(nextIndex1).getNodeType() != Node.ELEMENT_NODE) {
                nextIndex1++;
            }

            while (nextIndex2 < children2.getLength() &&
                    children2.item(nextIndex2).getNodeType() != Node.ELEMENT_NODE) {
                nextIndex2++;
            }

            Element nextElement1 = (Element) (nextIndex1 < children1.getLength()
                    ? children1.item(nextIndex1) : null);
            Element nextElement2 = (Element) (nextIndex2 < children2.getLength()
                    ? children2.item(nextIndex2) : null);
            if (nextElement1 == null) {
                return nextElement2 == null;
            } else if (nextElement2 == null) {
                return false;
            } else if (!isEquivalent(nextElement1, nextElement2)) {
                return false;
            }
            nextIndex1++;
            nextIndex2++;
        }
    }

    /**
     * Finds the corresponding element in a document to a given element in another
     * document. Note that this does <b>not</b> do any kind of equivalence check
     * (see {@link #isEquivalent(Element, Element)}), and currently the search
     * is only by id; there is no structural search.
     *
     * @param element the element to find an equivalent for
     * @param document the document to search for an equivalent element in
     * @return an equivalent element, or null
     */
    @Nullable
    public static Element findCorresponding(@NonNull Element element, @NonNull Document document) {
        // Make sure the method is called correctly -- the element is for a different
        // document than the one we are searching
        assert element.getOwnerDocument() != document;

        // First search by id. This allows us to find the corresponding
        String id = element.getAttributeNS(ANDROID_URI, ATTR_ID);
        if (id != null && id.length() > 0) {
            if (id.startsWith(ID_PREFIX)) {
                id = NEW_ID_PREFIX + id.substring(ID_PREFIX.length());
            }

            return findCorresponding(document.getDocumentElement(), id);
        }

        // TODO: Search by structure - look in the document and
        // find a corresponding element in the same location in the structure,
        // e.g. 4th child of root, 3rd child, 6th child, then pick node with tag "foo".

        return null;
    }

    /** Helper method for {@link #findCorresponding(Element, Document)} */
    @Nullable
    private static Element findCorresponding(@NonNull Element element, @NonNull String targetId) {
        String id = element.getAttributeNS(ANDROID_URI, ATTR_ID);
        if (id != null) { // Work around DOM bug
            if (id.equals(targetId)) {
                return element;
            } else if (id.startsWith(ID_PREFIX)) {
                id = NEW_ID_PREFIX + id.substring(ID_PREFIX.length());
                if (id.equals(targetId)) {
                    return element;
                }
            }
        }

        NodeList children = element.getChildNodes();
        for (int i = 0, n = children.getLength(); i < n; i++) {
            Node node = children.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element child = (Element) node;
                Element match = findCorresponding(child, targetId);
                if (match != null) {
                    return match;
                }
            }
        }

        return null;
    }

    /**
     * Parses the given XML string as a DOM document, using Eclipse's structured
     * XML model (which for example allows us to distinguish empty elements
     * (<foo/>) from elements with no children (<foo></foo>).
     *
     * @param xml the XML content to be parsed (must be well formed)
     * @return the DOM document, or null
     */
    @Nullable
    public static Document parseStructuredDocument(@NonNull String xml) {
        IStructuredModel model = createStructuredModel(xml);
        if (model instanceof IDOMModel) {
            IDOMModel domModel = (IDOMModel) model;
            return domModel.getDocument();
        }

        return null;
    }

    /**
     * Parses the given XML string and builds an Eclipse structured model for it.
     *
     * @param xml the XML content to be parsed (must be well formed)
     * @return the structured model
     */
    @Nullable
    public static IStructuredModel createStructuredModel(@NonNull String xml) {
        IStructuredModel model = createEmptyModel();
        IStructuredDocument document = model.getStructuredDocument();
        model.aboutToChangeModel();
        document.set(xml);
        model.changedModel();

        return model;
    }

    /**
     * Creates an empty Eclipse XML model
     *
     * @return a new Eclipse XML model
     */
    @NonNull
    public static IStructuredModel createEmptyModel() {
        IModelManager modelManager = StructuredModelManager.getModelManager();
        return modelManager.createUnManagedStructuredModelFor(ContentTypeID_XML);
    }

    /**
     * Creates an empty Eclipse XML document
     *
     * @return an empty Eclipse XML document
     */
    @Nullable
    public static Document createEmptyDocument() {
        IStructuredModel model = createEmptyModel();
        if (model instanceof IDOMModel) {
            IDOMModel domModel = (IDOMModel) model;
            return domModel.getDocument();
        }

        return null;
    }

    /**
     * Creates an empty non-Eclipse XML document.
     * This is used when you need to use XML operations not supported by
     * the Eclipse XML model (such as serialization).
     * <p>
     * The new document will not validate, will ignore comments, and will
     * support namespace.
     *
     * @return the new document
     */
    @Nullable
    public static Document createEmptyPlainDocument() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        factory.setValidating(false);
        factory.setIgnoringComments(true);
        DocumentBuilder builder;
        try {
            builder = factory.newDocumentBuilder();
            return builder.newDocument();
        } catch (ParserConfigurationException e) {
            AdtPlugin.log(e, null);
        }

        return null;
    }

    /**
     * Parses the given XML string as a DOM document, using the JDK parser.
     * The parser does not validate, and is namespace aware.
     *
     * @param xml the XML content to be parsed (must be well formed)
     * @param logParserErrors if true, log parser errors to the log, otherwise
     *            silently return null
     * @return the DOM document, or null
     */
    @Nullable
    public static Document parseDocument(@NonNull String xml, boolean logParserErrors) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        InputSource is = new InputSource(new StringReader(xml));
        factory.setNamespaceAware(true);
        factory.setValidating(false);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.parse(is);
        } catch (Exception e) {
            if (logParserErrors) {
                AdtPlugin.log(e, null);
            }
        }

        return null;
    }

    /** Can be used to sort attributes by name */
    private static final Comparator<Attr> ATTRIBUTE_COMPARATOR = new Comparator<Attr>() {
        @Override
        public int compare(Attr a1, Attr a2) {
            return a1.getName().compareTo(a2.getName());
        }
    };
}
