// 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.query2.output;

import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.joining;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.graph.Digraph;
import com.google.devtools.build.lib.graph.Node;
import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.DependencyFilter;
import com.google.devtools.build.lib.packages.License;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.query2.AbstractBlazeQueryEnvironment;
import com.google.devtools.build.lib.query2.engine.AggregatingQueryExpressionVisitor.ContainsFunctionQueryExpressionVisitor;
import com.google.devtools.build.lib.query2.engine.OutputFormatterCallback;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
import com.google.devtools.build.lib.query2.engine.SynchronizedDelegatingOutputFormatterCallback;
import com.google.devtools.build.lib.query2.engine.ThreadSafeOutputFormatterCallback;
import com.google.devtools.build.lib.query2.output.QueryOptions.OrderOutput;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.common.options.EnumConverter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Interface for classes which order, format and print the result of a Blaze
 * graph query.
 */
public abstract class OutputFormatter implements Serializable {

  /**
   * Discriminator for different kinds of OutputFormatter.
   */
  public enum OutputType {
    LABEL,
    LABEL_KIND,
    BUILD,
    MINRANK,
    MAXRANK,
    PACKAGE,
    LOCATION,
    GRAPH,
    XML,
    PROTO,
    RECORD,
  }

  /**
   * Where the value of an attribute comes from
   */
  protected enum AttributeValueSource {
    RULE,     // Explicitly specified on the rule
    PACKAGE,  // Package default
    DEFAULT   // Rule class default
  }

  public static final Function<Node<Target>, Target> EXTRACT_NODE_LABEL = Node::getLabel;

  /**
   * Converter from strings to OutputFormatter.OutputType.
   */
  public static class Converter extends EnumConverter<OutputType> {
    public Converter() { super(OutputType.class, "output formatter"); }
  }

  public static ImmutableList<OutputFormatter> getDefaultFormatters() {
    return ImmutableList.of(
        new LabelOutputFormatter(false),
        new LabelOutputFormatter(true),
        new BuildOutputFormatter(),
        new MinrankOutputFormatter(),
        new MaxrankOutputFormatter(),
        new PackageOutputFormatter(),
        new LocationOutputFormatter(),
        new GraphOutputFormatter(),
        new XmlOutputFormatter(),
        new ProtoOutputFormatter());
  }

  public static String formatterNames(Iterable<OutputFormatter> formatters) {
    return Streams.stream(formatters).map(OutputFormatter::getName).collect(joining(", "));
  }

  /**
   * Returns the output formatter for the specified command-line options.
   */
  public static OutputFormatter getFormatter(
      Iterable<OutputFormatter> formatters, String type) {
    for (OutputFormatter formatter : formatters) {
      if (formatter.getName().equals(type)) {
        return formatter;
      }
    }

    return null;
  }

  /**
   * Given a set of query options, returns a BinaryPredicate suitable for
   * passing to {@link Rule#getLabels()}, {@link XmlOutputFormatter}, etc.
   */
  public static DependencyFilter getDependencyFilter(
      QueryOptions queryOptions) {
    // TODO(bazel-team): Optimize: and(ALL_DEPS, x) -> x, etc.
    return DependencyFilter.and(
        queryOptions.includeHostDeps ? DependencyFilter.ALL_DEPS : DependencyFilter.NO_HOST_DEPS,
        queryOptions.includeImplicitDeps
            ? DependencyFilter.ALL_DEPS
            : DependencyFilter.NO_IMPLICIT_DEPS);
  }

  /**
   * Workaround for a bug in {@link java.nio.channels.Channels#newChannel(OutputStream)}, which
   * attempts to close the output stream on interrupt, which can cause a deadlock if there is an
   * ongoing write. If this formatter uses Channels.newChannel, then it must return false here, and
   * perform its own buffering.
   */
  public boolean canBeBuffered() {
    return true;
  }

  public void verifyCompatible(QueryEnvironment<?> env, QueryExpression expr)
      throws QueryException {
  }

  /**
   * Format the result (a set of target nodes implicitly ordered according to
   * the graph maintained by the QueryEnvironment), and print it to "out".
   */
  public abstract void output(QueryOptions options, Digraph<Target> result, OutputStream out,
      AspectResolver aspectProvider)
          throws IOException, InterruptedException;

