/* * Copyright 2014 the original author or authors. * * 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 org.gradle.platform.base.internal.registry; import com.google.common.collect.ImmutableList; import org.gradle.api.Action; import org.gradle.api.Nullable; import org.gradle.api.Task; import org.gradle.api.internal.project.taskfactory.ITaskFactory; import org.gradle.internal.Cast; import org.gradle.model.ModelMap; import org.gradle.model.internal.core.*; import org.gradle.model.internal.inspect.*; import org.gradle.model.internal.type.ModelType; import org.gradle.platform.base.BinaryContainer; import org.gradle.platform.base.BinarySpec; import org.gradle.platform.base.BinaryTasks; import org.gradle.platform.base.plugins.BinaryBasePlugin; import java.util.ArrayList; import java.util.List; import static org.gradle.model.internal.core.NodePredicate.allLinks; public class BinaryTasksModelRuleExtractor extends AbstractAnnotationDrivenComponentModelRuleExtractor<BinaryTasks> { private static final ModelType<BinarySpec> BINARY_SPEC = ModelType.of(BinarySpec.class); private static final ModelType<ITaskFactory> TASK_FACTORY = ModelType.of(ITaskFactory.class); private static final ModelType<Task> TASK = ModelType.of(Task.class); private static final ModelReference<BinaryContainer> BINARIES_CONTAINER = ModelReference.of("binaries", ModelType.of(BinaryContainer.class)); @Nullable @Override public <R, S> ExtractedModelRule registration(MethodRuleDefinition<R, S> ruleDefinition, MethodModelRuleExtractionContext context) { return createRegistration(ruleDefinition, context); } private <R, S extends BinarySpec> ExtractedModelRule createRegistration(final MethodRuleDefinition<R, ?> ruleDefinition, RuleSourceValidationProblemCollector problems) { RuleMethodDataCollector dataCollector = new RuleMethodDataCollector(); verifyMethodSignature(dataCollector, ruleDefinition, problems); if (problems.hasProblems()) { return null; } ModelType<S> binaryType = dataCollector.getParameterType(BINARY_SPEC); return new ExtractedBinaryTasksRule<S>(ruleDefinition, binaryType); } private void verifyMethodSignature(RuleMethodDataCollector taskDataCollector, MethodRuleDefinition<?, ?> ruleDefinition, RuleSourceValidationProblemCollector problems) { validateIsVoidMethod(ruleDefinition, problems); visitSubject(taskDataCollector, ruleDefinition, TASK, problems); visitDependency(taskDataCollector, ruleDefinition, BINARY_SPEC, problems); } private static class BinaryTaskRule<T extends BinarySpec> extends ModelMapBasedRule<T, T> { public BinaryTaskRule(ModelType<T> binaryType, MethodRuleDefinition<?, ?> ruleDefinition) { super(ModelReference.of(binaryType), binaryType, ruleDefinition, ModelReference.of(TASK_FACTORY)); } @Override protected void execute(ModelRuleInvoker<?> invoker, final T binary, List<ModelView<?>> inputs) { NamedEntityInstantiator<Task> taskFactory = Cast.uncheckedCast(ModelViews.getInstance(inputs.get(0), TASK_FACTORY)); ModelMap<Task> cast = DomainObjectCollectionBackedModelMap.wrap( "tasks", Task.class, binary.getTasks(), taskFactory, new Task.Namer(), new Action<Task>() { @Override public void execute(Task task) { binary.getTasks().add(task); binary.builtBy(task); } }); List<ModelView<?>> inputsWithBinary = new ArrayList<ModelView<?>>(inputs.size()); inputsWithBinary.addAll(inputs.subList(1, inputs.size())); inputsWithBinary.add(InstanceModelView.of(getSubject().getPath(), getSubject().getType(), binary)); invoke(invoker, inputsWithBinary, cast, binary, binary); } } private static class ExtractedBinaryTasksRule<T extends BinarySpec> extends AbstractExtractedModelRule { private final ModelType<T> binaryType; public ExtractedBinaryTasksRule(MethodRuleDefinition<?, ?> ruleDefinition, ModelType<T> binaryType) { super(ruleDefinition); this.binaryType = binaryType; } @Override public void apply(MethodModelRuleApplicationContext context, MutableModelNode target) { MethodRuleDefinition<?, ?> ruleDefinition = getRuleDefinition(); final BinaryTaskRule<T> binaryTaskRule = new BinaryTaskRule<T>(binaryType, ruleDefinition); final ModelAction binaryTaskAction = context.contextualize(binaryTaskRule); context.getRegistry().configure(ModelActionRole.Defaults, DirectNodeNoInputsModelAction.of( BINARIES_CONTAINER, ruleDefinition.getDescriptor(), new Action<MutableModelNode>() { @Override public void execute(MutableModelNode modelNode) { modelNode.applyTo(allLinks(), ModelActionRole.Finalize, binaryTaskAction); } } )); } @Override public List<? extends Class<?>> getRuleDependencies() { return ImmutableList.of(BinaryBasePlugin.class); } } }