// Copyright 2015 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.rules.android;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.MultidexMode;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;

/**
 * Builds Jack actions for a Java or Android target.
 *
 * <p>Jack is the new Android toolchain which integrates proguard-compatible code minification
 * et al. and has an intermediate library format to front-load the dexing work.
 *
 * @see <a href="http://tools.android.com/tech-docs/jackandjill">Jack documentation</a>
 * @see JackLibraryProvider
 */
public final class JackCompilationHelper {

  private static final String PARTIAL_JACK_DIRECTORY = "_jill";

  private static final String JACK_DIRECTORY = "_jack";

  /** Filetype for the intermediate library created by Jack. */
  public static final FileType JACK_LIBRARY_TYPE = FileType.of(".jack");

  /** Flag to indicate that the next argument is a Jack property. */
  static final String JACK_PROPERTY = "-D";
  /** Flag to indicate that resource conflicts should be resolved by taking the first element. */
  static final String PROPERTY_KEEP_FIRST_RESOURCE = "jack.import.resource.policy=keep-first";
  /** Flag to indicate that type conflicts should be resolved by taking the first element. */
  static final String PROPERTY_KEEP_FIRST_TYPE = "jack.import.type.policy=keep-first";
  /** Flag to turn on/off sanity checks in Jack. */
  static final String SANITY_CHECKS = "--sanity-checks";
  /** Value of the sanity checks flag which disables sanity checks. */
  static final String SANITY_CHECKS_OFF = "off";
  /** Value of the sanity checks flag which enables sanity checks. */
  static final String SANITY_CHECKS_ON = "on";
  /** Flag to enable tolerant mode in Jill, for compiling special jars (e.g., bootclasspath). */
  static final String TOLERANT = "--tolerant";

  /** Flag to indicate the classpath of Jack libraries, separated by semicolons. */
  static final String CLASSPATH = "-cp";
  /** Flag to load a Jack library into the Jack compiler so it will be part of the output. */
  static final String IMPORT_JACK_LIBRARY = "--import";
  /** Flag to import a zip file of Java sources into a Jack library. */
  static final String IMPORT_SOURCE_ZIP = "--import-source-zip";
  /** Flag to import a single file into a Jack library's resources. */
  static final String IMPORT_RESOURCE_FILE = "--import-resource-file";
  /** Flag to add a zip file full of resources to the Jack library. */
  static final String IMPORT_RESOURCE_ZIP = "--import-resource-zip";
  /** Flag to add the names of annotation processors. */
  static final String PROCESSOR_NAMES = "--processor";
  /** Flag to add the classpath of annotation processors. */
  static final String PROCESSOR_CLASSPATH = "--processorpath";
  /** Flag to include a Proguard configuration. */
  static final String CONFIG_PROGUARD = "--config-proguard";
  /** Flag to set the multidex mode when compiling to dex with Jack. */
  static final String MULTI_DEX = "--multi-dex";
  /** Flag to specify the path to the main dex list in manual main dex mode. */
  static final String MAIN_DEX_LIST = "--main-dex-list";

  /** Flag indicating the filename Jill should output the converted jar to. */
  static final String JILL_OUTPUT = "--output";
  /** Flag to output a jack library. */
  static final String OUTPUT_JACK = "--output-jack";
  /** Flag to output a zip file containing dex files and resources for packaging. */
  static final String OUTPUT_DEX_ZIP = "--output-dex-zip";
  /** Name of the zip file containing the dex files and java resources for packaging. */
  static final String ZIP_OUTPUT_FILENAME = "classes.dex.zip";

  /** Rule context used to build and register actions. */
  private final RuleContext ruleContext;

  /** True to use Jack's internal sanity checks, trading speed for crash-on-bugs. */
  private final boolean useSanityChecks;
  /** True to make Jill more tolerant, when compiling special jars (e.g., bootclasspath) */
  private final boolean useTolerant;

  /** Binary used to extract resources from a jar file. */
  private final FilesToRunProvider resourceExtractorBinary;
  /** Binary used to build Jack libraries and dex files. */
  private final FilesToRunProvider jackBinary;
  /** Binary used to convert jars to Jack libraries. */
  private final FilesToRunProvider jillBinary;
  /**
   * Jack libraries containing Android/Java base classes.
   *
   * <p>These will be placed first on the classpath.
   */
  private final NestedSet<Artifact> baseClasspath;

  /** The destination for the Jack artifact to be created, or null to skip this. */
  @Nullable private final Artifact outputArtifact;

  /** Java files for the rule's Jack library. */
  private final ImmutableSet<Artifact> javaSources;
  /** Zip files of java sources for the rule's Jack library. */
  private final ImmutableSet<Artifact> sourceJars;

