Require endpoint-narrow polymorphic evidence before linking transitions.
Fail closed on broad enum widens so dispatchers link one event per endpoint instead of every transition on the machine. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -37,21 +37,50 @@ public final class CallChainLinkPolicy {
|
|||||||
if (trigger == null || trigger.isExternal() || !trigger.isAmbiguous()) {
|
if (trigger == null || trigger.isExternal() || !trigger.isAmbiguous()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
List<String> poly = trigger.getPolymorphicEvents();
|
String eventTypeFqn = trigger.getEventTypeFqn();
|
||||||
if (poly == null || poly.size() <= 1) {
|
if (eventTypeFqn == null || eventTypeFqn.isBlank()) {
|
||||||
|
eventTypeFqn = machineEventTypeFqn;
|
||||||
|
}
|
||||||
|
List<String> concrete = concretePolymorphicCandidates(
|
||||||
|
trigger.getPolymorphicEvents(), eventTypeFqn, context);
|
||||||
|
if (concrete.size() <= 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String event = trigger.getEvent();
|
String event = trigger.getEvent();
|
||||||
if (event != null && event.startsWith("ENUM_SET:")) {
|
if (event != null && event.startsWith("ENUM_SET:")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (event != null && event.contains(".valueOf(")) {
|
return MachineEnumCanonicalizer.isDynamicTriggerExpression(event);
|
||||||
return MachineEnumCanonicalizer.isDynamicTriggerExpression(event)
|
|
||||||
&& !isTrustedEnumPolymorphicWiden(trigger, machineEventTypeFqn, context);
|
|
||||||
}
|
}
|
||||||
return MachineEnumCanonicalizer.isDynamicTriggerExpression(event)
|
|
||||||
&& event != null
|
/**
|
||||||
&& !isTrustedEnumPolymorphicWiden(trigger, machineEventTypeFqn, context);
|
* True when call-graph evidence resolves to a single concrete machine enum event for this chain.
|
||||||
|
* Dispatcher/rich-event paths should narrow to one constant per endpoint before linking.
|
||||||
|
*/
|
||||||
|
public static boolean isEndpointNarrowPolyEvidence(
|
||||||
|
TriggerPoint trigger,
|
||||||
|
String machineEventTypeFqn,
|
||||||
|
CodebaseContext context) {
|
||||||
|
if (trigger == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String eventTypeFqn = trigger.getEventTypeFqn();
|
||||||
|
if (eventTypeFqn == null || eventTypeFqn.isBlank()) {
|
||||||
|
eventTypeFqn = machineEventTypeFqn;
|
||||||
|
}
|
||||||
|
List<String> concrete = concretePolymorphicCandidates(
|
||||||
|
trigger.getPolymorphicEvents(), eventTypeFqn, context);
|
||||||
|
return concrete.size() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEndpointNarrowPolyEvidence(TriggerPoint trigger) {
|
||||||
|
return isEndpointNarrowPolyEvidence(trigger, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEndpointNarrowPolyEvidence(
|
||||||
|
TriggerPoint trigger,
|
||||||
|
String machineEventTypeFqn) {
|
||||||
|
return isEndpointNarrowPolyEvidence(trigger, machineEventTypeFqn, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,18 +112,14 @@ public final class CallChainLinkPolicy {
|
|||||||
}
|
}
|
||||||
List<String> poly = trigger.getPolymorphicEvents();
|
List<String> poly = trigger.getPolymorphicEvents();
|
||||||
List<String> concrete = concretePolymorphicCandidates(poly, eventTypeFqn, context);
|
List<String> concrete = concretePolymorphicCandidates(poly, eventTypeFqn, context);
|
||||||
if (concrete.size() <= 1) {
|
if (concrete.size() != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (String pe : concrete) {
|
return MachineEnumCanonicalizer.polymorphicEventMatchesMachineEventType(
|
||||||
if (!MachineEnumCanonicalizer.polymorphicEventMatchesMachineEventType(pe, eventTypeFqn, context)) {
|
concrete.get(0), eventTypeFqn, context);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> concretePolymorphicCandidates(
|
static List<String> concretePolymorphicCandidates(
|
||||||
List<String> poly,
|
List<String> poly,
|
||||||
String eventTypeFqn,
|
String eventTypeFqn,
|
||||||
CodebaseContext context) {
|
CodebaseContext context) {
|
||||||
@@ -149,12 +174,12 @@ public final class CallChainLinkPolicy {
|
|||||||
if (shouldFailClosedOnAmbiguousCallGraphWiden(trigger, machineEventTypeFqn, context)) {
|
if (shouldFailClosedOnAmbiguousCallGraphWiden(trigger, machineEventTypeFqn, context)) {
|
||||||
return LinkResolution.AMBIGUOUS_WIDEN;
|
return LinkResolution.AMBIGUOUS_WIDEN;
|
||||||
}
|
}
|
||||||
if (matched != null && !matched.isEmpty()) {
|
|
||||||
return LinkResolution.RESOLVED;
|
|
||||||
}
|
|
||||||
if (ambiguousSource) {
|
if (ambiguousSource) {
|
||||||
return LinkResolution.AMBIGUOUS_WIDEN;
|
return LinkResolution.AMBIGUOUS_WIDEN;
|
||||||
}
|
}
|
||||||
|
if (matched != null && !matched.isEmpty()) {
|
||||||
|
return LinkResolution.RESOLVED;
|
||||||
|
}
|
||||||
return LinkResolution.NO_MATCH;
|
return LinkResolution.NO_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,8 +121,10 @@ public class TransitionLinkerEnricher implements AnalysisEnricher {
|
|||||||
if (crossStateTypeConflict) {
|
if (crossStateTypeConflict) {
|
||||||
ambiguousSource = true;
|
ambiguousSource = true;
|
||||||
} else if (sourcesByEvent.values().stream().anyMatch(sources -> sources.size() > 1)) {
|
} else if (sourcesByEvent.values().stream().anyMatch(sources -> sources.size() > 1)) {
|
||||||
// Same event from multiple sources within one state enum is normal — link all.
|
ambiguousSource = !CallChainLinkPolicy.isEndpointNarrowPolyEvidence(
|
||||||
ambiguousSource = false;
|
tp,
|
||||||
|
machineTypes != null ? machineTypes.eventTypeFqn() : null,
|
||||||
|
context);
|
||||||
} else {
|
} else {
|
||||||
Set<String> allDistinctSources = new LinkedHashSet<>();
|
Set<String> allDistinctSources = new LinkedHashSet<>();
|
||||||
sourcesByEvent.values().forEach(allDistinctSources::addAll);
|
sourcesByEvent.values().forEach(allDistinctSources::addAll);
|
||||||
|
|||||||
@@ -48,81 +48,41 @@ class CallChainLinkPolicyTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldAllowTrustedMachineScopedValueOfWiden() {
|
void shouldAllowEndpointNarrowSingleConcretePoly() {
|
||||||
TriggerPoint trigger = TriggerPoint.builder()
|
TriggerPoint trigger = TriggerPoint.builder()
|
||||||
.ambiguous(true)
|
.ambiguous(true)
|
||||||
.eventTypeFqn("com.example.OrderEvent")
|
.eventTypeFqn("com.example.OrderEvent")
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
.polymorphicEvents(List.of("com.example.OrderEvent.PAY", "com.example.OrderEvent.SHIP"))
|
.polymorphicEvents(List.of("com.example.OrderEvent.PAY"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
assertThat(CallChainLinkPolicy.isEndpointNarrowPolyEvidence(trigger)).isTrue();
|
||||||
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(trigger)).isTrue();
|
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(trigger)).isTrue();
|
||||||
assertThat(CallChainLinkPolicy.shouldFailClosedOnAmbiguousCallGraphWiden(trigger)).isFalse();
|
assertThat(CallChainLinkPolicy.shouldFailClosedOnAmbiguousCallGraphWiden(trigger)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldAllowTrustedWidenUsingMachineEventTypeWhenTriggerTypeIsNull() {
|
void shouldFailClosedWhenMultipleConcretePolyCandidatesRemain() {
|
||||||
TriggerPoint trigger = TriggerPoint.builder()
|
TriggerPoint trigger = TriggerPoint.builder()
|
||||||
.ambiguous(true)
|
.ambiguous(true)
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
.polymorphicEvents(List.of("com.example.OrderEvent.PAY", "com.example.OrderEvent.SHIP"))
|
.polymorphicEvents(List.of("com.example.OrderEvent.PAY", "com.example.OrderEvent.SHIP"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
assertThat(CallChainLinkPolicy.isEndpointNarrowPolyEvidence(
|
||||||
|
trigger, "com.example.OrderEvent")).isFalse();
|
||||||
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(
|
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(
|
||||||
|
trigger, "com.example.OrderEvent")).isFalse();
|
||||||
|
assertThat(CallChainLinkPolicy.shouldFailClosedOnAmbiguousCallGraphWiden(
|
||||||
trigger, "com.example.OrderEvent")).isTrue();
|
trigger, "com.example.OrderEvent")).isTrue();
|
||||||
assertThat(CallChainLinkPolicy.shouldFailClosedOnAmbiguousCallGraphWiden(
|
|
||||||
trigger, "com.example.OrderEvent")).isFalse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldResolveLinkWhenTrustedWidenPassesUsingMachineEventType() {
|
void shouldResolveLinkWhenEndpointNarrowPolyHasMatches() {
|
||||||
TriggerPoint trigger = TriggerPoint.builder()
|
|
||||||
.ambiguous(false)
|
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
|
||||||
.polymorphicEvents(List.of("com.example.OrderEvent.PAY", "com.example.OrderEvent.SHIP"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
assertThat(CallChainLinkPolicy.resolveLinkResolution(
|
|
||||||
trigger,
|
|
||||||
List.of(),
|
|
||||||
false,
|
|
||||||
"com.example.OrderEvent")).isEqualTo(LinkResolution.NO_MATCH);
|
|
||||||
assertThat(CallChainLinkPolicy.shouldFailClosedOnAmbiguousCallGraphWiden(
|
|
||||||
trigger, "com.example.OrderEvent")).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldNotTrustImportStylePolymorphicWidenWithoutPackage() {
|
|
||||||
TriggerPoint trigger = TriggerPoint.builder()
|
TriggerPoint trigger = TriggerPoint.builder()
|
||||||
.ambiguous(true)
|
.ambiguous(true)
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
.polymorphicEvents(List.of("OrderEvent.PAY", "OrderEvent.SHIP"))
|
.polymorphicEvents(List.of("OrderEvent.PAY"))
|
||||||
.build();
|
|
||||||
|
|
||||||
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(trigger)).isFalse();
|
|
||||||
assertThat(CallChainLinkPolicy.shouldFailClosedOnAmbiguousCallGraphWiden(trigger)).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldTrustImportStylePolymorphicWidenWhenMachineEventTypeIsKnown() {
|
|
||||||
TriggerPoint trigger = TriggerPoint.builder()
|
|
||||||
.ambiguous(true)
|
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
|
||||||
.polymorphicEvents(List.of("OrderEvent.PAY", "OrderEvent.SHIP"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(
|
|
||||||
trigger, "com.example.order.OrderEvent")).isTrue();
|
|
||||||
assertThat(CallChainLinkPolicy.shouldFailClosedOnAmbiguousCallGraphWiden(
|
|
||||||
trigger, "com.example.order.OrderEvent")).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldResolveWhenTrustedWidenHasMatchesDespiteAmbiguousCallGraphFlag() {
|
|
||||||
TriggerPoint trigger = TriggerPoint.builder()
|
|
||||||
.ambiguous(true)
|
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
|
||||||
.polymorphicEvents(List.of("OrderEvent.PAY", "OrderEvent.SHIP"))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
var matched = List.of(
|
var matched = List.of(
|
||||||
@@ -138,11 +98,31 @@ class CallChainLinkPolicyTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldTrustBareConstantPolymorphicCandidatesWhenMachineEventTypeIsKnown() {
|
void shouldNotResolveWhenBroadPolyWidenHasMatches() {
|
||||||
TriggerPoint trigger = TriggerPoint.builder()
|
TriggerPoint trigger = TriggerPoint.builder()
|
||||||
.ambiguous(true)
|
.ambiguous(true)
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
.polymorphicEvents(List.of("PAY", "SHIP"))
|
.polymorphicEvents(List.of("OrderEvent.PAY", "OrderEvent.SHIP"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var matched = List.of(
|
||||||
|
click.kamil.springstatemachineexporter.analysis.model.MatchedTransition.builder()
|
||||||
|
.event("com.example.order.OrderEvent.PAY")
|
||||||
|
.build());
|
||||||
|
|
||||||
|
assertThat(CallChainLinkPolicy.resolveLinkResolution(
|
||||||
|
trigger,
|
||||||
|
matched,
|
||||||
|
false,
|
||||||
|
"com.example.order.OrderEvent")).isEqualTo(LinkResolution.AMBIGUOUS_WIDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldTrustImportStyleSingleConcretePolyWhenMachineEventTypeIsKnown() {
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder()
|
||||||
|
.ambiguous(true)
|
||||||
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
|
.polymorphicEvents(List.of("OrderEvent.PAY"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(
|
assertThat(CallChainLinkPolicy.isTrustedEnumPolymorphicWiden(
|
||||||
|
|||||||
@@ -237,9 +237,7 @@ class TransitionLinkerEnricherTest {
|
|||||||
.triggerPoint(TriggerPoint.builder()
|
.triggerPoint(TriggerPoint.builder()
|
||||||
.ambiguous(true)
|
.ambiguous(true)
|
||||||
.event("OrderEvent.valueOf(eventStr)")
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
.polymorphicEvents(List.of(
|
.polymorphicEvents(List.of("com.example.order.OrderEvent.PAY"))
|
||||||
"com.example.order.OrderEvent.PAY",
|
|
||||||
"com.example.order.OrderEvent.SHIP"))
|
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -258,6 +256,49 @@ class TransitionLinkerEnricherTest {
|
|||||||
assertThat(updatedChain.getLinkResolution()).isEqualTo(LinkResolution.RESOLVED);
|
assertThat(updatedChain.getLinkResolution()).isEqualTo(LinkResolution.RESOLVED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNotLinkAllTransitionsWhenPolyContainsManyEnumConstants() {
|
||||||
|
Transition pay = new Transition();
|
||||||
|
pay.setSourceStates(List.of(State.of("NEW", "com.example.order.OrderState.NEW")));
|
||||||
|
pay.setTargetStates(List.of(State.of("PAID", "com.example.order.OrderState.PAID")));
|
||||||
|
pay.setEvent(Event.of("PAY", "com.example.order.OrderEvent.PAY"));
|
||||||
|
|
||||||
|
Transition ship = new Transition();
|
||||||
|
ship.setSourceStates(List.of(State.of("PAID", "com.example.order.OrderState.PAID")));
|
||||||
|
ship.setTargetStates(List.of(State.of("SHIPPED", "com.example.order.OrderState.SHIPPED")));
|
||||||
|
ship.setEvent(Event.of("SHIP", "com.example.order.OrderEvent.SHIP"));
|
||||||
|
|
||||||
|
Transition cancel = new Transition();
|
||||||
|
cancel.setSourceStates(List.of(State.of("NEW", "com.example.order.OrderState.NEW")));
|
||||||
|
cancel.setTargetStates(List.of(State.of("CANCELLED", "com.example.order.OrderState.CANCELLED")));
|
||||||
|
cancel.setEvent(Event.of("CANCEL", "com.example.order.OrderEvent.CANCEL"));
|
||||||
|
|
||||||
|
CallChain chain = CallChain.builder()
|
||||||
|
.triggerPoint(TriggerPoint.builder()
|
||||||
|
.ambiguous(true)
|
||||||
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
|
.polymorphicEvents(List.of(
|
||||||
|
"com.example.order.OrderEvent.PAY",
|
||||||
|
"com.example.order.OrderEvent.SHIP",
|
||||||
|
"com.example.order.OrderEvent.CANCEL"))
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
AnalysisResult result = AnalysisResult.builder()
|
||||||
|
.name("com.example.config.OrderStateMachineConfiguration")
|
||||||
|
.eventTypeFqn("com.example.order.OrderEvent")
|
||||||
|
.stateTypeFqn("com.example.order.OrderState")
|
||||||
|
.transitions(List.of(pay, ship, cancel))
|
||||||
|
.metadata(CodebaseMetadata.builder().callChains(List.of(chain)).build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
enricher.enrich(result, null, null);
|
||||||
|
|
||||||
|
CallChain updatedChain = result.getMetadata().getCallChains().get(0);
|
||||||
|
assertThat(updatedChain.getMatchedTransitions()).isNullOrEmpty();
|
||||||
|
assertThat(updatedChain.getLinkResolution()).isEqualTo(LinkResolution.AMBIGUOUS_WIDEN);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldNotInferSourceStateWhenDifferentEnumsShareSameConstantName() {
|
void shouldNotInferSourceStateWhenDifferentEnumsShareSameConstantName() {
|
||||||
Transition t1 = new Transition();
|
Transition t1 = new Transition();
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class TrustedEnumWidenLinkingRegressionTest {
|
|||||||
.event("OrderEvent.valueOf(eventStr)")
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
.ambiguous(true)
|
.ambiguous(true)
|
||||||
.external(false)
|
.external(false)
|
||||||
.polymorphicEvents(List.of("OrderEvent.PAY", "OrderEvent.SHIP"))
|
.polymorphicEvents(List.of("OrderEvent.PAY"))
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class TrustedEnumWidenLinkingRegressionTest {
|
|||||||
assertThat(linked.getLinkResolution()).isEqualTo(LinkResolution.RESOLVED);
|
assertThat(linked.getLinkResolution()).isEqualTo(LinkResolution.RESOLVED);
|
||||||
assertThat(linked.getMatchedTransitions()).hasSizeGreaterThanOrEqualTo(1);
|
assertThat(linked.getMatchedTransitions()).hasSizeGreaterThanOrEqualTo(1);
|
||||||
assertThat(linked.getTriggerPoint().getPolymorphicEvents())
|
assertThat(linked.getTriggerPoint().getPolymorphicEvents())
|
||||||
.containsExactly("com.example.order.OrderEvent.PAY", "com.example.order.OrderEvent.SHIP");
|
.containsExactly("com.example.order.OrderEvent.PAY");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -102,7 +102,7 @@ class TrustedEnumWidenLinkingRegressionTest {
|
|||||||
.event("OrderEvent.valueOf(eventStr)")
|
.event("OrderEvent.valueOf(eventStr)")
|
||||||
.ambiguous(true)
|
.ambiguous(true)
|
||||||
.external(false)
|
.external(false)
|
||||||
.polymorphicEvents(List.of("OrderEvent.PAY", "OrderEvent.SHIP"))
|
.polymorphicEvents(List.of("OrderEvent.PAY"))
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ class DispatcherEndpointTest {
|
|||||||
TriggerPoint linkedTrigger = result.getMetadata().getCallChains().get(0).getTriggerPoint();
|
TriggerPoint linkedTrigger = result.getMetadata().getCallChains().get(0).getTriggerPoint();
|
||||||
assertThat(linkedTrigger.getPolymorphicEvents())
|
assertThat(linkedTrigger.getPolymorphicEvents())
|
||||||
.contains("com.example.OrderEvent.PAY", "com.example.OrderEvent.SHIP");
|
.contains("com.example.OrderEvent.PAY", "com.example.OrderEvent.SHIP");
|
||||||
assertThat(result.getMetadata().getCallChains().get(0).getMatchedTransitions()).hasSize(2);
|
assertThat(result.getMetadata().getCallChains().get(0).getMatchedTransitions()).isNullOrEmpty();
|
||||||
|
assertThat(result.getMetadata().getCallChains().get(0).getLinkResolution())
|
||||||
|
.isEqualTo(LinkResolution.AMBIGUOUS_WIDEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,6 +125,21 @@
|
|||||||
"metadata" : {
|
"metadata" : {
|
||||||
"triggers" : [ ],
|
"triggers" : [ ],
|
||||||
"entryPoints" : [ {
|
"entryPoints" : [ {
|
||||||
|
"type" : "REST",
|
||||||
|
"name" : "POST /api/orders/reactive",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.web.OrderController",
|
||||||
|
"methodName" : "reactiveOrder",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
|
||||||
|
"metadata" : {
|
||||||
|
"path" : "/api/orders/reactive",
|
||||||
|
"verb" : "POST"
|
||||||
|
},
|
||||||
|
"parameters" : [ {
|
||||||
|
"name" : "orderId",
|
||||||
|
"type" : "String",
|
||||||
|
"annotations" : [ ]
|
||||||
|
} ]
|
||||||
|
}, {
|
||||||
"type" : "REST",
|
"type" : "REST",
|
||||||
"name" : "GET /api/base/{id}",
|
"name" : "GET /api/base/{id}",
|
||||||
"className" : "click.kamil.examples.statemachine.extended.web.PaymentController",
|
"className" : "click.kamil.examples.statemachine.extended.web.PaymentController",
|
||||||
@@ -155,7 +170,46 @@
|
|||||||
"annotations" : [ "PathVariable" ]
|
"annotations" : [ "PathVariable" ]
|
||||||
} ]
|
} ]
|
||||||
} ],
|
} ],
|
||||||
"callChains" : [ ],
|
"callChains" : [ {
|
||||||
|
"entryPoint" : {
|
||||||
|
"type" : "REST",
|
||||||
|
"name" : "POST /api/orders/reactive",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.web.OrderController",
|
||||||
|
"methodName" : "reactiveOrder",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
|
||||||
|
"metadata" : {
|
||||||
|
"path" : "/api/orders/reactive",
|
||||||
|
"verb" : "POST"
|
||||||
|
},
|
||||||
|
"parameters" : [ {
|
||||||
|
"name" : "orderId",
|
||||||
|
"type" : "String",
|
||||||
|
"annotations" : [ ]
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
"methodChain" : [ "click.kamil.examples.statemachine.extended.web.OrderController.reactiveOrder", "click.kamil.examples.statemachine.extended.service.ReactiveOrderService.processReactive" ],
|
||||||
|
"triggerPoint" : {
|
||||||
|
"event" : "java.lang.String.REACTIVE_EVENT",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.service.ReactiveOrderService",
|
||||||
|
"methodName" : "processReactive",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/ReactiveOrderService.java",
|
||||||
|
"sourceModule" : null,
|
||||||
|
"stateMachineId" : null,
|
||||||
|
"sourceState" : "java.lang.String.START",
|
||||||
|
"lineNumber" : 18,
|
||||||
|
"polymorphicEvents" : [ "java.lang.String.REACTIVE_EVENT" ],
|
||||||
|
"external" : false,
|
||||||
|
"constraint" : null,
|
||||||
|
"ambiguous" : false
|
||||||
|
},
|
||||||
|
"contextMachineId" : null,
|
||||||
|
"matchedTransitions" : [ {
|
||||||
|
"sourceState" : "String.START",
|
||||||
|
"targetState" : "String.PROCESSING",
|
||||||
|
"event" : "String.REACTIVE_EVENT"
|
||||||
|
} ],
|
||||||
|
"linkResolution" : "RESOLVED"
|
||||||
|
} ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"default" : {
|
"default" : {
|
||||||
"app.states.initial" : "INIT_STATE"
|
"app.states.initial" : "INIT_STATE"
|
||||||
|
|||||||
@@ -125,6 +125,21 @@
|
|||||||
"metadata" : {
|
"metadata" : {
|
||||||
"triggers" : [ ],
|
"triggers" : [ ],
|
||||||
"entryPoints" : [ {
|
"entryPoints" : [ {
|
||||||
|
"type" : "REST",
|
||||||
|
"name" : "POST /api/orders/reactive",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.web.OrderController",
|
||||||
|
"methodName" : "reactiveOrder",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
|
||||||
|
"metadata" : {
|
||||||
|
"path" : "/api/orders/reactive",
|
||||||
|
"verb" : "POST"
|
||||||
|
},
|
||||||
|
"parameters" : [ {
|
||||||
|
"name" : "orderId",
|
||||||
|
"type" : "String",
|
||||||
|
"annotations" : [ ]
|
||||||
|
} ]
|
||||||
|
}, {
|
||||||
"type" : "REST",
|
"type" : "REST",
|
||||||
"name" : "GET /api/base/{id}",
|
"name" : "GET /api/base/{id}",
|
||||||
"className" : "click.kamil.examples.statemachine.extended.web.PaymentController",
|
"className" : "click.kamil.examples.statemachine.extended.web.PaymentController",
|
||||||
@@ -155,7 +170,46 @@
|
|||||||
"annotations" : [ "PathVariable" ]
|
"annotations" : [ "PathVariable" ]
|
||||||
} ]
|
} ]
|
||||||
} ],
|
} ],
|
||||||
"callChains" : [ ],
|
"callChains" : [ {
|
||||||
|
"entryPoint" : {
|
||||||
|
"type" : "REST",
|
||||||
|
"name" : "POST /api/orders/reactive",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.web.OrderController",
|
||||||
|
"methodName" : "reactiveOrder",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
|
||||||
|
"metadata" : {
|
||||||
|
"path" : "/api/orders/reactive",
|
||||||
|
"verb" : "POST"
|
||||||
|
},
|
||||||
|
"parameters" : [ {
|
||||||
|
"name" : "orderId",
|
||||||
|
"type" : "String",
|
||||||
|
"annotations" : [ ]
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
"methodChain" : [ "click.kamil.examples.statemachine.extended.web.OrderController.reactiveOrder", "click.kamil.examples.statemachine.extended.service.ReactiveOrderService.processReactive" ],
|
||||||
|
"triggerPoint" : {
|
||||||
|
"event" : "java.lang.String.REACTIVE_EVENT",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.service.ReactiveOrderService",
|
||||||
|
"methodName" : "processReactive",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/ReactiveOrderService.java",
|
||||||
|
"sourceModule" : null,
|
||||||
|
"stateMachineId" : null,
|
||||||
|
"sourceState" : "java.lang.String.START",
|
||||||
|
"lineNumber" : 18,
|
||||||
|
"polymorphicEvents" : [ "java.lang.String.REACTIVE_EVENT" ],
|
||||||
|
"external" : false,
|
||||||
|
"constraint" : null,
|
||||||
|
"ambiguous" : false
|
||||||
|
},
|
||||||
|
"contextMachineId" : null,
|
||||||
|
"matchedTransitions" : [ {
|
||||||
|
"sourceState" : "String.START",
|
||||||
|
"targetState" : "String.PROCESSING",
|
||||||
|
"event" : "String.REACTIVE_EVENT"
|
||||||
|
} ],
|
||||||
|
"linkResolution" : "RESOLVED"
|
||||||
|
} ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"default" : {
|
"default" : {
|
||||||
"app.states.initial" : "INIT_STATE"
|
"app.states.initial" : "INIT_STATE"
|
||||||
|
|||||||
@@ -60,8 +60,62 @@
|
|||||||
"eventTypeFqn" : "String",
|
"eventTypeFqn" : "String",
|
||||||
"metadata" : {
|
"metadata" : {
|
||||||
"triggers" : [ ],
|
"triggers" : [ ],
|
||||||
"entryPoints" : [ ],
|
"entryPoints" : [ {
|
||||||
"callChains" : [ ],
|
"type" : "JMS",
|
||||||
|
"name" : "JMS: order.queue",
|
||||||
|
"className" : "click.kamil.maven.api.JmsOrderListener",
|
||||||
|
"methodName" : "onMessage",
|
||||||
|
"sourceFile" : "api-module/src/main/java/click/kamil/maven/api/JmsOrderListener.java",
|
||||||
|
"metadata" : {
|
||||||
|
"protocol" : "JMS",
|
||||||
|
"destination" : "order.queue"
|
||||||
|
},
|
||||||
|
"parameters" : [ {
|
||||||
|
"name" : "message",
|
||||||
|
"type" : "String",
|
||||||
|
"annotations" : [ ]
|
||||||
|
} ]
|
||||||
|
} ],
|
||||||
|
"callChains" : [ {
|
||||||
|
"entryPoint" : {
|
||||||
|
"type" : "JMS",
|
||||||
|
"name" : "JMS: order.queue",
|
||||||
|
"className" : "click.kamil.maven.api.JmsOrderListener",
|
||||||
|
"methodName" : "onMessage",
|
||||||
|
"sourceFile" : "api-module/src/main/java/click/kamil/maven/api/JmsOrderListener.java",
|
||||||
|
"metadata" : {
|
||||||
|
"protocol" : "JMS",
|
||||||
|
"destination" : "order.queue"
|
||||||
|
},
|
||||||
|
"parameters" : [ {
|
||||||
|
"name" : "message",
|
||||||
|
"type" : "String",
|
||||||
|
"annotations" : [ ]
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
"methodChain" : [ "click.kamil.maven.api.JmsOrderListener.onMessage", "click.kamil.maven.core.MavenOrderStateMachine.OrderService.onMessage" ],
|
||||||
|
"triggerPoint" : {
|
||||||
|
"event" : "java.lang.String.ORDER_EVENT",
|
||||||
|
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderService",
|
||||||
|
"methodName" : "onMessage",
|
||||||
|
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
||||||
|
"sourceModule" : null,
|
||||||
|
"stateMachineId" : null,
|
||||||
|
"sourceState" : "java.lang.String.BUSY",
|
||||||
|
"lineNumber" : 52,
|
||||||
|
"polymorphicEvents" : [ "java.lang.String.ORDER_EVENT" ],
|
||||||
|
"external" : false,
|
||||||
|
"constraint" : null,
|
||||||
|
"ambiguous" : false
|
||||||
|
},
|
||||||
|
"contextMachineId" : null,
|
||||||
|
"matchedTransitions" : [ {
|
||||||
|
"sourceState" : "String.BUSY",
|
||||||
|
"targetState" : "String.DONE",
|
||||||
|
"event" : "String.ORDER_EVENT"
|
||||||
|
} ],
|
||||||
|
"linkResolution" : "RESOLVED"
|
||||||
|
} ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"default" : { }
|
"default" : { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -636,6 +636,45 @@
|
|||||||
"event" : "String.AUTHORIZE"
|
"event" : "String.AUTHORIZE"
|
||||||
} ],
|
} ],
|
||||||
"linkResolution" : "RESOLVED"
|
"linkResolution" : "RESOLVED"
|
||||||
|
}, {
|
||||||
|
"entryPoint" : {
|
||||||
|
"type" : "REST",
|
||||||
|
"name" : "POST /api/payment/{id}/capture",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.web.PaymentController",
|
||||||
|
"methodName" : "capturePaymentEndpoint",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/PaymentController.java",
|
||||||
|
"metadata" : {
|
||||||
|
"path" : "/api/payment/{id}/capture",
|
||||||
|
"verb" : "POST"
|
||||||
|
},
|
||||||
|
"parameters" : [ {
|
||||||
|
"name" : "id",
|
||||||
|
"type" : "String",
|
||||||
|
"annotations" : [ "PathVariable" ]
|
||||||
|
} ]
|
||||||
|
},
|
||||||
|
"methodChain" : [ "click.kamil.examples.statemachine.extended.web.PaymentController.capturePaymentEndpoint", "click.kamil.examples.statemachine.extended.service.PaymentServiceImpl.capturePayment" ],
|
||||||
|
"triggerPoint" : {
|
||||||
|
"event" : "java.lang.String.CAPTURE",
|
||||||
|
"className" : "click.kamil.examples.statemachine.extended.service.PaymentServiceImpl",
|
||||||
|
"methodName" : "capturePayment",
|
||||||
|
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/service/PaymentServiceImpl.java",
|
||||||
|
"sourceModule" : null,
|
||||||
|
"stateMachineId" : "paymentStateMachine",
|
||||||
|
"sourceState" : "java.lang.String.AUTHORIZED",
|
||||||
|
"lineNumber" : 35,
|
||||||
|
"polymorphicEvents" : [ "java.lang.String.CAPTURE" ],
|
||||||
|
"external" : false,
|
||||||
|
"constraint" : null,
|
||||||
|
"ambiguous" : false
|
||||||
|
},
|
||||||
|
"contextMachineId" : "paymentId",
|
||||||
|
"matchedTransitions" : [ {
|
||||||
|
"sourceState" : "String.AUTHORIZED",
|
||||||
|
"targetState" : "String.CAPTURED",
|
||||||
|
"event" : "String.CAPTURE"
|
||||||
|
} ],
|
||||||
|
"linkResolution" : "RESOLVED"
|
||||||
} ],
|
} ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"default" : {
|
"default" : {
|
||||||
|
|||||||
@@ -738,16 +738,8 @@
|
|||||||
"ambiguous" : true
|
"ambiguous" : true
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : null,
|
||||||
"sourceState" : "click.kamil.examples.statemachine.polymorphic.OrderStates.SUBMITTED",
|
"linkResolution" : "AMBIGUOUS_WIDEN"
|
||||||
"targetState" : "click.kamil.examples.statemachine.polymorphic.OrderStates.PAID",
|
|
||||||
"event" : "click.kamil.examples.statemachine.polymorphic.OrderEvents.PAY"
|
|
||||||
}, {
|
|
||||||
"sourceState" : "click.kamil.examples.statemachine.polymorphic.OrderStates.PAID",
|
|
||||||
"targetState" : "click.kamil.examples.statemachine.polymorphic.OrderStates.CANCELED",
|
|
||||||
"event" : "click.kamil.examples.statemachine.polymorphic.OrderEvents.ABCD"
|
|
||||||
} ],
|
|
||||||
"linkResolution" : "RESOLVED"
|
|
||||||
} ],
|
} ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"default" : {
|
"default" : {
|
||||||
|
|||||||
Reference in New Issue
Block a user