  /**
   * Unordered streamed output formatter (wrt. dependency ordering).
   *
   * <p>Formatters that support streamed output may be used when only the set of query results is
   * requested but their ordering is irrelevant.
   *
   * <p>The benefit of using a streamed formatter is that we can save the potentially expensive
   * subgraph extraction step before presenting the query results and that depending on the query
   * environment used, it can be more memory performant, as it does not aggregate all the data
   * before writting in the output.
   */
  public interface StreamedFormatter {
    /** Specifies options to be used by subsequent calls to {@link #createStreamCallback}. */
    void setOptions(QueryOptions options, AspectResolver aspectResolver);

    /**
     * Returns a {@link ThreadSafeOutputFormatterCallback} whose
     * {@link OutputFormatterCallback#process} outputs formatted {@link Target}s to the given
     * {@code out}.
     *
     * <p>Takes any options specified via the most recent call to {@link #setOptions} into
     * consideration.
     *
     * <p>Intended to be use for streaming out during evaluation of a query.
     */
    ThreadSafeOutputFormatterCallback<Target> createStreamCallback(
        OutputStream out, QueryOptions options, QueryEnvironment<?> env);

    /**
     * Same as {@link #createStreamCallback}, but intended to be used for outputting the
     * already-computed result of a query.
     */
    OutputFormatterCallback<Target> createPostFactoStreamCallback(
        OutputStream out, QueryOptions options);
  }

  /**
   * Returns the user-visible name of the output formatter.
   */
  public abstract String getName();

  abstract static class AbstractUnorderedFormatter extends OutputFormatter
      implements StreamedFormatter {
    protected QueryOptions options;
    protected AspectResolver aspectResolver;
    protected DependencyFilter dependencyFilter;

    protected Iterable<Target> getOrderedTargets(
        Digraph<Target> result, QueryOptions options) {
      Iterable<Node<Target>> orderedResult =
          options.orderOutput == OrderOutput.DEPS
              ? result.getTopologicalOrder()
              : result.getTopologicalOrder(new TargetOrdering());
      return Iterables.transform(orderedResult, EXTRACT_NODE_LABEL);
    }

    @Override
    public void setOptions(QueryOptions options, AspectResolver aspectResolver) {
      this.options = options;
      this.aspectResolver = aspectResolver;
      this.dependencyFilter = OutputFormatter.getDependencyFilter(options);
    }

    @Override
    public void output(
        QueryOptions options,
        Digraph<Target> result,
        OutputStream out,
        AspectResolver aspectResolver) throws IOException, InterruptedException {
      setOptions(options, aspectResolver);
      OutputFormatterCallback.processAllTargets(
          createPostFactoStreamCallback(out, options), getOrderedTargets(result, options));
    }
  }

  /** Abstract class supplying a {@link PrintStream} to implementations, flushing it on close. */
  private abstract static class TextOutputFormatterCallback<T> extends OutputFormatterCallback<T> {
    protected PrintStream printStream;

    private TextOutputFormatterCallback(OutputStream out) {
      this.printStream = new PrintStream(out);
    }

    @Override
    public void close(boolean failFast) throws IOException {
      if (!failFast) {
        flushAndCheckError(printStream);
      }
    }
  }

  /**
   * An output formatter that prints the labels of the resulting target set in
   * topological order, optionally with the target's kind.
   */
  private static class LabelOutputFormatter extends AbstractUnorderedFormatter {

    private final boolean showKind;

    private LabelOutputFormatter(boolean showKind) {
      this.showKind = showKind;
    }

    @Override
    public String getName() {
      return showKind ? "label_kind" : "label";
    }

    @Override
    public OutputFormatterCallback<Target> createPostFactoStreamCallback(
        OutputStream out, final QueryOptions options) {
      return new TextOutputFormatterCallback<Target>(out) {
        @Override
        public void processOutput(Iterable<Target> partialResult) {
          for (Target target : partialResult) {
            if (showKind) {
              printStream.print(target.getTargetKind());
              printStream.print(' ');
            }
            printStream.printf(
                "%s%s", target.getLabel().getDefaultCanonicalForm(), options.getLineTerminator());
          }
        }
      };
    }

    @Override
    public ThreadSafeOutputFormatterCallback<Target> createStreamCallback(
        OutputStream out, QueryOptions options, QueryEnvironment<?> env) {
      return new SynchronizedDelegatingOutputFormatterCallback<>(
          createPostFactoStreamCallback(out, options));
    }
  }

  /**
   * An ordering of Targets based on the ordering of their labels.
   */
  @VisibleForTesting
  public static class TargetOrdering implements Comparator<Target> {
    @Override
    public int compare(Target o1, Target o2) {
      return o1.getLabel().compareTo(o2.getLabel());
    }
  }

