/*
 * 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.common.SdkConstants;
import com.android.common.annotations.NonNull;
import com.android.common.annotations.Nullable;
import com.android.manifmerger.IMergerLog.FileAndLine;
import com.android.manifmerger.IMergerLog.Severity;
import com.android.common.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);
  }

}