  /** Java resources for the rule's Jack library. */
  private final ImmutableMap<PathFragment, Artifact> resources;

  /** Jack libraries to be provided to depending rules on the classpath, from srcs and exports. */
  private final NestedSet<Artifact> exportedJacks;
  /**
   * Jar libraries to be provided to depending rules on the classpath, from srcs and exports.
   * These will be placed after the jack files from exportedJacks and before this rule's jack file.
   */
  private final ImmutableSet<Artifact> exportedJars;

  /** Jack libraries to be provided only to this rule on the classpath, from srcs and deps. */
  private final NestedSet<Artifact> classpathJacks;
  /**
   * Jar libraries to be provided only to this rule on the classpath, from srcs and deps.
   * These will be placed after the jack files from classpathJacks.
   */
  private final ImmutableSet<Artifact> classpathJars;

  /**
   * Jack libraries from dependency libraries to be included in dexing.
   * Does not include the library generated by this rule or any reached only through neverlink libs.
   */
  private final NestedSet<Artifact> dexJacks;
  /** Jar libraries from dependency libraries to be included in dexing. */
  private final ImmutableSet<Artifact> dexJars;

  /** Minimal state used only to give nice error messages in case of oopses. */
  private JackLibraryProvider alreadyCompiledLibrary;

  private boolean wasDexBuilt;

  /** The classpath to be used for annotation processors. */
  private final NestedSet<Artifact> processorClasspathJars;

  /** The names of classes to be used as annotation processors. */
  private final ImmutableSet<String> processorNames;

  /** Creates a new JackCompilationHelper. Called from {@link Builder#build()}. */
  private JackCompilationHelper(
      RuleContext ruleContext,
      boolean useSanityChecks,
      boolean useTolerant,
      FilesToRunProvider resourceExtractorBinary,
      FilesToRunProvider jackBinary,
      FilesToRunProvider jillBinary,
      NestedSet<Artifact> baseClasspath,
      @Nullable Artifact outputArtifact,
      ImmutableSet<Artifact> javaSources,
      ImmutableSet<Artifact> sourceJars,
      ImmutableMap<PathFragment, Artifact> resources,
      NestedSet<Artifact> processorClasspathJars,
      ImmutableSet<String> processorNames,
      NestedSet<Artifact> exportedJacks,
      ImmutableSet<Artifact> exportedJars,
      NestedSet<Artifact> classpathJacks,
      ImmutableSet<Artifact> classpathJars,
      NestedSet<Artifact> dexJacks,
      ImmutableSet<Artifact> dexJars) {
    this.ruleContext = ruleContext;
    this.useSanityChecks = useSanityChecks;
    this.useTolerant = useTolerant;
    this.resourceExtractorBinary = resourceExtractorBinary;
    this.jackBinary = jackBinary;
    this.jillBinary = jillBinary;
    this.baseClasspath = baseClasspath;
    this.outputArtifact = outputArtifact;
    this.javaSources = javaSources;
    this.sourceJars = sourceJars;
    this.resources = resources;
    this.processorClasspathJars = processorClasspathJars;
    this.processorNames = processorNames;
    this.exportedJacks = exportedJacks;
    this.exportedJars = exportedJars;
    this.classpathJacks = classpathJacks;
    this.classpathJars = classpathJars;
    this.dexJacks = dexJacks;
    this.dexJars = dexJars;
  }