  /**
   * An output formatter that prints the names of the packages of the target
   * set, in lexicographical order without duplicates.
   */
  private static class PackageOutputFormatter extends AbstractUnorderedFormatter {


    @Override
    public String getName() {
      return "package";
    }

    @Override
    public OutputFormatterCallback<Target> createPostFactoStreamCallback(
        OutputStream out, final QueryOptions options) {
      return new TextOutputFormatterCallback<Target>(out) {
        private final Set<String> packageNames = Sets.newTreeSet();

        @Override
        public void processOutput(Iterable<Target> partialResult) {

          for (Target target : partialResult) {
            packageNames.add(target.getLabel().getPackageIdentifier().toString());
          }
        }

        @Override
        public void close(boolean failFast) throws IOException {
          if (!failFast) {
            final String lineTerm = options.getLineTerminator();
            for (String packageName : packageNames) {
              printStream.printf("%s%s", packageName, lineTerm);
            }
          }
          super.close(failFast);
        }
      };
    }

    @Override
    public ThreadSafeOutputFormatterCallback<Target> createStreamCallback(
        OutputStream out, QueryOptions options, QueryEnvironment<?> env) {
      return new SynchronizedDelegatingOutputFormatterCallback<>(
          createPostFactoStreamCallback(out, options));
    }
  }

  /**
   * An output formatter that prints the labels of the targets, preceded by
   * their locations and kinds, in topological order.  For output files, the
   * location of the generating rule is given; for input files, the location of
   * line 1 is given.
   */
  private static class LocationOutputFormatter extends AbstractUnorderedFormatter {

    @Override
    public String getName() {
      return "location";
    }

    @Override
    public void verifyCompatible(QueryEnvironment<?> env, QueryExpression expr)
        throws QueryException {
      if (!(env instanceof AbstractBlazeQueryEnvironment)) {
        return;
      }

      ContainsFunctionQueryExpressionVisitor noteBuildFilesAndLoadLilesVisitor =
          new ContainsFunctionQueryExpressionVisitor(ImmutableList.of("loadfiles", "buildfiles"));

      if (expr.accept(noteBuildFilesAndLoadLilesVisitor)) {
        throw new QueryException(
            "Query expressions involving 'buildfiles' or 'loadfiles' cannot be used with "
            + "--output=location");
      }
    }

    @Override
    public OutputFormatterCallback<Target> createPostFactoStreamCallback(
        OutputStream out, final QueryOptions options) {
      return new TextOutputFormatterCallback<Target>(out) {

        @Override
        public void processOutput(Iterable<Target> partialResult) {
          final String lineTerm = options.getLineTerminator();
          for (Target target : partialResult) {
            Location location = target.getLocation();
            printStream.print(
                location.print()
                    + ": "
                    + target.getTargetKind()
                    + " "
                    + target.getLabel().getDefaultCanonicalForm()
                    + lineTerm);
          }
        }
      };
    }

    @Override
    public ThreadSafeOutputFormatterCallback<Target> createStreamCallback(
        OutputStream out, QueryOptions options, QueryEnvironment<?> env) {
      return new SynchronizedDelegatingOutputFormatterCallback<>(
          createPostFactoStreamCallback(out, options));
    }
  }

  /**
   * An output formatter that prints the generating rules using the syntax of
   * the BUILD files. If multiple targets are generated by the same rule, it is
   * printed only once.
   */
  private static class BuildOutputFormatter extends AbstractUnorderedFormatter {

    @Override
    public String getName() {
      return "build";
    }

