/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.android.build.gradle.managed.adaptor;
import static com.android.builder.core.VariantType.ANDROID_TEST;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.build.gradle.api.AndroidSourceDirectorySet;
import com.android.build.gradle.api.AndroidSourceFile;
import com.android.build.gradle.api.AndroidSourceSet;
import com.android.build.gradle.api.VariantFilter;
import com.android.build.gradle.internal.BuildTypeData;
import com.android.build.gradle.internal.CompileOptions;
import com.android.build.gradle.internal.ProductFlavorData;
import com.android.build.gradle.internal.VariantManager;
import com.android.build.gradle.internal.dsl.CoreNdkOptions;
import com.android.build.gradle.internal.coverage.JacocoExtension;
import com.android.build.gradle.internal.dsl.AaptOptions;
import com.android.build.gradle.internal.dsl.AdbOptions;
import com.android.build.gradle.internal.dsl.CoreBuildType;
import com.android.build.gradle.internal.dsl.CoreProductFlavor;
import com.android.build.gradle.internal.dsl.DexOptions;
import com.android.build.gradle.internal.dsl.LintOptions;
import com.android.build.gradle.internal.dsl.PackagingOptions;
import com.android.build.gradle.internal.dsl.PreprocessingOptions;
import com.android.build.gradle.internal.dsl.Splits;
import com.android.build.gradle.internal.dsl.TestOptions;
import com.android.build.gradle.managed.BuildType;
import com.android.build.gradle.managed.ProductFlavor;
import com.android.build.gradle.managed.SigningConfig;
import com.android.build.gradle.model.AndroidComponentModelSourceSet;
import com.android.build.gradle.managed.AndroidConfig;
import com.android.builder.core.BuilderConstants;
import com.android.builder.core.LibraryRequest;
import com.android.builder.testing.api.DeviceProvider;
import com.android.builder.testing.api.TestServer;
import com.android.ide.common.rendering.api.ActionBarCallback;
import com.android.sdklib.repository.FullRevision;
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 org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.file.SourceDirectorySet;
import org.gradle.language.base.FunctionalSourceSet;
import org.gradle.language.base.LanguageSourceSet;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import groovy.lang.Closure;
/**
* An adaptor to convert a managed.AndroidConfig to an model.AndroidConfig.
*/
public class AndroidConfigAdaptor implements com.android.build.gradle.AndroidConfig {
private final AndroidConfig model;
private NamedDomainObjectContainer<AndroidSourceSet> sourceSetsContainer;
public AndroidConfigAdaptor(
AndroidConfig model,
NamedDomainObjectContainer<AndroidSourceSet> sourceSetsContainer) {
this.model = model;
this.sourceSetsContainer = sourceSetsContainer;
applyProjectSourceSet();
}
@Override
public String getBuildToolsVersion() {
return model.getBuildToolsVersion();
}
@Override
public String getCompileSdkVersion() {
return model.getCompileSdkVersion();
}
@Override
public FullRevision getBuildToolsRevision() {
return model.getBuildToolsRevision();
}
@Override
public boolean getEnforceUniquePackageName() {
return false;
}
@Override
public CoreProductFlavor getDefaultConfig() {
return new ProductFlavorAdaptor(model.getDefaultConfig());
}
@Override
@NonNull
public List<DeviceProvider> getDeviceProviders() {
return model.getDeviceProviders() == null ?
Lists.<DeviceProvider>newArrayList() :
model.getDeviceProviders();
}
@Override
@NonNull
public List<TestServer> getTestServers() {
return model.getTestServers();
}
@Override
public String getDefaultPublishConfig() {
return model.getDefaultPublishConfig();
}
@Override
public boolean getPublishNonDefault() {
return model.getPublishNonDefault();
}
@Override
public Action<VariantFilter> getVariantFilter() {
return model.getVariantFilter();
}
@Override
public String getResourcePrefix() {
return model.getResourcePrefix();
}
@Override
public List<String> getFlavorDimensionList() {
return null;
}
@Override
public boolean getGeneratePureSplits() {
return model.getGeneratePureSplits();
}
@Override
public PreprocessingOptions getPreprocessingOptions() {
return model.getPreProcessingOptions();
}
@Override
public Collection<CoreBuildType> getBuildTypes() {
return ImmutableList.copyOf(Iterables.transform(model.getBuildTypes().values(),
new Function<BuildType, CoreBuildType>() {
@Override
public CoreBuildType apply(BuildType buildType) {
return new BuildTypeAdaptor(buildType);
}
}));
}
@Override
public Collection<CoreProductFlavor> getProductFlavors() {
return ImmutableList.copyOf(Iterables.transform(model.getProductFlavors().values(),
new Function<ProductFlavor, CoreProductFlavor>() {
@Override
public CoreProductFlavor apply(ProductFlavor flavor) {
return new ProductFlavorAdaptor(flavor);
}
}));
}
@Override
public Collection<com.android.builder.model.SigningConfig> getSigningConfigs() {
return ImmutableList.copyOf(Iterables.transform(model.getSigningConfigs().values(),
new Function<SigningConfig, com.android.builder.model.SigningConfig>() {
@Override
public com.android.builder.model.SigningConfig apply(SigningConfig signingConfig) {
return new SigningConfigAdaptor(signingConfig);
}
}));
}
@Override
public NamedDomainObjectContainer<AndroidSourceSet> getSourceSets() {
return sourceSetsContainer;
}
@Override
public Boolean getPackageBuildConfig() {
return true;
}
public AndroidComponentModelSourceSet getSources() {
return model.getSources();
}
public void setSources(AndroidComponentModelSourceSet sources) {
model.setSources(sources);
}
public CoreNdkOptions getNdk() {
return new NdkOptionsAdaptor(model.getNdk());
}
@Override
public AdbOptions getAdbOptions() {
return model.getAdbOptions();
}
@Override
public AaptOptions getAaptOptions() {
return model.getAaptOptions();
}
@Override
public CompileOptions getCompileOptions() {
return model.getCompileOptions();
}
@Override
public DexOptions getDexOptions() {
return model.getDexOptions();
}
@Override
public JacocoExtension getJacoco() {
return model.getJacoco();
}
@Override
public LintOptions getLintOptions() {
return model.getLintOptions();
}
@Override
public PackagingOptions getPackagingOptions() {
return model.getPackagingOptions();
}
@Override
public TestOptions getTestOptions() {
return model.getTestOptions();
}
@Override
public Splits getSplits() {
return model.getSplits();
}
@Override
public Collection<LibraryRequest> getLibraryRequests() {
return model.getLibraryRequests();
}
private void applyProjectSourceSet() {
for (FunctionalSourceSet source : getSources()) {
String name = source.getName();
AndroidSourceSet androidSource = name.equals(BuilderConstants.MAIN) ?
sourceSetsContainer.maybeCreate(getDefaultConfig().getName()) :
sourceSetsContainer.maybeCreate(name);
convertSourceFile(androidSource.getManifest(), source, "manifest");
convertSourceSet(androidSource.getResources(), source, "resource");
convertSourceSet(androidSource.getJava(), source, "java");
convertSourceSet(androidSource.getRes(), source, "res");
convertSourceSet(androidSource.getAssets(), source, "assets");
convertSourceSet(androidSource.getAidl(), source, "aidl");
convertSourceSet(androidSource.getRenderscript(), source, "renderscript");
convertSourceSet(androidSource.getJni(), source, "jni");
convertSourceSet(androidSource.getJniLibs(), source, "jniLibs");
}
}
@Nullable
private static AndroidSourceSet findAndroidSourceSet(
VariantManager variantManager,
String name) {
BuildTypeData buildTypeData = variantManager.getBuildTypes().get(name);
if (buildTypeData != null) {
return buildTypeData.getSourceSet();
}
boolean isTest = name.startsWith(ANDROID_TEST.getPrefix());
name = name.replaceFirst(ANDROID_TEST.getPrefix(), "");
ProductFlavorData productFlavorData = variantManager.getProductFlavors().get(name);
if (productFlavorData != null) {
return isTest ? productFlavorData.getTestSourceSet(ANDROID_TEST) : productFlavorData.getSourceSet();
}
return null;
}
/**
* Convert a FunctionalSourceSet to an AndroidSourceFile.
*/
private static void convertSourceFile(
AndroidSourceFile androidFile,
FunctionalSourceSet source,
String sourceName) {
LanguageSourceSet languageSourceSet = source.findByName(sourceName);
if (languageSourceSet == null) {
return;
}
SourceDirectorySet dir = languageSourceSet.getSource();
if (dir == null) {
return;
}
// We use the first file in the file tree until Gradle has a way to specify one source file
// instead of an entire source set.
Set<File> files = dir.getAsFileTree().getFiles();
if (!files.isEmpty()) {
androidFile.srcFile(Iterables.getOnlyElement(files));
}
}
/**
* Convert a FunctionalSourceSet to an AndroidSourceDirectorySet.
*/
private static void convertSourceSet(
AndroidSourceDirectorySet androidDir,
FunctionalSourceSet source,
String sourceName) {
LanguageSourceSet languageSourceSet = source.findByName(sourceName);
if (languageSourceSet == null) {
return;
}
SourceDirectorySet dir = languageSourceSet.getSource();
if (dir == null) {
return;
}
androidDir.setSrcDirs(dir.getSrcDirs());
androidDir.include(dir.getIncludes());
androidDir.exclude(dir.getExcludes());
}
}