  /**
   * Builds one or more dex files from the jack libraries in the transitive closure of this rule.
   *
   * <p>This method should only be called once, as it will generate the same artifact each time.
   * It will fail if called a second time.
   *
   * @param multidexMode The multidex flag to send to Jack.
   * @param manualMainDexList Iff multidexMode is MANUAL_MAIN_DEX, an artifact representing the file
   *     with the list of class filenames which should go in the main dex. Else, absent.
   * @param proguardSpecs A collection of Proguard configuration files to be used to process the
   *     Jack libraries before building a dex out of them.
   * @returns A zip file containing the dex file(s) and Java resource(s) generated by Jack.
   */
  // TODO(bazel-team): this method (compile to jack library, compile all transitive jacks to dex)
  // may be too much overhead for manydex (dex per library) mode.
  // Instead, consider running jack --output-dex right on the source files, bypassing the
  // intermediate jack library format.
  public Artifact compileAsDex(
      MultidexMode multidexMode,
      Optional<Artifact> manualMainDexList,
      Collection<Artifact> proguardSpecs) {
    Preconditions.checkNotNull(multidexMode);
    Preconditions.checkNotNull(manualMainDexList);
    Preconditions.checkNotNull(proguardSpecs);
    Preconditions.checkArgument(
        multidexMode.isSupportedByJack(),
        "Multidex mode '%s' is not supported by Jack",
        multidexMode);
    Preconditions.checkArgument(
        manualMainDexList.isPresent() == (multidexMode == MultidexMode.MANUAL_MAIN_DEX),
        "The main dex list must be supplied if and only if the multidex mode is 'manual_main_dex'");
    Preconditions.checkState(!wasDexBuilt, "A dex file has already been built.");

    Artifact outputZip = AndroidBinary.getDxArtifact(ruleContext, ZIP_OUTPUT_FILENAME);

    NestedSet<Artifact> transitiveJackLibraries =
        compileAsLibrary().getTransitiveJackLibrariesToLink();
    CustomCommandLine.Builder builder =
        CustomCommandLine.builder()
            // Have jack double-check its behavior and crash rather than producing invalid output
            .add(SANITY_CHECKS)
            .add(useSanityChecks ? SANITY_CHECKS_ON : SANITY_CHECKS_OFF)
            // Have jack take the first match in the event of a class or resource name collision.
            .add(JACK_PROPERTY)
            .add(PROPERTY_KEEP_FIRST_RESOURCE)
            .add(JACK_PROPERTY)
            .add(PROPERTY_KEEP_FIRST_TYPE);

    for (Artifact jackLibrary : transitiveJackLibraries) {
      builder.addExecPath(IMPORT_JACK_LIBRARY, jackLibrary);
    }
    for (Artifact proguardSpec : proguardSpecs) {
      builder.addExecPath(CONFIG_PROGUARD, proguardSpec);
    }
    builder.add(MULTI_DEX).add(multidexMode.getJackFlagValue());
    if (manualMainDexList.isPresent()) {
      builder.addExecPath(MAIN_DEX_LIST, manualMainDexList.get());
    }
    builder.addExecPath(OUTPUT_DEX_ZIP, outputZip);
    ruleContext.registerAction(
        new SpawnAction.Builder()
            .setExecutable(jackBinary)
            .addTransitiveInputs(transitiveJackLibraries)
            .addInputs(proguardSpecs)
            .addInputs(manualMainDexList.asSet())
            .addOutput(outputZip)
            .setCommandLine(builder.build())
            .setProgressMessage("Dexing " + ruleContext.getLabel() + " with Jack")
            .setMnemonic("AndroidJackDex")
            .build(ruleContext));
    return outputZip;
  }

  /**
   * Constructs the actions to compile a jack library for a neverlink lib.
   *
   * @returns a {@link JackLibraryProvider} containing the resulting transitive jack libraries.
   */
  public JackLibraryProvider compileAsNeverlinkLibrary() {
    JackLibraryProvider nonNeverlink = compileAsLibrary();
    return JackLibraryProvider.create(
        /* transitiveJackLibrariesToLink */
        NestedSetBuilder.<Artifact>emptySet(Order.NAIVE_LINK_ORDER),
        nonNeverlink.getTransitiveJackClasspathLibraries());
  }

