3 Commits

Author SHA1 Message Date
8d4ba0697e transition enricher 2026-06-18 23:02:39 +02:00
d93d36e8ad html exporter fixed 2026-06-18 22:06:57 +02:00
5894303510 fqn names of events and states 2026-06-18 22:02:42 +02:00
51 changed files with 2037 additions and 379 deletions

22
InspectGolden.java Normal file
View File

@@ -0,0 +1,22 @@
import java.nio.file.*;
import java.util.*;
import click.kamil.springstatemachineexporter.service.ExportService;
import click.kamil.springstatemachineexporter.exporter.*;
import click.kamil.springstatemachineexporter.analysis.service.EnrichmentService;
public class InspectGolden {
public static void main(String[] args) throws Exception {
Path inputDir = Path.of("state_machines/complex_state_machine");
Path tempDir = Files.createTempDirectory("golden-update-");
List<StateMachineExporter> exporters = List.of(new PlantUml(), new Dot(), new Scxml(), new JsonExporter());
EnrichmentService enrichmentService = new EnrichmentService(Collections.emptyList());
ExportService exportService = new ExportService(exporters, enrichmentService);
exportService.runExporter(inputDir, tempDir, null, true);
try (var stream = Files.list(tempDir)) {
stream.forEach(System.out::println);
}
}
}

4
run_golden.gradle Normal file
View File

@@ -0,0 +1,4 @@
task runGolden(type: JavaExec) {
mainClass = "click.kamil.springstatemachineexporter.GoldenUpdater"
classpath = sourceSets.test.runtimeClasspath
}

View File

@@ -53,3 +53,14 @@ tasks.named('test') {
useJUnitPlatform()
systemProperty "updateGolden", System.getProperty("updateGolden")
}
task runGolden(type: JavaExec) {
mainClass = "click.kamil.springstatemachineexporter.GoldenUpdater"
classpath = sourceSets.test.runtimeClasspath
}
task runGoldenFixed(type: JavaExec) {
mainClass = "click.kamil.springstatemachineexporter.GoldenUpdater"
classpath = sourceSets.test.runtimeClasspath
workingDir = rootProject.projectDir
}

View File

@@ -0,0 +1,96 @@
package click.kamil.springstatemachineexporter.analysis.enricher;
import click.kamil.springstatemachineexporter.analysis.model.AnalysisResult;
import click.kamil.springstatemachineexporter.analysis.model.CallChain;
import click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata;
import click.kamil.springstatemachineexporter.analysis.model.MatchedTransition;
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
import click.kamil.springstatemachineexporter.analysis.service.CodebaseIntelligenceProvider;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import click.kamil.springstatemachineexporter.model.State;
import click.kamil.springstatemachineexporter.model.Transition;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class TransitionLinkerEnricher implements AnalysisEnricher {
@Override
public void enrich(AnalysisResult result, CodebaseContext context, CodebaseIntelligenceProvider intelligence) {
if (result.getMetadata() == null || result.getMetadata().getCallChains() == null) {
return;
}
List<CallChain> updatedChains = new ArrayList<>();
List<Transition> stateMachineTransitions = result.getTransitions();
for (CallChain chain : result.getMetadata().getCallChains()) {
TriggerPoint tp = chain.getTriggerPoint();
if (tp == null || tp.getEvent() == null) {
updatedChains.add(chain);
continue;
}
String triggerEvent = simplify(tp.getEvent());
String triggerSource = tp.getSourceState() != null ? simplify(tp.getSourceState()) : null;
List<MatchedTransition> matched = new ArrayList<>();
for (Transition t : stateMachineTransitions) {
if (t.getEvent() != null) {
String smEventRaw = t.getEvent().fullIdentifier() != null ? t.getEvent().fullIdentifier() : t.getEvent().rawName();
String smEvent = simplify(smEventRaw);
if (smEvent.equals(triggerEvent)) {
// Event matches. Check source state if provided
for (State smSourceState : t.getSourceStates()) {
String smSourceRaw = smSourceState.fullIdentifier() != null ? smSourceState.fullIdentifier() : smSourceState.rawName();
String smSource = simplify(smSourceRaw);
if (triggerSource == null || triggerSource.equals(smSource)) {
for (State smTargetState : t.getTargetStates()) {
String sourceRaw = smSourceState.fullIdentifier() != null ? smSourceState.fullIdentifier() : smSourceState.rawName();
String targetRaw = smTargetState.fullIdentifier() != null ? smTargetState.fullIdentifier() : smTargetState.rawName();
matched.add(MatchedTransition.builder()
.sourceState(sourceRaw)
.targetState(targetRaw)
.event(smEventRaw)
.build());
}
}
}
}
}
}
// Create a new CallChain with the matched transitions
CallChain updatedChain = CallChain.builder()
.entryPoint(chain.getEntryPoint())
.methodChain(chain.getMethodChain())
.triggerPoint(chain.getTriggerPoint())
.contextMachineId(chain.getContextMachineId())
.matchedTransitions(matched)
.build();
updatedChains.add(updatedChain);
}
// Update the metadata with the new call chains
CodebaseMetadata updatedMetadata = CodebaseMetadata.builder()
.triggers(result.getMetadata().getTriggers())
.entryPoints(result.getMetadata().getEntryPoints())
.callChains(updatedChains)
.properties(result.getMetadata().getProperties())
.build();
result.setMetadata(updatedMetadata);
}
private String simplify(String name) {
if (name == null) return "";
int dot = name.lastIndexOf('.');
if (dot >= 0) {
return name.substring(dot + 1);
}
return name;
}
}

View File

