// 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.objc;

import static com.google.devtools.build.lib.actions.Artifact.IS_TREE_ARTIFACT;
import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.rules.objc.XcodeProductType.LIBRARY_STATIC;
import static java.nio.charset.StandardCharsets.ISO_8859_1;

import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
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.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.PopulateTreeArtifactAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.AppleToolchain;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaGenJarsProvider;
import com.google.devtools.build.lib.rules.java.JavaHelper;
import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
import com.google.devtools.build.lib.rules.java.Jvm;
import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraCompileArgs;
import com.google.devtools.build.lib.rules.objc.J2ObjcSource.SourceType;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;

/**
 * J2ObjC transpilation aspect for Java rules.
 */
public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectFactory {
  public static final String NAME = "J2ObjcAspect";
  private final String toolsRepository;
  private final BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect;

  private static final ExtraCompileArgs EXTRA_COMPILE_ARGS = new ExtraCompileArgs(
      "-fno-strict-overflow");

  public J2ObjcAspect(String toolsRepository, BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect) {
    this.toolsRepository = toolsRepository;
    this.bazelJ2ObjcProtoAspect = bazelJ2ObjcProtoAspect;
  }

  private static final Iterable<Attribute> DEPENDENT_ATTRIBUTES = ImmutableList.of(
      new Attribute(":jre_lib", Mode.TARGET),
      new Attribute("deps", Mode.TARGET),
      new Attribute("exports", Mode.TARGET),
      new Attribute("runtime_deps", Mode.TARGET));

  private static final Label JRE_CORE_LIB =
      Label.parseAbsoluteUnchecked("//third_party/java/j2objc:jre_core_lib");

  private static final Label JRE_EMUL_LIB =
      Label.parseAbsoluteUnchecked("//third_party/java/j2objc:jre_emul_lib");

  private static final LateBoundLabel<BuildConfiguration> JRE_LIB =
      new LateBoundLabel<BuildConfiguration>(JRE_CORE_LIB, J2ObjcConfiguration.class) {
    @Override
    public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) {
      return configuration.getFragment(J2ObjcConfiguration.class).explicitJreDeps()
          ? JRE_CORE_LIB : JRE_EMUL_LIB;
    }
  };

  /**
   * Adds additional attribute aspects and attributes to the given AspectDefinition.Builder.
   */
  protected AspectDefinition.Builder addAdditionalAttributes(
      AspectDefinition.Builder builder) {
    return builder.attributeAspect("deps", this, bazelJ2ObjcProtoAspect)
        .attributeAspect("exports", this, bazelJ2ObjcProtoAspect)
        .attributeAspect("runtime_deps", this, bazelJ2ObjcProtoAspect);
  }

  @Override
  public AspectDefinition getDefinition(AspectParameters aspectParameters) {
    return addAdditionalAttributes(new AspectDefinition.Builder("J2ObjCAspect"))
        .requireProvider(JavaSourceInfoProvider.class)
        .requireProvider(JavaCompilationArgsProvider.class)
        .requiresConfigurationFragments(
            AppleConfiguration.class,
            J2ObjcConfiguration.class,
            ObjcConfiguration.class)
        .requiresHostConfigurationFragments(Jvm.class)
        .add(attr("$j2objc", LABEL).cfg(HOST).exec()
            .value(Label.parseAbsoluteUnchecked(
                toolsRepository + "//tools/j2objc:j2objc_deploy.jar")))
        .add(attr("$j2objc_wrapper", LABEL)
            .allowedFileTypes(FileType.of(".py"))
            .cfg(HOST)
            .exec()
            .singleArtifact()
            .value(Label.parseAbsoluteUnchecked(
                toolsRepository + "//tools/j2objc:j2objc_wrapper")))
        .add(attr("$jre_emul_jar", LABEL).cfg(HOST)
            .value(Label.parseAbsoluteUnchecked(
                toolsRepository + "//third_party/java/j2objc:jre_emul.jar")))
        .add(attr(":jre_lib", LABEL).value(JRE_LIB))
        .add(attr("$xcrunwrapper", LABEL).cfg(HOST).exec()
            .value(Label.parseAbsoluteUnchecked(
                toolsRepository + "//tools/objc:xcrunwrapper")))
        .add(attr(ObjcRuleClasses.LIBTOOL_ATTRIBUTE, LABEL).cfg(HOST).exec()
              .value(Label.parseAbsoluteUnchecked(
                toolsRepository + "//tools/objc:libtool")))
        .add(attr(":xcode_config", LABEL)
            .allowedRuleClasses("xcode_config")
            .checkConstraints()
            .direct_compile_time_input()
            .cfg(HOST)
            .value(new AppleToolchain.XcodeConfigLabel(toolsRepository)))
        .add(attr("$zipper", LABEL)
            .cfg(HOST)
            .exec()
            .value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/zip:zipper")))
        .build();
  }

  @Override
  public ConfiguredAspect create(
      ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters)
      throws InterruptedException {
    ConfiguredAspect.Builder builder = new ConfiguredAspect.Builder(NAME, ruleContext);
    JavaCompilationArgsProvider compilationArgsProvider =
        base.getProvider(JavaCompilationArgsProvider.class);
    JavaSourceInfoProvider sourceInfoProvider =
        base.getProvider(JavaSourceInfoProvider.class);
    JavaGenJarsProvider genJarProvider =
        base.getProvider(JavaGenJarsProvider.class);
    ImmutableSet<Artifact> javaInputFiles = ImmutableSet.<Artifact>builder()
        .addAll(sourceInfoProvider.getSourceFiles())
        .addAll(sourceInfoProvider.getSourceJars())
        .addAll(sourceInfoProvider.getSourceJarsForJarFiles())
        .build();

    Optional<Artifact> genSrcJar;
    boolean annotationProcessingEnabled = ruleContext.getFragment(J2ObjcConfiguration.class)
        .annotationProcessingEnabled();
    if (genJarProvider != null && annotationProcessingEnabled) {
      genSrcJar = Optional.fromNullable(genJarProvider.getGenSourceJar());
    } else {
      genSrcJar = Optional.<Artifact>absent();
    }

    XcodeProvider xcodeProvider;
    ObjcCommon common;

    if (!javaInputFiles.isEmpty()) {
      J2ObjcSource j2ObjcSource = buildJ2ObjcSource(ruleContext, javaInputFiles, genSrcJar);
      J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider =
          depJ2ObjcMappingFileProvider(ruleContext);
      createJ2ObjcTranspilationAction(
          ruleContext,
          depJ2ObjcMappingFileProvider.getHeaderMappingFiles(),
          depJ2ObjcMappingFileProvider.getClassMappingFiles(),
          javaInputFiles,
          compilationArgsProvider,
          j2ObjcSource,
          genSrcJar);

      boolean zipTreeArtifact = ruleContext.getFragment(J2ObjcConfiguration.class)
          .zipTreeArtifact();
      if (genSrcJar.isPresent() && zipTreeArtifact) {
        for (Action action : genJarTreeArtifactCreationActions(ruleContext)) {
          ruleContext.registerAction(action);
        }
      }
      common = common(
          ruleContext,
          j2ObjcSource.getObjcSrcs(),
          j2ObjcSource.getObjcHdrs(),
          j2ObjcSource.getHeaderSearchPaths(),
          DEPENDENT_ATTRIBUTES);

      xcodeProvider = xcodeProvider(
          ruleContext,
          common,
          j2ObjcSource.getObjcHdrs(),
          j2ObjcSource.getHeaderSearchPaths(),
          DEPENDENT_ATTRIBUTES);

      new CompilationSupport(ruleContext)
          .registerCompileAndArchiveActions(common, EXTRA_COMPILE_ARGS)
          .registerFullyLinkAction(common.getObjcProvider());
    } else {
      common = common(
          ruleContext,
          ImmutableList.<Artifact>of(),
          ImmutableList.<Artifact>of(),
          ImmutableList.<PathFragment>of(),
          DEPENDENT_ATTRIBUTES);
      xcodeProvider = xcodeProvider(
          ruleContext,
          common,
          ImmutableList.<Artifact>of(),
          ImmutableList.<PathFragment>of(),
          DEPENDENT_ATTRIBUTES);
    }

    return builder
        .addProvider(j2ObjcMappingFileProvider(ruleContext, !javaInputFiles.isEmpty()))
        .addProvider(common.getObjcProvider())
        .addProvider(xcodeProvider)
        .build();
  }

  private J2ObjcMappingFileProvider j2ObjcMappingFileProvider(RuleContext ruleContext,
      boolean hasTranslatedSource) {
    J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider =
        depJ2ObjcMappingFileProvider(ruleContext);
    J2ObjcMappingFileProvider j2ObjcMappingFileProvider = depJ2ObjcMappingFileProvider;
    if (hasTranslatedSource) {
      // J2ObjC merges all input header mapping files into the output header mapping file, so we
      // only need to export the output header mapping file here.
      NestedSet<Artifact> headerMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
          .add(j2ObjcOutputHeaderMappingFile(ruleContext))
          .build();
      NestedSet<Artifact> dependencyMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
          .add(j2ObjcOutputDependencyMappingFile(ruleContext))
          .addTransitive(depJ2ObjcMappingFileProvider.getDependencyMappingFiles())
          .build();

      NestedSet<Artifact> archiveSourceMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
          .add(j2ObjcOutputArchiveSourceMappingFile(ruleContext))
          .addTransitive(depJ2ObjcMappingFileProvider.getArchiveSourceMappingFiles())
          .build();

      j2ObjcMappingFileProvider = new J2ObjcMappingFileProvider(
          headerMappingFiles,
          depJ2ObjcMappingFileProvider.getClassMappingFiles(),
          dependencyMappingFiles,
          archiveSourceMappingFiles);
    }

    return j2ObjcMappingFileProvider;
  }

  private List<Artifact> genJarOutputs(RuleContext ruleContext) {
    boolean zipTreeArtifact = ruleContext
        .getFragment(J2ObjcConfiguration.class)
        .zipTreeArtifact();

    if (zipTreeArtifact) {
      return ImmutableList.of(
          j2ObjcGenJarSourceZip(ruleContext),
          j2ObjcGenJarSourceZipManifest(ruleContext),
          j2ObjcGenJarHeaderZip(ruleContext),
          j2ObjcGenJarHeaderZipManifest(ruleContext));
    } else {
      return ImmutableList.of(
          j2ObjcGenJarTranslatedSourceFiles(ruleContext),
          j2objcGenJarTranslatedHeaderFiles(ruleContext));
    }
  }

  private List<String> genJarFlags(RuleContext ruleContext) {
    boolean zipTreeArtifact = ruleContext.getFragment(J2ObjcConfiguration.class).zipTreeArtifact();

    if (zipTreeArtifact) {
      return ImmutableList.of(
          "--output_gen_source_zip", j2ObjcGenJarSourceZip(ruleContext).getExecPathString(),
          "--output_gen_header_zip", j2ObjcGenJarHeaderZip(ruleContext).getExecPathString());
    } else {
      return ImmutableList.of(
          "--output_gen_source_dir",
          j2ObjcGenJarTranslatedSourceFiles(ruleContext).getExecPathString(),
          "--output_gen_header_dir",
          j2objcGenJarTranslatedHeaderFiles(ruleContext).getExecPathString());
    }
  }

  private List<Action> genJarTreeArtifactCreationActions(RuleContext ruleContext) {
    Artifact sourceFiles = j2ObjcGenJarTranslatedSourceFiles(ruleContext);
    Artifact headerFiles = j2objcGenJarTranslatedHeaderFiles(ruleContext);

    ImmutableList.Builder<Action> actions = ImmutableList.builder();
    actions.add(new PopulateTreeArtifactAction(
        ruleContext.getActionOwner(),
        j2ObjcGenJarSourceZip(ruleContext),
        j2ObjcGenJarSourceZipManifest(ruleContext),
        sourceFiles,
        ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST)));

    actions.add(new PopulateTreeArtifactAction(
        ruleContext.getActionOwner(),
        j2ObjcGenJarHeaderZip(ruleContext),
        j2ObjcGenJarHeaderZipManifest(ruleContext),
        headerFiles,
        ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST)));

    return actions.build();
  }

  private void createJ2ObjcTranspilationAction(
      RuleContext ruleContext,
      NestedSet<Artifact> depsHeaderMappingFiles,
      NestedSet<Artifact> depsClassMappingFiles,
      Iterable<Artifact> sources,
      JavaCompilationArgsProvider compArgsProvider,
      J2ObjcSource j2ObjcSource,
      Optional<Artifact> genSrcJar) {
    CustomCommandLine.Builder argBuilder = CustomCommandLine.builder();
    PathFragment javaExecutable = ruleContext.getFragment(Jvm.class, HOST).getJavaExecutable();
    argBuilder.add("--java").add(javaExecutable.getPathString());

    Artifact j2ObjcDeployJar = ruleContext.getPrerequisiteArtifact("$j2objc", Mode.HOST);
    argBuilder.addExecPath("--j2objc", j2ObjcDeployJar);

    argBuilder.add("--main_class").add("com.google.devtools.j2objc.J2ObjC");
    argBuilder.addJoinExecPaths(
        "--translated_source_files",
        ",",
        Iterables.filter(j2ObjcSource.getObjcSrcs(), Predicates.not(IS_TREE_ARTIFACT)));
    argBuilder.add("--objc_file_path").addPath(j2ObjcSource.getObjcFilePath());

    Artifact outputDependencyMappingFile = j2ObjcOutputDependencyMappingFile(ruleContext);
    argBuilder.addExecPath("--output_dependency_mapping_file", outputDependencyMappingFile);

    ImmutableList.Builder<Artifact> genSrcOutputFiles = ImmutableList.builder();
    if (genSrcJar.isPresent()) {
      genSrcOutputFiles.addAll(genJarOutputs(ruleContext));
      argBuilder.addExecPath("--gen_src_jar", genSrcJar.get());
      argBuilder.add(genJarFlags(ruleContext));
    }

    Iterable<String> translationFlags = ruleContext
        .getFragment(J2ObjcConfiguration.class)
        .getTranslationFlags();
    argBuilder.add(translationFlags);

    if (!depsHeaderMappingFiles.isEmpty()) {
      argBuilder.addJoinExecPaths("--header-mapping", ",", depsHeaderMappingFiles);
    }

    Artifact outputHeaderMappingFile = j2ObjcOutputHeaderMappingFile(ruleContext);
    argBuilder.addExecPath("--output-header-mapping", outputHeaderMappingFile);

    if (!depsClassMappingFiles.isEmpty()) {
      argBuilder.addJoinExecPaths("--mapping", ",", depsClassMappingFiles);
    }

    Artifact archiveSourceMappingFile = j2ObjcOutputArchiveSourceMappingFile(ruleContext);
    argBuilder.addExecPath("--output_archive_source_mapping_file", archiveSourceMappingFile);

    Artifact compiledLibrary = ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext).archive();
    argBuilder.addExecPath("--compiled_archive_file_path", compiledLibrary);

    Artifact bootclasspathJar = ruleContext.getPrerequisiteArtifact("$jre_emul_jar", Mode.HOST);
    argBuilder.add("-Xbootclasspath:" + bootclasspathJar.getExecPathString());

    argBuilder.add("-d").addPath(j2ObjcSource.getObjcFilePath());

    // In J2ObjC, the jars you pass as dependencies must be precisely the same as the
    // jars used to transpile those dependencies--we cannot use ijars here.
    NestedSet<Artifact> compileTimeJars =
        compArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars();
    if (!compileTimeJars.isEmpty()) {
      argBuilder.addJoinExecPaths("-classpath", ":", compileTimeJars);
    }

    argBuilder.addExecPaths(sources);

    Artifact paramFile = j2ObjcOutputParamFile(ruleContext);
    ruleContext.registerAction(new ParameterFileWriteAction(
        ruleContext.getActionOwner(),
        paramFile,
        argBuilder.build(),
        ParameterFile.ParameterFileType.UNQUOTED,
        ISO_8859_1));

    SpawnAction.Builder builder = new SpawnAction.Builder()
        .setMnemonic("TranspilingJ2objc")
        .setExecutable(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST))
        .addInput(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST))
        .addInput(j2ObjcDeployJar)
        .addInput(bootclasspathJar)
        .addInputs(sources)
        .addInputs(genSrcJar.asSet())
        .addTransitiveInputs(compileTimeJars)
        .addTransitiveInputs(JavaHelper.getHostJavabaseInputs(ruleContext))
        .addTransitiveInputs(depsHeaderMappingFiles)
        .addTransitiveInputs(depsClassMappingFiles)
        .addInput(paramFile)
        .setCommandLine(CustomCommandLine.builder()
            .addPaths("@%s", paramFile.getExecPath())
            .build())
        .addOutputs(Iterables.filter(j2ObjcSource.getObjcSrcs(), Predicates.not(IS_TREE_ARTIFACT)))
        .addOutputs(Iterables.filter(j2ObjcSource.getObjcHdrs(), Predicates.not(IS_TREE_ARTIFACT)))
        .addOutputs(genSrcOutputFiles.build())
        .addOutput(outputHeaderMappingFile)
        .addOutput(outputDependencyMappingFile)
        .addOutput(archiveSourceMappingFile);

    ruleContext.registerAction(builder.build(ruleContext));
  }

  private J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider(RuleContext ruleContext) {
    NestedSetBuilder<Artifact> depsHeaderMappingsBuilder = NestedSetBuilder.stableOrder();
    NestedSetBuilder<Artifact> depsClassMappingsBuilder = NestedSetBuilder.stableOrder();
    NestedSetBuilder<Artifact> depsDependencyMappingsBuilder = NestedSetBuilder.stableOrder();
    NestedSetBuilder<Artifact> depsArchiveSourceMappingsBuilder = NestedSetBuilder.stableOrder();

    for (J2ObjcMappingFileProvider mapping : getJ2ObjCMappings(ruleContext)) {
      depsHeaderMappingsBuilder.addTransitive(mapping.getHeaderMappingFiles());
      depsClassMappingsBuilder.addTransitive(mapping.getClassMappingFiles());
      depsDependencyMappingsBuilder.addTransitive(mapping.getDependencyMappingFiles());
      depsArchiveSourceMappingsBuilder.addTransitive(mapping.getArchiveSourceMappingFiles());
    }

    return new J2ObjcMappingFileProvider(
        depsHeaderMappingsBuilder.build(),
        depsClassMappingsBuilder.build(),
        depsDependencyMappingsBuilder.build(),
        depsArchiveSourceMappingsBuilder.build());
  }

  private static List<? extends J2ObjcMappingFileProvider> getJ2ObjCMappings(RuleContext context) {
    ImmutableList.Builder<J2ObjcMappingFileProvider> mappingFileProviderBuilder =
        new ImmutableList.Builder<>();
    addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "deps");
    addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "runtime_deps");
    addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "exports");
    return mappingFileProviderBuilder.build();
  }

  private static void addJ2ObjCMappingsForAttribute(
      ImmutableList.Builder<J2ObjcMappingFileProvider> builder, RuleContext context,
      String attributeName) {
    if (context.attributes().has(attributeName, BuildType.LABEL_LIST)) {
      for (TransitiveInfoCollection dependencyInfoDatum :
          context.getPrerequisites(attributeName, Mode.TARGET)) {
        J2ObjcMappingFileProvider provider =
            dependencyInfoDatum.getProvider(J2ObjcMappingFileProvider.class);
        if (provider != null) {
          builder.add(provider);
        }
      }
    }
  }

  private static Artifact j2ObjcOutputHeaderMappingFile(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".mapping.j2objc");
  }

  private static Artifact j2ObjcOutputDependencyMappingFile(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".dependency_mapping.j2objc");
  }

  private static Artifact j2ObjcOutputParamFile(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".param.j2objc");
  }

  private static Artifact j2ObjcOutputArchiveSourceMappingFile(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(
        ruleContext, ".archive_source_mapping.j2objc");
  }

  private static Artifact j2ObjcGenJarTranslatedSourceFiles(RuleContext ruleContext) {
    PathFragment rootRelativePath = ruleContext
        .getUniqueDirectory("_j2objc/gen_jar_files")
        .getRelative("source_files");
    return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory());
  }

  private static Artifact j2objcGenJarTranslatedHeaderFiles(RuleContext ruleContext) {
    PathFragment rootRelativePath = ruleContext
        .getUniqueDirectory("_j2objc/gen_jar_files")
        .getRelative("header_files");
    return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory());
  }

  private static Artifact j2ObjcGenJarSourceZip(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_source.zip");
  }

  private static Artifact j2ObjcGenJarSourceZipManifest(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_source.txt");
  }

  private static Artifact j2ObjcGenJarHeaderZip(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_header.zip");
  }

  private static Artifact j2ObjcGenJarHeaderZipManifest(RuleContext ruleContext) {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_header.txt");
  }

  private J2ObjcSource buildJ2ObjcSource(RuleContext ruleContext,
      Iterable<Artifact> javaInputSourceFiles, Optional<Artifact> genSrcJar) {
    PathFragment objcFileRootRelativePath = ruleContext.getUniqueDirectory("_j2objc");
    PathFragment objcFileRootExecPath = ruleContext
        .getConfiguration()
        .getBinFragment()
        .getRelative(objcFileRootRelativePath);
    Iterable<Artifact> objcSrcs = getOutputObjcFiles(ruleContext, javaInputSourceFiles,
        objcFileRootRelativePath, ".m");
    Iterable<Artifact> objcHdrs = getOutputObjcFiles(ruleContext, javaInputSourceFiles,
        objcFileRootRelativePath, ".h");
    Iterable<PathFragment> headerSearchPaths = J2ObjcLibrary.j2objcSourceHeaderSearchPaths(
        ruleContext, objcFileRootExecPath, javaInputSourceFiles);

    Optional<Artifact> genJarTranslatedSrcs = Optional.absent();
    Optional<Artifact> genJarTranslatedHdrs = Optional.absent();
    Optional<PathFragment> genJarFileHeaderSearchPaths = Optional.absent();

    if (genSrcJar.isPresent()) {
      genJarTranslatedSrcs = Optional.of(j2ObjcGenJarTranslatedSourceFiles(ruleContext));
      genJarTranslatedHdrs = Optional.of(j2objcGenJarTranslatedHeaderFiles(ruleContext));
      genJarFileHeaderSearchPaths = Optional.of(genJarTranslatedHdrs.get().getExecPath());
    }

    return new J2ObjcSource(
        ruleContext.getRule().getLabel(),
        Iterables.concat(objcSrcs, genJarTranslatedSrcs.asSet()),
        Iterables.concat(objcHdrs, genJarTranslatedHdrs.asSet()),
        objcFileRootExecPath,
        SourceType.JAVA,
        Iterables.concat(headerSearchPaths, genJarFileHeaderSearchPaths.asSet()));
  }

  private Iterable<Artifact> getOutputObjcFiles(RuleContext ruleContext,
      Iterable<Artifact> javaSrcs, PathFragment objcFileRootRelativePath, String suffix) {
    ImmutableList.Builder<Artifact> objcSources = ImmutableList.builder();

    for (Artifact javaSrc : javaSrcs) {
      objcSources.add(ruleContext.getRelatedArtifact(
          objcFileRootRelativePath.getRelative(javaSrc.getExecPath()), suffix));
    }

    return objcSources.build();
  }

  /**
   * Sets up and returns an {@link ObjcCommon} object containing the J2ObjC-translated code.
   *
   */
  static ObjcCommon common(RuleContext ruleContext, Iterable<Artifact> transpiledSources,
      Iterable<Artifact> transpiledHeaders, Iterable<PathFragment> headerSearchPaths,
      Iterable<Attribute> dependentAttributes) {
    ObjcCommon.Builder builder = new ObjcCommon.Builder(ruleContext);
    IntermediateArtifacts intermediateArtifacts =
        ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext);

    if (!Iterables.isEmpty(transpiledSources) || !Iterables.isEmpty(transpiledHeaders)) {
      CompilationArtifacts compilationArtifacts = new CompilationArtifacts.Builder()
          .addNonArcSrcs(transpiledSources)
          .setIntermediateArtifacts(intermediateArtifacts)
          .setPchFile(Optional.<Artifact>absent())
          .addAdditionalHdrs(transpiledHeaders)
          .build();
      builder.setCompilationArtifacts(compilationArtifacts);
      builder.setHasModuleMap();
    }

    for (Attribute dependentAttribute : dependentAttributes) {
      if (ruleContext.getAttribute(dependentAttribute.getName()) != null) {
        builder.addDepObjcProviders(ruleContext.getPrerequisites(
            dependentAttribute.getName(),
            dependentAttribute.getAccessMode(),
            ObjcProvider.class));
      }
    }

    return builder
        .addUserHeaderSearchPaths(headerSearchPaths)
        .setIntermediateArtifacts(intermediateArtifacts)
        .build();
  }

  /**
   * Sets up and returns an {@link XcodeProvider} object containing the J2ObjC-translated code.
   *
   */
  static XcodeProvider xcodeProvider(RuleContext ruleContext, ObjcCommon common,
      Iterable<Artifact> transpiledHeaders, Iterable<PathFragment> headerSearchPaths,
      Iterable<Attribute> dependentAttributes) {
    XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder();
    XcodeSupport xcodeSupport = new XcodeSupport(ruleContext);
    xcodeSupport.addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), LIBRARY_STATIC);

    for (Attribute dependentAttribute : dependentAttributes) {
      if (ruleContext.getAttribute(dependentAttribute.getName()) != null) {
        xcodeSupport.addDependencies(xcodeProviderBuilder, dependentAttribute);
      }
    }

    if (!Iterables.isEmpty(transpiledHeaders)) {
      xcodeProviderBuilder
          .addUserHeaderSearchPaths(headerSearchPaths)
          .addCopts(ruleContext.getFragment(ObjcConfiguration.class).getCopts())
          .addHeaders(transpiledHeaders);
    }

    if (common.getCompilationArtifacts().isPresent()) {
      xcodeProviderBuilder.setCompilationArtifacts(common.getCompilationArtifacts().get());
    }

    return xcodeProviderBuilder.build();
  }
}