  /**
   * Constructs the actions to compile a jack library for a non-neverlink lib.
   *
   * @returns a {@link JackLibraryProvider} containing the resulting transitive jack libraries.
   */
  public JackLibraryProvider compileAsLibrary() {
    if (alreadyCompiledLibrary != null) {
      // Because the JackCompilationHelper is immutable, compileAsLibrary will always produce the
      // same result for the life of the helper. The resulting library may be needed by clients
      // which also need to build a dex, e.g., AndroidBinary.
      return alreadyCompiledLibrary;
    }
    Function<Artifact, Artifact> nonLibraryFileConverter =
        CacheBuilder.newBuilder()
            .initialCapacity(exportedJars.size() + classpathJars.size())
            .build(
                new CacheLoader<Artifact, Artifact>() {
                  @Override
                  public Artifact load(Artifact artifact) throws Exception {
                    if (JavaSemantics.JAR.matches(artifact.getFilename())) {
                      return postprocessPartialJackAndAddResources(
                          convertJarToPartialJack(artifact), extractResourcesFromJar(artifact));
                    } else if (JACK_LIBRARY_TYPE.matches(artifact.getFilename())) {
                      return artifact;
                    }
                    throw new AssertionError("Invalid type for library file: " + artifact);
                  }
                });

    NestedSet<Artifact> transitiveClasspath =
        new NestedSetBuilder<Artifact>(Order.NAIVE_LINK_ORDER)
            .addAll(Iterables.transform(classpathJars, nonLibraryFileConverter))
            .addTransitive(classpathJacks)
            .build();

    // The base classpath needs to be first in the set's iteration order.
    // Then any jars or jack files specified directly, then dependencies from providers.
    NestedSet<Artifact> classpath =
        new NestedSetBuilder<Artifact>(Order.NAIVE_LINK_ORDER)
            .addTransitive(baseClasspath)
            .addTransitive(transitiveClasspath)
            .build();

    NestedSetBuilder<Artifact> exports = new NestedSetBuilder<>(Order.NAIVE_LINK_ORDER);
    NestedSetBuilder<Artifact> dexContents = new NestedSetBuilder<>(Order.NAIVE_LINK_ORDER);

    if (outputArtifact != null) {
      if (javaSources.isEmpty() && sourceJars.isEmpty() && resources.isEmpty()) {
        // We still have to create SOMETHING to fulfill the artifact, but man, screw it
        buildEmptyJackAction();
      } else {
        buildJackAction(javaSources, sourceJars, resources, classpath);
        exports.add(outputArtifact);
        dexContents.add(outputArtifact);
      }
    }

    // These need to be added now so that they can be after the outputArtifact (if present).
    exports
        .addAll(Iterables.transform(exportedJars, nonLibraryFileConverter))
        .addTransitive(exportedJacks)
        .addTransitive(transitiveClasspath);
    dexContents
        .addAll(Iterables.transform(dexJars, nonLibraryFileConverter))
        .addTransitive(dexJacks);

    alreadyCompiledLibrary = JackLibraryProvider.create(dexContents.build(), exports.build());
    return alreadyCompiledLibrary;
  }

  /**
   * Generates an action which converts the jar to partial Jack format and returns the Jack file.
   *
   * <p>Partial Jack format does not contain resources or pre-dex files.
   *
   * @see #postprocessPartialJackAndAddResources(Artifact,Artifact)
   */
  private Artifact convertJarToPartialJack(Artifact jar) {
    Artifact result = ruleContext.getUniqueDirectoryArtifact(
        PARTIAL_JACK_DIRECTORY,
        FileSystemUtils.replaceExtension(jar.getRootRelativePath(), ".jack"),
        ruleContext.getBinOrGenfilesDirectory());
    SpawnAction.Builder builder =
        new SpawnAction.Builder()
            .setExecutable(jillBinary);
    if (useTolerant) {
      builder.addArgument(TOLERANT);
    }
    ruleContext.registerAction(
        builder
            .addArgument(JILL_OUTPUT)
            .addOutputArgument(result)
            .addInputArgument(jar)
            .setProgressMessage(
                "Converting " + jar.getExecPath().getBaseName() + " to Jack library with Jill")
            .setMnemonic("AndroidJill")
            .build(ruleContext));
    return result;
  }

  /**
   * Generates an action which creates a zip file from the contents of the input jar, filtering out
   * non-resource files and returning a zip file containing only resources.
   */
  private Artifact extractResourcesFromJar(Artifact jar) {
    Artifact result =  ruleContext.getUniqueDirectoryArtifact(
        PARTIAL_JACK_DIRECTORY,
        FileSystemUtils.replaceExtension(jar.getRootRelativePath(), "-resources.zip"),
        ruleContext.getBinOrGenfilesDirectory());

    ruleContext.registerAction(
        new SpawnAction.Builder()
            .setExecutable(resourceExtractorBinary)
            .addInputArgument(jar)
            .addOutputArgument(result)
            .setProgressMessage("Extracting resources from " + jar.getExecPath().getBaseName())
            .setMnemonic("AndroidJillResources")
            .build(ruleContext));
    return result;
  }

  /**
   * Generates an action to finish processing a partial Jack library generated by
   * {@link #convertJarToPartialJack(Artifact)} and add resources from
   * {@link #extractResourcesFromJar(Artifact)}, then returns the final library.
   */
  private Artifact postprocessPartialJackAndAddResources(
      Artifact partialJackLibrary, Artifact resources) {
    Artifact result = ruleContext.getUniqueDirectoryArtifact(
        JACK_DIRECTORY,
        partialJackLibrary.getRootRelativePath().relativeTo(
            ruleContext.getUniqueDirectory(PARTIAL_JACK_DIRECTORY)),
        ruleContext.getBinOrGenfilesDirectory());
    CustomCommandLine.Builder builder =
        CustomCommandLine.builder()
            // Have jack double-check its behavior and crash rather than producing invalid output
            .add(SANITY_CHECKS)
            .add(useSanityChecks ? SANITY_CHECKS_ON : SANITY_CHECKS_OFF)
            .addExecPath(IMPORT_JACK_LIBRARY, partialJackLibrary)
            .addExecPath(IMPORT_RESOURCE_ZIP, resources)
            .addExecPath(OUTPUT_JACK, result);
    ruleContext.registerAction(
        new SpawnAction.Builder()
            .setExecutable(jackBinary)
            .addInput(partialJackLibrary)
            .addInput(resources)
            .addOutput(result)
            .setCommandLine(builder.build())
            .setProgressMessage(
                "Processing " + partialJackLibrary.getExecPath().getBaseName() + " as Jack library")
            .setMnemonic("AndroidJillPostprocess")
            .build(ruleContext));
    return result;
  }