@@ -60,7 +60,7 @@ public class AnalysisResult {
if (transitions != null) {
for (var t : transitions) {
if (t.getEvent() != null) {
t.setEvent(resolver.resolveValue(t.getEvent(), properties));
t.setEvent(click.kamil.springstatemachineexporter.model.Event.of(t.getEvent().rawName(), resolver.resolveValue(t.getEvent().fullIdentifier(), properties)));
}
// Resolve states within transitions
t.setSourceStates(t.getSourceStates().stream()

View File

@@ -15,4 +15,6 @@ public class CallChain {
private final EntryPoint entryPoint;
private final List<String> methodChain; // e.g., ["Controller.submit", "Service.process", "Service.send"]
private final TriggerPoint triggerPoint;
private final String contextMachineId;
private final List<MatchedTransition> matchedTransitions;
}

View File

@@ -0,0 +1,16 @@
package click.kamil.springstatemachineexporter.analysis.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Builder;
import lombok.Data;
import lombok.extern.jackson.Jacksonized;
@Data
@Builder
@Jacksonized
@JsonIgnoreProperties(ignoreUnknown = true)
public class MatchedTransition {
private final String sourceState;
private final String targetState;
private final String event;
}

View File

@@ -18,5 +18,6 @@ public class TriggerPoint {
private final String sourceFile;
private final String sourceModule;
private final String stateMachineId; // Optional: to link to a specific SM instance
private final String sourceState; // Optional: if we can determine the expected current state
private final int lineNumber;
}

View File

@@ -39,10 +39,12 @@ public class CallGraphBuilder {
List<String> path = findPath(startMethod, targetMethod, callGraph, new HashSet<>());
if (path != null) {
TriggerPoint resolvedTp = resolveTriggerPointParameters(tp, path, callGraph);
String contextMachineId = extractContextMachineId(path, callGraph);
chains.add(CallChain.builder()
.entryPoint(ep)
.triggerPoint(resolvedTp)
.methodChain(path)
.contextMachineId(contextMachineId)
.build());
}
}
@@ -97,6 +99,24 @@ public class CallGraphBuilder {
return tp;
}
private String extractContextMachineId(List<String> path, Map<String, List<CallEdge>> callGraph) {
for (String node : path) {
List<CallEdge> edges = callGraph.get(node);
if (edges != null) {
for (CallEdge edge : edges) {
String target = edge.getTargetMethod();
if (target != null && (target.contains(".restore") || target.contains(".read"))) {
// Persister signatures usually like: restore(stateMachine, contextObj)
if (edge.getArguments().size() >= 2) {
return edge.getArguments().get(1); // The contextObj / machineId
}
}
}
}
}
return null;
}
private Map<String, List<CallEdge>> buildCallGraph() {
graph = new HashMap<>();
for (CompilationUnit cu : context.getCompilationUnits()) {
@@ -131,13 +151,15 @@ public class CallGraphBuilder {
String superFqn = context.getSuperclassFqn(td);
if (superFqn != null) {
TypeDeclaration superTd = context.getTypeDeclaration(superFqn);
String calledMethod = null;
if (superTd != null) {
String calledMethod = resolveMethodInType(superTd, methodName);
if (calledMethod != null) {
List<String> args = resolveArguments(node.arguments());
graph.computeIfAbsent(currentMethodFqn, k -> new ArrayList<>()).add(new CallEdge(calledMethod, args));
}
calledMethod = resolveMethodInType(superTd, methodName);
}
if (calledMethod == null) {
calledMethod = superFqn + "." + methodName;
}
List<String> args = resolveArguments(node.arguments());
graph.computeIfAbsent(currentMethodFqn, k -> new ArrayList<>()).add(new CallEdge(calledMethod, args));
}
}
}
@@ -153,8 +175,8 @@ public class CallGraphBuilder {
for (Object argObj : astArguments) {
Expression expr = (Expression) argObj;
String val = constantResolver.resolve(expr, context);
if (val == null && expr instanceof SimpleName sn) {
val = sn.getIdentifier();
if (val == null) {
val = expr.toString(); // Fallback to raw string (handles Enums, 'new Class()', etc)
}
args.add(val);
}
@@ -217,22 +239,25 @@ public class CallGraphBuilder {
private List<String> findPath(String start, String target, Map<String, List<CallEdge>> graph, Set<String> visited) {
if (start.equals(target)) return new ArrayList<>(List.of(start));
if (!visited.add(start)) return null;
if (!visited.add(start)) return null; // Path-scoped cycle detection
List<CallEdge> neighbors = graph.get(start);
if (neighbors != null) {
for (CallEdge edge : neighbors) {
String neighbor = edge.getTargetMethod();
if (neighbor.equals(target) || isHeuristicMatch(neighbor, target)) {
visited.remove(start);
return new ArrayList<>(List.of(start, target));
}
List<String> path = findPath(neighbor, target, graph, visited);
if (path != null) {
path.add(0, start);
visited.remove(start);
return path;
}
}
}
visited.remove(start);
return null;
}

View File

@@ -33,7 +33,8 @@ public class GenericEventDetector {
public boolean visit(MethodInvocation node) {
String methodName = node.getName().getIdentifier();
if ("sendEvent".equals(methodName)) {
if ("sendEvent".equals(methodName) || "sendEvents".equals(methodName) ||
"sendEventCollect".equals(methodName) || "sendEventMono".equals(methodName)) {
processSendEvent(node, cu, triggers);
}
@@ -124,8 +125,11 @@ public class GenericEventDetector {
if (type == null) return null;
String sourceState = extractSourceState(node);
return TriggerPoint.builder()
.event(eventValue)
.sourceState(sourceState)
.className(context.getFqn(type))
.methodName(method != null ? method.getName().getIdentifier() : "initializer")
.sourceFile(context.getRelativePath(context.getFqn(type)))
@@ -133,15 +137,105 @@ public class GenericEventDetector {
.build();
}
private String extractSourceState(ASTNode node) {
ASTNode current = node.getParent();
while (current != null && !(current instanceof MethodDeclaration)) {
if (current instanceof IfStatement ifStmt) {
Expression expr = ifStmt.getExpression();
String state = extractStateFromExpression(expr);
if (state != null) return state;
} else if (current instanceof SwitchCase switchCase) {
if (!switchCase.expressions().isEmpty()) {
return getSimpleNameString((Expression) switchCase.expressions().get(0));
}
} else if (current instanceof SwitchStatement switchStmt) {
// If it's a switch block but we haven't hit a SwitchCase directly (AST hierarchy usually has SwitchCase as siblings of block statements)
// Actually, walking up from the node, we will hit the SwitchStatement, but we need the SwitchCase right before us in the block.
ASTNode parentBlock = current;
// It's complex to walk siblings. A simpler heuristic is to just use IfStatement and SwitchCase (if wrapped correctly).
}
current = current.getParent();
}
return null;
}
private String extractStateFromExpression(Expression expr) {
if (expr instanceof InfixExpression infix) {
if (infix.getOperator() == InfixExpression.Operator.EQUALS) {
Expression left = infix.getLeftOperand();
Expression right = infix.getRightOperand();
// Usually one is a method call like getState(), the other is an enum
if (left instanceof QualifiedName || left instanceof SimpleName && !(right instanceof SimpleName)) {
return getSimpleNameString(left);
}
if (right instanceof QualifiedName || right instanceof SimpleName && !(left instanceof SimpleName)) {
return getSimpleNameString(right);
}
return getSimpleNameString(right); // Fallback
}
} else if (expr instanceof MethodInvocation mi) {
if ("equals".equals(mi.getName().getIdentifier()) && !mi.arguments().isEmpty()) {
return getSimpleNameString((Expression) mi.arguments().get(0));
}
}
return null;
}
private String getSimpleNameString(Expression expr) {
if (expr instanceof QualifiedName qn) {
return qn.getName().getIdentifier();
} else if (expr instanceof FieldAccess fa) {
return fa.getName().getIdentifier();
} else if (expr instanceof StringLiteral sl) {
return sl.getLiteralValue();
}
return expr.toString();
}
private String extractEventFromMessageBuilder(Expression expr) {
if (expr instanceof SimpleName sn) {
String varName = sn.getIdentifier();
MethodDeclaration enclosingMethod = findEnclosingMethod(expr);
if (enclosingMethod != null) {
// Find variable declaration
final Expression[] initializer = new Expression[1];
enclosingMethod.accept(new ASTVisitor() {
@Override
public boolean visit(VariableDeclarationFragment node) {
if (node.getName().getIdentifier().equals(varName) && node.getInitializer() != null) {
initializer[0] = node.getInitializer();
}
return super.visit(node);
}
@Override
public boolean visit(Assignment node) {
if (node.getLeftHandSide() instanceof SimpleName asn && asn.getIdentifier().equals(varName)) {
initializer[0] = node.getRightHandSide();
}
return super.visit(node);
}
});
if (initializer[0] != null) {
return extractEventFromMessageBuilder(initializer[0]); // recursive
}
}
}
if (!(expr instanceof MethodInvocation mi)) return null;
// Trace back chain: MessageBuilder.withPayload(event).setHeader(...).build()
MethodInvocation current = mi;
while (current != null) {
String name = current.getName().getIdentifier();
if ("withPayload".equals(name) && !current.arguments().isEmpty()) {
if (("withPayload".equals(name) || "just".equals(name)) && !current.arguments().isEmpty()) {
Expression payloadExpr = (Expression) current.arguments().get(0);
// If it's Mono.just(msg), where msg is a variable
if ("just".equals(name)) {
String extracted = extractEventFromMessageBuilder(payloadExpr);
if (extracted != null) return extracted;
}
String resolved = constantResolver.resolve(payloadExpr, context);
if (resolved != null) return resolved;

View File

@@ -4,6 +4,7 @@ import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver
import click.kamil.springstatemachineexporter.model.Action;
import click.kamil.springstatemachineexporter.model.Guard;
import click.kamil.springstatemachineexporter.model.State;
import click.kamil.springstatemachineexporter.model.Event;
import click.kamil.springstatemachineexporter.model.Transition;
import click.kamil.springstatemachineexporter.model.TransitionType;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
@@ -213,9 +214,30 @@ public class AstTransitionParser {
Expression resolved = resolveArg((Expression) args.get(0), argsMap);
String eventValue = constantResolver.resolve(resolved, context);
if (eventValue != null) {
t.setEvent(eventValue);
t.setEvent(Event.of(resolved.toString(), eventValue));
} else if (resolved instanceof QualifiedName qn) {
String qualifier = qn.getQualifier().toString();
String name = qn.getName().getIdentifier();
TypeDeclaration td = context.getTypeDeclaration(qualifier, cu);
if (td != null) {
t.setEvent(Event.of(resolved.toString(), context.getFqn(td) + "." + name));
} else {
t.setEvent(Event.of(resolved.toString(), qn.getFullyQualifiedName()));
}
} else if (resolved instanceof SimpleName sn) {
String name = sn.getIdentifier();
String full = name;
for (Object impObj : cu.imports()) {
ImportDeclaration imp = (ImportDeclaration) impObj;
String impName = imp.getName().getFullyQualifiedName();
if (impName.endsWith("." + name)) {
full = impName;
break;
}
}
t.setEvent(Event.of(resolved.toString(), full));
} else {
t.setEvent(QuotedExpression.of(resolved).toStringWithoutQuotes());
t.setEvent(Event.of(QuotedExpression.of(resolved).toStringWithoutQuotes()));
}
}
case "guard" -> {

View File

@@ -48,6 +48,12 @@ public class ExporterCommand implements Callable<Integer> {
@Option(names = {"-p", "--profiles"}, description = "Spring profiles to activate for property resolution.", split = ",")
private List<String> activeProfiles;
@Option(names = {"--event"}, description = "Format for events when they are enums: fn (fullName, default), fqn (fully qualified name), sn (short name)", defaultValue = "fn")
private click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat;
@Option(names = {"--state"}, description = "Format for states when they are enums: fn (fullName, default), fqn (fully qualified name), sn (short name)", defaultValue = "fn")
private click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat;
@Override
public Integer call() throws Exception {
var out = spec.commandLine().getOut();
@@ -71,9 +77,9 @@ public class ExporterCommand implements Callable<Integer> {
try {
List<String> profiles = activeProfiles != null ? activeProfiles : java.util.Collections.emptyList();
if (jsonFile != null) {
exportService.runJsonExporter(jsonFile, outputDir, selectedFormats, profiles);
exportService.runJsonExporter(jsonFile, outputDir, selectedFormats, profiles, eventFormat, stateFormat);
} else {
exportService.runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, profiles);
exportService.runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, profiles, eventFormat, stateFormat);
}
out.println(CommandLine.Help.Ansi.AUTO.string("%n@|bold,green SUCCESS:|@ All state machines have been exported to " + outputDir.toAbsolutePath()));
return 0;

View File

@@ -41,7 +41,7 @@ public class Dot implements StateMachineExporter {
for (Transition t : transitions) {
if (t.getType() == TransitionType.CHOICE && t.getSourceStates() != null) {
for (State source : t.getSourceStates()) {
String simplified = simplify(source.toString());
String simplified = simplify(options.formatState(source));
statesWithChoice.add(simplified);
if (!choiceColorMap.containsKey(simplified)) {
choiceColorMap.put(simplified, CHOICE_COLORS[colorIndex % CHOICE_COLORS.length]);
@@ -86,11 +86,11 @@ public class Dot implements StateMachineExporter {
}
for (State rawSourceState : t.getSourceStates()) {
String rawSource = rawSourceState.toString();
String rawSource = options.formatState(rawSourceState);
String source = simplify(rawSource);
for (State rawTargetState : targets) {
String rawTarget = rawTargetState.toString();
String rawTarget = options.formatState(rawTargetState);
String target = simplify(rawTarget);
String edgeSource = source;
@@ -100,8 +100,11 @@ public class Dot implements StateMachineExporter {
// Label: event [guard] / actions
StringBuilder label = new StringBuilder();
if (t.getEvent() != null && !t.getEvent().isBlank()) {
label.append(escapeDotString(t.getEvent()));
if (t.getEvent() != null) {
String eventStr = options.formatEvent(t.getEvent());
if (eventStr != null && !eventStr.isBlank()) {
label.append(escapeDotString(eventStr));
}
}
// Guard

View File

@@ -0,0 +1,5 @@
package click.kamil.springstatemachineexporter.exporter;
public enum EnumFormat {
fn, fqn, sn
}

View File

@@ -12,4 +12,37 @@ public class ExportOptions {
boolean renderChoicesAsDiamonds = true;
@Builder.Default
boolean embedIdentifiers = false;
@Builder.Default
boolean includeMetadataPane = true;
@Builder.Default
EnumFormat eventFormat = EnumFormat.fn;
@Builder.Default
EnumFormat stateFormat = EnumFormat.fn;
public String formatState(click.kamil.springstatemachineexporter.model.State state) {
if (state == null) return null;
return format(state.rawName(), state.fullIdentifier(), stateFormat);
}
public String formatEvent(click.kamil.springstatemachineexporter.model.Event event) {
if (event == null) return null;
return format(event.rawName(), event.fullIdentifier(), eventFormat);
}
private String format(String raw, String fqn, EnumFormat format) {
if (fqn == null) return raw;
switch (format) {
case fqn: return fqn;
case sn: return fqn.substring(fqn.lastIndexOf('.') + 1);
case fn:
int lastDot = fqn.lastIndexOf('.');
if (lastDot > 0) {
int prevDot = fqn.lastIndexOf('.', lastDot - 1);
return prevDot > 0 ? fqn.substring(prevDot + 1) : fqn;
}
return fqn;
default: return raw;
}
}
}

View File

@@ -63,7 +63,7 @@ public class PlantUml implements StateMachineExporter {
for (Transition t : transitions) {
if (t.getType() == TransitionType.CHOICE && t.getSourceStates() != null) {
for (State source : t.getSourceStates()) {
statesWithChoice.add(simplify(source.toString()));
statesWithChoice.add(simplify(options.formatState(source)));
}
}
}
@@ -77,7 +77,7 @@ public class PlantUml implements StateMachineExporter {
Set<String> junctionStates = transitions.stream()
.filter(t -> t.getType() == TransitionType.JUNCTION)
.flatMap(t -> t.getSourceStates().stream())
.map(s -> simplify(s.toString()))
.map(s -> simplify(options.formatState(s)))
.collect(Collectors.toCollection(java.util.LinkedHashSet::new));
for (String junction : junctionStates) {
if (options.isRenderChoicesAsDiamonds()) {
@@ -96,16 +96,16 @@ public class PlantUml implements StateMachineExporter {
List<String> targets;
if (t.getTargetStates() == null || t.getTargetStates().isEmpty()) {
if (!allowNoTarget) {
targets = t.getSourceStates().stream().map(s -> s.toString()).toList();
targets = t.getSourceStates().stream().map(s -> options.formatState(s)).toList();
} else {
continue;
}
} else {
targets = t.getTargetStates().stream().map(s -> s.toString()).toList();
targets = t.getTargetStates().stream().map(s -> options.formatState(s)).toList();
}
for (State rawSourceState : t.getSourceStates()) {
String source = simplify(rawSourceState.toString());
String source = simplify(options.formatState(rawSourceState));
for (String rawTarget : targets) {
String target = simplify(rawTarget);
@@ -116,13 +116,17 @@ public class PlantUml implements StateMachineExporter {
sb.append(" <<").append(styleClass).append(">>");
if (t.getEvent() != null && !t.getEvent().isBlank()) {
sb.append(" <<e_").append(normalize(t.getEvent())).append(">>");
if (t.getEvent() != null) {
String eventStr = options.formatEvent(t.getEvent());
if (eventStr != null && !eventStr.isBlank()) {
sb.append(" <<e_").append(normalize(eventStr)).append(">>");
}
}
String label = buildLabel(t, options.isUseLambdaGuards());
String label = buildLabel(t, options);
if (options.isEmbedIdentifiers()) {
String linkId = t.getEvent() != null ? "link_" + normalize(t.getEvent()) : "link_anon_" + normalize(source) + "_" + normalize(target);
String eventStr = t.getEvent() != null ? options.formatEvent(t.getEvent()) : null;
String linkId = eventStr != null && !eventStr.isBlank() ? "link_" + normalize(source) + "__" + normalize(eventStr) : "link_anon_" + normalize(source) + "_" + normalize(target);
// Force a label even if empty to ensure the link group exists in SVG
String displayLabel = label.isEmpty() ? " " : label;
// Brackets [...] in the label break PlantUML link syntax [[url label]],
@@ -191,14 +195,17 @@ public class PlantUml implements StateMachineExporter {
return state.replaceAll("[^a-zA-Z0-9_.]", "");
}
private String buildLabel(Transition t, boolean useLambdaGuards) {
private String buildLabel(Transition t, ExportOptions options) {
List<String> parts = new ArrayList<>();
if (t.getEvent() != null && !t.getEvent().isBlank()) {
parts.add(t.getEvent());
if (t.getEvent() != null) {
String eventStr = options.formatEvent(t.getEvent());
if (eventStr != null && !eventStr.isBlank()) {
parts.add(eventStr);
}
}
if (t.getGuard() != null) {
String g = t.getGuard().expression();
if (useLambdaGuards && t.getGuard().isLambda()) {
if (options.isUseLambdaGuards() && t.getGuard().isLambda()) {
parts.add("[" + LAMBDA + "]");
} else {
parts.add("[" + g.replaceAll("[\\n\\r]+", " ").replaceAll("\\s{2,}", " ").trim() + "]");
@@ -206,7 +213,7 @@ public class PlantUml implements StateMachineExporter {
}
if (t.getActions() != null && !t.getActions().isEmpty()) {
parts.add("/ " + t.getActions().stream()
.map(a -> (useLambdaGuards && a.isLambda()) ? LAMBDA : a.expression().replaceAll("[\\n\\r]+", " ").replaceAll("\\s{2,}", " ").trim())
.map(a -> (options.isUseLambdaGuards() && a.isLambda()) ? LAMBDA : a.expression().replaceAll("[\\n\\r]+", " ").replaceAll("\\s{2,}", " ").trim())
.collect(Collectors.joining(", ")));
}
Optional.ofNullable(t.getOrder())

View File

@@ -31,8 +31,8 @@ public class Scxml implements StateMachineExporter {
Set<String> allStates = new java.util.LinkedHashSet<>();
for (Transition t : transitions) {
t.getSourceStates().forEach(s -> allStates.add(s.toString()));
t.getTargetStates().forEach(s -> allStates.add(s.toString()));
t.getSourceStates().forEach(s -> allStates.add(options.formatState(s)));
t.getTargetStates().forEach(s -> allStates.add(options.formatState(s)));
}
allStates.addAll(startStates);
allStates.addAll(endStates);
@@ -41,7 +41,7 @@ public class Scxml implements StateMachineExporter {
sb.append(" <state id=\"").append(simplify(state)).append("\">\n");
for (Transition t : transitions) {
if (t.getSourceStates() == null || t.getSourceStates().stream().noneMatch(s -> s.toString().equals(state)))
if (t.getSourceStates() == null || t.getSourceStates().stream().noneMatch(s -> options.formatState(s).equals(state)))
continue;
boolean allowNoTarget = t.getType() == TransitionType.JOIN || t.getType() == TransitionType.FORK;
@@ -58,7 +58,7 @@ public class Scxml implements StateMachineExporter {
}
for (State target : targets) {
sb.append(renderTransition(t, target, options.isUseLambdaGuards()));
sb.append(renderTransition(t, target, options));
}
}
sb.append(" </state>\n");
@@ -73,15 +73,18 @@ public class Scxml implements StateMachineExporter {
return ".scxml.xml";
}
private String renderTransition(Transition t, State target, boolean useLambdaGuards) {
private String renderTransition(Transition t, State target, ExportOptions options) {
StringBuilder sb = new StringBuilder();
sb.append(" <transition target=\"").append(simplify(target.toString())).append("\"");
sb.append(" <transition target=\"").append(simplify(options.formatState(target))).append("\"");
if (t.getEvent() != null && !t.getEvent().isBlank()) {
sb.append(" event=\"").append(escapeXml(t.getEvent())).append("\"");
if (t.getEvent() != null) {
String eventStr = options.formatEvent(t.getEvent());
if (eventStr != null && !eventStr.isBlank()) {
sb.append(" event=\"").append(escapeXml(eventStr)).append("\"");
}
}
String guard = getGuardText(t, useLambdaGuards);
String guard = getGuardText(t, options.isUseLambdaGuards());
if (!guard.isBlank()) {
sb.append(" cond=\"").append(escapeXml(guard)).append("\"");
}

View File

@@ -0,0 +1,16 @@
package click.kamil.springstatemachineexporter.model;
public record Event(String rawName, String fullIdentifier) {
public static Event of(String name) {
return new Event(name, name);
}
public static Event of(String raw, String full) {
return new Event(raw, full);
}
@Override
public String toString() {
return fullIdentifier != null ? fullIdentifier : rawName;
}
}

View File

@@ -14,7 +14,7 @@ public class Transition {
private TransitionType type;
private List<State> sourceStates = new ArrayList<>();
private List<State> targetStates = new ArrayList<>();
private String event;
private Event event;
private Guard guard;
private List<Action> actions = new ArrayList<>();

View File

@@ -44,7 +44,8 @@ public class ExportService {
new TriggerEnricher(),
new EntryPointEnricher(),
new PropertyEnricher(),
new CallChainEnricher()
new CallChainEnricher(),
new click.kamil.springstatemachineexporter.analysis.enricher.TransitionLinkerEnricher()
)));
}
@@ -52,14 +53,22 @@ public class ExportService {
public static final Set<String> STATE_MACHINE_RETURN_TYPES = Set.of("StateMachine", "StateMachineFactory", "StateMachineModelFactory");
public void runExporter(Path inputDir, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds) throws IOException {
runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, Collections.emptyList());
runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, Collections.emptyList(), click.kamil.springstatemachineexporter.exporter.EnumFormat.fn, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn);
}
public void runExporter(Path inputDir, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<String> activeProfiles) throws IOException {
runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, activeProfiles, null, null);
runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, activeProfiles, null, null, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn);
}
public void runExporter(Path inputDir, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<String> activeProfiles, Path flowsOverride, String machineFilter) throws IOException {
runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, activeProfiles, flowsOverride, machineFilter, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn);
}
public void runExporter(Path inputDir, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<String> activeProfiles, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat) throws IOException {
runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, activeProfiles, null, null, eventFormat, stateFormat);
}
public void runExporter(Path inputDir, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<String> activeProfiles, Path flowsOverride, String machineFilter, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat) throws IOException {
CodebaseContext context = new CodebaseContext();
context.setActiveProfiles(activeProfiles);
@@ -116,21 +125,25 @@ public class ExportService {
context.scan(allPaths, Collections.emptySet());
CodebaseIntelligenceProvider intelligence = new JdtIntelligenceProvider(context, inputDir);
exportAll(context, intelligence, outputDir, selectedFormats, renderChoicesAsDiamonds, flows, machineFilter, activeProfiles != null ? activeProfiles : Collections.emptyList());
exportAll(context, intelligence, outputDir, selectedFormats, renderChoicesAsDiamonds, flows, machineFilter, activeProfiles != null ? activeProfiles : Collections.emptyList(), eventFormat, stateFormat);
}
public void runJsonExporter(Path jsonFile, Path outputDir, List<String> selectedFormats) throws IOException {
runJsonExporter(jsonFile, outputDir, selectedFormats, Collections.emptyList());
runJsonExporter(jsonFile, outputDir, selectedFormats, Collections.emptyList(), click.kamil.springstatemachineexporter.exporter.EnumFormat.fn, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn);
}
public void runJsonExporter(Path jsonFile, Path outputDir, List<String> selectedFormats, List<String> activeProfiles) throws IOException {
runJsonExporter(jsonFile, outputDir, selectedFormats, activeProfiles, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn, click.kamil.springstatemachineexporter.exporter.EnumFormat.fn);
}
public void runJsonExporter(Path jsonFile, Path outputDir, List<String> selectedFormats, List<String> activeProfiles, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat) throws IOException {
JsonImportService jsonImportService = new JsonImportService();
AnalysisResult result = jsonImportService.importAnalysisResult(jsonFile);
// Apply property resolution pass if placeholders exist
resolveProperties(result, activeProfiles);
generateOutputs(outputDir, result, selectedFormats);
generateOutputs(outputDir, result, selectedFormats, eventFormat, stateFormat);
}
private void resolveProperties(AnalysisResult result, List<String> activeProfiles) {
@@ -154,7 +167,7 @@ public class ExportService {
result.applyResolution(merged);
}
private void exportAll(CodebaseContext context, CodebaseIntelligenceProvider intelligence, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<BusinessFlow> flows, String machineFilter, List<String> activeProfiles) throws IOException {
private void exportAll(CodebaseContext context, CodebaseIntelligenceProvider intelligence, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<BusinessFlow> flows, String machineFilter, List<String> activeProfiles, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat) throws IOException {
Set<String> processedLocations = new HashSet<>();
// 1. Find entry point classes (annotated or extending adapter)
@@ -163,7 +176,7 @@ public class ExportService {
String fqn = context.getFqn(td);
if (machineFilter != null && !fqn.contains(machineFilter)) continue;
if (processedLocations.add(fqn)) {
processEntryPoint(td, outputDir, context, intelligence, selectedFormats, renderChoicesAsDiamonds, flows, activeProfiles);
processEntryPoint(td, outputDir, context, intelligence, selectedFormats, renderChoicesAsDiamonds, flows, activeProfiles, eventFormat, stateFormat);
}
}
@@ -177,12 +190,12 @@ public class ExportService {
if (machineFilter != null && !uniqueId.contains(machineFilter)) continue;
if (processedLocations.add(uniqueId)) {
processBeanMethod(m, outputDir, context, intelligence, selectedFormats, renderChoicesAsDiamonds, flows, activeProfiles);
processBeanMethod(m, outputDir, context, intelligence, selectedFormats, renderChoicesAsDiamonds, flows, activeProfiles, eventFormat, stateFormat);
}
}
}
private void processEntryPoint(TypeDeclaration td, Path outputDir, CodebaseContext context, CodebaseIntelligenceProvider intelligence, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<BusinessFlow> flows, List<String> activeProfiles) throws IOException {
private void processEntryPoint(TypeDeclaration td, Path outputDir, CodebaseContext context, CodebaseIntelligenceProvider intelligence, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<BusinessFlow> flows, List<String> activeProfiles, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat) throws IOException {
String className = context.getFqn(td);
log.info("Processing state machine config: {}", className);
@@ -200,6 +213,11 @@ public class ExportService {
Set<String> endStates = TransitionStateUtils.findEndStates(transitions, endStatesAst);
Set<click.kamil.springstatemachineexporter.model.State> allStates = TransitionStateUtils.findAllStates(transitions, initialStatesAst, endStatesAst);
if (allStates.isEmpty() && transitions.isEmpty()) {
log.info("Skipping empty state machine config: {}", className);
return;
}
AnalysisResult result = AnalysisResult.builder()
.name(className)
.states(allStates)
@@ -214,10 +232,10 @@ public class ExportService {
resolveProperties(result, activeProfiles);
generateOutputs(outputDir, result, selectedFormats);
generateOutputs(outputDir, result, selectedFormats, eventFormat, stateFormat);
}
private void processBeanMethod(MethodDeclaration m, Path outputDir, CodebaseContext context, CodebaseIntelligenceProvider intelligence, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<BusinessFlow> flows, List<String> activeProfiles) throws IOException {
private void processBeanMethod(MethodDeclaration m, Path outputDir, CodebaseContext context, CodebaseIntelligenceProvider intelligence, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<BusinessFlow> flows, List<String> activeProfiles, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat) throws IOException {
TypeDeclaration parentClass = (TypeDeclaration) m.getParent();
String parentFqn = context.getFqn(parentClass);
String methodName = m.getName().getIdentifier();
@@ -231,6 +249,11 @@ public class ExportService {
Set<String> endStates = TransitionStateUtils.findEndStates(transitions, null);
Set<click.kamil.springstatemachineexporter.model.State> allStates = TransitionStateUtils.findAllStates(transitions, null, null);
if (allStates.isEmpty() && transitions.isEmpty()) {
log.info("Skipping empty state machine bean: {}", uniqueName);
return;
}
AnalysisResult result = AnalysisResult.builder()
.name(uniqueName)
.states(allStates)
@@ -245,10 +268,10 @@ public class ExportService {
resolveProperties(result, activeProfiles);
generateOutputs(outputDir, result, selectedFormats);
generateOutputs(outputDir, result, selectedFormats, eventFormat, stateFormat);
}
private void generateOutputs(Path outputDir, AnalysisResult result, List<String> selectedFormats) throws IOException {
private void generateOutputs(Path outputDir, AnalysisResult result, List<String> selectedFormats, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat) throws IOException {
if (selectedFormats == null || selectedFormats.isEmpty()) {
return;
}
@@ -259,6 +282,8 @@ public class ExportService {
ExportOptions options = ExportOptions.builder()
.renderChoicesAsDiamonds(result.isRenderChoicesAsDiamonds())
.eventFormat(eventFormat)
.stateFormat(stateFormat)
.build();
for (StateMachineExporter exporter : exporters) {

View File

@@ -34,7 +34,7 @@ public class GoldenUpdater {
System.out.println("Updating golden files for: " + scenario.name());
Path tempDir = Files.createTempDirectory("golden-update-");
try {
exportService.runExporter(scenario.inputPath(), tempDir, null, true);
exportService.runExporter(scenario.inputPath(), tempDir, List.of("puml", "dot", "scxml", "json"), true);
List<Path> generatedDirs;
try (var stream = Files.list(tempDir)) {

View File

@@ -0,0 +1,121 @@
package click.kamil.springstatemachineexporter.analysis.enricher;
import click.kamil.springstatemachineexporter.analysis.model.AnalysisResult;
import click.kamil.springstatemachineexporter.analysis.model.CallChain;
import click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata;
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
import click.kamil.springstatemachineexporter.model.Event;
import click.kamil.springstatemachineexporter.model.State;
import click.kamil.springstatemachineexporter.model.Transition;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class TransitionLinkerEnricherTest {
private final TransitionLinkerEnricher enricher = new TransitionLinkerEnricher();
@Test
void shouldLinkTransitionByEventOnly() {
Transition t1 = new Transition();
t1.setSourceStates(List.of(State.of("NEW", "NEW")));
t1.setTargetStates(List.of(State.of("PAID", "PAID")));
t1.setEvent(Event.of("PAY", "PAY"));
Transition t2 = new Transition();
t2.setSourceStates(List.of(State.of("FAILED", "FAILED")));
t2.setTargetStates(List.of(State.of("PAID", "PAID")));
t2.setEvent(Event.of("PAY", "PAY"));
CallChain chain = CallChain.builder()
.triggerPoint(TriggerPoint.builder().event("PAY").build())
.build();
AnalysisResult result = AnalysisResult.builder()
.transitions(List.of(t1, t2))
.metadata(CodebaseMetadata.builder().callChains(List.of(chain)).build())
.build();
enricher.enrich(result, null, null);
CallChain updatedChain = result.getMetadata().getCallChains().get(0);
assertThat(updatedChain.getMatchedTransitions()).hasSize(2);
assertThat(updatedChain.getMatchedTransitions())
.extracting("sourceState")
.containsExactlyInAnyOrder("NEW", "FAILED");
}
@Test
void shouldLinkTransitionByEventAndSourceState() {
Transition t1 = new Transition();
t1.setSourceStates(List.of(State.of("NEW", "NEW")));
t1.setTargetStates(List.of(State.of("PAID", "PAID")));
t1.setEvent(Event.of("PAY", "PAY"));
Transition t2 = new Transition();
t2.setSourceStates(List.of(State.of("FAILED", "FAILED")));
t2.setTargetStates(List.of(State.of("PAID", "PAID")));
t2.setEvent(Event.of("PAY", "PAY"));
CallChain chain = CallChain.builder()
.triggerPoint(TriggerPoint.builder().event("PAY").sourceState("NEW").build())
.build();
AnalysisResult result = AnalysisResult.builder()
.transitions(List.of(t1, t2))
.metadata(CodebaseMetadata.builder().callChains(List.of(chain)).build())
.build();
enricher.enrich(result, null, null);
CallChain updatedChain = result.getMetadata().getCallChains().get(0);
assertThat(updatedChain.getMatchedTransitions()).hasSize(1);
assertThat(updatedChain.getMatchedTransitions().get(0).getSourceState()).isEqualTo("NEW");
assertThat(updatedChain.getMatchedTransitions().get(0).getTargetState()).isEqualTo("PAID");
}
@Test
void shouldLinkTransitionByFullIdentifier() {
Transition t1 = new Transition();
t1.setSourceStates(List.of(State.of("\"NEW\"", "NEW")));
t1.setTargetStates(List.of(State.of("\"PAID\"", "PAID")));
// This simulates how Spring Config usually has Event as OrderEvents.PAY but its resolved string is "PAY_ORDER"
t1.setEvent(Event.of("OrderEvents.PAY", "PAY_ORDER"));
CallChain chain = CallChain.builder()
.triggerPoint(TriggerPoint.builder().event("PAY_ORDER").sourceState("NEW").build())
.build();
AnalysisResult result = AnalysisResult.builder()
.transitions(List.of(t1))
.metadata(CodebaseMetadata.builder().callChains(List.of(chain)).build())
.build();
enricher.enrich(result, null, null);
CallChain updatedChain = result.getMetadata().getCallChains().get(0);
assertThat(updatedChain.getMatchedTransitions()).hasSize(1);
assertThat(updatedChain.getMatchedTransitions().get(0).getSourceState()).isEqualTo("NEW");
assertThat(updatedChain.getMatchedTransitions().get(0).getTargetState()).isEqualTo("PAID");
assertThat(updatedChain.getMatchedTransitions().get(0).getEvent()).isEqualTo("PAY_ORDER");
}
@Test
void shouldHandleUnknownEvents() {
CallChain chain = CallChain.builder()
.triggerPoint(TriggerPoint.builder().event(null).build()) // Dynamic or unresolved event
.build();
AnalysisResult result = AnalysisResult.builder()
.transitions(List.of(new Transition()))
.metadata(CodebaseMetadata.builder().callChains(List.of(chain)).build())
.build();
enricher.enrich(result, null, null);
CallChain updatedChain = result.getMetadata().getCallChains().get(0);
assertThat(updatedChain.getMatchedTransitions()).isNull();
}
}

View File

@@ -0,0 +1,47 @@
package click.kamil.springstatemachineexporter.analysis.service;
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class GenericEventDetectorTest {
@Test
void testMessageBuilderVariableAssignment(@TempDir Path tempDir) throws IOException {
Path dir = tempDir.resolve("com/example");
Files.createDirectories(dir);
Files.writeString(dir.resolve("MyService.java"),
"package com.example;\n" +
"import org.springframework.messaging.support.MessageBuilder;\n" +
"import org.springframework.messaging.Message;\n" +
"import org.springframework.statemachine.StateMachine;\n" +
"public class MyService {\n" +
" private StateMachine<String, String> stateMachine;\n" +
" private void a(MyInterface myEvent) {\n" +
" Message<MyInterface> msg = MessageBuilder.withPayload(myEvent).setHeader(\"k\", \"v\").build();\n" +
" stateMachine.sendEvent(Mono.just(msg));\n" +
" }\n" +
"}\n");
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
GenericEventDetector detector = new GenericEventDetector(context, new ConstantResolver(), List.of());
CompilationUnit cu = context.getCompilationUnits().iterator().next();
List<TriggerPoint> triggers = detector.detect(cu);
assertThat(triggers).hasSize(1);
assertThat(triggers.get(0).getEvent()).isEqualTo("myEvent");
assertThat(triggers.get(0).getMethodName()).isEqualTo("a");
}
}

View File

@@ -47,9 +47,7 @@ class AstTransitionParserTest {
.isEqualTo(TransitionType.EXTERNAL);
assertThat(transition.getSourceStates()).extracting(State::toString).containsExactly("CREATED");
assertThat(transition.getTargetStates()).extracting(State::toString).containsExactly("PAID");
assertThat(transition)
.extracting(Transition::getEvent)
.isEqualTo("PAY");
assertThat(transition.getEvent().toString()).isEqualTo("PAY");
}
@Test
@@ -211,8 +209,8 @@ class AstTransitionParserTest {
List<Transition> transitions = AstTransitionParser.parseTransitions(method, context);
assertThat(transitions).hasSize(2);
assertThat(transitions.get(0).getEvent()).isEqualTo("E1");
assertThat(transitions.get(1).getEvent()).isEqualTo("E2");
assertThat(transitions.get(0).getEvent().toString()).isEqualTo("E1");
assertThat(transitions.get(1).getEvent().toString()).isEqualTo("E2");
}
@Test

View File

@@ -58,8 +58,8 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(childTd);
assertThat(transitions).hasSize(2);
assertThat(transitions).anyMatch(t -> t.getEvent().equals("BASE_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().equals("CHILD_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("BASE_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("CHILD_E1"));
}
@Test
@@ -93,7 +93,7 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(childTd);
assertThat(transitions).hasSize(1);
assertThat(transitions.get(0).getEvent()).isEqualTo("OVERRIDDEN_E1");
assertThat(transitions.get(0).getEvent().toString()).isEqualTo("OVERRIDDEN_E1");
}
@Test
@@ -119,7 +119,7 @@ class StateMachineAggregatorTest {
assertThat(transitions).hasSize(1);
assertThat(transitions.get(0).getSourceStates()).extracting(State::toString).containsExactly("START");
assertThat(transitions.get(0).getTargetStates()).extracting(State::toString).containsExactly("END");
assertThat(transitions.get(0).getEvent()).isEqualTo("GO");
assertThat(transitions.get(0).getEvent().toString()).isEqualTo("GO");
}
@Test
@@ -143,8 +143,8 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(td);
assertThat(transitions).hasSize(2);
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E2"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E2"));
}
@Test
@@ -241,9 +241,9 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(childTd);
assertThat(transitions).hasSize(3);
assertThat(transitions).anyMatch(t -> t.getEvent().equals("GP_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().equals("P_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().equals("C_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("GP_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("P_E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("C_E1"));
}
@Test
@@ -267,8 +267,8 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(td);
assertThat(transitions).hasSize(2);
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E2"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E2"));
}
@Test
@@ -381,7 +381,7 @@ class StateMachineAggregatorTest {
// It might not find ExternalTransitions.addCommon unless it's static or we handle imports.
// Let's see if it works or if we need to improve the aggregator.
assertThat(transitions).hasSize(1);
assertThat(transitions.get(0).getEvent()).isEqualTo("EXT_E1");
assertThat(transitions.get(0).getEvent().toString()).isEqualTo("EXT_E1");
}
@Test
@@ -408,8 +408,8 @@ class StateMachineAggregatorTest {
// Should not crash and should find both transitions
assertThat(transitions).hasSize(2);
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E2"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E2"));
}
@Test
@@ -434,7 +434,7 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(td);
assertThat(transitions).hasSize(1);
assertThat(transitions.get(0).getEvent()).isEqualTo("TRY_E1");
assertThat(transitions.get(0).getEvent().toString()).isEqualTo("TRY_E1");
}
@Test
@@ -536,8 +536,8 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(td);
assertThat(transitions).hasSize(2);
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().equals("E2"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E1"));
assertThat(transitions).anyMatch(t -> t.getEvent().toString().equals("E2"));
}
@Test
@@ -585,7 +585,7 @@ class StateMachineAggregatorTest {
List<Transition> transitions = aggregator.aggregateTransitions(td);
assertThat(transitions).hasSize(1);
assertThat(transitions.get(0).getEvent()).isEqualTo("E1");
assertThat(transitions.get(0).getEvent().toString()).isEqualTo("E1");
}
private void writeClass(String name, String source) throws IOException {

View File

@@ -20,7 +20,7 @@ class JsonExporterTest {
transition.setType(TransitionType.EXTERNAL);
transition.setSourceStates(List.of(State.of("S1")));
transition.setTargetStates(List.of(State.of("S2")));
transition.setEvent("E1");
transition.setEvent(click.kamil.springstatemachineexporter.model.Event.of("E1"));
AnalysisResult result = AnalysisResult.builder()
.name("TestSM")
@@ -33,7 +33,7 @@ class JsonExporterTest {
assertThat(json)
.contains("\"name\" : \"TestSM\"")
.contains("\"event\" : \"E1\"")
.contains("\"rawName\" : \"E1\"")
.contains("\"rawName\" : \"S1\"")
.contains("\"rawName\" : \"S2\"");
}

View File

@@ -0,0 +1,67 @@
package click.kamil.springstatemachineexporter.exporter;
import click.kamil.springstatemachineexporter.analysis.model.AnalysisResult;
import click.kamil.springstatemachineexporter.model.Event;
import click.kamil.springstatemachineexporter.model.State;
import click.kamil.springstatemachineexporter.model.Transition;
import click.kamil.springstatemachineexporter.model.TransitionType;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
class PlantUmlTest {
@Test
void shouldFormatTransitionsWithDifferentEnumFormats() {
// Given
PlantUml exporter = new PlantUml();
Transition transition = new Transition();
transition.setType(TransitionType.EXTERNAL);
transition.setSourceStates(List.of(State.of("States.S1", "com.example.States.S1")));
transition.setTargetStates(List.of(State.of("States.S2", "com.example.States.S2")));
transition.setEvent(Event.of("Events.E1", "com.example.Events.E1"));
AnalysisResult result = AnalysisResult.builder()
.name("TestSM")
.transitions(List.of(transition))
.startStates(Set.of("States.S1"))
.endStates(Set.of("States.S2"))
.build();
// Test FN (Full Name - Default)
ExportOptions optionsFn = ExportOptions.builder()
.stateFormat(EnumFormat.fn)
.eventFormat(EnumFormat.fn)
.build();
String pumlFn = exporter.export(result, optionsFn);
assertThat(pumlFn)
.contains("States.S1 -[#")
.contains("]-> States.S2")
.contains(" : Events.E1");
// Test FQN (Fully Qualified Name)
ExportOptions optionsFqn = ExportOptions.builder()
.stateFormat(EnumFormat.fqn)
.eventFormat(EnumFormat.fqn)
.build();
String pumlFqn = exporter.export(result, optionsFqn);
assertThat(pumlFqn)
.contains("com.example.States.S1 -[#")
.contains("]-> com.example.States.S2")
.contains(" : com.example.Events.E1");
// Test SN (Short Name)
ExportOptions optionsSn = ExportOptions.builder()
.stateFormat(EnumFormat.sn)
.eventFormat(EnumFormat.sn)
.build();
String pumlSn = exporter.export(result, optionsSn);
assertThat(pumlSn)
.contains("S1 -[#")
.contains("]-> S2")
.contains(" : E1");
}
}

View File

@@ -27,7 +27,7 @@ public class DeferredProfileResolutionTest {
assertThat(result.getStartStates()).containsExactly("START_RESOLVED");
Transition t = result.getTransitions().get(0);
assertThat(t.getEvent()).isEqualTo("RESOLVED_EVENT");
assertThat(t.getEvent().fullIdentifier()).isEqualTo("RESOLVED_EVENT");
assertThat(t.getSourceStates().get(0).fullIdentifier()).isEqualTo("START_RESOLVED");
}
@@ -53,7 +53,7 @@ public class DeferredProfileResolutionTest {
State s2 = State.of("END", "END");
Transition t1 = new Transition();
t1.setEvent("${app.event.name:RESOLVED_EVENT}");
t1.setEvent(click.kamil.springstatemachineexporter.model.Event.of("${app.event.name:RESOLVED_EVENT}"));
t1.setSourceStates(List.of(s1));
t1.setTargetStates(List.of(s2));

View File

@@ -0,0 +1,55 @@
package click.kamil.springstatemachineexporter.service;
import click.kamil.springstatemachineexporter.exporter.StateMachineExporter;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class ExportServiceEmptyStateTest {
@TempDir
Path tempDir;
@Test
void shouldSkipEmptyStateMachineConfigurations() throws Exception {
// Arrange
Path inputDir = tempDir.resolve("input");
Files.createDirectories(inputDir);
Path outputDir = tempDir.resolve("output");
Files.createDirectories(outputDir);
String code = """
package com.example;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
@Configuration
@EnableStateMachine
public class EmptyStateMachineConfig extends StateMachineConfigurerAdapter<String, String> {
// No configurers overridden, meaning 0 states and 0 transitions parsed
}
""";
Files.writeString(inputDir.resolve("EmptyStateMachineConfig.java"), code);
ExportService exportService = new ExportService(Collections.emptyList()); // No exporters needed, checking if it generates anything (it generates JSON natively)
// Act
exportService.runExporter(inputDir, outputDir, List.of("plantuml"), true);
// Assert
// The output directory should have no files created in it
long fileCount = Files.walk(outputDir)
.filter(Files::isRegularFile)
.count();
assertThat(fileCount).isZero();
}
}

View File

@@ -23,7 +23,7 @@ class JsonImportServiceTest {
"type" : "EXTERNAL",
"sourceStates" : [ { "rawName" : "S1", "fullIdentifier" : "S1" } ],
"targetStates" : [ { "rawName" : "S2", "fullIdentifier" : "S2" } ],
"event" : "E1"
"event" : { "rawName" : "E1", "fullIdentifier" : "E1" }
} ],
"startStates" : [ "S1" ],
"endStates" : [ "S2" ]
@@ -36,7 +36,7 @@ class JsonImportServiceTest {
assertThat(model.getName()).isEqualTo("ImportedSM");
assertThat(model.getTransitions()).hasSize(1);
assertThat(model.getTransitions().get(0).getEvent()).isEqualTo("E1");
assertThat(model.getTransitions().get(0).getEvent().rawName()).isEqualTo("E1");
assertThat(model.getStartStates()).containsExactly("S1");
assertThat(model.getEndStates()).containsExactly("S2");
}

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.STATE11",
"fullIdentifier" : "States.STATE11"
} ],
"event" : "Events.EVENT10",
"event" : {
"rawName" : "Events.EVENT10",
"fullIdentifier" : "Events.EVENT10"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.STATE12",
"fullIdentifier" : "States.STATE12"
} ],
"event" : "Events.EVENT11",
"event" : {
"rawName" : "Events.EVENT11",
"fullIdentifier" : "Events.EVENT11"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.STATE13",
"fullIdentifier" : "States.STATE13"
} ],
"event" : "Events.EVENT12",
"event" : {
"rawName" : "Events.EVENT12",
"fullIdentifier" : "Events.EVENT12"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.STATE14",
"fullIdentifier" : "States.STATE14"
} ],
"event" : "Events.EVENT13",
"event" : {
"rawName" : "Events.EVENT13",
"fullIdentifier" : "Events.EVENT13"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.STATE15",
"fullIdentifier" : "States.STATE15"
} ],
"event" : "Events.EVENT14",
"event" : {
"rawName" : "Events.EVENT14",
"fullIdentifier" : "Events.EVENT14"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATE16",
"fullIdentifier" : "States.STATE16"
} ],
"event" : "Events.EVENT15",
"event" : {
"rawName" : "Events.EVENT15",
"fullIdentifier" : "Events.EVENT15"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -7,6 +7,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/SecurityInterceptor.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 17
}, {
"event" : "PLACE_ORDER",
@@ -15,6 +16,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 16
}, {
"event" : "CANCEL_ORDER",
@@ -23,6 +25,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 21
}, {
"event" : "PAY_ORDER",
@@ -31,6 +34,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/ReactivePaymentService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
}, {
"event" : "SHIP_ORDER",
@@ -39,6 +43,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ShippingJmsListener.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 17
}, {
"event" : "RETURN_ORDER",
@@ -47,6 +52,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ReturnsRabbitListener.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 17
} ],
"entryPoints" : [ {
@@ -178,8 +184,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 16
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "NEW",
"targetState" : "CHECK_AVAILABILITY",
"event" : "PLACE_ORDER"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -205,8 +218,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 21
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "PAID",
"targetState" : "CANCELLED",
"event" : "CANCEL_ORDER"
} ]
}, {
"entryPoint" : {
"type" : "CUSTOM",
@@ -227,8 +247,11 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/SecurityInterceptor.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 17
}
},
"contextMachineId" : null,
"matchedTransitions" : [ ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -254,8 +277,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/ReactivePaymentService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "PENDING_PAYMENT",
"targetState" : "PAID",
"event" : "PAY_ORDER"
} ]
}, {
"entryPoint" : {
"type" : "JMS",
@@ -281,8 +311,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ShippingJmsListener.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 17
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "PAID",
"targetState" : "SHIPPED",
"event" : "SHIP_ORDER"
} ]
}, {
"entryPoint" : {
"type" : "RABBIT",
@@ -308,8 +345,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ReturnsRabbitListener.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 17
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "DELIVERED",
"targetState" : "RETURNED",
"event" : "RETURN_ORDER"
} ]
} ],
"properties" : {
"default" : { }
@@ -328,7 +372,10 @@
"rawName" : "\"CHECK_AVAILABILITY\"",
"fullIdentifier" : "CHECK_AVAILABILITY"
} ],
"event" : "PLACE_ORDER",
"event" : {
"rawName" : "OrderEvents.PLACE",
"fullIdentifier" : "PLACE_ORDER"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -377,7 +424,10 @@
"rawName" : "\"PAID\"",
"fullIdentifier" : "PAID"
} ],
"event" : "PAY_ORDER",
"event" : {
"rawName" : "OrderEvents.PAY",
"fullIdentifier" : "PAY_ORDER"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -391,7 +441,10 @@
"rawName" : "\"SHIPPED\"",
"fullIdentifier" : "SHIPPED"
} ],
"event" : "SHIP_ORDER",
"event" : {
"rawName" : "OrderEvents.SHIP",
"fullIdentifier" : "SHIP_ORDER"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -405,7 +458,10 @@
"rawName" : "\"DELIVERED\"",
"fullIdentifier" : "DELIVERED"
} ],
"event" : "FINALIZE",
"event" : {
"rawName" : "\"FINALIZE\"",
"fullIdentifier" : "FINALIZE"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -419,7 +475,10 @@
"rawName" : "\"CANCELLED\"",
"fullIdentifier" : "CANCELLED"
} ],
"event" : "CANCEL_ORDER",
"event" : {
"rawName" : "OrderEvents.CANCEL",
"fullIdentifier" : "CANCEL_ORDER"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -433,7 +492,10 @@
"rawName" : "\"RETURNED\"",
"fullIdentifier" : "RETURNED"
} ],
"event" : "RETURN_ORDER",
"event" : {
"rawName" : "OrderEvents.RETURN",
"fullIdentifier" : "RETURN_ORDER"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -7,6 +7,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 34
}, {
"event" : "AUDIT_EVENT",
@@ -15,6 +16,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/AuditInterceptor.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 16
}, {
"event" : "EXTERNAL_TRIGGER",
@@ -23,6 +25,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 19
}, {
"event" : "SUBMIT_EVENT",
@@ -31,6 +34,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 20
}, {
"event" : "CANCEL_EVENT",
@@ -39,6 +43,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 25
}, {
"event" : "[LIFECYCLE:RESTORE]",
@@ -47,6 +52,7 @@
"sourceFile" : null,
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 29
}, {
"event" : "REACTIVE_EVENT",
@@ -55,6 +61,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/ReactiveOrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
} ],
"entryPoints" : [ {
@@ -152,8 +159,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 19
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "PROCESSING",
"event" : "EXTERNAL_TRIGGER"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -175,8 +189,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 20
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "PROCESSING",
"event" : "SUBMIT_EVENT"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -198,8 +219,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 25
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "PROCESSING",
"targetState" : "CANCELLED",
"event" : "CANCEL_EVENT"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -221,8 +249,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 34
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "PROCESSING",
"targetState" : "COMPLETED",
"event" : "FINISH"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -248,8 +283,11 @@
"sourceFile" : null,
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 29
}
},
"contextMachineId" : "orderId",
"matchedTransitions" : [ ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -275,8 +313,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/ReactiveOrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "PROCESSING",
"event" : "REACTIVE_EVENT"
} ]
}, {
"entryPoint" : {
"type" : "CUSTOM",
@@ -297,8 +342,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/AuditInterceptor.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 16
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "START",
"event" : "AUDIT_EVENT"
} ]
} ],
"properties" : {
"default" : {
@@ -322,7 +374,10 @@
"rawName" : "\"PROCESSING\"",
"fullIdentifier" : "PROCESSING"
} ],
"event" : "SUBMIT_EVENT",
"event" : {
"rawName" : "MyEvents.SUBMIT",
"fullIdentifier" : "SUBMIT_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -336,7 +391,10 @@
"rawName" : "\"COMPLETED\"",
"fullIdentifier" : "COMPLETED"
} ],
"event" : "FINISH",
"event" : {
"rawName" : "\"FINISH\"",
"fullIdentifier" : "FINISH"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -350,7 +408,10 @@
"rawName" : "\"CANCELLED\"",
"fullIdentifier" : "CANCELLED"
} ],
"event" : "CANCEL_EVENT",
"event" : {
"rawName" : "MyEvents.CANCEL",
"fullIdentifier" : "CANCEL_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -364,7 +425,10 @@
"rawName" : "\"PROCESSING\"",
"fullIdentifier" : "PROCESSING"
} ],
"event" : "REACTIVE_EVENT",
"event" : {
"rawName" : "\"REACTIVE_EVENT\"",
"fullIdentifier" : "REACTIVE_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -378,7 +442,10 @@
"rawName" : "\"START\"",
"fullIdentifier" : "START"
} ],
"event" : "AUDIT_EVENT",
"event" : {
"rawName" : "\"AUDIT_EVENT\"",
"fullIdentifier" : "AUDIT_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -392,7 +459,10 @@
"rawName" : "\"PROCESSING\"",
"fullIdentifier" : "PROCESSING"
} ],
"event" : "EXTERNAL_TRIGGER",
"event" : {
"rawName" : "\"EXTERNAL_TRIGGER\"",
"fullIdentifier" : "EXTERNAL_TRIGGER"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -7,6 +7,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 34
}, {
"event" : "AUDIT_EVENT",
@@ -15,6 +16,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/AuditInterceptor.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 16
}, {
"event" : "EXTERNAL_TRIGGER",
@@ -23,6 +25,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 19
}, {
"event" : "SUBMIT_EVENT",
@@ -31,6 +34,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 20
}, {
"event" : "CANCEL_EVENT",
@@ -39,6 +43,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 25
}, {
"event" : "[LIFECYCLE:RESTORE]",
@@ -47,6 +52,7 @@
"sourceFile" : null,
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 29
}, {
"event" : "REACTIVE_EVENT",
@@ -55,6 +61,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/ReactiveOrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
} ],
"entryPoints" : [ {
@@ -152,8 +159,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 19
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "PROCESSING",
"event" : "EXTERNAL_TRIGGER"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -175,8 +189,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 20
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "PROCESSING",
"event" : "SUBMIT_EVENT"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -198,8 +219,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/OrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 25
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "PROCESSING",
"targetState" : "CANCELLED",
"event" : "CANCEL_EVENT"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -221,8 +249,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 34
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "PROCESSING",
"targetState" : "COMPLETED",
"event" : "FINISH"
} ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -248,8 +283,11 @@
"sourceFile" : null,
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 29
}
},
"contextMachineId" : "orderId",
"matchedTransitions" : [ ]
}, {
"entryPoint" : {
"type" : "REST",
@@ -275,8 +313,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/ReactiveOrderService.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "PROCESSING",
"event" : "REACTIVE_EVENT"
} ]
}, {
"entryPoint" : {
"type" : "CUSTOM",
@@ -297,8 +342,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/AuditInterceptor.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 16
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "START",
"event" : "AUDIT_EVENT"
} ]
} ],
"properties" : {
"default" : {
@@ -322,7 +374,10 @@
"rawName" : "\"PROCESSING\"",
"fullIdentifier" : "PROCESSING"
} ],
"event" : "SUBMIT_EVENT",
"event" : {
"rawName" : "MyEvents.SUBMIT",
"fullIdentifier" : "SUBMIT_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -336,7 +391,10 @@
"rawName" : "\"COMPLETED\"",
"fullIdentifier" : "COMPLETED"
} ],
"event" : "FINISH",
"event" : {
"rawName" : "\"FINISH\"",
"fullIdentifier" : "FINISH"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -350,7 +408,10 @@
"rawName" : "\"CANCELLED\"",
"fullIdentifier" : "CANCELLED"
} ],
"event" : "CANCEL_EVENT",
"event" : {
"rawName" : "MyEvents.CANCEL",
"fullIdentifier" : "CANCEL_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -364,7 +425,10 @@
"rawName" : "\"PROCESSING\"",
"fullIdentifier" : "PROCESSING"
} ],
"event" : "REACTIVE_EVENT",
"event" : {
"rawName" : "\"REACTIVE_EVENT\"",
"fullIdentifier" : "REACTIVE_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -378,7 +442,10 @@
"rawName" : "\"START\"",
"fullIdentifier" : "START"
} ],
"event" : "AUDIT_EVENT",
"event" : {
"rawName" : "\"AUDIT_EVENT\"",
"fullIdentifier" : "AUDIT_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -392,7 +459,10 @@
"rawName" : "\"PROCESSING\"",
"fullIdentifier" : "PROCESSING"
} ],
"event" : "EXTERNAL_TRIGGER",
"event" : {
"rawName" : "\"EXTERNAL_TRIGGER\"",
"fullIdentifier" : "EXTERNAL_TRIGGER"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.STATE11",
"fullIdentifier" : "States.STATE11"
} ],
"event" : "Events.EVENT10",
"event" : {
"rawName" : "Events.EVENT10",
"fullIdentifier" : "Events.EVENT10"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.STATE12",
"fullIdentifier" : "States.STATE12"
} ],
"event" : "Events.EVENT11",
"event" : {
"rawName" : "Events.EVENT11",
"fullIdentifier" : "Events.EVENT11"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.STATE13",
"fullIdentifier" : "States.STATE13"
} ],
"event" : "Events.EVENT12",
"event" : {
"rawName" : "Events.EVENT12",
"fullIdentifier" : "Events.EVENT12"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.STATE14",
"fullIdentifier" : "States.STATE14"
} ],
"event" : "Events.EVENT13",
"event" : {
"rawName" : "Events.EVENT13",
"fullIdentifier" : "Events.EVENT13"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.STATE15",
"fullIdentifier" : "States.STATE15"
} ],
"event" : "Events.EVENT14",
"event" : {
"rawName" : "Events.EVENT14",
"fullIdentifier" : "Events.EVENT14"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATE16",
"fullIdentifier" : "States.STATE16"
} ],
"event" : "Events.EVENT15",
"event" : {
"rawName" : "Events.EVENT15",
"fullIdentifier" : "Events.EVENT15"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -232,7 +277,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -246,7 +294,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -260,7 +311,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -274,7 +328,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -288,7 +345,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -302,7 +362,10 @@
"rawName" : "States.STATEY",
"fullIdentifier" : "States.STATEY"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -764,7 +827,10 @@
"rawName" : "States.STATE_EXTRA_1",
"fullIdentifier" : "States.STATE_EXTRA_1"
} ],
"event" : "Events.EVENTX",
"event" : {
"rawName" : "Events.EVENTX",
"fullIdentifier" : "Events.EVENTX"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -813,7 +879,10 @@
"rawName" : "States.STATE_EXTRA_3",
"fullIdentifier" : "States.STATE_EXTRA_3"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -827,7 +896,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -841,7 +913,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.STATE11",
"fullIdentifier" : "States.STATE11"
} ],
"event" : "Events.EVENT10",
"event" : {
"rawName" : "Events.EVENT10",
"fullIdentifier" : "Events.EVENT10"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.STATE12",
"fullIdentifier" : "States.STATE12"
} ],
"event" : "Events.EVENT11",
"event" : {
"rawName" : "Events.EVENT11",
"fullIdentifier" : "Events.EVENT11"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.STATE13",
"fullIdentifier" : "States.STATE13"
} ],
"event" : "Events.EVENT12",
"event" : {
"rawName" : "Events.EVENT12",
"fullIdentifier" : "Events.EVENT12"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.STATE14",
"fullIdentifier" : "States.STATE14"
} ],
"event" : "Events.EVENT13",
"event" : {
"rawName" : "Events.EVENT13",
"fullIdentifier" : "Events.EVENT13"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.STATE15",
"fullIdentifier" : "States.STATE15"
} ],
"event" : "Events.EVENT14",
"event" : {
"rawName" : "Events.EVENT14",
"fullIdentifier" : "Events.EVENT14"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATE16",
"fullIdentifier" : "States.STATE16"
} ],
"event" : "Events.EVENT15",
"event" : {
"rawName" : "Events.EVENT15",
"fullIdentifier" : "Events.EVENT15"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -232,7 +277,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -246,7 +294,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -260,7 +311,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -274,7 +328,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -288,7 +345,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -302,7 +362,10 @@
"rawName" : "States.STATEY",
"fullIdentifier" : "States.STATEY"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -764,7 +827,10 @@
"rawName" : "States.STATE_EXTRA_1_1",
"fullIdentifier" : "States.STATE_EXTRA_1_1"
} ],
"event" : "Events.EVENT_1_1",
"event" : {
"rawName" : "Events.EVENT_1_1",
"fullIdentifier" : "Events.EVENT_1_1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -813,7 +879,10 @@
"rawName" : "States.STATE_EXTRA_1",
"fullIdentifier" : "States.STATE_EXTRA_1"
} ],
"event" : "Events.EVENT_1_2",
"event" : {
"rawName" : "Events.EVENT_1_2",
"fullIdentifier" : "Events.EVENT_1_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -827,7 +896,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -841,7 +913,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -855,7 +930,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "States.FORK",
"fullIdentifier" : "States.FORK"
} ],
"event" : "Events.TO_FORK",
"event" : {
"rawName" : "Events.TO_FORK",
"fullIdentifier" : "Events.TO_FORK"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -53,7 +56,10 @@
"rawName" : "States.REGION1_STATE2",
"fullIdentifier" : "States.REGION1_STATE2"
} ],
"event" : "Events.R1_NEXT",
"event" : {
"rawName" : "Events.R1_NEXT",
"fullIdentifier" : "Events.R1_NEXT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -67,7 +73,10 @@
"rawName" : "States.REGION2_STATE2",
"fullIdentifier" : "States.REGION2_STATE2"
} ],
"event" : "Events.R2_NEXT",
"event" : {
"rawName" : "Events.R2_NEXT",
"fullIdentifier" : "Events.R2_NEXT"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -98,7 +107,10 @@
"rawName" : "States.END",
"fullIdentifier" : "States.END"
} ],
"event" : "Events.TO_END",
"event" : {
"rawName" : "Events.TO_END",
"fullIdentifier" : "Events.TO_END"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATEY",
"fullIdentifier" : "States.STATEY"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -358,7 +403,10 @@
"rawName" : "States.STATE_EXTRA_2",
"fullIdentifier" : "States.STATE_EXTRA_2"
} ],
"event" : "Events.EVENT_1_2",
"event" : {
"rawName" : "Events.EVENT_1_2",
"fullIdentifier" : "Events.EVENT_1_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -372,7 +420,10 @@
"rawName" : "States.STATE_EXTRA_3",
"fullIdentifier" : "States.STATE_EXTRA_3"
} ],
"event" : "Events.EVENT_1_2",
"event" : {
"rawName" : "Events.EVENT_1_2",
"fullIdentifier" : "Events.EVENT_1_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -386,7 +437,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATEY",
"fullIdentifier" : "States.STATEY"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -358,7 +403,10 @@
"rawName" : "States.STATE_EXTRA_1",
"fullIdentifier" : "States.STATE_EXTRA_1"
} ],
"event" : "Events.EVENT_1_2",
"event" : {
"rawName" : "Events.EVENT_1_2",
"fullIdentifier" : "Events.EVENT_1_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -372,7 +420,10 @@
"rawName" : "States.STATE_EXTRA_2",
"fullIdentifier" : "States.STATE_EXTRA_2"
} ],
"event" : "Events.EVENT_1_3",
"event" : {
"rawName" : "Events.EVENT_1_3",
"fullIdentifier" : "Events.EVENT_1_3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -386,7 +437,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -400,7 +454,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -7,6 +7,7 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/inheritance/service/ProcessingServiceImpl.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 15
} ],
"entryPoints" : [ {
@@ -53,8 +54,15 @@
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/inheritance/service/ProcessingServiceImpl.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 15
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "START",
"targetState" : "WORKING",
"event" : "INHERITED_SUBMIT"
} ]
} ],
"properties" : {
"default" : { }
@@ -73,7 +81,10 @@
"rawName" : "\"WORKING\"",
"fullIdentifier" : "WORKING"
} ],
"event" : "INHERITED_SUBMIT",
"event" : {
"rawName" : "\"INHERITED_SUBMIT\"",
"fullIdentifier" : "INHERITED_SUBMIT"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "OrderStates.PAID",
"fullIdentifier" : "OrderStates.PAID"
} ],
"event" : "OrderEvents.PAY",
"event" : {
"rawName" : "OrderEvents.PAY",
"fullIdentifier" : "OrderEvents.PAY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "OrderStates.FULFILLED",
"fullIdentifier" : "OrderStates.FULFILLED"
} ],
"event" : "OrderEvents.FULFILL",
"event" : {
"rawName" : "OrderEvents.FULFILL",
"fullIdentifier" : "OrderEvents.FULFILL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "OrderStates.CANCELED",
"fullIdentifier" : "OrderStates.CANCELED"
} ],
"event" : "OrderEvents.CANCEL",
"event" : {
"rawName" : "OrderEvents.CANCEL",
"fullIdentifier" : "OrderEvents.CANCEL"
},
"guard" : {
"expression" : "new Guard<OrderStates,OrderEvents>(){\n @Override public boolean evaluate( StateContext<OrderStates,OrderEvents> context){\n return false;\n }\n}\n",
"isLambda" : true,
@@ -71,7 +80,10 @@
"rawName" : "OrderStates.CANCELED",
"fullIdentifier" : "OrderStates.CANCELED"
} ],
"event" : "OrderEvents.CANCEL",
"event" : {
"rawName" : "OrderEvents.CANCEL",
"fullIdentifier" : "OrderEvents.CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -82,7 +94,10 @@
"fullIdentifier" : "OrderStates.SUBMITTED"
} ],
"targetStates" : [ ],
"event" : "OrderEvents.ABCD",
"event" : {
"rawName" : "OrderEvents.ABCD",
"fullIdentifier" : "OrderEvents.ABCD"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -96,7 +111,10 @@
"rawName" : "OrderStates.PAID1",
"fullIdentifier" : "OrderStates.PAID1"
} ],
"event" : "OrderEvents.ABCD",
"event" : {
"rawName" : "OrderEvents.ABCD",
"fullIdentifier" : "OrderEvents.ABCD"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -212,7 +230,10 @@
"fullIdentifier" : "OrderStates.PAID2"
} ],
"targetStates" : [ ],
"event" : "OrderEvents.ABCD",
"event" : {
"rawName" : "OrderEvents.ABCD",
"fullIdentifier" : "OrderEvents.ABCD"
},
"guard" : null,
"actions" : [ {
"expression" : "new Action<OrderStates,OrderEvents>(){\n @Override public void execute( StateContext<OrderStates,OrderEvents> context){\n }\n}\n",

View File

@@ -7,6 +7,7 @@
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 40
}, {
"event" : "ORDER_EVENT",
@@ -15,6 +16,7 @@
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 52
} ],
"entryPoints" : [ {
@@ -100,8 +102,15 @@
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 40
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "INIT",
"targetState" : "BUSY",
"event" : "SUBMIT"
} ]
} ],
"properties" : {
"default" : { }
@@ -120,7 +129,10 @@
"rawName" : "\"BUSY\"",
"fullIdentifier" : "BUSY"
} ],
"event" : "SUBMIT",
"event" : {
"rawName" : "\"SUBMIT\"",
"fullIdentifier" : "SUBMIT"
},
"guard" : null,
"actions" : [ {
"expression" : "loggingAction()",
@@ -141,7 +153,10 @@
"rawName" : "\"DONE\"",
"fullIdentifier" : "DONE"
} ],
"event" : "ORDER_EVENT",
"event" : {
"rawName" : "\"ORDER_EVENT\"",
"fullIdentifier" : "ORDER_EVENT"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.STATE11",
"fullIdentifier" : "States.STATE11"
} ],
"event" : "Events.EVENT10",
"event" : {
"rawName" : "Events.EVENT10",
"fullIdentifier" : "Events.EVENT10"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.STATE12",
"fullIdentifier" : "States.STATE12"
} ],
"event" : "Events.EVENT11",
"event" : {
"rawName" : "Events.EVENT11",
"fullIdentifier" : "Events.EVENT11"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.STATE13",
"fullIdentifier" : "States.STATE13"
} ],
"event" : "Events.EVENT12",
"event" : {
"rawName" : "Events.EVENT12",
"fullIdentifier" : "Events.EVENT12"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.STATE14",
"fullIdentifier" : "States.STATE14"
} ],
"event" : "Events.EVENT13",
"event" : {
"rawName" : "Events.EVENT13",
"fullIdentifier" : "Events.EVENT13"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.STATE15",
"fullIdentifier" : "States.STATE15"
} ],
"event" : "Events.EVENT14",
"event" : {
"rawName" : "Events.EVENT14",
"fullIdentifier" : "Events.EVENT14"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATE16",
"fullIdentifier" : "States.STATE16"
} ],
"event" : "Events.EVENT15",
"event" : {
"rawName" : "Events.EVENT15",
"fullIdentifier" : "Events.EVENT15"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -232,7 +277,10 @@
"rawName" : "States.STATEY",
"fullIdentifier" : "States.STATEY"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -694,7 +742,10 @@
"rawName" : "States.STATE_EXTRA_1",
"fullIdentifier" : "States.STATE_EXTRA_1"
} ],
"event" : "Events.EVENTX",
"event" : {
"rawName" : "Events.EVENTX",
"fullIdentifier" : "Events.EVENTX"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -7,6 +7,7 @@
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
} ],
"entryPoints" : [ {
@@ -65,8 +66,15 @@
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
"sourceModule" : null,
"stateMachineId" : null,
"sourceState" : null,
"lineNumber" : 18
}
},
"contextMachineId" : null,
"matchedTransitions" : [ {
"sourceState" : "NEW",
"targetState" : "PROCESSING",
"event" : "SUBMIT"
} ]
} ],
"properties" : {
"default" : { }
@@ -85,7 +93,10 @@
"rawName" : "\"PROCESSING\"",
"fullIdentifier" : "PROCESSING"
} ],
"event" : "SUBMIT",
"event" : {
"rawName" : "\"SUBMIT\"",
"fullIdentifier" : "SUBMIT"
},
"guard" : null,
"actions" : [ {
"expression" : "processAction()",
@@ -106,7 +117,10 @@
"rawName" : "\"COMPLETED\"",
"fullIdentifier" : "COMPLETED"
} ],
"event" : "FINISH",
"event" : {
"rawName" : "\"FINISH\"",
"fullIdentifier" : "FINISH"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "OrderStates.PAID",
"fullIdentifier" : "OrderStates.PAID"
} ],
"event" : "OrderEvents.PAY",
"event" : {
"rawName" : "OrderEvents.PAY",
"fullIdentifier" : "OrderEvents.PAY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "OrderStates.FULFILLED",
"fullIdentifier" : "OrderStates.FULFILLED"
} ],
"event" : "OrderEvents.FULFILL",
"event" : {
"rawName" : "OrderEvents.FULFILL",
"fullIdentifier" : "OrderEvents.FULFILL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "OrderStates.CANCELED",
"fullIdentifier" : "OrderStates.CANCELED"
} ],
"event" : "OrderEvents.CANCEL",
"event" : {
"rawName" : "OrderEvents.CANCEL",
"fullIdentifier" : "OrderEvents.CANCEL"
},
"guard" : {
"expression" : "new Guard<OrderStates,OrderEvents>(){\n @Override public boolean evaluate( StateContext<OrderStates,OrderEvents> context){\n return false;\n }\n}\n",
"isLambda" : true,
@@ -71,7 +80,10 @@
"rawName" : "OrderStates.CANCELED",
"fullIdentifier" : "OrderStates.CANCELED"
} ],
"event" : "OrderEvents.CANCEL",
"event" : {
"rawName" : "OrderEvents.CANCEL",
"fullIdentifier" : "OrderEvents.CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -82,7 +94,10 @@
"fullIdentifier" : "OrderStates.SUBMITTED"
} ],
"targetStates" : [ ],
"event" : "OrderEvents.ABCD",
"event" : {
"rawName" : "OrderEvents.ABCD",
"fullIdentifier" : "OrderEvents.ABCD"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -233,7 +248,10 @@
"fullIdentifier" : "OrderStates.PAID1"
} ],
"targetStates" : [ ],
"event" : "OrderEvents.ABCD",
"event" : {
"rawName" : "OrderEvents.ABCD",
"fullIdentifier" : "OrderEvents.ABCD"
},
"guard" : null,
"actions" : [ {
"expression" : "new Action<OrderStates,OrderEvents>(){\n @Override public void execute( StateContext<OrderStates,OrderEvents> context){\n ;\n }\n}\n",

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.STATE11",
"fullIdentifier" : "States.STATE11"
} ],
"event" : "Events.EVENT10",
"event" : {
"rawName" : "Events.EVENT10",
"fullIdentifier" : "Events.EVENT10"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.STATE12",
"fullIdentifier" : "States.STATE12"
} ],
"event" : "Events.EVENT11",
"event" : {
"rawName" : "Events.EVENT11",
"fullIdentifier" : "Events.EVENT11"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.STATE13",
"fullIdentifier" : "States.STATE13"
} ],
"event" : "Events.EVENT12",
"event" : {
"rawName" : "Events.EVENT12",
"fullIdentifier" : "Events.EVENT12"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.STATE14",
"fullIdentifier" : "States.STATE14"
} ],
"event" : "Events.EVENT13",
"event" : {
"rawName" : "Events.EVENT13",
"fullIdentifier" : "Events.EVENT13"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.STATE15",
"fullIdentifier" : "States.STATE15"
} ],
"event" : "Events.EVENT14",
"event" : {
"rawName" : "Events.EVENT14",
"fullIdentifier" : "Events.EVENT14"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATE16",
"fullIdentifier" : "States.STATE16"
} ],
"event" : "Events.EVENT15",
"event" : {
"rawName" : "Events.EVENT15",
"fullIdentifier" : "Events.EVENT15"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -232,7 +277,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -246,7 +294,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -260,7 +311,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -274,7 +328,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -288,7 +345,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -302,7 +362,10 @@
"rawName" : "States.STATEY",
"fullIdentifier" : "States.STATEY"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -764,7 +827,10 @@
"rawName" : "States.STATE_EXTRA_1",
"fullIdentifier" : "States.STATE_EXTRA_1"
} ],
"event" : "Events.EVENTX",
"event" : {
"rawName" : "Events.EVENTX",
"fullIdentifier" : "Events.EVENTX"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -813,7 +879,10 @@
"rawName" : "States.STATE_EXTRA_3",
"fullIdentifier" : "States.STATE_EXTRA_3"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -827,7 +896,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -841,7 +913,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -22,7 +22,10 @@
"rawName" : "States.STATE2",
"fullIdentifier" : "States.STATE2"
} ],
"event" : "Events.EVENT1",
"event" : {
"rawName" : "Events.EVENT1",
"fullIdentifier" : "Events.EVENT1"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -36,7 +39,10 @@
"rawName" : "States.STATE3",
"fullIdentifier" : "States.STATE3"
} ],
"event" : "Events.EVENT2",
"event" : {
"rawName" : "Events.EVENT2",
"fullIdentifier" : "Events.EVENT2"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -50,7 +56,10 @@
"rawName" : "States.STATE4",
"fullIdentifier" : "States.STATE4"
} ],
"event" : "Events.EVENT3",
"event" : {
"rawName" : "Events.EVENT3",
"fullIdentifier" : "Events.EVENT3"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -64,7 +73,10 @@
"rawName" : "States.STATE5",
"fullIdentifier" : "States.STATE5"
} ],
"event" : "Events.EVENT4",
"event" : {
"rawName" : "Events.EVENT4",
"fullIdentifier" : "Events.EVENT4"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -78,7 +90,10 @@
"rawName" : "States.STATE6",
"fullIdentifier" : "States.STATE6"
} ],
"event" : "Events.EVENT5",
"event" : {
"rawName" : "Events.EVENT5",
"fullIdentifier" : "Events.EVENT5"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -92,7 +107,10 @@
"rawName" : "States.STATE7",
"fullIdentifier" : "States.STATE7"
} ],
"event" : "Events.EVENT6",
"event" : {
"rawName" : "Events.EVENT6",
"fullIdentifier" : "Events.EVENT6"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -106,7 +124,10 @@
"rawName" : "States.STATE8",
"fullIdentifier" : "States.STATE8"
} ],
"event" : "Events.EVENT7",
"event" : {
"rawName" : "Events.EVENT7",
"fullIdentifier" : "Events.EVENT7"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -120,7 +141,10 @@
"rawName" : "States.STATE9",
"fullIdentifier" : "States.STATE9"
} ],
"event" : "Events.EVENT8",
"event" : {
"rawName" : "Events.EVENT8",
"fullIdentifier" : "Events.EVENT8"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -134,7 +158,10 @@
"rawName" : "States.STATE10",
"fullIdentifier" : "States.STATE10"
} ],
"event" : "Events.EVENT9",
"event" : {
"rawName" : "Events.EVENT9",
"fullIdentifier" : "Events.EVENT9"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -148,7 +175,10 @@
"rawName" : "States.STATE11",
"fullIdentifier" : "States.STATE11"
} ],
"event" : "Events.EVENT10",
"event" : {
"rawName" : "Events.EVENT10",
"fullIdentifier" : "Events.EVENT10"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -162,7 +192,10 @@
"rawName" : "States.STATE12",
"fullIdentifier" : "States.STATE12"
} ],
"event" : "Events.EVENT11",
"event" : {
"rawName" : "Events.EVENT11",
"fullIdentifier" : "Events.EVENT11"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -176,7 +209,10 @@
"rawName" : "States.STATE13",
"fullIdentifier" : "States.STATE13"
} ],
"event" : "Events.EVENT12",
"event" : {
"rawName" : "Events.EVENT12",
"fullIdentifier" : "Events.EVENT12"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -190,7 +226,10 @@
"rawName" : "States.STATE14",
"fullIdentifier" : "States.STATE14"
} ],
"event" : "Events.EVENT13",
"event" : {
"rawName" : "Events.EVENT13",
"fullIdentifier" : "Events.EVENT13"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -204,7 +243,10 @@
"rawName" : "States.STATE15",
"fullIdentifier" : "States.STATE15"
} ],
"event" : "Events.EVENT14",
"event" : {
"rawName" : "Events.EVENT14",
"fullIdentifier" : "Events.EVENT14"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -218,7 +260,10 @@
"rawName" : "States.STATE16",
"fullIdentifier" : "States.STATE16"
} ],
"event" : "Events.EVENT15",
"event" : {
"rawName" : "Events.EVENT15",
"fullIdentifier" : "Events.EVENT15"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -232,7 +277,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -246,7 +294,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -260,7 +311,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -274,7 +328,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -288,7 +345,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -302,7 +362,10 @@
"rawName" : "States.STATEY",
"fullIdentifier" : "States.STATEY"
} ],
"event" : "Events.EVENTY",
"event" : {
"rawName" : "Events.EVENTY",
"fullIdentifier" : "Events.EVENTY"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -764,7 +827,10 @@
"rawName" : "States.STATE_EXTRA_1",
"fullIdentifier" : "States.STATE_EXTRA_1"
} ],
"event" : "Events.EVENTX",
"event" : {
"rawName" : "Events.EVENTX",
"fullIdentifier" : "Events.EVENTX"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -778,7 +844,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL",
"event" : {
"rawName" : "Events.EVENT_CANCEL",
"fullIdentifier" : "Events.EVENT_CANCEL"
},
"guard" : null,
"actions" : [ ],
"order" : null
@@ -792,7 +861,10 @@
"rawName" : "States.CANCEL",
"fullIdentifier" : "States.CANCEL"
} ],
"event" : "Events.EVENT_CANCEL_2",
"event" : {
"rawName" : "Events.EVENT_CANCEL_2",
"fullIdentifier" : "Events.EVENT_CANCEL_2"
},
"guard" : null,
"actions" : [ ],
"order" : null

