// Copyright 2014 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.actions;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.shell.ShellUtils;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Nullable;

/**
 * An Artifact represents a file used by the build system, whether it's a source
 * file or a derived (output) file. Not all Artifacts have a corresponding
 * FileTarget object in the <code>build.packages</code> API: for example,
 * low-level intermediaries internal to a given rule, such as a Java class files
 * or C++ object files. However all FileTargets have a corresponding Artifact.
 *
 * <p>In any given call to Builder#buildArtifacts(), no two Artifacts in the
 * action graph may refer to the same path.
 *
 * <p>Artifacts generally fall into two classifications, source and derived, but
 * there exist a few other cases that are fuzzy and difficult to classify. The
 * following cases exist:
 * <ul>
 * <li>Well-formed source Artifacts will have null generating Actions and a root
 * that is orthogonal to execRoot. (With the root coming from the package path.)
 * <li>Well-formed derived Artifacts will have non-null generating Actions, and
 * a root that is below execRoot.
 * <li>Symlinked include source Artifacts under the output/include tree will
 * appear to be derived artifacts with null generating Actions.
 * <li>Some derived Artifacts, mostly in the genfiles tree and mostly discovered
 * during include validation, will also have null generating Actions.
 * </ul>
 *
 * In the usual case, an Artifact represents a single file. However, an Artifact may
 * also represent the following:
 * <ul>
 * <li>A TreeArtifact, which is a directory containing a tree of unknown {@link Artifact}s.
 * In the future, Actions will be able to examine these files as inputs and declare them as outputs
 * at execution time, but this is not yet implemented. This is used for Actions where
 * the inputs and/or outputs might not be discoverable except during Action execution.
 * <li>A directory of unknown contents, but not a TreeArtifact.
 * This is a legacy facility and should not be used by any new rule implementations.
 * In particular, the file system cache integrity checks fail for directories.
 * <li>An 'aggregating middleman' special Artifact, which may be expanded using a
 * {@link ArtifactExpander} at Action execution time. This is used by a handful of rules to save
 * memory.
 * <li>A 'constant metadata' special Artifact. These represent real files, changes to which are
 * ignored by the build system. They are useful for files which change frequently but do not affect
 * the result of a build, such as timestamp files.
 * <li>A 'Fileset' special Artifact. This is a legacy type of Artifact and should not be used
 * by new rule implementations.
 * </ul>
 * <p>This class is "theoretically" final; it should not be subclassed except by
 * {@link SpecialArtifact}.
 */
@Immutable
@SkylarkModule(name = "File",
    category = SkylarkModuleCategory.BUILTIN,
    doc = "<p>This type represents a file used by the build system. It can be "
        + "either a source file or a derived file produced by a rule.</p>"
        + "<p>The File constructor is private, so you cannot call it directly to create new "
        + "Files. If you have a Skylark rule that needs to create a new File, you might need to "
        + "add the label to the attrs (if it's an input) or the outputs (if it's an output). Then "
        + "you can access the File through the rule's <a href='ctx.html'>context</a>. You can "
        + "also use <a href='ctx.html#new_file'>ctx.new_file</a> to create a new file in the rule "
        + "implementation.</p>")