  /**
   * Creates an action to build an empty jack library given by outputArtifact.
   */
  private void buildEmptyJackAction() {
    ruleContext.registerAction(
        new SpawnAction.Builder()
            .setExecutable(jackBinary)
            .addArgument(OUTPUT_JACK)
            .addOutputArgument(outputArtifact)
            .setProgressMessage("Compiling " + ruleContext.getLabel() + " as Jack library")
            .setMnemonic("AndroidJackLibraryNull")
            .build(ruleContext));
  }

  /**
   * Creates an action to compile the given sources as a jack library given by outputArtifact.
   *
   * @param javaSources Iterable of .java files to compile using jack.
   * @param sourceJars Iterable of .srcjar files to unpack and compile using jack.
   * @param resources Mapping from library paths to resource files to be imported into the jack
   *     library.
   * @param classpathJackLibraries Libraries used for compilation.
   * @returns An artifact representing the combined jack library, or null if none was created.
   */
  private void buildJackAction(
      Iterable<Artifact> javaSources,
      Iterable<Artifact> sourceJars,
      Map<PathFragment, Artifact> resources,
      NestedSet<Artifact> classpathJackLibraries) {
    CustomCommandLine.Builder builder =
        CustomCommandLine.builder()
            // Have jack double-check its behavior and crash rather than producing invalid output
            .add(SANITY_CHECKS)
            .add(useSanityChecks ? SANITY_CHECKS_ON : SANITY_CHECKS_OFF)
            .addExecPath(OUTPUT_JACK, outputArtifact)
            .addJoinExecPaths(CLASSPATH, ":", classpathJackLibraries);
    if (!processorNames.isEmpty()) {
      builder.add(PROCESSOR_NAMES).add(Joiner.on(',').join(processorNames));
    }
    if (!processorClasspathJars.isEmpty()) {
      builder.addJoinExecPaths(PROCESSOR_CLASSPATH, ":", processorClasspathJars);
    }
    for (Entry<PathFragment, Artifact> resource : resources.entrySet()) {
      builder.add(IMPORT_RESOURCE_FILE);
      // Splits paths at the appropriate root (java root, if present; source/genfiles/etc. if not).
      // The part of the path after the : is used as the path to the resource within the jack/apk,
      // while the part of the path before the : is the remainder of the path to the resource file.
      // In cases where the path to the file and the path within the jack/apk are the same,
      // such as when a source file is not under a java root, this prefix will be empty.
      PathFragment execPath = resource.getValue().getExecPath();
      PathFragment resourcePath = resource.getKey();
      if (execPath.equals(resourcePath)) {
        builder.addPaths(":%s", resourcePath);
      } else {
        // execPath must end with resourcePath in all cases
        PathFragment rootPrefix =
            execPath.subFragment(0, execPath.segmentCount() - resourcePath.segmentCount());
        builder.addPaths("%s:%s", rootPrefix, resourcePath);
      }
    }
    builder.addBeforeEachExecPath(IMPORT_SOURCE_ZIP, sourceJars).addExecPaths(javaSources);
    ruleContext.registerAction(
        new SpawnAction.Builder()
            .setExecutable(jackBinary)
            .addTransitiveInputs(classpathJackLibraries)
            .addOutput(outputArtifact)
            .addTransitiveInputs(processorClasspathJars)
            .addInputs(resources.values())
            .addInputs(sourceJars)
            .addInputs(javaSources)
            .setCommandLine(builder.build())
            .setProgressMessage("Compiling " + ruleContext.getLabel() + " as Jack library")
            .setMnemonic("AndroidJackLibrary")
            .build(ruleContext));
  }

  /**
   * Builder for JackCompilationHelper to configure all of its tools and sources.
   */
  public static final class Builder {

    /** Rule context used to build and register actions. */
    @Nullable private RuleContext ruleContext;

    /** Whether to enable tolerant mode in Jill, e.g., when compiling a bootclasspath. */
    private boolean useTolerant;