    @Override
    public OutputFormatterCallback<Target> createPostFactoStreamCallback(
        OutputStream out, final QueryOptions options) {
      return new TextOutputFormatterCallback<Target>(out) {
        private final Set<Label> printed = CompactHashSet.create();

        private void outputRule(Rule rule, PrintStream printStream) throws InterruptedException {
          final String lineTerm = options.getLineTerminator();
          final String outputAttributePattern = "  %s = %s," + lineTerm;
          printStream.printf("# %s%s", rule.getLocation(), lineTerm);
          printStream.printf("%s(%s", rule.getRuleClass(), lineTerm);
          printStream.printf("  name = \"%s\",%s", rule.getName(), lineTerm);

          RawAttributeMapper attributeMap = RawAttributeMapper.of(rule);
          for (Attribute attr : rule.getAttributes()) {
            // Ignore the "name" attribute here, as we already print it above.
            // This is not strictly necessary, but convention has it that the
            // name attribute is printed first.
            if ("name".equals(attr.getName())) {
              continue;
            }
            if (attributeMap.isConfigurable(attr.getName())) {
              // We don't know the actual value for configurable attributes, so we reconstruct
              // the select without trying to resolve it.
              printStream.printf(
                  outputAttributePattern,
                  attr.getPublicName(),
                  outputConfigurableAttrValue(rule, attributeMap, attr));
              continue;
            }
            PossibleAttributeValues values = getPossibleAttributeValues(rule, attr);
            if (values.source != AttributeValueSource.RULE) {
              continue; // Don't print default values.
            }
            if (Iterables.size(values) != 1) {
              // Computed defaults that depend on configurable attributes can have multiple values.
              continue;
            }
            printStream.printf(
                outputAttributePattern,
                attr.getPublicName(),
                outputAttrValue(Iterables.getOnlyElement(values)));
          }
          printStream.printf(")\n%s", lineTerm);
        }

        /** Returns the given attribute value with BUILD output syntax. Does not support selects. */
        private String outputAttrValue(Object value) {
          if (value instanceof License) {
            List<String> licenseTypes = new ArrayList<>();
            for (License.LicenseType licenseType : ((License) value).getLicenseTypes()) {
              licenseTypes.add(licenseType.toString().toLowerCase());
            }
            value = licenseTypes;
          } else if (value instanceof List<?> && EvalUtils.isImmutable(value)) {
            // Display it as a list (and not as a tuple). Attributes can never be tuples.
            value = new ArrayList<>((List<?>) value);
          } else if (value instanceof TriState) {
            value = ((TriState) value).toInt();
          }
          return new LabelPrinter().repr(value).toString();
        }

        /**
         * Returns the given configurable attribute value with BUILD output syntax.
         *
         * <p>Since query doesn't know which select path should be chosen, this doesn't try to
         * resolve the final value. Instead it just reconstructs the select.
         */
        private String outputConfigurableAttrValue(
            Rule rule, RawAttributeMapper attributeMap, Attribute attr) {
          List<String> selectors = new ArrayList<>();
          for (BuildType.Selector<?> selector :
              ((BuildType.SelectorList<?>) attributeMap.getRawAttributeValue(rule, attr))
                  .getSelectors()) {
            if (selector.isUnconditional()) {
              selectors.add(
                  outputAttrValue(
                      Iterables.getOnlyElement(selector.getEntries().entrySet()).getValue()));
            } else {
              selectors.add(String.format("select(%s)", outputAttrValue(selector.getEntries())));
            }
          }
          return String.join(" + ", selectors);
        }

        @Override
        public void processOutput(Iterable<Target> partialResult) throws InterruptedException {

          for (Target target : partialResult) {
            Rule rule = target.getAssociatedRule();
            if (rule == null || printed.contains(rule.getLabel())) {
              continue;
            }
            outputRule(rule, printStream);
            printed.add(rule.getLabel());
          }
        }
      };
    }

    @Override
    public ThreadSafeOutputFormatterCallback<Target> createStreamCallback(
        OutputStream out, QueryOptions options, QueryEnvironment<?> env) {
      return new SynchronizedDelegatingOutputFormatterCallback<>(
          createPostFactoStreamCallback(out, options));
    }
  }

  private static class RankAndLabel implements Comparable<RankAndLabel> {
    private final int rank;
    private final Label label;

    private RankAndLabel(int rank, Label label) {
      this.rank = rank;
      this.label = label;
    }

    @Override
    public int compareTo(RankAndLabel o) {
      if (this.rank != o.rank) {
        return this.rank - o.rank;
      }
      return this.label.compareTo(o.label);
    }

    @Override
    public String toString() {
      return rank + " " + label.getDefaultCanonicalForm();
    }
  }

  /**
   * An output formatter that prints the labels in minimum rank order, preceded by
   * their rank number.  "Roots" have rank 0, their direct prerequisites have
   * rank 1, etc.  All nodes in a cycle are considered of equal rank.  MINRANK
   * shows the lowest rank for a given node, i.e. the length of the shortest
   * path from a zero-rank node to it.
   *
   * <p>If the result came from a <code>deps(x)</code> query, then the MINRANKs
   * correspond to the shortest path from x to each of its prerequisites.
   */
  private static class MinrankOutputFormatter extends OutputFormatter {

    @Override
    public String getName() {
      return "minrank";
    }

