package org.netbeans.gradle.project.properties.standard;
import java.util.ArrayList;
import java.util.List;
import org.jtrim.collections.CollectionsEx;
import org.netbeans.gradle.project.api.config.ConfigPath;
import org.netbeans.gradle.project.api.config.ConfigTree;
import org.netbeans.gradle.project.api.config.PropertyDef;
import org.netbeans.gradle.project.api.config.PropertyKeyEncodingDef;
import org.netbeans.gradle.project.api.config.PropertyValueDef;
import org.netbeans.gradle.project.api.config.ValueMerger;
import org.netbeans.gradle.project.api.config.ValueReference;
import org.netbeans.gradle.project.properties.PredefinedTask;
public final class CustomTasksProperty {
private static final ConfigPath CONFIG_ROOT = ConfigPath.fromKeys("common-tasks");
private static final String CONFIG_KEY_TASK = "task";
private static final String CONFIG_KEY_DISPLAY_NAME = "display-name";
private static final String CONFIG_KEY_NON_BLOCKING = "non-blocking";
private static final String CONFIG_KEY_TASK_NAMES = "task-names";
private static final String CONFIG_KEY_TASK_NAME = "name";
private static final String CONFIG_KEY_TASK_MUST_EXIST = "#attr-must-exist";
private static final String CONFIG_KEY_TASK_ARGS = "task-args";
private static final String CONFIG_KEY_JVM_ARGS = "task-jvm-args";
private static final String CONFIG_KEY_ARG = "arg";
private static final String VALUE_YES = "yes";
private static final String VALUE_NO = "no";
public static final PropertyDef<PredefinedTasks, PredefinedTasks> PROPERTY_DEF = createPropertyDef();
private static PropertyDef<PredefinedTasks, PredefinedTasks> createPropertyDef() {
PropertyDef.Builder<PredefinedTasks, PredefinedTasks> result
= new PropertyDef.Builder<>(CONFIG_ROOT);
result.setKeyEncodingDef(getKeyEncodingDef());
result.setValueDef(getValueDef());
result.setValueMerger(getValueMerger());
return result.create();
}
private static String boolToConfig(boolean value) {
return value ? VALUE_YES : VALUE_NO;
}
private static boolean getBooleanValueDefaultFalse(ConfigTree config) {
return VALUE_YES.equalsIgnoreCase(config.getValue(""));
}
private static PropertyValueDef<PredefinedTasks, PredefinedTasks> getValueDef() {
return CommonProperties.getIdentityValueDef();
}
private static PredefinedTask.Name decodeName(ConfigTree nameNode) {
String name = nameNode.getValue("");
boolean mustExist = getBooleanValueDefaultFalse(nameNode.getChildTree(CONFIG_KEY_TASK_MUST_EXIST));
return new PredefinedTask.Name(name, mustExist);
}
private static List<String> parseArgs(ConfigTree argRoot) {
List<ConfigTree> argNodes = argRoot.getChildTrees(CONFIG_KEY_ARG);
List<String> result = new ArrayList<>(argNodes.size());
for (ConfigTree argNode: argNodes) {
result.add(argNode.getValue(""));
}
return result;
}
private static PredefinedTask decodeTask(ConfigTree config) {
String displayName = config.getChildTree(CONFIG_KEY_DISPLAY_NAME).getValue("?");
boolean nonBlocking = getBooleanValueDefaultFalse(config.getChildTree(CONFIG_KEY_NON_BLOCKING));
List<ConfigTree> nameNodes = config
.getChildTree(CONFIG_KEY_TASK_NAMES)
.getChildTrees(CONFIG_KEY_TASK_NAME);
List<PredefinedTask.Name> taskNames = new ArrayList<>(nameNodes.size());
for (ConfigTree nameNode: nameNodes) {
taskNames.add(decodeName(nameNode));
}
List<String> taskArgs = parseArgs(config.getChildTree(CONFIG_KEY_TASK_ARGS));
List<String> jvmArgs = parseArgs(config.getChildTree(CONFIG_KEY_JVM_ARGS));
return new PredefinedTask(displayName, taskNames, taskArgs, jvmArgs, nonBlocking);
}
private static List<PredefinedTask> decodeTaskList(ConfigTree config) {
List<ConfigTree> taskNodes = config.getChildTrees(CONFIG_KEY_TASK);
List<PredefinedTask> result = new ArrayList<>(taskNodes.size());
for (ConfigTree taskNode: taskNodes) {
result.add(decodeTask(taskNode));
}
return result;
}
private static PredefinedTasks decodeConfig(ConfigTree config) {
return new PredefinedTasks(decodeTaskList(config));
}
private static void encodeTaskName(PredefinedTask.Name name, ConfigTree.Builder result) {
result.getChildBuilder(CONFIG_KEY_TASK_MUST_EXIST).setValue(boolToConfig(name.isMustExist()));
result.setValue(name.getName());
}
private static void encodeArgs(List<String> args, ConfigTree.Builder result) {
for (String arg: args) {
result.addChildBuilder(CONFIG_KEY_ARG).setValue(arg);
}
}
private static void encodeTask(PredefinedTask task, ConfigTree.Builder result) {
result.getChildBuilder(CONFIG_KEY_DISPLAY_NAME).setValue(task.getDisplayName());
result.getChildBuilder(CONFIG_KEY_NON_BLOCKING).setValue(boolToConfig(task.isNonBlocking()));
ConfigTree.Builder rootNameBuilder = result.getChildBuilder(CONFIG_KEY_TASK_NAMES);
for (PredefinedTask.Name name: task.getTaskNames()) {
ConfigTree.Builder nameBuilder = rootNameBuilder.addChildBuilder(CONFIG_KEY_TASK_NAME);
encodeTaskName(name, nameBuilder);
}
encodeArgs(task.getArguments(), result.getChildBuilder(CONFIG_KEY_TASK_ARGS));
encodeArgs(task.getJvmArguments(), result.getChildBuilder(CONFIG_KEY_JVM_ARGS));
}
private static ConfigTree encodeConfig(PredefinedTasks tasks) {
ConfigTree.Builder result = new ConfigTree.Builder();
for (PredefinedTask task: tasks.getTasks()) {
ConfigTree.Builder taskBuilder = result.addChildBuilder(CONFIG_KEY_TASK);
encodeTask(task, taskBuilder);
}
return result.create();
}
public static PropertyKeyEncodingDef<PredefinedTasks> getKeyEncodingDef() {
return new PropertyKeyEncodingDef<PredefinedTasks>() {
@Override
public PredefinedTasks decode(ConfigTree config) {
return decodeConfig(config);
}
@Override
public ConfigTree encode(PredefinedTasks value) {
return encodeConfig(value);
}
};
}
private static ValueMerger<PredefinedTasks> getValueMerger() {
return new ValueMerger<PredefinedTasks>() {
@Override
public PredefinedTasks mergeValues(PredefinedTasks child, ValueReference<PredefinedTasks> parent) {
if (child == null) {
return parent.getValue();
}
PredefinedTasks parentValue = parent.getValue();
if (parentValue == null) {
return child;
}
List<PredefinedTask> tasks1 = child.getTasks();
List<PredefinedTask> tasks2 = parentValue.getTasks();
return new PredefinedTasks(CollectionsEx.viewConcatList(tasks1, tasks2));
}
};
}
private CustomTasksProperty() {
throw new AssertionError();
}
}