View File

@@ -56,6 +56,9 @@ public class HtmlExporterCommand implements Callable<Integer> {
@Option(names = {"--no-diamonds"}, description = "Disable rendering choice pseudostates as PlantUML diamonds (render them as normal state nodes instead).")
private boolean noDiamonds;
@Option(names = {"--no-metadata-pane"}, description = "Disable rendering the left metadata pane (entry points, flows) in the HTML viewer.")
private boolean noMetadataPane;
@Override
public Integer call() throws Exception {
var out = spec.commandLine().getOut();
@@ -78,12 +81,17 @@ public class HtmlExporterCommand implements Callable<Integer> {
List<String> formats = List.of("html", "json");
List<String> profiles = activeProfiles != null ? activeProfiles : java.util.Collections.emptyList();
if (noMetadataPane) {
System.setProperty("html.hideMetadataPane", "true");
}
if (jsonFile != null) {
exportService.runJsonExporter(jsonFile, outputDir, formats, profiles);
} else {
boolean renderChoicesAsDiamonds = !noDiamonds;
exportService.runExporter(inputDir, outputDir, formats, renderChoicesAsDiamonds, profiles, flowsFile, machineFilter);
}
System.clearProperty("html.hideMetadataPane");
out.println(CommandLine.Help.Ansi.AUTO.string("%n@|bold,green SUCCESS:|@ Interactive documentation generated successfully."));

View File

@@ -56,12 +56,64 @@ public class HtmlExporter implements StateMachineExporter {
// 5. Prepare Metadata JSON
String metadataJson = objectMapper.writeValueAsString(result);
// Check if we should render metadata pane
boolean hideMetadataProp = Boolean.getBoolean("html.hideMetadataPane");
boolean hasEntryPoints = false;
if (result.getMetadata() != null && result.getMetadata().getEntryPoints() != null && !result.getMetadata().getEntryPoints().isEmpty()) {
Set<String> smEvents = result.getTransitions().stream()
.filter(t -> t.getEvent() != null)
.map(t -> {
String eventStr = t.getEvent().fullIdentifier() != null ? t.getEvent().fullIdentifier() : t.getEvent().rawName();
return eventStr == null ? null : eventStr.replaceAll("[^a-zA-Z0-9_]", "_");
})
.collect(Collectors.toSet());
if (result.getMetadata().getCallChains() != null) {
hasEntryPoints = result.getMetadata().getCallChains().stream()
.anyMatch(c -> c.getMatchedTransitions() != null && !c.getMatchedTransitions().isEmpty());
}
}
boolean hasFlows = result.getFlows() != null && !result.getFlows().isEmpty();
boolean shouldRenderPane = !hideMetadataProp && options.isIncludeMetadataPane() && (hasEntryPoints || hasFlows);
// 6. Inject Data
return template
String finalHtml = template
.replace("{{MACHINE_NAME}}", result.getName())
.replace("{{SVG_CONTENT}}", decoratedSvg)
.replace("{{METADATA_JSON}}", metadataJson);
if (shouldRenderPane) {
// If template.html uses {{SIDEBAR_HTML}} and {{TOGGLE_BUTTON_HTML}}, replace with actual HTML
finalHtml = finalHtml.replace("{{SIDEBAR_HTML}}", "<div id=\"sidebar\">\n" +
" <div class=\"sidebar-header\">\n" +
" <header>\n" +
" <h1>Explorer</h1>\n" +
" <p>{{MACHINE_NAME}}</p>\n" +
" </header>\n" +
" </div>\n" +
" \n" +
" <div class=\"tabs\">\n" +
" <div class=\"tab active\" data-tab=\"explorer\">Explorer</div>\n" +
" <div class=\"tab\" data-tab=\"flows\">Business Flows</div>\n" +
" </div>\n" +
"\n" +
" <div id=\"tab-explorer\" class=\"tab-content active\">\n" +
" <div id=\"ep-list\"></div>\n" +
" </div>\n" +
"\n" +
" <div id=\"tab-flows\" class=\"tab-content\">\n" +
" <div id=\"flow-list\"></div>\n" +
" </div>\n" +
"</div>").replace("{{MACHINE_NAME}}", result.getName());
finalHtml = finalHtml.replace("{{TOGGLE_BUTTON_HTML}}", " <button id=\"toggle-sidebar\" aria-label=\"Toggle Sidebar\" title=\"Toggle Sidebar\">\n" +
" <svg viewBox=\"0 0 24 24\"><path d=\"M4 6h16M4 12h16M4 18h16\"></path></svg>\n" +
" </button>");
} else {
finalHtml = finalHtml.replace("{{SIDEBAR_HTML}}", "").replace("{{TOGGLE_BUTTON_HTML}}", "");
}
return finalHtml;
} catch (Exception e) {
log.error("Failed to export to HTML", e);
throw new RuntimeException("HTML export failed", e);

View File

@@ -261,32 +261,10 @@
</head>
<body>
<div id="sidebar">
<div class="sidebar-header">
<header>
<h1>Explorer</h1>
<p>{{MACHINE_NAME}}</p>
</header>
</div>
<div class="tabs">
<div class="tab active" data-tab="explorer">Explorer</div>
<div class="tab" data-tab="flows">Business Flows</div>
</div>
<div id="tab-explorer" class="tab-content active">
<div id="ep-list"></div>
</div>
<div id="tab-flows" class="tab-content">
<div id="flow-list"></div>
</div>
</div>
{{SIDEBAR_HTML}}
<div id="main">
<button id="toggle-sidebar" aria-label="Toggle Sidebar" title="Toggle Sidebar">
<svg viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h16"></path></svg>
</button>
{{TOGGLE_BUTTON_HTML}}
<div id="svg-container">
{{SVG_CONTENT}}
</div>
@@ -304,18 +282,21 @@
const svg = document.querySelector('#svg-container svg');
panZoomInstance = svgPanZoom(svg, { zoomEnabled: true, controlIconsEnabled: true, fit: true, center: true });
document.getElementById('toggle-sidebar').addEventListener('click', () => {
const sidebar = document.getElementById('sidebar');
sidebar.classList.toggle('collapsed');
const toggleSidebar = document.getElementById('toggle-sidebar');
if (toggleSidebar) {
toggleSidebar.addEventListener('click', () => {
const sidebar = document.getElementById('sidebar');
if (sidebar) sidebar.classList.toggle('collapsed');
// Re-center SVG pan-zoom after transition
setTimeout(() => {
if (panZoomInstance) {
panZoomInstance.resize();
panZoomInstance.center();
}
}, 300);
});
// Re-center SVG pan-zoom after transition
setTimeout(() => {
if (panZoomInstance) {
panZoomInstance.resize();
panZoomInstance.center();
}
}, 300);
});
}
setupTabs();
populateSidebar();
@@ -325,8 +306,10 @@
function setupTabs() {
const flows = metadata.flows || [];
const tabsEl = document.querySelector('.tabs');
if (!tabsEl) return;
if (flows.length === 0) {
document.querySelector('.tabs').style.display = 'none';
tabsEl.style.display = 'none';
document.querySelector('.tab-content[data-tab="flows"]')?.remove();
return;
}
@@ -342,15 +325,15 @@
function populateSidebar() {
const list = document.getElementById('ep-list');
if (!list) return;
const entryPoints = metadata.metadata.entryPoints || [];
const machineEvents = new Set(metadata.transitions.map(t => t.event).filter(Boolean));
entryPoints.forEach(ep => {
// Quality Filter: Hide if it doesn't trigger a machine event
const chains = (metadata.metadata.callChains || []).filter(c =>
c.entryPoint.className === ep.className &&
c.entryPoint.methodName === ep.methodName &&
machineEvents.has(c.triggerPoint.event)
c.matchedTransitions && c.matchedTransitions.length > 0
);
if (chains.length === 0) return;
@@ -364,6 +347,22 @@
<div class="ep-fqn">${ep.className}.${ep.methodName}</div>
${sourceHint}
`;
// Add tags for matched events
let triggersHtml = '<div class="ep-transitions" style="margin-top: 8px;">Triggers: ';
const addedEvents = new Set();
chains.forEach(c => {
c.matchedTransitions.forEach(t => {
const evName = t.event || "";
if (!addedEvents.has(evName)) {
addedEvents.add(evName);
triggersHtml += `<span class="badge transition" style="font-size: 0.65rem; padding: 2px 6px;">${evName}</span> `;
}
});
});
triggersHtml += '</div>';
card.innerHTML += triggersHtml;
card.onmouseenter = () => highlightEntryPoint(ep);
card.onmouseleave = clearHighlights;
list.appendChild(card);
@@ -372,6 +371,7 @@
function populateFlows() {
const list = document.getElementById('flow-list');
if (!list) return;
const flows = metadata.flows || [];
if (flows.length === 0) {
@@ -394,14 +394,21 @@
function highlightEntryPoint(ep) {
clearHighlights();
const machineEvents = new Set(metadata.transitions.map(t => t.event).filter(Boolean));
const chains = metadata.metadata.callChains || [];
const relevantEvents = chains
.filter(c => c.entryPoint.className === ep.className && c.entryPoint.methodName === ep.methodName && machineEvents.has(c.triggerPoint.event))
.map(c => c.triggerPoint.event);
if (relevantEvents.length === 0) return;
highlightEvents(relevantEvents);
let steps = [];
chains.forEach(c => {
if (c.entryPoint.className === ep.className && c.entryPoint.methodName === ep.methodName) {
if (c.matchedTransitions && c.matchedTransitions.length > 0) {
c.matchedTransitions.forEach(t => {
steps.push({ event: t.event, source: t.sourceState });
});
}
}
});
if (steps.length === 0) return;
highlightEvents(steps);
}
function highlightFlow(flow) {
@@ -419,19 +426,38 @@
});
steps.forEach(step => {
let linkId = "";
if (step.includes("->")) {
// Named Choice Branch: "SRC->TGT"
let targetEvent = "";
let targetSource = "";
let targetAnon = "";
if (typeof step === 'object') {
targetEvent = normalize(step.event);
targetSource = normalize(step.source);
} else if (step.includes("->")) {
const parts = step.split("->");
linkId = "#link_anon_" + normalize(parts[0]) + "_" + normalize(parts[1]);
targetAnon = "#link_anon_" + normalize(parts[0]) + "_" + normalize(parts[1]);
} else {
// Standard Event
linkId = "#link_" + normalize(step);
targetEvent = normalize(step);
}
svg.querySelectorAll('a').forEach(link => {
const href = link.getAttribute('xlink:href') || link.getAttribute('href');
if (href === linkId) {
if (!href) return;
let matches = false;
if (targetAnon) {
matches = (href === targetAnon);
} else if (targetEvent) {
if (targetSource) {
// Exact match
matches = (href === "#link_" + targetSource + "__" + targetEvent);
} else {
// Match all sources for this event
matches = href.startsWith("#link_") && href.endsWith("__" + targetEvent);
}
}
if (matches) {
highlightLinkGroup(link);
}
});
@@ -496,20 +522,31 @@
const isAnon = linkId.startsWith('anon_');
let metaTrans = null;
let cleanEventName = linkId;
if (isAnon) {
metaTrans = transitions.find(t =>
!t.event &&
"anon_" + normalize(t.sourceStates[0].fullIdentifier) + "_" + normalize(t.targetStates[0].fullIdentifier) === linkId
);
cleanEventName = "Internal logic";
} else {
metaTrans = transitions.find(t => normalize(t.event) === linkId);
metaTrans = transitions.find(t => {
if (!t.event) return false;
const evStr = t.event.fullIdentifier || t.event.rawName || t.event;
const sourceStr = t.sourceStates && t.sourceStates.length > 0 ? (t.sourceStates[0].fullIdentifier || t.sourceStates[0].rawName) : "";
const expectedLinkId = normalize(sourceStr) + "__" + normalize(evStr);
return expectedLinkId === linkId;
});
if (metaTrans && metaTrans.event) {
cleanEventName = metaTrans.event.fullIdentifier || metaTrans.event.rawName || metaTrans.event;
}
}
if (metaTrans || isAnon) {
link.style.cursor = 'pointer';
const setupTippy = (el) => {
tippy(el, {
content: createTooltip(isAnon ? "Internal logic" : linkId, metaTrans),
content: createTooltip(cleanEventName, metaTrans),
allowHTML: true,
theme: 'modern',
interactive: true,
@@ -535,7 +572,13 @@
}
function createTooltip(name, trans) {
const chains = (metadata.metadata.callChains || []).filter(c => normalize(c.triggerPoint.event) === name);
const chains = (metadata.metadata.callChains || []).filter(c => {
if (!c.matchedTransitions || c.matchedTransitions.length === 0) return false;
return c.matchedTransitions.some(t => {
const cEventStr = typeof t.event === 'object' ? (t.event.fullIdentifier || t.event.rawName || t.event) : t.event;
return normalize(cEventStr) === name;
});
});
let html = `<div class="tooltip-content">
<div style="font-weight:900; font-size:1.1rem; margin-bottom:12px; border-bottom:1px solid #eee; padding-bottom:8px; line-height:1.3;">

View File

@@ -81,8 +81,84 @@ public class HtmlExporterTest {
// 7. Assertions - Surgical SVG Identification
// Every event should be wrapped in an identifying hyperlink for robust JS selection
assertThat(html).contains("#link_CREATE");
assertThat(html).contains("#link_ASSIGN");
assertThat(html).contains("#link_CLOSE_TICKET");
assertThat(html).contains("__CREATE");
assertThat(html).contains("__ASSIGN");
assertThat(html).contains("__CLOSE_TICKET");
}
@Test
void shouldRenderSidebarWhenMatchedTransitionsExist() throws IOException {
click.kamil.springstatemachineexporter.analysis.model.EntryPoint ep = click.kamil.springstatemachineexporter.analysis.model.EntryPoint.builder().name("Test").build();
click.kamil.springstatemachineexporter.analysis.model.CallChain chain = click.kamil.springstatemachineexporter.analysis.model.CallChain.builder()
.matchedTransitions(List.of(click.kamil.springstatemachineexporter.analysis.model.MatchedTransition.builder().event("TEST_EVENT").build()))
.build();
click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata metadata = click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata.builder()
.entryPoints(List.of(ep))
.callChains(List.of(chain))
.build();
AnalysisResult result = AnalysisResult.builder()
.name("SidebarTest")
.transitions(List.of())
.startStates(java.util.Collections.emptySet())
.endStates(java.util.Collections.emptySet())
.metadata(metadata)
.build();
HtmlExporter exporter = new HtmlExporter();
String html = exporter.export(result, ExportOptions.builder().includeMetadataPane(true).build());
assertThat(html).contains("id=\"sidebar\"");
assertThat(html).contains("id=\"ep-list\"");
}
@Test
void shouldNotRenderSidebarWhenNoMatchedTransitionsExist() throws IOException {
click.kamil.springstatemachineexporter.analysis.model.EntryPoint ep = click.kamil.springstatemachineexporter.analysis.model.EntryPoint.builder().name("Test").build();
click.kamil.springstatemachineexporter.analysis.model.CallChain chain = click.kamil.springstatemachineexporter.analysis.model.CallChain.builder()
.triggerPoint(click.kamil.springstatemachineexporter.analysis.model.TriggerPoint.builder().event("TEST_EVENT").build())
.matchedTransitions(List.of()) // EMPTY
.build();
click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata metadata = click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata.builder()
.entryPoints(List.of(ep))
.callChains(List.of(chain))
.build();
Transition transition = new Transition();
transition.setEvent(click.kamil.springstatemachineexporter.model.Event.of("TEST_EVENT"));
transition.setSourceStates(List.of());
transition.setTargetStates(List.of());
AnalysisResult result = AnalysisResult.builder()
.name("SidebarTestEmpty")
.transitions(List.of(transition))
.startStates(java.util.Collections.emptySet())
.endStates(java.util.Collections.emptySet())
.metadata(metadata)
.build();
HtmlExporter exporter = new HtmlExporter();
String html = exporter.export(result, ExportOptions.builder().includeMetadataPane(true).build());
assertThat(html).doesNotContain("id=\"sidebar\"");
assertThat(html).doesNotContain("id=\"ep-list\"");
}
@Test
void shouldContainCorrectJsLogicForEventTooltipResolution() throws IOException {
HtmlExporter exporter = new HtmlExporter();
AnalysisResult result = AnalysisResult.builder()
.name("JsTest")
.transitions(List.of())
.startStates(java.util.Collections.emptySet())
.endStates(java.util.Collections.emptySet())
.build();
String html = exporter.export(result, ExportOptions.builder().build());
// Verify that the template gracefully unwraps the Event JSON object for interactive hovers in attachInteractivity
assertThat(html).contains("const evStr = t.event.fullIdentifier || t.event.rawName || t.event;");
// Verify that the template gracefully unwraps the Event JSON object when filtering call chains in createTooltip
assertThat(html).contains("const cEventStr = typeof t.event === 'object' ? (t.event.fullIdentifier || t.event.rawName || t.event) : t.event;");
}
}