public class Artifact
    implements FileType.HasFilename, ActionInput, SkylarkValue, Comparable<Object> {

  /**
   * Compares artifact according to their exec paths. Sorts null values first.
   */
  public static final Comparator<Artifact> EXEC_PATH_COMPARATOR = new Comparator<Artifact>() {
    @Override
    public int compare(Artifact a, Artifact b) {
      if (a == b) {
        return 0;
      } else if (a == null) {
        return -1;
      } else if (b == null) {
        return -1;
      } else {
        return a.execPath.compareTo(b.execPath);
      }
    }
  };

  /** Compares artifacts according to their root relative paths. */
  public static final Comparator<Artifact> ROOT_RELATIVE_PATH_COMPARATOR =
      new Comparator<Artifact>() {
        @Override
        public int compare(Artifact lhs, Artifact rhs) {
          return lhs.getRootRelativePath().compareTo(rhs.getRootRelativePath());
        }
      };

  @Override
  public int compareTo(Object o) {
    if (o instanceof Artifact) {
      return EXEC_PATH_COMPARATOR.compare(this, (Artifact) o);
    }
    return EvalUtils.compareByClass(this, o);
  }


  /** An object that can expand middleman artifacts. */
  public interface ArtifactExpander {

    /**
     * Expands the given artifact, and populates "output" with the result.
     *
     * <p>{@code artifact.isMiddlemanArtifact() || artifact.isTreeArtifact()} must be true.
     * Only aggregating middlemen and tree artifacts are expanded.
     */
    void expand(Artifact artifact, Collection<? super Artifact> output);
  }

  public static final ImmutableList<Artifact> NO_ARTIFACTS = ImmutableList.of();

  /**
   * A Predicate that evaluates to true if the Artifact is not a middleman artifact.
   */
  public static final Predicate<Artifact> MIDDLEMAN_FILTER = new Predicate<Artifact>() {
    @Override
    public boolean apply(Artifact input) {
      return !input.isMiddlemanArtifact();
    }
  };

  /**
   * A Predicate that evaluates to true if the Artifact <b>is</b> a tree artifact.
   */
  public static final Predicate<Artifact> IS_TREE_ARTIFACT = new Predicate<Artifact>() {
    @Override
    public boolean apply(Artifact input) {
      return input.isTreeArtifact();
    }
  };

  private final int hashCode;
  private final Path path;
  private final Root root;
  private final PathFragment execPath;
  private final PathFragment rootRelativePath;
  private final ArtifactOwner owner;

  /**
   * Constructs an artifact for the specified path, root and execPath. The root must be an ancestor
   * of path, and execPath must be a non-absolute tail of path. Outside of testing, this method
   * should only be called by ArtifactFactory. The ArtifactOwner may be null.
   *
   * <p>In a source Artifact, the path tail after the root will be identical to the execPath, but
   * the root will be orthogonal to execRoot.
   * <pre>
   *  [path] == [/root/][execPath]
   * </pre>
   *
   * <p>In a derived Artifact, the execPath will overlap with part of the root, which in turn will
   * be below of the execRoot.
   * <pre>
   *  [path] == [/root][pathTail] == [/execRoot][execPath] == [/execRoot][rootPrefix][pathTail]
   * <pre>
   */
  @VisibleForTesting
  public Artifact(Path path, Root root, PathFragment execPath, ArtifactOwner owner) {
    if (root == null || !path.startsWith(root.getPath())) {
      throw new IllegalArgumentException(root + ": illegal root for " + path
          + " (execPath: " + execPath + ")");
    }
    if (execPath == null || execPath.isAbsolute() || !path.asFragment().endsWith(execPath)) {
      throw new IllegalArgumentException(execPath + ": illegal execPath for " + path
          + " (root: " + root + ")");
    }
    this.hashCode = path.hashCode();
    this.path = path;
    this.root = root;
    this.execPath = execPath;
    // These two lines establish the invariant that
    // execPath == rootRelativePath <=> execPath.equals(rootRelativePath)
    // This is important for isSourceArtifact.
    PathFragment rootRel = path.relativeTo(root.getPath());
    if (!execPath.endsWith(rootRel)) {
      throw new IllegalArgumentException(execPath + ": illegal execPath doesn't end with "
          + rootRel + " at " + path + " with root " + root);
    }
    this.rootRelativePath = rootRel.equals(execPath) ? execPath : rootRel;
    this.owner = Preconditions.checkNotNull(owner, path);
  }

  /**
   * Constructs an artifact for the specified path, root and execPath. The root must be an ancestor
   * of path, and execPath must be a non-absolute tail of path. Should only be called for testing.
   *
   * <p>In a source Artifact, the path tail after the root will be identical to the execPath, but
   * the root will be orthogonal to execRoot.
   * <pre>
   *  [path] == [/root/][execPath]
   * </pre>
   *
   * <p>In a derived Artifact, the execPath will overlap with part of the root, which in turn will
   * be below of the execRoot.
   * <pre>
   *  [path] == [/root][pathTail] == [/execRoot][execPath] == [/execRoot][rootPrefix][pathTail]
   * <pre>
   */
  @VisibleForTesting
  public Artifact(Path path, Root root, PathFragment execPath) {
    this(path, root, execPath, ArtifactOwner.NULL_OWNER);
  }

  /**
   * Constructs a source or derived Artifact for the specified path and specified root. The root
   * must be an ancestor of the path.
   */
  @VisibleForTesting  // Only exists for testing.
  public Artifact(Path path, Root root) {
    this(path, root, root.getExecPath().getRelative(path.relativeTo(root.getPath())),
        ArtifactOwner.NULL_OWNER);
  }

  /**
   * Constructs a source or derived Artifact for the specified root-relative path and root.
   */
  @VisibleForTesting  // Only exists for testing.
  public Artifact(PathFragment rootRelativePath, Root root) {
    this(root.getPath().getRelative(rootRelativePath), root,
        root.getExecPath().getRelative(rootRelativePath), ArtifactOwner.NULL_OWNER);
  }

  public final Path getPath() {
    return path;
  }

  public boolean hasParent() {
    return getParent() != null;
  }

  /**
   * Returns the parent Artifact containing this Artifact. Artifacts without parents shall
   * return null.
   */
  @Nullable public Artifact getParent() {
    return null;
  }

  /**
   * Returns the directory name of this artifact, similar to dirname(1).
   *
   * <p> The directory name is always a relative path to the execution directory.
   */
  @SkylarkCallable(name = "dirname", structField = true,
      doc = "The name of the directory containing this file.")
  public final String getDirname() {
    PathFragment parent = getExecPath().getParentDirectory();
    return (parent == null) ? "/" : parent.getSafePathString();
  }

  /**
   * Returns the base file name of this artifact, similar to basename(1).
   */
  @Override
  @SkylarkCallable(name = "basename", structField = true,
      doc = "The base file name of this file.")
  public final String getFilename() {
    return getExecPath().getBaseName();
  }

  @SkylarkCallable(name = "extension", structField = true, doc = "The file extension of this file.")
  public final String getExtension() {
    return getExecPath().getFileExtension();
  }

  /**
   * Returns the artifact owner. May be null.
   */
  @Nullable public final Label getOwner() {
    return owner.getLabel();
  }

  /**
   * Get the {@code LabelAndConfiguration} of the {@code ConfiguredTarget} that owns this artifact,
   * if it was set. Otherwise, this should be a dummy value -- either {@link
   * ArtifactOwner#NULL_OWNER} or a dummy owner set in tests. Such a dummy value should only occur
   * for source artifacts if created without specifying the owner, or for special derived artifacts,
   * such as target completion middleman artifacts, build info artifacts, and the like.
   */
  public final ArtifactOwner getArtifactOwner() {
    return owner;
  }

  @SkylarkCallable(name = "owner", structField = true, allowReturnNones = true,
    doc = "A label of a target that produces this File."
  )
  public Label getOwnerLabel() {
    return owner.getLabel();
  }

  /**
   * Returns the root beneath which this Artifact resides, if any. This may be one of the
   * package-path entries (for source Artifacts), or one of the bin, genfiles or includes dirs
   * (for derived Artifacts). It will always be an ancestor of getPath().
   */
  @SkylarkCallable(name = "root", structField = true,
      doc = "The root beneath which this file resides."
  )
  public final Root getRoot() {
    return root;
  }

  public final PathFragment getExecPath() {
    return execPath;
  }

  /**
   * Returns the path of this Artifact relative to this containing Artifact. Since
   * ordinary Artifacts correspond to only one Artifact -- itself -- for ordinary Artifacts,
   * this just returns the empty path. For special Artifacts, throws
   * {@link UnsupportedOperationException}. See also {@link Artifact#getParentRelativePath()}.
   */
  public PathFragment getParentRelativePath() {
    return PathFragment.EMPTY_FRAGMENT;
  }

  /**
   * Returns true iff this is a source Artifact as determined by its path and
   * root relationships. Note that this will report all Artifacts in the output
   * tree, including in the include symlink tree, as non-source.
   */
  @SkylarkCallable(name = "is_source", structField =  true,
      doc = "Returns true if this is a source file, i.e. it is not generated")
  public final boolean isSourceArtifact() {
    return execPath == rootRelativePath;
  }

  /**
   * Returns true iff this is a middleman Artifact as determined by its root.
   */
  public final boolean isMiddlemanArtifact() {
    return getRoot().isMiddlemanRoot();
  }

  /**
   * Returns true iff this is a TreeArtifact representing a directory tree containing Artifacts.
   */
  // TODO(rduan): Document this Skylark method once TreeArtifact is no longer experimental.
  @SkylarkCallable(name = "is_directory", structField = true, documented = false)
  public boolean isTreeArtifact() {
    return false;
  }

  /**
   * Returns whether the artifact represents a Fileset.
   */
  public boolean isFileset() {
    return false;
  }

  /**
   * Returns true iff metadata cache must return constant metadata for the
   * given artifact.
   */
  public boolean isConstantMetadata() {
    return false;
  }

  /**
   * Special artifact types.
   *
   * @see SpecialArtifact
   */
  @VisibleForTesting
  public static enum SpecialArtifactType {
    FILESET,
    TREE,
    CONSTANT_METADATA,
  }

  /**
   * A special kind of artifact that either is a fileset or needs special metadata caching behavior.
   *
   * <p>We subclass {@link Artifact} instead of storing the special attributes inside in order
   * to save memory. The proportion of artifacts that are special is very small, and by not having
   * to keep around the attribute for the rest we save some memory.
   */
  @Immutable
  @VisibleForTesting
  public static final class SpecialArtifact extends Artifact {
    private final SpecialArtifactType type;

    @VisibleForTesting
    public SpecialArtifact(Path path, Root root, PathFragment execPath, ArtifactOwner owner,
        SpecialArtifactType type) {
      super(path, root, execPath, owner);
      this.type = type;
    }

    @Override
    public final boolean isFileset() {
      return type == SpecialArtifactType.FILESET;
    }

    @Override
    public boolean isConstantMetadata() {
      return type == SpecialArtifactType.CONSTANT_METADATA;
    }

    @Override
    public boolean isTreeArtifact() {
      return type == SpecialArtifactType.TREE;
    }

    @Override
    public boolean hasParent() {
      return false;
    }

    @Override
    @Nullable
    public Artifact getParent() {
      return null;
    }

    @Override
    @Nullable
    public PathFragment getParentRelativePath() {
      return null;
    }
  }

  /**
   * A special kind of artifact that represents a concrete file created at execution time under
   * its associated TreeArtifact.
   *
   * <p> TreeFileArtifacts should be only created during execution time inside some special actions
   * to support action inputs and outputs that are unpredictable at analysis time.
   * TreeFileArtifacts should not be created directly by any rules at analysis time.
   *
   * <p>We subclass {@link Artifact} instead of storing the extra fields directly inside in order
   * to save memory. The proportion of TreeFileArtifacts is very small, and by not having to keep
   * around the extra fields for the rest we save some memory.
   */
  @Immutable
  public static final class TreeFileArtifact extends Artifact {
    private final Artifact parentTreeArtifact;
    private final PathFragment parentRelativePath;

    /**
     * Constructs a TreeFileArtifact with the given parent-relative path under the given parent
     * TreeArtifact. The {@link ArtifactOwner} of the TreeFileArtifact is the {@link ArtifactOwner}
     * of the parent TreeArtifact.
     */
    TreeFileArtifact(Artifact parent, PathFragment parentRelativePath) {
      this(parent, parentRelativePath, parent.getArtifactOwner());
    }

    /**
     * Constructs a TreeFileArtifact with the given parent-relative path under the given parent
     * TreeArtifact, owned by the given {@code artifactOwner}.
     */
    TreeFileArtifact(Artifact parent, PathFragment parentRelativePath,
        ArtifactOwner artifactOwner) {
      super(
          parent.getPath().getRelative(parentRelativePath),
          parent.getRoot(),
          parent.getExecPath().getRelative(parentRelativePath),
          artifactOwner);
      Preconditions.checkState(
          parent.isTreeArtifact(),
          "The parent of TreeFileArtifact (parent-relative path: %s) is not a TreeArtifact: %s",
          parentRelativePath,
          parent);
      this.parentTreeArtifact = parent;
      this.parentRelativePath = parentRelativePath;
    }

    @Override
    public Artifact getParent() {
      return parentTreeArtifact;
    }

    @Override
    public PathFragment getParentRelativePath() {
      return parentRelativePath;
    }
  }

  /**
   * Returns the relative path to this artifact relative to its root.  (Useful
   * when deriving output filenames from input files, etc.)
   */
  public final PathFragment getRootRelativePath() {
    return rootRelativePath;
  }

  /**
   * For targets in external repositories, this returns the path the artifact live at in the
   * runfiles tree. For local targets, it returns the rootRelativePath.
   */
  public final PathFragment getRunfilesPath() {
    PathFragment relativePath = rootRelativePath;
    if (relativePath.segmentCount() > 1
        && relativePath.getSegment(0).equals(Label.EXTERNAL_PATH_PREFIX)) {
      // Turn external/repo/foo into ../repo/foo.
      relativePath = relativePath.relativeTo(Label.EXTERNAL_PATH_PREFIX);
      relativePath = new PathFragment("..").getRelative(relativePath);
    }
    return relativePath;
  }

  @SkylarkCallable(
      name = "short_path",
      structField = true,
      doc =
          "The path of this file relative to its root. This excludes the aforementioned "
              + "<i>root</i>, i.e. configuration-specific fragments of the path. This is also the "
              + "path under which the file is mapped if it's in the runfiles of a binary."
  )
  public final String getRunfilesPathString() {
    return getRunfilesPath().getPathString();
  }

  /**
   * Returns this.getExecPath().getPathString().
   */
  @Override
  @SkylarkCallable(
    name = "path",
    structField = true,
    doc =
        "The execution path of this file, relative to the workspace's execution directory. It "
            + "consists of two parts, an optional first part called the <i>root</i> (see also the "
            + "<a href=\"root.html\">root</a> module), and the second part which is the "
            + "<code>short_path</code>. The root may be empty, which it usually is for "
            + "non-generated files. For generated files it usually contains a "
            + "configuration-specific path fragment that encodes things like the target CPU "
            + "architecture that was used while building said file. Use the "
            + "<code>short_path</code> for the path under which the file is mapped if it's in the "
            + "runfiles of a binary."
  )
  public final String getExecPathString() {
    return getExecPath().getPathString();
  }

  /*
   * Returns getExecPathString escaped for potential use in a shell command.
   */
  public final String getShellEscapedExecPathString() {
    return ShellUtils.shellEscape(getExecPathString());
  }

  public final String getRootRelativePathString() {
    return getRootRelativePath().getPathString();
  }

  public final String prettyPrint() {
    // toDetailString would probably be more useful to users, but lots of tests rely on the
    // current values.
    return rootRelativePath.toString();
  }

  @Override
  public final boolean equals(Object other) {
    if (!(other instanceof Artifact)) {
      return false;
    }
    // We don't bother to check root in the equivalence relation, because we
    // assume that no root is an ancestor of another one.
    Artifact that = (Artifact) other;
    return this.path.equals(that.path);
  }

  @Override
  public final int hashCode() {
    // This is just path.hashCode().  We cache a copy in the Artifact object to reduce LLC misses
    // during operations which build a HashSet out of many Artifacts.  This is a slight loss for
    // memory but saves ~1% overall CPU in some real builds.
    return hashCode;
  }

  @Override
  public final String toString() {
    return "Artifact:" + toDetailString();
  }

  /**
   * Returns the root-part of a given path by trimming off the end specified by
   * a given tail. Assumes that the tail is known to match, and simply relies on
   * the segment lengths.
   */
  private static PathFragment trimTail(PathFragment path, PathFragment tail) {
    return path.subFragment(0, path.segmentCount() - tail.segmentCount());
  }

  /**
   * Returns a string representing the complete artifact path information.
   */
  public final String toDetailString() {
    if (isSourceArtifact()) {
      // Source Artifact: relPath == execPath, & real path is not under execRoot
      return "[" + root + "]" + rootRelativePath;
    } else {
      // Derived Artifact: path and root are under execRoot
      PathFragment execRoot = trimTail(path.asFragment(), execPath);
      return "[[" + execRoot + "]" + root.getPath().asFragment().relativeTo(execRoot) + "]"
          + rootRelativePath;
    }
  }

  /**
   * Serializes this artifact to a string that has enough data to reconstruct the artifact.
   */
  public final String serializeToString() {
    // In theory, it should be enough to serialize execPath and rootRelativePath (which is a suffix
    // of execPath). However, in practice there is code around that uses other attributes which
    // needs cleaning up.
    String result = execPath + " /" + rootRelativePath.toString().length();
    if (getOwner() != null) {
      result += " " + getOwner();
    }
    return result;
  }

  //---------------------------------------------------------------------------
  // Static methods to assist in working with Artifacts

  /**
   * Formatter for execPath PathFragment output.
   */
  private static final Function<Artifact, PathFragment> EXEC_PATH_FORMATTER =
      new Function<Artifact, PathFragment>() {
        @Override
        public PathFragment apply(Artifact input) {
          return input.getExecPath();
        }
      };

  public static final Function<Artifact, String> ROOT_RELATIVE_PATH_STRING =
      new Function<Artifact, String>() {
        @Override
        public String apply(Artifact artifact) {
          return artifact.getRootRelativePath().getPathString();
        }
      };

  public static final Function<Artifact, String> ABSOLUTE_PATH_STRING =
      new Function<Artifact, String>() {
        @Override
        public String apply(Artifact artifact) {
          return artifact.getPath().getPathString();
        }
      };

  /**
   * Converts a collection of artifacts into execution-time path strings, and
   * adds those to a given collection. Middleman artifacts are ignored by this
   * method.
   */
  public static void addExecPaths(Iterable<Artifact> artifacts, Collection<String> output) {
    addNonMiddlemanArtifacts(artifacts, output, ActionInputHelper.EXEC_PATH_STRING_FORMATTER);
  }

  /**
   * Converts a collection of artifacts into the outputs computed by
   * outputFormatter and adds them to a given collection. Middleman artifacts
   * are ignored.
   */
  static <E> void addNonMiddlemanArtifacts(Iterable<Artifact> artifacts,
      Collection<? super E> output, Function<? super Artifact, E> outputFormatter) {
    for (Artifact artifact : artifacts) {
      if (MIDDLEMAN_FILTER.apply(artifact)) {
        output.add(outputFormatter.apply(artifact));
      }
    }
  }

  /**
   * Lazily converts artifacts into absolute path strings. Middleman artifacts are ignored by
   * this method.
   */
  public static Iterable<String> toAbsolutePaths(Iterable<Artifact> artifacts) {
    return Iterables.transform(
        Iterables.filter(artifacts, MIDDLEMAN_FILTER),
        ABSOLUTE_PATH_STRING);
  }

  /**
   * Lazily converts artifacts into root-relative path strings. Middleman artifacts are ignored by
   * this method.
   */
  public static Iterable<String> toRootRelativePaths(Iterable<Artifact> artifacts) {
    return Iterables.transform(
        Iterables.filter(artifacts, MIDDLEMAN_FILTER),
        ROOT_RELATIVE_PATH_STRING);
  }

  /**
   * Lazily converts artifacts into execution-time path strings. Middleman artifacts are ignored by
   * this method.
   */
  public static Iterable<String> toExecPaths(Iterable<Artifact> artifacts) {
    return ActionInputHelper.toExecPaths(Iterables.filter(artifacts, MIDDLEMAN_FILTER));
  }

  /**
   * Converts a collection of artifacts into execution-time path strings, and
   * returns those as an immutable list. Middleman artifacts are ignored by this method.
   */
  public static List<String> asExecPaths(Iterable<Artifact> artifacts) {
    return ImmutableList.copyOf(toExecPaths(artifacts));
  }

  /**
   * Renders a collection of artifacts as execution-time paths and joins
   * them into a single string. Middleman artifacts are ignored by this method.
   */
  public static String joinExecPaths(String delimiter, Iterable<Artifact> artifacts) {
    return Joiner.on(delimiter).join(toExecPaths(artifacts));
  }

  /**
   * Renders a collection of artifacts as root-relative paths and joins
   * them into a single string. Middleman artifacts are ignored by this method.
   */
  public static String joinRootRelativePaths(String delimiter, Iterable<Artifact> artifacts) {
    return Joiner.on(delimiter).join(toRootRelativePaths(artifacts));
  }

  /**
   * Adds a collection of artifacts to a given collection, with
   * {@link MiddlemanType#AGGREGATING_MIDDLEMAN} middleman actions expanded once.
   */
  public static void addExpandedArtifacts(Iterable<Artifact> artifacts,
      Collection<? super Artifact> output, ArtifactExpander artifactExpander) {
    addExpandedArtifacts(artifacts, output, Functions.<Artifact>identity(), artifactExpander);
  }

  /**
   * Converts a collection of artifacts into execution-time path strings, and
   * adds those to a given collection. Middleman artifacts for
   * {@link MiddlemanType#AGGREGATING_MIDDLEMAN} middleman actions are expanded
   * once.
   */
  @VisibleForTesting
  public static void addExpandedExecPathStrings(Iterable<Artifact> artifacts,
                                                 Collection<String> output,
                                                 ArtifactExpander artifactExpander) {
    addExpandedArtifacts(artifacts, output, ActionInputHelper.EXEC_PATH_STRING_FORMATTER,
        artifactExpander);
  }

  /**
   * Converts a collection of artifacts into execution-time path fragments, and
   * adds those to a given collection. Middleman artifacts for
   * {@link MiddlemanType#AGGREGATING_MIDDLEMAN} middleman actions are expanded
   * once.
   */
  public static void addExpandedExecPaths(Iterable<Artifact> artifacts,
      Collection<PathFragment> output, ArtifactExpander artifactExpander) {
    addExpandedArtifacts(artifacts, output, EXEC_PATH_FORMATTER, artifactExpander);
  }

  /**
   * Converts a collection of artifacts into the outputs computed by
   * outputFormatter and adds them to a given collection. Middleman artifacts
   * are expanded once.
   */
  private static <E> void addExpandedArtifacts(Iterable<? extends Artifact> artifacts,
                                               Collection<? super E> output,
                                               Function<? super Artifact, E> outputFormatter,
                                               ArtifactExpander artifactExpander) {
    for (Artifact artifact : artifacts) {
      if (artifact.isMiddlemanArtifact() || artifact.isTreeArtifact()) {
        expandArtifact(artifact, output, outputFormatter, artifactExpander);
      } else {
        output.add(outputFormatter.apply(artifact));
      }
    }
  }

  private static <E> void expandArtifact(Artifact middleman,
      Collection<? super E> output,
      Function<? super Artifact, E> outputFormatter,
      ArtifactExpander artifactExpander) {
    Preconditions.checkArgument(middleman.isMiddlemanArtifact() || middleman.isTreeArtifact());
    List<Artifact> artifacts = new ArrayList<>();
    artifactExpander.expand(middleman, artifacts);
    for (Artifact artifact : artifacts) {
      output.add(outputFormatter.apply(artifact));
    }
  }

  /**
   * Converts a collection of artifacts into execution-time path strings, and
   * returns those as a list. Middleman artifacts are expanded once. The
   * returned list is mutable.
   */
  public static List<String> asExpandedExecPathStrings(Iterable<Artifact> artifacts,
                                                       ArtifactExpander artifactExpander) {
    List<String> result = new ArrayList<>();
    addExpandedExecPathStrings(artifacts, result, artifactExpander);
    return result;
  }

  /**
   * Converts a collection of artifacts into execution-time path fragments, and
   * returns those as a list. Middleman artifacts are expanded once. The
   * returned list is mutable.
   */
  public static List<PathFragment> asExpandedExecPaths(Iterable<Artifact> artifacts,
                                                       ArtifactExpander artifactExpander) {
    List<PathFragment> result = new ArrayList<>();
    addExpandedExecPaths(artifacts, result, artifactExpander);
    return result;
  }

  /**
   * Converts a collection of artifacts into execution-time path strings with
   * the root-break delimited with a colon ':', and adds those to a given list.
   * <pre>
   * Source: sourceRoot/rootRelative => :rootRelative
   * Derived: execRoot/rootPrefix/rootRelative => rootPrefix:rootRelative
   * </pre>
   */
  public static void addRootPrefixedExecPaths(Iterable<Artifact> artifacts,
      List<String> output) {
    for (Artifact artifact : artifacts) {
      output.add(asRootPrefixedExecPath(artifact));
    }
  }

  /**
   * Convenience method to filter the files to build for a certain filetype.
   *
   * @param artifacts the files to filter
   * @param allowedType the allowed filetype
   * @return all members of filesToBuild that are of one of the
   *     allowed filetypes
   */
  public static List<Artifact> filterFiles(Iterable<Artifact> artifacts, FileType allowedType) {
    List<Artifact> filesToBuild = new ArrayList<>();
    for (Artifact artifact : artifacts) {
      if (allowedType.matches(artifact.getFilename())) {
        filesToBuild.add(artifact);
      }
    }
    return filesToBuild;
  }

  @VisibleForTesting
  static String asRootPrefixedExecPath(Artifact artifact) {
    PathFragment execPath = artifact.getExecPath();
    PathFragment rootRel = artifact.getRootRelativePath();
    if (execPath.equals(rootRel)) {
      return ":" + rootRel.getPathString();
    } else { //if (execPath.endsWith(rootRel)) {
      PathFragment rootPrefix = trimTail(execPath, rootRel);
      return rootPrefix.getPathString() + ":" + rootRel.getPathString();
    }
  }

  /**
   * Converts artifacts into their exec paths. Returns an immutable list.
   */
  public static List<PathFragment> asPathFragments(Iterable<? extends Artifact> artifacts) {
    return ImmutableList.copyOf(Iterables.transform(artifacts, EXEC_PATH_FORMATTER));
  }

  /**
   * Returns the exec paths of the input artifacts in alphabetical order.
   */
  public static ImmutableList<PathFragment> asSortedPathFragments(Iterable<Artifact> input) {
    return Ordering.natural().immutableSortedCopy(Iterables.transform(
        input, EXEC_PATH_FORMATTER));
  }


  @Override
  public boolean isImmutable() {
    return true;
  }

  @Override
  public void write(Appendable buffer, char quotationMark) {
    Printer.append(buffer, toString()); // TODO(bazel-team): implement a readable representation
  }
}