    private static void outputToStreamOrSave(
        int rank,
        Label label,
        PrintStream out,
        @Nullable List<RankAndLabel> toSave,
        final String lineTerminator) {
      if (toSave != null) {
        toSave.add(new RankAndLabel(rank, label));
      } else {
        out.print(rank + " " + label.getDefaultCanonicalForm() + lineTerminator);
      }
    }

    @Override
    public void output(
        QueryOptions options,
        Digraph<Target> result,
        OutputStream out,
        AspectResolver aspectResolver)
            throws IOException {
      PrintStream printStream = new PrintStream(out);
      // getRoots() isn't defined for cyclic graphs, so in order to handle
      // cycles correctly, we need work on the strong component graph, as
      // cycles should be treated a "clump" of nodes all on the same rank.
      // Graphs may contain cycles because there are errors in BUILD files.

      List<RankAndLabel> outputToOrder =
          options.orderOutput == OrderOutput.FULL ? new ArrayList<RankAndLabel>() : null;
      Digraph<Set<Node<Target>>> scGraph = result.getStrongComponentGraph();
      Set<Node<Set<Node<Target>>>> rankNodes = scGraph.getRoots();
      Set<Node<Set<Node<Target>>>> seen = new HashSet<>();
      seen.addAll(rankNodes);
      final String lineTerm = options.getLineTerminator();
      for (int rank = 0; !rankNodes.isEmpty(); rank++) {
        // Print out this rank:
        for (Node<Set<Node<Target>>> xScc : rankNodes) {
          for (Node<Target> x : xScc.getLabel()) {
            outputToStreamOrSave(
                rank, x.getLabel().getLabel(), printStream, outputToOrder, lineTerm);
          }
        }

        // Find the next rank:
        Set<Node<Set<Node<Target>>>> nextRankNodes = new LinkedHashSet<>();
        for (Node<Set<Node<Target>>> x : rankNodes) {
          for (Node<Set<Node<Target>>> y : x.getSuccessors()) {
            if (seen.add(y)) {
              nextRankNodes.add(y);
            }
          }
        }
        rankNodes = nextRankNodes;
      }
      if (outputToOrder != null) {
        Collections.sort(outputToOrder);
        for (RankAndLabel item : outputToOrder) {
          printStream.printf("%s%s", item, lineTerm);
        }
      }

      flushAndCheckError(printStream);
    }
  }

  /**
   * An output formatter that prints the labels in maximum rank order, preceded
   * by their rank number.  "Roots" have rank 0, all other nodes have a rank
   * which is one greater than the maximum rank of each of their predecessors.
   * All nodes in a cycle are considered of equal rank.  MAXRANK shows the
   * highest rank for a given node, i.e. the length of the longest non-cyclic
   * path from a zero-rank node to it.
   *
   * <p>If the result came from a <code>deps(x)</code> query, then the MAXRANKs
   * correspond to the longest path from x to each of its prerequisites.
   */
  private static class MaxrankOutputFormatter extends OutputFormatter {

    @Override
    public String getName() {
      return "maxrank";
    }

    @Override
    public void output(
        QueryOptions options,
        Digraph<Target> result,
        OutputStream out,
        AspectResolver aspectResolver)
            throws IOException {
      // In order to handle cycles correctly, we need work on the strong
      // component graph, as cycles should be treated a "clump" of nodes all on
      // the same rank. Graphs may contain cycles because there are errors in BUILD files.

      // Dynamic programming algorithm:
      // rank(x) = max(rank(p)) + 1 foreach p in preds(x)
      // TODO(bazel-team): Move to Digraph.
      class DP {
        final Map<Node<Set<Node<Target>>>, Integer> ranks = new HashMap<>();

        int rank(Node<Set<Node<Target>>> node) {
          Integer rank = ranks.get(node);
          if (rank == null) {
            int maxPredRank = -1;
            for (Node<Set<Node<Target>>> p : node.getPredecessors()) {
              maxPredRank = Math.max(maxPredRank, rank(p));
            }
            rank = maxPredRank + 1;
            ranks.put(node, rank);
          }
          return rank;
        }
      }
      DP dp = new DP();

      // Now sort by rank...
      List<RankAndLabel> output = new ArrayList<>();
      for (Node<Set<Node<Target>>> x : result.getStrongComponentGraph().getNodes()) {
        int rank = dp.rank(x);
        for (Node<Target> y : x.getLabel()) {
          output.add(new RankAndLabel(rank, y.getLabel().getLabel()));
        }
      }
      if (options.orderOutput == OrderOutput.FULL) {
        // Use the natural order for RankAndLabels, which breaks ties alphabetically.
        Collections.sort(output);
      } else {
        Collections.sort(output, comparingInt(arg -> arg.rank));
      }
      final String lineTerm = options.getLineTerminator();
      PrintStream printStream = new PrintStream(out);
      for (RankAndLabel item : output) {
        printStream.printf("%s%s", item, lineTerm);
      }
      flushAndCheckError(printStream);
    }
  }

