package com.xfestudio.xfeservermanager.core.trigger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** Deterministically compiles a legacy visual or XFE Script v1 program to V2 in memory. */
public final class TriggerLegacyV2Compiler {
private TriggerLegacyV2Compiler() { }
public static TriggerProgramV2 compile(TriggerDefinition definition) {
TriggerDefinition.Program legacy = definition.executableProgram();
List<TriggerProgramV2.VariableDeclaration> declarations = legacy.event().variables().stream()
.map(variable -> new TriggerProgramV2.VariableDeclaration(
id(definition.id(), "variable/" + variable.contextKey()),
variable.name(), variable.type(),
new TriggerExpression(
id(definition.id(), "variable/" + variable.contextKey() + "/initial"),
TriggerExpression.Kind.LITERAL, variable.type(),
TriggerValueTypes.parseVariable(variable.type(), variable.initialValue()),
"", List.of()),
variable.visibility(), variable.storage(),
TriggerProgramV2.Lifetime.valueOf(variable.lifetime().toUpperCase(java.util.Locale.ROOT)),
variable.ttlSeconds()))
.toList();
List<TriggerProgramV2.Statement> body = actions(definition.id(), legacy.actions(), "action");
if (!legacy.conditions().isEmpty()) {
List<TriggerExpression> conditions = new ArrayList<>();
for (int index = 0; index < legacy.conditions().size(); index++) {
TriggerDefinition.Condition condition = legacy.conditions().get(index);
Map<String, Object> literal = new LinkedHashMap<>();
literal.put("field", condition.field());
literal.put("operator", condition.operator());
literal.put("value", condition.value());
conditions.add(new TriggerExpression(
id(definition.id(), "condition/" + index),
TriggerExpression.Kind.FUNCTION, "bool", null, "legacy_condition",
List.of(new TriggerExpression(
id(definition.id(), "condition/" + index + "/literal"),
TriggerExpression.Kind.LITERAL, "record", literal, "", List.of()))));
}
TriggerExpression combined = combine(definition.id(), legacy.conditionMode(), conditions);
body = List.of(new TriggerProgramV2.Statement(
id(definition.id(), "root-condition"), TriggerProgramV2.StatementKind.IF, "",
Map.of(), combined, List.of(), body, List.of()));
}
return new TriggerProgramV2(
TriggerProgramV2.SCHEMA_VERSION,
List.of(new TriggerProgramV2.EventBinding(
id(definition.id(), "event/0"), legacy.event().type(), legacy.event().configuration())),
declarations, List.of(), body);
}
private static List<TriggerProgramV2.Statement> actions(
UUID triggerId, List<TriggerDefinition.Action> actions, String path) {
List<TriggerProgramV2.Statement> statements = new ArrayList<>();
for (int index = 0; index < actions.size(); index++) {
TriggerDefinition.Action action = actions.get(index);
String nodePath = path + "/" + index;
if (TriggerActionTree.CONDITION_TYPE.equals(action.type())) {
TriggerDefinition.Condition condition = TriggerActionTree.condition(action);
Map<String, Object> literal = Map.of(
"field", condition.field(), "operator", condition.operator(), "value", condition.value());
TriggerExpression expression = new TriggerExpression(
id(triggerId, nodePath + "/expression"), TriggerExpression.Kind.FUNCTION,
"bool", null, "legacy_condition",
List.of(new TriggerExpression(
id(triggerId, nodePath + "/literal"), TriggerExpression.Kind.LITERAL,
"record", literal, "", List.of())));
statements.add(new TriggerProgramV2.Statement(
id(triggerId, nodePath), TriggerProgramV2.StatementKind.IF, "", Map.of(),
expression, List.of(), actions(triggerId, action.children(), nodePath), List.of()));
continue;
}
Map<String, TriggerExpression> inputs = new LinkedHashMap<>();
action.parameters().forEach((name, value) -> inputs.put(name,
new TriggerExpression(id(triggerId, nodePath + "/" + name),
TriggerExpression.Kind.LITERAL, "string", value, "", List.of())));
statements.add(new TriggerProgramV2.Statement(
id(triggerId, nodePath), TriggerProgramV2.StatementKind.ACTION,
action.type(), inputs, null, List.of(), List.of(), List.of()));
}
return List.copyOf(statements);
}
private static TriggerExpression combine(
UUID triggerId, TriggerDefinition.MatchMode mode, List<TriggerExpression> values) {
TriggerExpression result = values.get(0);
for (int index = 1; index < values.size(); index++) {
result = new TriggerExpression(
id(triggerId, "condition-combine/" + index), TriggerExpression.Kind.BINARY,
"bool", null, mode == TriggerDefinition.MatchMode.ALL ? "and" : "or",
List.of(result, values.get(index)));
}
return result;
}
private static UUID id(UUID triggerId, String path) {
return UUID.nameUUIDFromBytes((triggerId + ":" + path).getBytes(StandardCharsets.UTF_8));
}
}
package com.xfestudio.xfeservermanager.core.trigger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** Deterministically compiles a legacy visual or XFE Script v1 program to V2 in memory. */
public final class TriggerLegacyV2Compiler {
private TriggerLegacyV2Compiler() { }
public static TriggerProgramV2 compile(TriggerDefinition definition) {
TriggerDefinition.Program legacy = definition.executableProgram();
List<TriggerProgramV2.VariableDeclaration> declarations = legacy.event().variables().stream()
.map(variable -> new TriggerProgramV2.VariableDeclaration(
id(definition.id(), "variable/" + variable.contextKey()),
variable.name(), variable.type(),
new TriggerExpression(
id(definition.id(), "variable/" + variable.contextKey() + "/initial"),
TriggerExpression.Kind.LITERAL, variable.type(),
TriggerValueTypes.parseVariable(variable.type(), variable.initialValue()),
"", List.of()),
variable.visibility(), variable.storage(),
TriggerProgramV2.Lifetime.valueOf(variable.lifetime().toUpperCase(java.util.Locale.ROOT)),
variable.ttlSeconds()))
.toList();
List<TriggerProgramV2.Statement> body = actions(definition.id(), legacy.actions(), "action");
if (!legacy.conditions().isEmpty()) {
List<TriggerExpression> conditions = new ArrayList<>();
for (int index = 0; index < legacy.conditions().size(); index++) {
TriggerDefinition.Condition condition = legacy.conditions().get(index);
Map<String, Object> literal = new LinkedHashMap<>();
literal.put("field", condition.field());
literal.put("operator", condition.operator());
literal.put("value", condition.value());
conditions.add(new TriggerExpression(
id(definition.id(), "condition/" + index),
TriggerExpression.Kind.FUNCTION, "bool", null, "legacy_condition",
List.of(new TriggerExpression(
id(definition.id(), "condition/" + index + "/literal"),
TriggerExpression.Kind.LITERAL, "record", literal, "", List.of()))));
}
TriggerExpression combined = combine(definition.id(), legacy.conditionMode(), conditions);
body = List.of(new TriggerProgramV2.Statement(
id(definition.id(), "root-condition"), TriggerProgramV2.StatementKind.IF, "",
Map.of(), combined, List.of(), body, List.of()));
}
return new TriggerProgramV2(
TriggerProgramV2.SCHEMA_VERSION,
List.of(new TriggerProgramV2.EventBinding(
id(definition.id(), "event/0"), legacy.event().type(), legacy.event().configuration())),
declarations, List.of(), body);
}
private static List<TriggerProgramV2.Statement> actions(
UUID triggerId, List<TriggerDefinition.Action> actions, String path) {
List<TriggerProgramV2.Statement> statements = new ArrayList<>();
for (int index = 0; index < actions.size(); index++) {
TriggerDefinition.Action action = actions.get(index);
String nodePath = path + "/" + index;
if (TriggerActionTree.CONDITION_TYPE.equals(action.type())) {
TriggerDefinition.Condition condition = TriggerActionTree.condition(action);
Map<String, Object> literal = Map.of(
"field", condition.field(), "operator", condition.operator(), "value", condition.value());
TriggerExpression expression = new TriggerExpression(
id(triggerId, nodePath + "/expression"), TriggerExpression.Kind.FUNCTION,
"bool", null, "legacy_condition",
List.of(new TriggerExpression(
id(triggerId, nodePath + "/literal"), TriggerExpression.Kind.LITERAL,
"record", literal, "", List.of())));
statements.add(new TriggerProgramV2.Statement(
id(triggerId, nodePath), TriggerProgramV2.StatementKind.IF, "", Map.of(),
expression, List.of(), actions(triggerId, action.children(), nodePath), List.of()));
continue;
}
Map<String, TriggerExpression> inputs = new LinkedHashMap<>();
action.parameters().forEach((name, value) -> inputs.put(name,
new TriggerExpression(id(triggerId, nodePath + "/" + name),
TriggerExpression.Kind.LITERAL, "string", value, "", List.of())));
statements.add(new TriggerProgramV2.Statement(
id(triggerId, nodePath), TriggerProgramV2.StatementKind.ACTION,
action.type(), inputs, null, List.of(), List.of(), List.of()));
}
return List.copyOf(statements);
}
private static TriggerExpression combine(
UUID triggerId, TriggerDefinition.MatchMode mode, List<TriggerExpression> values) {
TriggerExpression result = values.get(0);
for (int index = 1; index < values.size(); index++) {
result = new TriggerExpression(
id(triggerId, "condition-combine/" + index), TriggerExpression.Kind.BINARY,
"bool", null, mode == TriggerDefinition.MatchMode.ALL ? "and" : "or",
List.of(result, values.get(index)));
}
return result;
}
private static UUID id(UUID triggerId, String path) {
return UUID.nameUUIDFromBytes((triggerId + ":" + path).getBytes(StandardCharsets.UTF_8));
}
}