    /** Binary used to extract resources from a jar file. */
    @Nullable private FilesToRunProvider resourceExtractorBinary;
    /** Binary used to build Jack libraries and dex files. */
    @Nullable private FilesToRunProvider jackBinary;
    /** Binary used to convert jars to Jack libraries. */
    @Nullable private FilesToRunProvider jillBinary;
    /**
     * Set of Jack libraries containing Android/Java base classes.
     *
     * <p>These will be placed first on the classpath.
     */
    @Nullable private NestedSet<Artifact> baseClasspath;

    /** The destination for the Jack artifact to be created. */
    @Nullable private Artifact outputArtifact;

    /** Java files for the rule's Jack library. */
    private final LinkedHashSet<Artifact> javaSources = new LinkedHashSet<>();
    /** Zip files of java sources for the rule's Jack library. */
    private final LinkedHashSet<Artifact> sourceJars = new LinkedHashSet<>();
    /** Map from paths within the Jack library to Java resources for the rule's Jack library. */
    private final LinkedHashMap<PathFragment, Artifact> resources = new LinkedHashMap<>();

    /** Jack libraries to be provided to depending rules on the classpath, from srcs and exports. */
    private final NestedSetBuilder<Artifact> exportedJackLibraries =
        new NestedSetBuilder<>(Order.NAIVE_LINK_ORDER);
    /**
     * Jar libraries to be provided to depending rules on the classpath, from srcs and exports.
     * These will be placed after the jack files from exportedJacks and before this rule's jack
     * file.
     */
    private final LinkedHashSet<Artifact> exportedNonLibraryFiles = new LinkedHashSet<>();

    /** Jack libraries to be provided only to this rule on the classpath, from srcs and deps. */
    private final NestedSetBuilder<Artifact> classpathJackLibraries =
        new NestedSetBuilder<>(Order.NAIVE_LINK_ORDER);
    /**
     * Jar libraries to be provided only to this rule on the classpath, from srcs and deps.
     * These will be placed after the jack files from classpathJacks.
     */
    private final LinkedHashSet<Artifact> classpathNonLibraryFiles = new LinkedHashSet<>();

    /** The names of classes to be used as annotation processors. */
    private final LinkedHashSet<String> processorNames = new LinkedHashSet<>();

    /** Jar libraries to be provided as annotation processors' classpath, from plugin deps. */
    private final NestedSetBuilder<Artifact> processorClasspathJars =
        new NestedSetBuilder<>(Order.NAIVE_LINK_ORDER);

    /**
     * Jack libraries from dependency libraries to be included in dexing.
     * Does not include the library generated by this rule or any reached only through neverlink
     * libs.
     */
    private final NestedSetBuilder<Artifact> dexJacks =
        new NestedSetBuilder<>(Order.NAIVE_LINK_ORDER);
    /** Jar libraries from dependency libraries to be included in dexing. */
    private final LinkedHashSet<Artifact> dexJars = new LinkedHashSet<>();

    /**
     * Sets the rule context in which this compilation helper will operate.
     *
     * <p>The compilation tools will be loaded automatically from the appropriate attributes:
     * Jack as $jack, Jill as $jill, and the resource extractor as $resource_extractor.
     *
     * <p>Jack's sanity checks will be enabled or disabled according to the AndroidConfiguration
     * accessed through this context.
     */
    public JackCompilationHelper.Builder setRuleContext(RuleContext ruleContext) {
      this.ruleContext = Preconditions.checkNotNull(ruleContext);
      return this;
    }

    /**
     * Sets the artifact the final Jack library should be output to.
     *
     * <p>The artifact specified will always be generated, although it may be empty if there are no
     * sources.
     *
     * <p>This method must be called if any of addJavaSources, addSourceJars, or addResources is.
     */
    public JackCompilationHelper.Builder setOutputArtifact(Artifact outputArtifact) {
      this.outputArtifact = Preconditions.checkNotNull(outputArtifact);
      return this;
    }

    /**
     * Sets the Jack binary used to perform operations on Jack libraries.
     */
    public JackCompilationHelper.Builder setJackBinary(FilesToRunProvider jackBinary) {
      this.jackBinary = Preconditions.checkNotNull(jackBinary);
      return this;
    }

    /**
     * Sets the Jill binary used to translate jars to jack files.
     */
    public JackCompilationHelper.Builder setJillBinary(FilesToRunProvider jillBinary) {
      this.jillBinary = Preconditions.checkNotNull(jillBinary);
      return this;
    }