  /**
   * Helper class for {@link #getPossibleAttributeValues}.
   */
  static class PossibleAttributeValues implements Iterable<Object> {
    final Iterable<Object> values;
    final AttributeValueSource source;

    PossibleAttributeValues(Iterable<Object> values, AttributeValueSource source) {
      this.values = values;
      this.source = source;
    }

    @Override
    public Iterator<Object> iterator() {
      return values.iterator();
    }
  }

  /**
   * Returns the possible values of the specified attribute in the specified rule. For simple
   * attributes, this is a single value. For configurable and computed attributes, this may be a
   * list of values. See {@link AggregatingAttributeMapper#getPossibleAttributeValues} for how the
   * values are determined.
   *
   * <p>This applies an important optimization for label lists: instead of returning all possible
   * values, it only returns possible <i>labels</i>. For example, given:
   *
   * <pre>
   * select({
   *     ":c": ["//a:one", "//a:two"],
   *     ":d": ["//a:two"]
   *     })</pre>
   *
   * it returns:
   *
   * <pre>["//a:one", "//a:two"]</pre>
   *
   * which loses track of which label appears in which branch.
   *
   * <p>This avoids the memory overruns that can happen be iterating over every possible value
   * for an <code>attr = select(...) + select(...) + select(...) + ...</code> expression. Query
   * operations generally don't care about specific attribute values - they just care which labels
   * are possible.
   */
  protected static PossibleAttributeValues getPossibleAttributeValues(Rule rule, Attribute attr)
    throws InterruptedException {
    AttributeValueSource source;

    if (attr.getName().equals("visibility")) {
      if (rule.isVisibilitySpecified()) {
        source = AttributeValueSource.RULE;
      } else if (rule.getPackage().isDefaultVisibilitySet()) {
        source = AttributeValueSource.PACKAGE;
      } else {
        source = AttributeValueSource.DEFAULT;
      }
    } else {
      source = rule.isAttributeValueExplicitlySpecified(attr)
          ? AttributeValueSource.RULE : AttributeValueSource.DEFAULT;
    }

    AggregatingAttributeMapper attributeMap = AggregatingAttributeMapper.of(rule);
    Iterable<?> list;
    if (attr.getType().equals(BuildType.LABEL_LIST)
        && attributeMap.isConfigurable(attr.getName())) {
      // TODO(gregce): Expand this to all collection types (we don't do this for scalars because
      // there's currently no syntax for expressing multiple scalar values). This unfortunately
      // isn't trivial because Bazel's label visitation logic includes special methods built
      // directly into Type.
      return new PossibleAttributeValues(
          ImmutableList.<Object>of(
              attributeMap.getReachableLabels(attr.getName(), /*includeSelectKeys=*/false)),
          source);
    } else if ((list =
            attributeMap.getConcatenatedSelectorListsOfListType(
                attr.getName(), attr.getType()))
        != null) {
      return new PossibleAttributeValues(Lists.newArrayList(list), source);
    } else {
      // The call to getPossibleAttributeValues below is especially slow with selector lists.
      return new PossibleAttributeValues(attributeMap.getPossibleAttributeValues(rule, attr),
          source);
    }
  }

  private static void flushAndCheckError(PrintStream printStream) throws IOException {
    if (printStream.checkError()) {
      throw new IOException("PrintStream encountered an error");
    }
  }

  /**
   * Returns the target location, eventually stripping out the workspace path to obtain a relative
   * target (stable across machines / workspaces).
   *
   * @param target The target to extract location from.
   * @param relative Whether to return a relative path or not.
   * @return the target location
   */
  protected static String getLocation(Target target, boolean relative) {
    Location location = target.getLocation();
    return relative
        ? location.print(target.getPackage().getPackageDirectory().asFragment(),
            target.getPackage().getNameFragment())
        : location.print();
  }

  private static class LabelPrinter extends Printer.BasePrinter {
    @Override
    public LabelPrinter repr(Object o) {
      if (o instanceof Label) {
        writeString(((Label) o).getCanonicalForm());
      } else {
        super.repr(o);
      }
      return this;
    }
  }
}
