// 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.rules.java;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;

import java.util.LinkedHashSet;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * A collection of artifacts for java compilations. It concisely describes the
 * outputs of a java-related rule, with runtime jars, compile-time jars,
 * unfiltered compile-time jars (these are run through ijar if they are
 * dependent upon by another target), source ijars, and instrumentation
 * manifests. Not all rules generate all kinds of artifacts. Each java-related
 * rule should add both a runtime jar and either a compile-time jar or an
 * unfiltered compile-time jar.
 *
 * <p>An instance of this class only collects the data for the current target,
 * not for the transitive closure of targets, so these still need to be
 * collected using some other mechanism, such as the {@link
 * JavaCompilationArgsProvider}.
 */
@Immutable
public final class JavaCompilationArtifacts {

  public static final JavaCompilationArtifacts EMPTY = new Builder().build();

  private final ImmutableList<Artifact> runtimeJars;
  private final ImmutableList<Artifact> compileTimeJars;
  private final ImmutableList<Artifact> instrumentationMetadata;
  private final Artifact compileTimeDependencyArtifact;
  private final Artifact instrumentedJar;

  private JavaCompilationArtifacts(
      ImmutableList<Artifact> runtimeJars,
      ImmutableList<Artifact> compileTimeJars,
      ImmutableList<Artifact> instrumentationMetadata,
      Artifact compileTimeDependencyArtifact,
      Artifact instrumentedJar) {
    this.runtimeJars = runtimeJars;
    this.compileTimeJars = compileTimeJars;
    this.instrumentationMetadata = instrumentationMetadata;
    this.compileTimeDependencyArtifact = compileTimeDependencyArtifact;
    this.instrumentedJar = instrumentedJar;
  }

  public ImmutableList<Artifact> getRuntimeJars() {
    return runtimeJars;
  }

  public ImmutableList<Artifact> getCompileTimeJars() {
    return compileTimeJars;
  }

  public ImmutableList<Artifact> getInstrumentationMetadata() {
    return instrumentationMetadata;
  }

  public Artifact getCompileTimeDependencyArtifact() {
    return compileTimeDependencyArtifact;
  }

  public Artifact getInstrumentedJar() {
    return instrumentedJar;
  }

  /**
   * A builder for {@link JavaCompilationArtifacts}.
   */
  public static final class Builder {
    private final Set<Artifact> runtimeJars = new LinkedHashSet<>();
    private final Set<Artifact> compileTimeJars = new LinkedHashSet<>();
    private final Set<Artifact> instrumentationMetadata = new LinkedHashSet<>();
    private Artifact compileTimeDependencies;
    private Artifact instrumentedJar;

    public JavaCompilationArtifacts build() {
      return new JavaCompilationArtifacts(
          ImmutableList.copyOf(runtimeJars),
          ImmutableList.copyOf(compileTimeJars),
          ImmutableList.copyOf(instrumentationMetadata),
          compileTimeDependencies,
          instrumentedJar);
    }

    public Builder addRuntimeJar(Artifact jar) {
      this.runtimeJars.add(jar);
      return this;
    }

    public Builder addRuntimeJars(Iterable<Artifact> jars) {
      Iterables.addAll(this.runtimeJars, jars);
      return this;
    }

    public Builder addCompileTimeJar(Artifact jar) {
      this.compileTimeJars.add(jar);
      return this;
    }

    public Builder addCompileTimeJars(Iterable<Artifact> jars) {
      Iterables.addAll(this.compileTimeJars, jars);
      return this;
    }

    public Builder addInstrumentationMetadata(Artifact instrumentationMetadata) {
      this.instrumentationMetadata.add(instrumentationMetadata);
      return this;
    }

    public Builder setCompileTimeDependencies(@Nullable Artifact compileTimeDependencies) {
      this.compileTimeDependencies = compileTimeDependencies;
      return this;
    }

    public Builder setInstrumentedJar(@Nullable Artifact instrumentedJar) {
      this.instrumentedJar = instrumentedJar;
      return this;
    }
  }
}

@@ -660,16 +660,56 @@
 .java;%0A%0A
+import com.google.auto.value.AutoValue;%0A
 import c
@@ -1761,20 +1761,34 @@
 ble%0A
-public final
+@AutoValue%0Apublic abstract
  cla
@@ -1896,36 +1896,38 @@
 uild();%0A%0A  p
-rivate final
+ublic abstract
  ImmutableLi
@@ -1931,33 +1931,36 @@
 eList%3CArtifact%3E 
-r
+getR
 untimeJars;%0A  pr
@@ -1957,362 +1957,93 @@
 Jars
+()
 ;%0A  p
-rivate final ImmutableList%3CArtifact%3E compileTimeJars;%0A  private final ImmutableList%3CArtifact%3E instrumentationMetadata;%0A  private final Artifact compileTimeDependencyArtifact;%0A  private final Artifact instrumentedJar;%0A%0A  private JavaCompilationArtifacts(%0A      ImmutableList%3CArtifact%3E runtimeJars,%0A      ImmutableList%3CArtifact%3E compileTimeJars,%0A     
+ublic abstract ImmutableList%3CArtifact%3E getCompileTimeJars();%0A  public abstract
  Imm
@@ -2055,33 +2055,36 @@
 eList%3CArtifact%3E 
-i
+getI
 nstrumentationMe
@@ -2093,260 +2093,40 @@
 data
-,%0A      Artifact compileTimeDependencyArtifact,%0A      Artifact instrumentedJar) %7B%0A    this.runtimeJars = runtimeJars;%0A    this.compileTimeJars = compileTimeJars;%0A    this.instrumentationMetadata = instrumentationMetadata;%0A    this.compileTimeDependency
+();%0A  @Nullable public abstract 
 Arti
@@ -2130,19 +2130,20 @@
 rtifact 
-= c
+getC
 ompileTi
@@ -2166,260 +2166,48 @@
 fact
+()
 ;%0A  
-  this.instrumentedJar = instrumentedJar;%0A  %7D%0A%0A  public ImmutableList%3CArtifact%3E getRuntimeJars() %7B%0A    return runtimeJars;%0A  %7D%0A%0A  public ImmutableList%3CArtifact%3E getCompileTimeJars() %7B%0A    return compileTimeJars;%0A  %7D%0A%0A  public ImmutableList%3C
+@Nullable public abstract 
 Artifact
 %3E ge
@@ -2194,33 +2194,32 @@
 bstract Artifact
-%3E
  getInstrumentat
@@ -2220,162 +2220,78 @@
 ment
-ationMetadata() %7B%0A    return instrumentationMetadata;%0A  %7D%0A%0A  public Artifact getCompileTimeDependencyArtifact() %7B%0A    return compileTimeDependency
+edJar();%0A%0A  /** Returns a builder for a %7B@link JavaCompilation
 Artifact
 ;%0A  
@@ -2286,22 +2286,22 @@
 Artifact
-;%0A  %7D%0A
+s%7D. */
 %0A  publi
@@ -2306,34 +2306,29 @@
 lic 
-Artifact getInstrumentedJa
+static Builder builde
 r() 
@@ -2340,31 +2340,29 @@
  return 
-instrumentedJar
+new Builder()
 ;%0A  %7D%0A%0A 
@@ -2834,16 +2834,26 @@
 urn new 
+AutoValue_
 JavaComp

Make JavaCompilationArtifacts an AutoValue. Helpful for debugging.