    /**
     * Sets the resource extractor binary used to extract resources from jars.
     */
    public JackCompilationHelper.Builder setResourceExtractorBinary(
        FilesToRunProvider resourceExtractorBinary) {
      this.resourceExtractorBinary = Preconditions.checkNotNull(resourceExtractorBinary);
      return this;
    }

    /**
     * Sets the base classpath, containing core classes (android.jar or Java bootclasspath).
     */
    public JackCompilationHelper.Builder setJackBaseClasspath(NestedSet<Artifact> baseClasspath) {
      this.baseClasspath = Preconditions.checkNotNull(baseClasspath);
      return this;
    }

    /**
     * Sets Jill to be tolerant, e.g., when translating a jar from the Java bootclasspath to jack.
     */
    public JackCompilationHelper.Builder setTolerant() {
      this.useTolerant = true;
      return this;
    }

    /**
     * Adds a collection of Java source files to be compiled by Jack.
     */
    public JackCompilationHelper.Builder addJavaSources(Collection<Artifact> javaSources) {
      this.javaSources.addAll(Preconditions.checkNotNull(javaSources));
      return this;
    }

    /**
     * Adds a collection of zip files containing Java sources to be compiled by Jack.
     */
    public JackCompilationHelper.Builder addSourceJars(Collection<Artifact> sourceJars) {
      this.sourceJars.addAll(Preconditions.checkNotNull(sourceJars));
      return this;
    }

    /**
     * Adds a collection of jar files to be converted to Jack libraries.
     *
     * <p>The Jack libraries created from these jar files will be used both as
     * dependencies on the classpath of this rule and exports to the classpath of depending rules,
     * as with jar files in the sources of a Java rule.
     * They will also be available to the compilation of the final dex file(s).
     * It has an identical effect as if these jars were specified in both deps and exports.
     */
    public JackCompilationHelper.Builder addCompiledJars(Collection<Artifact> compiledJars) {
      this.exportedNonLibraryFiles.addAll(Preconditions.checkNotNull(compiledJars));
      this.classpathNonLibraryFiles.addAll(compiledJars);
      this.dexJars.addAll(compiledJars);
      return this;
    }

    /**
     * Adds Java resources as a map keyed by the paths where they will be added to the Jack package
     * and the final APK. The resource path for an artifact must be a suffix of its exec path.
     */
    public JackCompilationHelper.Builder addResources(Map<PathFragment, Artifact> resources) {
      this.resources.putAll(Preconditions.checkNotNull(resources));
      return this;
    }

    /**
     * Adds a set of class names which will be used as annotation processors.
     */
    public JackCompilationHelper.Builder addProcessorNames(Collection<String> processorNames) {
      this.processorNames.addAll(Preconditions.checkNotNull(processorNames));
      return this;
    }

    /**
     * Adds a set of jars which will be used as the classpath for annotation processors.
     */
    public JackCompilationHelper.Builder addProcessorClasspathJars(
        Iterable<Artifact> processorClasspathJars) {
      this.processorClasspathJars.addAll(Preconditions.checkNotNull(processorClasspathJars));
      return this;
    }

    /**
     * Adds a set of normal dependencies.
     *
     * <p>These dependencies will be considered direct dependencies of this rule,
     * and indirect dependencies of any rules depending on this one.
     * They will also be available to the compilation of the final dex file(s).
     */
    public JackCompilationHelper.Builder addDeps(
        Iterable<? extends TransitiveInfoCollection> deps) {
      return addClasspathDeps(deps).addRuntimeDeps(deps);
    }

    /**
     * Adds a set of dependencies which will be exported to Jack rules which depend on this one.
     *
     * <p>These dependencies will be considered direct dependencies of rules depending on this one,
     * but not of this rule itself, in line with Java rule semantics.
     * They will also be available to the compilation of the final dex file(s).
     */
    public JackCompilationHelper.Builder addExports(
        Iterable<? extends TransitiveInfoCollection> exports) {
      return addExportedDeps(exports).addRuntimeDeps(exports);
    }

    /**
     * Adds a set of dependencies which will be used in dexing.
     *
     * <p>Unless {@link #addClasspathDeps} or {@link #addExportedDeps} are also called,
     * runtimeDeps will not be provided on the classpath of this rule or rules which depend on it.
     */
    public JackCompilationHelper.Builder addRuntimeDeps(
        Iterable<? extends TransitiveInfoCollection> runtimeDeps) {
      for (TransitiveInfoCollection dep : Preconditions.checkNotNull(runtimeDeps)) {
        JackLibraryProvider jackLibraryProvider = dep.getProvider(JackLibraryProvider.class);
        if (jackLibraryProvider != null) {
          dexJacks.addTransitive(jackLibraryProvider.getTransitiveJackLibrariesToLink());
        } else {
          NestedSet<Artifact> filesToBuild = dep.getProvider(FileProvider.class).getFilesToBuild();
          for (Artifact file :
              FileType.filter(filesToBuild, JavaSemantics.JAR, JACK_LIBRARY_TYPE)) {
            dexJars.add(file);
          }
        }
      }
      return this;
    }

