/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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.manifmerger;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.manifmerger.IMergerLog.FileAndLine;
import com.android.manifmerger.IMergerLog.Severity;
import com.android.xml.AndroidXPathFactory;

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 java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

/**
 * Merges a library manifest into a main application manifest.
 * <p/>
 * To use, create with {@link ManifestMerger#ManifestMerger(IMergerLog, ICallback)} then
 * call {@link ManifestMerger#process(File, File, File[])}.
 * <p/>
 * <pre> Merge operations:
 * - root manifest: attributes ignored, warn if defined.
 * - application:
 *      G- {@code @attributes}: most attributes are ignored in libs
 *          except: application:name if defined, it must match.
 *          except: application:agentBackup if defined, it must match.
 *          (these represent class names and we don't want a lib to assume their app or backup
 *           classes are being used when that will never be the case.)
 *      C- activity / activity-alias / service / receiver / provider
 *          => Merge as-is. Error if exists in the destination (same {@code @name})
 *             unless the definitions are exactly the same.
 *             New elements are always merged at the end of the application element.
 *          => Indicate if there's a dup.
 *      D- uses-library
 *          => Merge. OK if already exists same {@code @name}.
 *          => Merge {@code @required}: true>false.
 * A- instrumentation:
 *      => Do not merge. ignore the ones from libs.
 * C- permission / permission-group / permission-tree:
 *      => Merge as-is. Error if exists in the destination (same {@code @name})
 *         unless the definitions are exactly the same.
 * C- uses-permission:
 *      => Add. OK if already defined.
 * E- uses-sdk:
 *      {@code @minSdkVersion}: error if dest&lt;lib. Never automatically change dest minsdk.
 *                              Codenames are accepted if we can resolve their API level.
 *      {@code @targetSdkVersion}: warning if dest&lt;lib.
 *                                 Never automatically change dest targetsdk.
 *      {@code @maxSdkVersion}: obsolete, ignored. Not used in comparisons and not merged.
 * D- uses-feature with {@code @name}:
 *      => Merge with same {@code @name}
 *      => Merge {@code @required}: true>false.
 *      - Do not merge any {@code @glEsVersion} attribute at this point.
 * F- uses-feature with {@code @glEsVersion}:
 *      => Error if defined in lib+dest with dest&lt;lib. Never automatically change dest.
 * B- uses-configuration:
 *      => There can be many. Error if source defines one that is not an exact match in dest.
 *      (e.g. right now app must manually define something that matches exactly each lib)
 * B- supports-screens / compatible-screens:
 *      => Do not merge.
 *      => Error (warn?) if defined in lib and not strictly the same as in dest.
 * B- supports-gl-texture:
 *      => Do not merge. Can have more than one.
 *      => Error (warn?) if defined in lib and not present as-is in dest.
 *
 * Strategies:
 * A = Ignore, do not merge (no-op).
 * B = Do not merge but if defined in both must match equally.
 * C = Must not exist in dest or be exactly the same (key is the {@code @name} attribute).
 * D = Add new or merge with same key {@code @name}, adjust {@code @required} true>false.
 * E, F, G = Custom strategies; see above.
 *
 * What happens when merging libraries with conflicting information?
 * Say for example a main manifest has a minSdkVersion of 3, whereas libraries have
 * a minSdkVersion of 4 and 11. We could have 2 point of views:
 * - Play it safe: If we have a library with a minSdkVersion of 11, it means this
 *   library code knows it can't work reliably on a lower API level. So the safest end
 *   result would be a merged manifest with the highest minSdkVersion of all libraries.
 * - Trust the main manifest: When an app declares a given minSdkVersion, it also expects
 *   to run a given range of devices. If we change the final minSdkVersion, the app won't
 *   be available on as many devices as the developer might expect. And as a counterpoint
 *   to issue 1, the app may be careful and not call the library without checking the
 *   necessary features or APIs are available before hand.
 * Both points of views are conflicting. The solution taken here is to be conservative
 * and generate an error rather than merge and change a value that might be surprising.
 * On the other hand this can be problematic and force a developer to keep the main
 * manifest in sync with the libraries ones, in essence reducing the usefulness of the
 * automated merge to pure trivial cases. The idea is to just start this way and enhance
 * or revisit the mechanism later.
 * </pre>
 */
public class ManifestMerger {

    /** Logger object. Never null. */
    private final IMergerLog mLog;
    /** An optional callback that the merger can use to query the calling SDK. */
    private final ICallback mCallback;
    private XPath mXPath;
    private Document mMainDoc;

    private String NS_URI = SdkConstants.NS_RESOURCES;
    private String NS_PREFIX = AndroidXPathFactory.DEFAULT_NS_PREFIX;
    private int destMinSdk;

    /**
     * Sets of element/attribute that need to be treated as class names.
     * The attribute name must be the local name for the Android namespace.
     * For example "application/name" maps to &lt;application android:name=...&gt;.
     */
    private static final String[] sClassAttributes = {
            "application/name",
            "application/backupAgent",
            "activity/name",
            "receiver/name",
            "service/name",
            "provider/name",
            "instrumentation/name"
    };

    /**
     * Creates a new {@link ManifestMerger}.
     *
     * @param log A non-null merger log to capture all warnings, errors and their location.
     * @param callback An optional callback that the merger can use to query the calling SDK.
     */
    public ManifestMerger(@NonNull IMergerLog log, @Nullable ICallback callback) {
        mLog = log;
        mCallback = callback;
    }

    /**
     * Performs the merge operation.
     * <p/>
     * This does NOT stop on errors, in an attempt to accumulate as much
     * info as possible to return to the user.
     * Unless it failed to read the main manifest, a result file will be
     * created. However if process() returns false, the file should not
     * be used except for debugging purposes.
     *
     * @param outputFile The output path to generate. Can be the same as the main path.
     * @param mainFile The main manifest paths to read. What we merge into.
     * @param libraryFiles The library manifest paths to read. Must not be null.
     * @return True if the merge was completed, false otherwise.
     */
    public boolean process(File outputFile, File mainFile, File[] libraryFiles) {
        Document mainDoc = XmlUtils.parseDocument(mainFile, mLog);
        if (mainDoc == null) {
            return false;
        }

        boolean success = process(mainDoc, libraryFiles);

        if (!XmlUtils.printXmlFile(mainDoc, outputFile, mLog)) {
            success = false;
        }
        return success;
    }

