package org.netbeans.gradle.project.properties.standard;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jtrim.collections.CollectionsEx;
import org.jtrim.event.ListenerRef;
import org.jtrim.property.PropertyFactory;
import org.jtrim.property.PropertySource;
import org.jtrim.utils.ExceptionHelper;
import org.netbeans.gradle.project.NbGradleProject;
import org.netbeans.gradle.project.api.config.ActiveSettingsQuery;
import org.netbeans.gradle.project.api.config.ConfigPath;
import org.netbeans.gradle.project.api.config.ProfileDef;
import org.netbeans.gradle.project.api.config.ProfileKey;
import org.netbeans.gradle.project.api.config.PropertyDef;
import org.netbeans.gradle.project.api.config.PropertyValueDef;
import org.netbeans.gradle.project.api.config.SingleProfileSettings;
import org.netbeans.gradle.project.api.config.ValueMerger;
import org.netbeans.gradle.project.api.config.ValueReference;
import org.netbeans.gradle.project.api.task.BuiltInGradleCommandQuery;
import org.netbeans.gradle.project.api.task.GradleCommandTemplate;
import org.netbeans.gradle.project.properties.PredefinedTask;
public final class BuiltInTasksProperty {
private static final ConfigPath CONFIG_ROOT_BUILT_IN_TASKS = ConfigPath.fromKeys("built-in-tasks");
public static final PropertyDef<?, BuiltInTasks> PROPERTY_DEF = createPropertyDef();
public static BuiltInTasks createValue(Collection<? extends PredefinedTask> tasks) {
return createValue(new PredefinedTasks(tasks));
}
public static BuiltInTasks createValue(PredefinedTasks tasks) {
return new BuiltInTasksImpl(tasks);
}
public static PropertySource<BuiltInTasks> defaultValue(
final NbGradleProject project,
final ActiveSettingsQuery settingsQuery) {
ExceptionHelper.checkNotNullArgument(project, "project");
ExceptionHelper.checkNotNullArgument(settingsQuery, "settingsQuery");
return new PropertySource<BuiltInTasks>() {
@Override
public BuiltInTasks getValue() {
return builtInTasks(project, settingsQuery);
}
@Override
public ListenerRef addChangeListener(Runnable listener) {
return settingsQuery.currentProfileSettings().addChangeListener(listener);
}
};
}
private static BuiltInTasks builtInTasks(
final NbGradleProject project,
final ActiveSettingsQuery settingsQuery) {
return new BuiltInTasks() {
@Override
public PredefinedTasks getAllTasks() {
return collectAllTasks(project, settingsQuery);
}
@Override
public PredefinedTask tryGetByCommand(String command) {
ProfileDef key = getProfileDef(settingsQuery);
GradleCommandTemplate commandTemplate
= project.getMergedCommandQuery().tryGetDefaultGradleCommand(key, command);
return commandTemplate != null
? templateToPredefined(command, commandTemplate)
: null;
}
};
}
private static PredefinedTasks collectAllTasks(
NbGradleProject project,
ActiveSettingsQuery settingsQuery) {
ProfileDef key = getProfileDef(settingsQuery);
BuiltInGradleCommandQuery query = project.getMergedCommandQuery();
Set<String> supportedCommands = query.getSupportedCommands();
List<PredefinedTask> result = new ArrayList<>(supportedCommands.size());
for (String command: supportedCommands) {
GradleCommandTemplate commandTemplate
= query.tryGetDefaultGradleCommand(key, command);
if (commandTemplate != null) {
result.add(templateToPredefined(command, commandTemplate));
}
}
return new PredefinedTasks(result);
}
private static ProfileDef getProfileDef(ActiveSettingsQuery settingsQuery) {
SingleProfileSettings settings = settingsQuery.currentProfileSettings().getValue();
ProfileKey key = settings != null ? settings.getKey() : null;
return key != null
? new ProfileDef(key, key.getFileName())
: null;
}
private static PredefinedTask templateToPredefined(
String displayName, GradleCommandTemplate command) {
List<String> tasks = command.getTasks();
List<PredefinedTask.Name> taskNames = new ArrayList<>(tasks.size());
for (String taskName: command.getTasks()) {
taskNames.add(new PredefinedTask.Name(taskName, false));
}
return new PredefinedTask(displayName,
taskNames,
command.getArguments(),
command.getJvmArguments(),
!command.isBlocking());
}
private static PropertyDef<?, BuiltInTasks> createPropertyDef() {
PropertyDef.Builder<PredefinedTasks, BuiltInTasks> result
= new PropertyDef.Builder<>(CONFIG_ROOT_BUILT_IN_TASKS);
result.setKeyEncodingDef(CustomTasksProperty.getKeyEncodingDef());
result.setValueDef(getValueDef());
result.setValueMerger(getValueMerger());
return result.create();
}
private static PropertyValueDef<PredefinedTasks, BuiltInTasks> getValueDef() {
return new PropertyValueDef<PredefinedTasks, BuiltInTasks>() {
@Override
public PropertySource<BuiltInTasks> property(PredefinedTasks valueKey) {
BuiltInTasks value = valueKey != null
? new BuiltInTasksImpl(valueKey)
: null;
return PropertyFactory.<BuiltInTasks>constSource(value);
}
@Override
public PredefinedTasks getKeyFromValue(BuiltInTasks value) {
return value != null ? value.getAllTasks() : null;
}
};
}
private static ValueMerger<BuiltInTasks> getValueMerger() {
return new ValueMerger<BuiltInTasks>() {
@Override
public BuiltInTasks mergeValues(BuiltInTasks child, ValueReference<BuiltInTasks> parent) {
if (child == null) {
return parent.getValue();
}
BuiltInTasks parentValue = parent.getValue();
if (parentValue == null) {
return child;
}
return new InheritingBuiltInTask(child, parentValue);
}
};
}
private static final class InheritingBuiltInTask implements BuiltInTasks {
private final BuiltInTasks tasks1;
private final BuiltInTasks tasks2;
public InheritingBuiltInTask(BuiltInTasks tasks1, BuiltInTasks tasks2) {
assert tasks1 != null;
assert tasks2 != null;
this.tasks1 = tasks1;
this.tasks2 = tasks2;
}
@Override
public PredefinedTasks getAllTasks() {
List<PredefinedTask> taskList1 = tasks1.getAllTasks().getTasks();
List<PredefinedTask> taskList2 = tasks2.getAllTasks().getTasks();
return new PredefinedTasks(CollectionsEx.viewConcatList(taskList1, taskList2));
}
@Override
public PredefinedTask tryGetByCommand(String command) {
PredefinedTask result = tasks1.tryGetByCommand(command);
if (result == null) {
result = tasks2.tryGetByCommand(command);
}
return result;
}
}
private static final class BuiltInTasksImpl implements BuiltInTasks {
private final PredefinedTasks tasks;
private final Map<String, PredefinedTask> nameToTask;
private BuiltInTasksImpl(PredefinedTasks tasks) {
ExceptionHelper.checkNotNullArgument(tasks, "tasks");
this.tasks = tasks;
this.nameToTask = createNameToTask(tasks.getTasks());
}
private static Map<String, PredefinedTask> createNameToTask(Collection<PredefinedTask> tasks) {
Map<String, PredefinedTask> result = CollectionsEx.newHashMap(tasks.size());
for (PredefinedTask task: tasks) {
result.put(task.getDisplayName(), task);
}
return Collections.unmodifiableMap(result);
}
@Override
public PredefinedTask tryGetByCommand(String command) {
ExceptionHelper.checkNotNullArgument(command, "command");
return nameToTask.get(command);
}
@Override
public PredefinedTasks getAllTasks() {
return tasks;
}
}
private BuiltInTasksProperty() {
throw new AssertionError();
}
}