    /**
     * Adds a set of dependencies which will be placed on the classpath of this rule.
     *
     * <p>Unless {@link #addRuntimeDeps} is also called, classpathDeps will only be used for
     * compilation of this rule and will not be built into the final dex.
     *
     * @see #addDeps
     */
    public JackCompilationHelper.Builder addClasspathDeps(
        Iterable<? extends TransitiveInfoCollection> classpathDeps) {
      return addDependenciesInternal(
          Preconditions.checkNotNull(classpathDeps),
          classpathNonLibraryFiles,
          classpathJackLibraries);
    }

    /**
     * Adds a set of dependencies to be placed on the classpath of rules depending on this rule.
     *
     * <p>Unless {@link #addRuntimeDeps} is also called, exportedDeps will only be used for
     * compilation of depending rules and will not be built into the final dex.
     *
     * @see #addExports
     */
    public JackCompilationHelper.Builder addExportedDeps(
        Iterable<? extends TransitiveInfoCollection> exportedDeps) {
      return addDependenciesInternal(
          Preconditions.checkNotNull(exportedDeps), exportedNonLibraryFiles, exportedJackLibraries);
    }

    /**
     * Adds all libraries from deps to nonLibraryFiles and jackLibs based on their type.
     *
     * <p>Those exporting JackLibraryProvider have their jackClasspathLibraries added to jackLibs.
     * Others will have any jars or jacks in their filesToBuild added to nonLibraryFiles.
     *
     * <p>{@link #addRuntimeDeps} should also be called on deps for dependencies which will be built
     * into the final dex file(s).
     */
    private JackCompilationHelper.Builder addDependenciesInternal(
        Iterable<? extends TransitiveInfoCollection> deps,
        Collection<Artifact> nonLibraryFiles,
        NestedSetBuilder<Artifact> jackLibs) {
      for (TransitiveInfoCollection dep : deps) {
        JackLibraryProvider jackLibraryProvider = dep.getProvider(JackLibraryProvider.class);
        if (jackLibraryProvider != null) {
          jackLibs.addTransitive(jackLibraryProvider.getTransitiveJackClasspathLibraries());
        } else {
          NestedSet<Artifact> filesToBuild = dep.getProvider(FileProvider.class).getFilesToBuild();
          for (Artifact file :
              FileType.filter(filesToBuild, JavaSemantics.JAR, JACK_LIBRARY_TYPE)) {
            nonLibraryFiles.add(file);
          }
        }
      }
      return this;
    }

    /**
     * Constructs the JackCompilationHelper.
     *
     * <p>It's not recommended to call build() more than once, as the resulting
     * JackCompilationHelpers will attempt to generate the same actions.
     */
    public JackCompilationHelper build() {
      Preconditions.checkNotNull(ruleContext);

      boolean useSanityChecks =
          ruleContext
              .getFragment(AndroidConfiguration.class)
              .isJackSanityChecked();

      // It's okay not to have an outputArtifact if there is nothing to build.
      // e.g., if only translating jars with Jill, no final jack library will be created.
      // But if there is something to build, enforce that one has been specified.
      if (!javaSources.isEmpty() || !sourceJars.isEmpty() || !resources.isEmpty()) {
        Preconditions.checkNotNull(outputArtifact);
      }

      return new JackCompilationHelper(
          ruleContext,
          useSanityChecks,
          useTolerant,
          Preconditions.checkNotNull(resourceExtractorBinary),
          Preconditions.checkNotNull(jackBinary),
          Preconditions.checkNotNull(jillBinary),
          Preconditions.checkNotNull(baseClasspath),
          outputArtifact,
          ImmutableSet.copyOf(javaSources),
          ImmutableSet.copyOf(sourceJars),
          ImmutableMap.copyOf(resources),
          processorClasspathJars.build(),
          ImmutableSet.copyOf(processorNames),
          exportedJackLibraries.build(),
          ImmutableSet.copyOf(exportedNonLibraryFiles),
          classpathJackLibraries.build(),
          ImmutableSet.copyOf(classpathNonLibraryFiles),
          dexJacks.build(),
          ImmutableSet.copyOf(dexJars));
    }
  }
}