    /**
     * Performs the merge operation in-place in the given DOM.
     * <p/>
     * This does NOT stop on errors, in an attempt to accumulate as much
     * info as possible to return to the user.
     * <p/>
     * The method might modify the input XML document in-place for its own processing.
     *
     * @param mainDoc The document to merge into. Will be modified in-place.
     * @param libraryFiles The library manifest paths to read. Must not be null.
     *                     These will be modified in-place.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    public boolean process(Document mainDoc, File[] libraryFiles) {

        boolean success = true;
        mMainDoc = mainDoc;
        XmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST);

        String prefix = XmlUtils.lookupNsPrefix(mainDoc, SdkConstants.NS_RESOURCES);
        mXPath = AndroidXPathFactory.newXPath(prefix);

        expandFqcns(mainDoc);
        for (File libFile : libraryFiles) {
            Document libDoc = XmlUtils.parseDocument(libFile, mLog);
            if (libDoc == null || !mergeLibDoc(libDoc)) {
                success = false;
            }
        }

        mXPath = null;
        mMainDoc = null;
        return success;
    }

    /**
     * Performs the merge operation in-place in the given DOM.
     * <p/>
     * This does NOT stop on errors, in an attempt to accumulate as much
     * info as possible to return to the user.
     * <p/>
     * The method might modify the input XML documents in-place for its own processing.
     *
     * @param mainDoc The document to merge into. Will be modified in-place.
     * @param libraryDocs The library manifest documents to merge in. Must not be null.
     *                    These will be modified in-place.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    public boolean process(@NonNull Document mainDoc, @NonNull Document... libraryDocs) {

        boolean success = true;
        mMainDoc = mainDoc;
        XmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST);

        String prefix = XmlUtils.lookupNsPrefix(mainDoc, SdkConstants.NS_RESOURCES);
        mXPath = AndroidXPathFactory.newXPath(prefix);

        expandFqcns(mainDoc);
        for (Document libDoc : libraryDocs) {
            XmlUtils.decorateDocument(libDoc, IMergerLog.LIBRARY);
            if (!mergeLibDoc(libDoc)) {
                success = false;
            }
        }

        mXPath = null;
        mMainDoc = null;
        return success;
    }

    // --------

    /**
     * Merges the given library manifest into the destination manifest.
     * See {@link ManifestMerger} for merge details.
     *
     * @param libDoc The library document to merge from. Must not be null.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    private boolean mergeLibDoc(Document libDoc) {

        boolean err = false;

        expandFqcns(libDoc);

        // Strategy G (check <application> is compatible)
        err |= !checkApplication(libDoc);

        // Strategy B
        err |= !doNotMergeCheckEqual("/manifest/uses-configuration",  libDoc);     //$NON-NLS-1$
        err |= !doNotMergeCheckEqual("/manifest/supports-screens",    libDoc);     //$NON-NLS-1$
        err |= !doNotMergeCheckEqual("/manifest/compatible-screens",  libDoc);     //$NON-NLS-1$
        err |= !doNotMergeCheckEqual("/manifest/supports-gl-texture", libDoc);     //$NON-NLS-1$

        // Strategy C
        err |= !mergeNewOrEqual(
                    "/manifest/application/activity",                               //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    true);
        err |= !mergeNewOrEqual(
                    "/manifest/application/activity-alias",                         //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    true);
        err |= !mergeNewOrEqual(
                    "/manifest/application/service",                                //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    true);
        err |= !mergeNewOrEqual(
                    "/manifest/application/receiver",                               //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    true);
        err |= !mergeNewOrEqual(
                    "/manifest/application/provider",                               //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    true);
        err |= !mergeNewOrEqual(
                    "/manifest/permission",                                         //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    false);
        err |= !mergeNewOrEqual(
                    "/manifest/permission-group",                                   //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    false);
        err |= !mergeNewOrEqual(
                    "/manifest/permission-tree",                                    //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    false);
        err |= !mergeNewOrEqual(
                    "/manifest/uses-permission",                                    //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    libDoc,
                    false);

        // Strategy D
        err |= !mergeAdjustRequired(
                    "/manifest/application/uses-library",                           //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    "required",                                                     //$NON-NLS-1$
                    libDoc,
                    null /*alternateKeyAttr*/);
        err |= !mergeAdjustRequired(
                    "/manifest/uses-feature",                                       //$NON-NLS-1$
                    "name",                                                         //$NON-NLS-1$
                    "required",                                                     //$NON-NLS-1$
                    libDoc,
                    "glEsVersion" /*alternateKeyAttr*/);

        // Strategy E
        err |= !checkSdkVersion(libDoc);

        // Strategy F
        err |= !checkGlEsVersion(libDoc);

        return !err;
    }

    /**
     * Expand all possible class names attributes in the given document.
     * <p/>
     * Some manifest attributes represent class names. These can be specified as fully
     * qualified class names or use a short notation consisting of just the terminal
     * class simple name or a dot followed by a partial class name. Unfortunately this
     * makes textual comparison of the attributes impossible. To simplify this, we can
     * modify the document to fully expand all these class names. The list of elements
     * and attributes to process is listed by {@link #sClassAttributes} and the expansion
     * simply consists of appending the manifest' package if defined.
     *
     * @param doc The document in which to expand potential FQCNs.
     */
    private void expandFqcns(Document doc) {
        // Find the package attribute of the manifest.
        String pkg = null;
        Element manifest = findFirstElement(doc, "/manifest");
        if (manifest != null) {
            pkg = manifest.getAttribute("package");
        }

        if (pkg == null || pkg.length() == 0) {
            // We can't adjust FQCNs if we don't know the root package name.
            // It's not a proper manifest if this is missing anyway.
            assert manifest != null;
            mLog.error(Severity.WARNING,
                       xmlFileAndLine(manifest),
                       "Missing 'package' attribute in manifest.");
            return;
        }

        for (String elementAttr : sClassAttributes) {
            String[] names = elementAttr.split("/");
            if (names.length != 2) {
                continue;
            }
            String elemName = names[0];
            String attrName = names[1];
            NodeList elements = doc.getElementsByTagName(elemName);
            for (int i = 0; i < elements.getLength(); i++) {
                Node elem = elements.item(i);
                if (elem instanceof Element) {
                    Attr attr = ((Element) elem).getAttributeNodeNS(NS_URI, attrName);
                    if (attr != null) {
                        String value = attr.getNodeValue();

                        // We know it's a shortened FQCN if it starts with a dot
                        // or does not contain any dot.
                        if (value != null && value.length() > 0 &&
                                (value.indexOf('.') == -1 || value.charAt(0) == '.')) {
                            if (value.charAt(0) == '.') {
                                value = pkg + value;
                            } else {
                                value = pkg + '.' + value;
                            }
                            attr.setNodeValue(value);
                        }
                    }
                }
            }
        }
    }

    /**
     * Checks (but does not merge) the application attributes using the following rules:
     * <pre>
     * - {@code @name}: Ignore if empty. Warning if its expanded FQCN doesn't match the main doc.
     * - {@code @backupAgent}:  Ignore if empty. Warning if its expanded FQCN doesn't match main doc.
     * - All other attributes are ignored.
     * </pre>
     * The name and backupAgent represent classes and the merger will warn since if a lib has
     * these defined they will never be used anyway.
     * @param libDoc The library document to merge from. Must not be null.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    private boolean checkApplication(Document libDoc) {

        Element mainApp = findFirstElement(mMainDoc, "/manifest/application");  //$NON-NLS-1$
        Element libApp  = findFirstElement(libDoc,   "/manifest/application");  //$NON-NLS-1$

        // A manifest does not necessarily define an application.
        // If the lib has none, there's nothing to check for.
        if (libApp == null) {
            return true;
        }

        for (String attrName : new String[] { "name", "backupAgent" }) {
            String libValue  = getAttributeValue(libApp, attrName);
            if (libValue == null || libValue.length() == 0) {
                // Nothing to do if the attribute is not defined in the lib.
                continue;
            }
            // The main doc does not have to have an application node.
            String mainValue = mainApp == null ? "" : getAttributeValue(mainApp, attrName);
            if (!libValue.equals(mainValue)) {
                assert mainApp != null;
                mLog.conflict(Severity.WARNING,
                        xmlFileAndLine(mainApp),
                        xmlFileAndLine(libApp),
                        mainApp == null ?
                            "Library has <application android:%1$s='%3$s'> but main manifest has no application element." :
                            "Main manifest has <application android:%1$s='%2$s'> but library uses %1$s='%3$s'.",
                        attrName,
                        mainValue,
                        libValue);
            }
        }

        return true;
    }

    /**
     * Do not merge anything. Instead it checks that the requested elements from the
     * given library are all present and equal in the destination and prints a warning
     * if it's not the case.
     * <p/>
     * For example if a library supports a given screen configuration, print a
     * warning if the main manifest doesn't indicate the app supports the same configuration.
     * We should not merge it since we don't want to silently give the impression an app
     * supports a configuration just because it uses a library which does.
     * On the other hand we don't want to silently ignore this fact.
     * <p/>
     * TODO there should be a way to silence this warning.
     * The current behavior is certainly arbitrary and needs to be tweaked somehow.
     *
     * @param path The XPath of the elements to merge from the library. Must not be null.
     * @param libDoc The library document to merge from. Must not be null.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    private boolean doNotMergeCheckEqual(String path, Document libDoc) {

        for (Element src : findElements(libDoc, path)) {

            boolean found = false;

            for (Element dest : findElements(mMainDoc, path)) {
                if (compareElements(src, dest, false, null /*diff*/, null /*keyAttr*/)) {
                    found = true;
                    break;
                }
            }

            if (!found) {
                mLog.conflict(Severity.WARNING,
                        xmlFileAndLine(mMainDoc),
                        xmlFileAndLine(src),
                        "%1$s defined in library, missing from main manifest:\n%2$s",
                        path,
                        XmlUtils.dump(src, false /*nextSiblings*/));
            }
        }

        return true;
    }

    /**
     * Merges the requested elements from the library in the main document.
     * The key attribute name is used to identify the same elements.
     * Merged elements must either not exist in the destination or be identical.
     * <p/>
     * When merging, append to the end of the application element.
     * Also merges any preceding whitespace and up to one comment just prior to the merged element.
     *
     * @param path The XPath of the elements to merge from the library. Must not be null.
     * @param keyAttr The Android-namespace attribute used as key to identify similar elements.
     *   E.g. "name" for "android:name"
     * @param libDoc The library document to merge from. Must not be null.
     * @param warnDups When true, will print a warning when a library definition is already
     *   present in the destination and is equal.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    private boolean mergeNewOrEqual(
            String path,
            String keyAttr,
            Document libDoc,
            boolean warnDups) {

        // The parent of XPath /p1/p2/p3 is /p1/p2. To find it, delete the last "/segment"
        int pos = path.lastIndexOf('/');
        assert pos > 1;
        String parentPath = path.substring(0, pos);
        Element parent = findFirstElement(mMainDoc, parentPath);
        assert parent != null;
        if (parent == null) {
            mLog.error(Severity.ERROR,
                    xmlFileAndLine(mMainDoc),
                    "Could not find element %1$s.",
                    parentPath);
            return false;
        }

        boolean success = true;

        nextSource: for (Element src : findElements(libDoc, path)) {
            String name = getAttributeValue(src, keyAttr);
            if (name.length() == 0) {
                mLog.error(Severity.ERROR,
                        xmlFileAndLine(src),
                        "Undefined '%1$s' attribute in %2$s.",
                        keyAttr, path);
                success = false;
                continue;
            }

            // Look for the same item in the destination
            List<Element> dests = findElements(mMainDoc, path, keyAttr, name);
            if (dests.size() > 1) {
                // This should not be happening. We'll just use the first one found in this case.
                mLog.error(Severity.WARNING,
                        xmlFileAndLine(dests.get(0)),
                        "Manifest has more than one %1$s[@%2$s=%3$s] element.",
                        path, keyAttr, name);
            }
            for (Element dest : dests) {
                // If there's already a similar node in the destination, check it's identical.
                StringBuilder diff = new StringBuilder();
                if (compareElements(src, dest, false, diff, keyAttr)) {
                    // Same element. Skip.
                    if (warnDups) {
                        mLog.conflict(Severity.INFO,
                                xmlFileAndLine(dest),
                                xmlFileAndLine(src),
                                "Skipping identical %1$s[@%2$s=%3$s] element.",
                                path, keyAttr, name);
                    }
                    continue nextSource;
                } else {
                    // Print the diff we got from the comparison.
                    mLog.conflict(Severity.ERROR,
                            xmlFileAndLine(dest),
                            xmlFileAndLine(src),
                            "Trying to merge incompatible %1$s[@%2$s=%3$s] element:\n%4$s",
                            path, keyAttr, name, diff.toString());
                    success = false;
                    continue nextSource;
                }
            }

            // Ready to merge element src. Select which previous siblings to merge.
            Node start = selectPreviousSiblings(src);

            insertAtEndOf(parent, start, src);
        }

        return success;
    }

    /**
     * Returns the value of the given "android:attribute" in the given element.
     *
     * @param element The non-null element where to extract the attribute.
     * @param attrName The local name of the attribute.
     *                 It must use the {@link #NS_URI} but no prefix should be specified here.
     * @return The value of the attribute or a non-null empty string if not found.
     */
    private String getAttributeValue(Element element, String attrName) {
        Attr attr = element.getAttributeNodeNS(NS_URI, attrName);
        String value = attr == null ? "" : attr.getNodeValue();  //$NON-NLS-1$
        return value;
    }

    /**
     * Merge elements as identified by their key name attribute.
     * The element must have an option boolean "required" attribute which can be either "true" or
     * "false". Default is true if the attribute is misisng. When merging, a "false" is superseded
     * by a "true" (explicit or implicit).
     * <p/>
     * When merging, this does NOT merge any other attributes than {@code keyAttr} and
     * {@code requiredAttr}.
     *
     * @param path The XPath of the elements to merge from the library. Must not be null.
     * @param keyAttr The Android-namespace attribute used as key to identify similar elements.
     *   E.g. "name" for "android:name"
     * @param requiredAttr The name of the Android-namespace boolean attribute that must be merged.
     *   Typically should be "required".
     * @param libDoc The library document to merge from. Must not be null.
     * @param alternateKeyAttr When non-null, this is an alternate valid key attribute. If the
     *   default key attribute is missing, we won't output a warning if the alternate one is
     *   present.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    private boolean mergeAdjustRequired(
            String path,
            String keyAttr,
            String requiredAttr,
            Document libDoc,
            @Nullable String alternateKeyAttr) {

        // The parent of XPath /p1/p2/p3 is /p1/p2. To find it, delete the last "/segment"
        int pos = path.lastIndexOf('/');
        assert pos > 1;
        String parentPath = path.substring(0, pos);
        Element parent = findFirstElement(mMainDoc, parentPath);
        assert parent != null;
        if (parent == null) {
            mLog.error(Severity.ERROR,
                    xmlFileAndLine(mMainDoc),
                    "Could not find element %1$s.",
                    parentPath);
            return false;
        }

        boolean success = true;

        for (Element src : findElements(libDoc, path)) {
            Attr attr = src.getAttributeNodeNS(NS_URI, keyAttr);
            String name = attr == null ? "" : attr.getNodeValue().trim();  //$NON-NLS-1$
            if (name.length() == 0) {
                if (alternateKeyAttr != null) {
                    attr = src.getAttributeNodeNS(NS_URI, alternateKeyAttr);
                    String s = attr == null ? "" : attr.getNodeValue().trim(); //$NON-NLS-1$
                    if (s.length() != 0) {
                        // This element lacks the keyAttr but has the alternateKeyAttr. Skip it.
                        continue;
                    }
                }

                mLog.error(Severity.ERROR,
                        xmlFileAndLine(src),
                        "Undefined '%1$s' attribute in %2$s.",
                        keyAttr, path);
                success = false;
                continue;
            }

            // Look for the same item in the destination
            List<Element> dests = findElements(mMainDoc, path, keyAttr, name);
            if (dests.size() > 1) {
                // This should not be happening. We'll just use the first one found in this case.
                mLog.error(Severity.WARNING,
                        xmlFileAndLine(dests.get(0)),
                        "Manifest has more than one %1$s[@%2$s=%3$s] element.",
                        path, keyAttr, name);
            }
            if (dests.size() > 0) {
                attr = src.getAttributeNodeNS(NS_URI, requiredAttr);
                String value = attr == null ? "true" : attr.getNodeValue();    //$NON-NLS-1$
                if (value == null || !(value.equals("true") || value.equals("false"))) {
                    mLog.error(Severity.WARNING,
                            xmlFileAndLine(src),
                            "Invalid attribute '%1$s' in %2$s[@%3$s=%4$s] element:\nExpected 'true' or 'false' but found '%5$s'.",
                            requiredAttr, path, keyAttr, name, value);
                    continue;
                }
                boolean boolE = Boolean.parseBoolean(value);

                for (Element dest : dests) {
                    // Destination node exists. Compare the required attributes.

                    attr = dest.getAttributeNodeNS(NS_URI, requiredAttr);
                    value = attr == null ? "true" : attr.getNodeValue();    //$NON-NLS-1$
                    if (value == null || !(value.equals("true") || value.equals("false"))) {
                        mLog.error(Severity.WARNING,
                                xmlFileAndLine(dest),
                                "Invalid attribute '%1$s' in %2$s[@%3$s=%4$s] element:\nExpected 'true' or 'false' but found '%5$s'.",
                                requiredAttr, path, keyAttr, name, value);
                        continue;
                    }
                    boolean boolD = Boolean.parseBoolean(value);

                    if (!boolD && boolE) {
                        // Required attributes differ: destination is false and source was true
                        // so we need to change the destination to true.

                        // If attribute was already in the destination, change it in place
                        if (attr != null) {
                            attr.setNodeValue("true");                        //$NON-NLS-1$
                        } else {
                            // Otherwise, do nothing. The destination doesn't have the
                            // required=true attribute, and true is the default value.
                            // Consequently not setting is the right thing to do.

                            // -- code snippet for reference --
                            // If we wanted to create a new attribute, we'd use the code
                            // below. There's a simpler call to d.setAttributeNS(ns, name, value)
                            // but experience shows that it would create a new prefix out of the
                            // blue instead of looking it up.
                            //
                            // Attr a=d.getOwnerDocument().createAttributeNS(NS_URI, requiredAttr);
                            // String prefix = d.lookupPrefix(NS_URI);
                            // if (prefix != null) {
                            //     a.setPrefix(prefix);
                            // }
                            // a.setValue("true");  //$NON-NLS-1$
                            // d.setAttributeNodeNS(attr);
                        }
                    }
                }
            } else {
                // Destination doesn't exist. We simply merge the source element.
                // Select which previous siblings to merge.
                Node start = selectPreviousSiblings(src);

                Node node = insertAtEndOf(parent, start, src);

                NamedNodeMap attrs = node.getAttributes();
                if (attrs != null) {
                    for (int i = 0; i < attrs.getLength(); i++) {
                        Node a = attrs.item(i);
                        if (a.getNodeType() == Node.ATTRIBUTE_NODE) {
                            boolean keep = NS_URI.equals(a.getNamespaceURI());
                            if (keep) {
                                name = a.getLocalName();
                                keep = keyAttr.equals(name) || requiredAttr.equals(name);
                            }
                            if (!keep) {
                                attrs.removeNamedItemNS(NS_URI, name);
                                // Restart the loop from index 0 since there's no
                                // guarantee on the order of the nodes in the "map".
                                // This makes it O(n+2n) at most, where n is [2..3] in
                                // a typical case.
                                i = -1;
                            }
                        }
                    }
                }
            }
        }

        return success;
    }



    /**
     * Checks (but does not merge) uses-feature glEsVersion attribute using the following rules:
     * <pre>
     * - Error if defined in lib+dest with dest&lt;lib.
     * - Never automatically change dest.
     * - Default implied value is 1.0 (0x00010000).
     * </pre>
     *
     * @param libDoc The library document to merge from. Must not be null.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    private boolean checkGlEsVersion(Document libDoc) {

        String parentPath = "/manifest";                                    //$NON-NLS-1$
        Element parent = findFirstElement(mMainDoc, parentPath);
        assert parent != null;
        if (parent == null) {
            mLog.error(Severity.ERROR,
                    xmlFileAndLine(mMainDoc),
                    "Could not find element %1$s.",
                    parentPath);
            return false;
        }

        // Find the max glEsVersion on the destination side
        String path = "/manifest/uses-feature";                             //$NON-NLS-1$
        String keyAttr = "glEsVersion";                                     //$NON-NLS-1$
        long destGlEsVersion = 0x00010000L; // default minimum is 1.0
        Element destNode = null;
        boolean result = true;
        for (Element dest : findElements(mMainDoc, path)) {
            Attr attr = dest.getAttributeNodeNS(NS_URI, keyAttr);
            String value = attr == null ? "" : attr.getNodeValue().trim();   //$NON-NLS-1$
            if (value.length() != 0) {
                try {
                    // Note that the value can be an hex number such as 0x00020001 so we
                    // need Integer.decode instead of Integer.parseInt.
                    // Note: Integer.decode cannot handle "ffffffff", see JDK issue 6624867
                    // so we just treat the version as a long and test like this, ignoring
                    // the fact that a value of 0xFFFF/.0xFFFF is probably invalid anyway
                    // in the context of glEsVersion.
                    long version = Long.decode(value);
                    if (version >= destGlEsVersion) {
                        destGlEsVersion = version;
                        destNode = dest;
                    } else if (version < 0x00010000) {
                        mLog.error(Severity.WARNING,
                                xmlFileAndLine(dest),
                                "Ignoring <uses-feature android:glEsVersion='%1$s'> because it's smaller than 1.0.",
                                value);
                    }
                } catch (NumberFormatException e) {
                    // Note: NumberFormatException.toString() has no interesting information
                    // so we don't output it.
                    mLog.error(Severity.ERROR,
                            xmlFileAndLine(dest),
                            "Failed to parse <uses-feature android:glEsVersion='%1$s'>: must be an integer in the form 0x00020001.",
                            value);
                    result = false;
                }
            }
        }

        // If we found at least one valid with no error, use that, otherwise bail out.
        if (!result && destNode == null) {
            return false;
        }

        // Now find the max glEsVersion on the source side.

        long srcGlEsVersion = 0x00010000L; // default minimum is 1.0
        Element srcNode = null;
        result = true;
        for (Element src : findElements(libDoc, path)) {
            Attr attr = src.getAttributeNodeNS(NS_URI, keyAttr);
            String value = attr == null ? "" : attr.getNodeValue().trim();   //$NON-NLS-1$
            if (value.length() != 0) {
                try {
                    // See comment on Long.decode above.
                    long version = Long.decode(value);
                    if (version >= srcGlEsVersion) {
                        srcGlEsVersion = version;
                        srcNode = src;
                    } else if (version < 0x00010000) {
                        mLog.error(Severity.WARNING,
                                xmlFileAndLine(src),
                                "Ignoring <uses-feature android:glEsVersion='%1$s'> because it's smaller than 1.0.",
                                value);
                    }
                } catch (NumberFormatException e) {
                    // Note: NumberFormatException.toString() has no interesting information
                    // so we don't output it.
                    mLog.error(Severity.ERROR,
                            xmlFileAndLine(src),
                            "Failed to parse <uses-feature android:glEsVersion='%1$s'>: must be an integer in the form 0x00020001.",
                            value);
                    result = false;
                }
            }
        }

        if (srcNode != null && destGlEsVersion < srcGlEsVersion) {
            mLog.conflict(Severity.WARNING,
                    xmlFileAndLine(destNode == null ? mMainDoc : destNode),
                    xmlFileAndLine(srcNode),
                    "Main manifest has <uses-feature android:glEsVersion='0x%1$08x'> but library uses glEsVersion='0x%2$08x'%3$s",
                    destGlEsVersion,
                    srcGlEsVersion,
                    destNode != null ? "" :   //$NON-NLS-1$
                        "\nNote: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000."
                    );
            result = false;
        }

        return result;
    }

    /**
     * Checks (but does not merge) uses-sdk attributes using the following rules:
     * <pre>
     * - {@code @minSdkVersion}: error if dest&lt;lib. Never automatically change dest minsdk.
     * - {@code @targetSdkVersion}: warning if dest&lt;lib. Never automatically change destination.
     * - {@code @maxSdkVersion}: obsolete, ignored. Not used in comparisons and not merged.
     * - The API level can be a codename if we have a callback that can convert it to an integer.
     * </pre>
     * @param libDoc The library document to merge from. Must not be null.
     * @return True on success, false if any error occurred (printed to the {@link IMergerLog}).
     */
    private boolean checkSdkVersion(Document libDoc) {

        boolean result = true;

        Element destUsesSdk = findFirstElement(mMainDoc, "/manifest/uses-sdk");  //$NON-NLS-1$
        Element srcUsesSdk  = findFirstElement(libDoc,   "/manifest/uses-sdk");  //$NON-NLS-1$

        AtomicInteger destValue = new AtomicInteger(1);
        AtomicInteger srcValue  = new AtomicInteger(1);
        AtomicBoolean destImplied = new AtomicBoolean(true);
        AtomicBoolean srcImplied = new AtomicBoolean(true);

        // Check minSdkVersion
        destMinSdk = 1;
        result = extractSdkVersionAttribute(
                    libDoc,
                    destUsesSdk, srcUsesSdk,
                    "min",  //$NON-NLS-1$
                    destValue, srcValue,
                    destImplied, srcImplied);

        if (result) {
            // Make it an error for an application to use a library with a greater
            // minSdkVersion. This means the library code may crash unexpectedly.
            // TODO it would be nice to be able to work around this in case the
            // user think s/he knows what s/he's doing.
            // We could define a simple XML comment flag: <!-- @NoMinSdkVersionMergeError -->

            destMinSdk = destValue.get();

            if (destMinSdk < srcValue.get()) {
                mLog.conflict(Severity.ERROR,
                        xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk),
                        xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk),
                        "Main manifest has <uses-sdk android:minSdkVersion='%1$d'> but library uses minSdkVersion='%2$d'%3$s",
                        destMinSdk,
                        srcValue.get(),
                        !destImplied.get() ? "" :   //$NON-NLS-1$
                            "\nNote: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1."
                        );
                result = false;
            }
        }

        // Check targetSdkVersion.

        // Note that destValue/srcValue purposely defaults to whatever minSdkVersion was last read
        // since that's their definition when missing.
        destImplied.set(true);
        srcImplied.set(true);

        boolean result2 = extractSdkVersionAttribute(
                    libDoc,
                    destUsesSdk, srcUsesSdk,
                    "target",  //$NON-NLS-1$
                    destValue, srcValue,
                    destImplied, srcImplied);

        result &= result2;
        if (result2) {
            // Make it a warning for an application to use a library with a greater
            // targetSdkVersion.

            int destTargetSdk = destImplied.get() ? destMinSdk : destValue.get();

            if (destTargetSdk < srcValue.get()) {
                mLog.conflict(Severity.WARNING,
                        xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk),
                        xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk),
                        "Main manifest has <uses-sdk android:targetSdkVersion='%1$d'> but library uses targetSdkVersion='%2$d'%3$s",
                        destTargetSdk,
                        srcValue.get(),
                        !destImplied.get() ? "" :   //$NON-NLS-1$
                            "\nNote: main manifest lacks a <uses-sdk android:targetSdkVersion> declaration, which defaults to value minSdkVersion or 1."
                        );
                result = false;
            }
        }

        return result;
    }

    /**
     * Implementation detail for {@link #checkSdkVersion(Document)}.
     * Note that the various atomic out-variables must be preset to their default before
     * the call.
     * <p/>
     * destValue/srcValue will be filled with the integer value of the field, if present
     * and a correct number, in which case destImplied/destImplied are also set to true.
     * Otherwise the values and the implied variables are left untouched.
     */
    private boolean extractSdkVersionAttribute(
            Document libDoc,
            Element destUsesSdk,
            Element srcUsesSdk,
            String attr,
            AtomicInteger destValue,
            AtomicInteger srcValue,
            AtomicBoolean destImplied,
            AtomicBoolean srcImplied) {
        String s = destUsesSdk == null ? ""                                      //$NON-NLS-1$
                     : destUsesSdk.getAttributeNS(NS_URI, attr + "SdkVersion");  //$NON-NLS-1$

        boolean result = true;
        assert s != null;
        s = s.trim();
        try {
            if (s.length() > 0) {
                destValue.set(Integer.parseInt(s));
                destImplied.set(false);
            }
        } catch (NumberFormatException e) {
            boolean error = true;
            if (mCallback != null) {
                // Versions can contain codenames such as "JellyBean".
                // We'll accept it only if have a callback that can give us the API level for it.
                int apiLevel = mCallback.queryCodenameApiLevel(s);
                if (apiLevel > ICallback.UNKNOWN_CODENAME) {
                    destValue.set(apiLevel);
                    destImplied.set(false);
                    error = false;
                }
            }
            if (error) {
                // Note: NumberFormatException.toString() has no interesting information
                // so we don't output it.
                mLog.error(Severity.ERROR,
                    xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk),
                    "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number or codename.",
                    attr,
                    s);
                result = false;
            }
        }

        s = srcUsesSdk == null ? ""                                      //$NON-NLS-1$
              : srcUsesSdk.getAttributeNS(NS_URI, attr + "SdkVersion");  //$NON-NLS-1$
        assert s != null;
        s = s.trim();
        try {
            if (s.length() > 0) {
                srcValue.set(Integer.parseInt(s));
                srcImplied.set(false);
            }
        } catch (NumberFormatException e) {
            boolean error = true;
            if (mCallback != null) {
                // Versions can contain codenames such as "JellyBean".
                // We'll accept it only if have a callback that can give us the API level for it.
                int apiLevel = mCallback.queryCodenameApiLevel(s);
                if (apiLevel > ICallback.UNKNOWN_CODENAME) {
                    srcValue.set(apiLevel);
                    srcImplied.set(false);
                    error = false;
                }
            }
            if (error) {
                mLog.error(Severity.ERROR,
                    xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk),
                    "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number or codename.",
                    attr,
                    s);
                result = false;
            }
        }

        return result;
    }


    // -----


    /**
     * Given an element E, select which previous siblings we want to merge.
     * We want to include any whitespace up to the closing of the previous element.
     * We also want to include up preceding comment nodes and their preceding whitespace.
     * <p/>
     * This may returns either {@code end} or a previous sibling. Never returns null.
     */
    @NonNull
    private Node selectPreviousSiblings(Node end) {

        Node start = end;
        Node prev = start.getPreviousSibling();
        while (prev != null) {
            short t = prev.getNodeType();
            if (t == Node.TEXT_NODE) {
                String text = prev.getNodeValue();
                if (text == null || text.trim().length() != 0) {
                    // Not whitespace, we don't want it.
                    break;
                }
            } else if (t == Node.COMMENT_NODE) {
                // It's a comment. We'll take it.
            } else {
                // Not a comment node nor a whitespace text. We don't want it.
                break;
            }
            start = prev;
            prev = start.getPreviousSibling();
        }

        return start;
    }

    /**
     * Inserts all siblings from {@code start} to {@code end} at the end
     * of the given destination element.
     * <p/>
     * Implementation detail: this clones the source nodes into the destination.
     *
     * @param dest The destination at the end of which to insert. Cannot be null.
     * @param start The first element to insert. Must not be null.
     * @param end The last element to insert (included). Must not be null.
     *   Must be a direct "next sibling" of the start node.
     *   Can be equal to the start node to insert just that one node.
     * @return The copy of the {@code end} node in the destination document or null
     *   if no such copy was created and added to the destination.
     */
    private Node insertAtEndOf(Element dest, Node start, Node end) {
        // Check whether we'll need to adjust URI prefixes
        String destPrefix = XmlUtils.lookupNsPrefix(mMainDoc, NS_URI);
        String srcPrefix  = XmlUtils.lookupNsPrefix(start.getOwnerDocument(), NS_URI);
        boolean needPrefixChange = destPrefix != null && !destPrefix.equals(srcPrefix);

        // First let's figure out the insertion point.
        // We want the end of the last 'content' element of the
        // destination element and basically we want to insert right
        // before the last whitespace of the destination element.
        Node target = dest.getLastChild();
        while (target != null) {
            if (target.getNodeType() == Node.TEXT_NODE) {
                String text = target.getNodeValue();
                if (text == null || text.trim().length() != 0) {
                    // Not whitespace, insert after.
                    break;
                }
            } else {
                // Not text. Insert after
                break;
            }
            target = target.getPreviousSibling();
        }
        if (target != null) {
            target = target.getNextSibling();
        }

        // Destination and start..end must not be part of the same document
        // because we try to import below. If they were, it would mess the
        // structure.
        assert dest.getOwnerDocument() == mMainDoc;
        assert dest.getOwnerDocument() != start.getOwnerDocument();
        assert start.getOwnerDocument() == end.getOwnerDocument();

        while (start != null) {
            Node node = mMainDoc.importNode(start, true /*deep*/);
            if (needPrefixChange) {
                changePrefix(node, srcPrefix, destPrefix);
            }
            dest.insertBefore(node, target);

            if (start == end) {
                return node;
            }
            start = start.getNextSibling();
        }
        return null;
    }

    /**
     * Changes the namespace prefix of all nodes, recursively.
     *
     * @param node The node to process, as well as all it's descendants. Can be null.
     * @param srcPrefix The prefix to match.
     * @param destPrefix The new prefix to replace with.
     */
    private void changePrefix(Node node, String srcPrefix, String destPrefix) {
        for (; node != null; node = node.getNextSibling()) {
            if (srcPrefix.equals(node.getPrefix())) {
                node.setPrefix(destPrefix);
            }
            Node child = node.getFirstChild();
            if (child != null) {
                changePrefix(child, srcPrefix, destPrefix);
            }
        }
    }

    /**
     * Compares two {@link Element}s recursively. They must be identical with the same
     * structure and order. Whitespace and comments are ignored.
     *
     * @param e1 The first element to compare.
     * @param e2 The second element to compare with.
     * @param nextSiblings If true, will also compare the following siblings.
     *   If false, it will just compare the given node.
     * @param diff An optional {@link StringBuilder} where to accumulate a diff output.
     * @param keyAttr An optional key attribute to always add to elements when dumping a diff.
     * @return True if {@code e1} and {@code e2} are equal.
     */
    private boolean compareElements(
            @NonNull Node e1,
            @NonNull Node e2,
            boolean nextSiblings,
            @Nullable StringBuilder diff,
            @Nullable String keyAttr) {
        return compareElements(e1, e2, nextSiblings, diff, 0, keyAttr);
    }

    /**
     * Do not call directly. This is an implementation detail for
     * {@link #compareElements(Node, Node, boolean, StringBuilder, String)}.
     */
    private boolean compareElements(
            @NonNull Node e1,
            @NonNull Node e2,
            boolean nextSiblings,
            @Nullable StringBuilder diff,
            int diffOffset,
            @Nullable String keyAttr) {
        while(true) {
            // Find the next non-whitespace text or non-comment in e1.
            while (e1 != null) {
                short t = e1.getNodeType();

                if (t == Node.COMMENT_NODE) {
                    e1 = e1.getNextSibling();
                } else if (t == Node.TEXT_NODE) {
                    String s = e1.getNodeValue().trim();
                    if (s.length() == 0) {
                        e1 = e1.getNextSibling();
                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }

            // Find the next non-whitespace text or non-comment in e2.
            while (e2 != null) {
                short t = e2.getNodeType();

                if (t == Node.COMMENT_NODE) {
                    e2 = e2.getNextSibling();
                } else if (t == Node.TEXT_NODE) {
                    String s = e2.getNodeValue().trim();
                    if (s.length() == 0) {
                        e2 = e2.getNextSibling();
                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }

            // Same elements, or both null?
            if (e1 == e2 || (e1 == null && e2 == null)) {
                return true;
            }

            // Is one null but not the other?
            if ((e1 == null && e2 != null) || (e1 != null && e2 == null)) {
                break;  // dumpMismatchAndExit
            }

            assert e1 != null;
            assert e2 != null;

            // Same type?
            short t = e1.getNodeType();
            if (t != e2.getNodeType()) {
                break;  // dumpMismatchAndExit
            }

            // Same node name? Must both be null or have the same value.
            String s1 = e1.getNodeName();
            String s2 = e2.getNodeName();
            if ( !( (s1 == null && s2 == null) || (s1 != null && s1.equals(s2)) ) ) {
                break;  // dumpMismatchAndExit
            }

            // Same node value? Must both be null or have the same value once whitespace is trimmed.
            s1 = e1.getNodeValue();
            s2 = e2.getNodeValue();
            if (s1 != null) {
                s1 = s1.trim();
            }
            if (s2 != null) {
                s2 = s2.trim();
            }
            if ( !( (s1 == null && s2 == null) || (s1 != null && s1.equals(s2)) ) ) {
                break;  // dumpMismatchAndExit
            }

            if (diff != null) {
                // So far e1 and e2 seem pretty much equal. Dump it to the diff.
                // We need to print to the diff before dealing with the children or attributes.
                // Note: diffOffset + 1 because we want to reserve 2 spaces to write -/+
                diff.append(XmlUtils.dump(e1, diffOffset + 1,
                                          false /*nextSiblings*/, false /*deep*/, keyAttr));
            }

            // Now compare the attributes. When using the w3c.DOM this way, attributes are
            // accessible via the Node/Element attributeMap and are not actually exposed
            // as ATTR_NODEs in the node list. The downside is that we don't really
            // have the proper attribute order but that's not an issue as far as the validity
            // of the XML since attribute order should never matter.
            List<Attr> a1 = XmlUtils.sortedAttributeList(e1.getAttributes());
            List<Attr> a2 = XmlUtils.sortedAttributeList(e2.getAttributes());
            if (a1.size() > 0 || a2.size() > 0) {

                  int count1 = 0;
                  int count2 = 0;
                Map<String, AttrDiff> map = new TreeMap<String, AttrDiff>();
                for (Attr a : a1) {
                    AttrDiff ad1 = new AttrDiff(a, "--");       //$NON-NLS-1$
                    map.put(ad1.mKey, ad1);
                    count1++;
                }

                for (Attr a : a2) {
                    AttrDiff ad2 = new AttrDiff(a, "++");       //$NON-NLS-1$
                    AttrDiff ad1 = map.get(ad2.mKey);
                    if (ad1 != null) {
                        ad1.mSide = "  ";                       //$NON-NLS-1$
                        count1--;
                    } else {
                        map.put(ad2.mKey, ad2);
                        count2++;
                    }
                }

                if (count1 != 0 || count2 != 0) {
                    // We found some items not matching in both sets. Dump the result.
                    if (diff != null) {
                        for (AttrDiff ad : map.values()) {
                            diff.append(ad.mSide)
                                .append(XmlUtils.dump(ad.mAttr, diffOffset,
                                                      false /*nextSiblings*/, false /*deep*/,
                                                      keyAttr));
                        }
                    }
                    // Exit without dumping
                    return false;
                }
            }

            // Compare recursively for elements.
            if (t == Node.ELEMENT_NODE &&
                    !compareElements(
                            e1.getFirstChild(), e2.getFirstChild(), true,
                            diff, diffOffset + 1, keyAttr)) {
                // Exit without dumping since the recursive call take cares of its own diff
                return false;
            }

            if (nextSiblings) {
                e1 = e1.getNextSibling();
                e2 = e2.getNextSibling();
                continue;
            } else {
                return true;
            }
        }

        // <INTERCAL COME FROM dumpMismatchAndExit PLEASE>
        if (diff != null) {
            diff.append("--")
                .append(XmlUtils.dump(e1, diffOffset,
                                      false /*nextSiblings*/, false /*deep*/, keyAttr));
            diff.append("++")
                .append(XmlUtils.dump(e2, diffOffset,
                                      false /*nextSiblings*/, false /*deep*/, keyAttr));
        }
        return false;
    }

    private static class AttrDiff {
        public final String mKey;
        public final Attr mAttr;
        public String mSide;

        public AttrDiff(Attr attr, String side) {
            mKey = getKey(attr);
            mAttr = attr;
            mSide = side;
        }

        String getKey(Attr attr) {
            return String.format("%s=%s", attr.getNodeName(), attr.getNodeValue());
        }
    }

    /**
     * Finds the first element matching the given XPath expression in the given document.
     *
     * @param doc The document where to find the expression.
     * @param path The XPath expression. It must yield an {@link Element} node type.
     * @return The {@link Element} found or null.
     */
    @Nullable
    private Element findFirstElement(
            @NonNull Document doc,
            @NonNull String path) {
        Node result;
        try {
            result = (Node) mXPath.evaluate(path, doc, XPathConstants.NODE);
            if (result instanceof Element) {
                return (Element) result;
            }

            if (result != null) {
                mLog.error(Severity.ERROR,
                        xmlFileAndLine(doc),
                        "Unexpected Node type %s when evaluating %s",   //$NON-NLS-1$
                        result.getClass().getName(), path);
            }
        } catch (XPathExpressionException e) {
            mLog.error(Severity.ERROR,
                    xmlFileAndLine(doc),
                    "XPath error on expr %s: %s",                       //$NON-NLS-1$
                    path, e.toString());
        }
        return null;
    }

    /**
     * Finds zero or more elements matching the given XPath expression in the given document.
     *
     * @param doc The document where to find the expression.
     * @param path The XPath expression. Only {@link Element}s nodes will be returned.
     * @return A list of {@link Element} found, possibly empty but never null.
     */
    private List<Element> findElements(
            @NonNull Document doc,
            @NonNull String path) {
        return findElements(doc, path, null, null);
    }


    /**
     * Finds zero or more elements matching the given XPath expression in the given document.
     * <p/>
     * Furthermore, the elements must have an attribute matching the given attribute name
     * and value if provided. (If you don't need to match an attribute, use the other version.)
     * <p/>
     * Note that if you provide {@code attrName} as non-null then the {@code attrValue}
     * must be non-null too. In this case the XPath expression will be modified to add
     * the check by naively appending a "[name='value']" filter.
     *
     * @param doc The document where to find the expression.
     * @param path The XPath expression. Only {@link Element}s nodes will be returned.
     * @param attrName The name of the optional attribute to match. Can be null.
     * @param attrValue The value of the optional attribute to match.
     *   Can be null if {@code attrName} is null, otherwise must be non-null.
     * @return A list of {@link Element} found, possibly empty but never null.
     *
     * @see #findElements(Document, String)
     */
    private List<Element> findElements(
            @NonNull Document doc,
            @NonNull String path,
            @Nullable String attrName,
            @Nullable String attrValue) {
        List<Element> elements = new ArrayList<Element>();

        if (attrName != null) {
            assert attrValue != null;
            // Generate expression /manifest/application/activity[@android:name='my.fqcn']
            path = String.format("%1$s[@%2$s:%3$s='%4$s']",                     //$NON-NLS-1$
                    path, NS_PREFIX, attrName, attrValue);
        }

        try {
            NodeList results = (NodeList) mXPath.evaluate(path, doc, XPathConstants.NODESET);
            if (results != null && results.getLength() > 0) {
                for (int i = 0; i < results.getLength(); i++) {
                    Node n = results.item(i);
                    assert n instanceof Element;
                    if (n instanceof Element) {
                        elements.add((Element) n);
                    } else {
                        mLog.error(Severity.ERROR,
                                xmlFileAndLine(doc),
                                "Unexpected Node type %s when evaluating %s",   //$NON-NLS-1$
                                n.getClass().getName(), path);
                    }
                }
            }

        } catch (XPathExpressionException e) {
            mLog.error(Severity.ERROR,
                    xmlFileAndLine(doc),
                    "XPath error on expr %s: %s",                       //$NON-NLS-1$
                    path, e.toString());
        }

        return elements;
    }

    /**
     * Returns a new {@link FileAndLine} structure that identifies
     * the base filename & line number from which the XML node was parsed.
     * <p/>
     * When the line number is unknown (e.g. if a {@link Document} instance is given)
     * then line number 0 will be used.
     *
     * @param node The node or document where the error occurs. Must not be null.
     * @return A new non-null {@link FileAndLine} combining the file name and line number.
     */
    private @NonNull FileAndLine xmlFileAndLine(@NonNull Node node) {
        String name = XmlUtils.extractXmlFilename(node);
        int line = XmlUtils.extractLineNumber(node); // 0 in case of error or unknown
        return new FileAndLine(name, line);
    }

}
