From 9b62be913c9ff003327fb09ad30017e54a00928d Mon Sep 17 00:00:00 2001 From: Kamil Patryk Kozakowski Date: Fri, 17 Jul 2026 07:40:54 +0200 Subject: [PATCH] B --- .../enricher/TransitionLinkerEnricher.java | 51 +---------- .../HeuristicEventMatchingEngine.java | 11 ++- .../resolver/MachineEnumCanonicalizer.java | 12 +-- .../service/AbstractCallGraphEngine.java | 3 +- .../service/CarrierConstraintSupport.java | 89 +++++++++++++++++++ .../analysis/service/EventCarrierPolicy.java | 73 ++++++++++++--- .../service/GenericEventDetector.java | 29 +++++- .../service/CarrierConstraintSupportTest.java | 46 ++++++++++ .../service/EventCarrierPolicyTest.java | 66 ++++++++++++-- 9 files changed, 294 insertions(+), 86 deletions(-) create mode 100644 state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupport.java create mode 100644 state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupportTest.java diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/TransitionLinkerEnricher.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/TransitionLinkerEnricher.java index 6fcb1f0..5921ca2 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/TransitionLinkerEnricher.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/TransitionLinkerEnricher.java @@ -8,6 +8,7 @@ import click.kamil.springstatemachineexporter.analysis.model.LifecycleTriggerMar import click.kamil.springstatemachineexporter.analysis.model.LinkResolution; import click.kamil.springstatemachineexporter.analysis.model.MatchedTransition; import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint; +import click.kamil.springstatemachineexporter.analysis.service.CarrierConstraintSupport; import click.kamil.springstatemachineexporter.analysis.service.CodebaseIntelligenceProvider; import click.kamil.springstatemachineexporter.analysis.service.EventCarrierPolicy; import click.kamil.springstatemachineexporter.analysis.service.JsonExportContextFactory; @@ -279,49 +280,11 @@ public class TransitionLinkerEnricher implements AnalysisEnricher { if (constraint == null || machineName == null) { return true; } - String machineConstraint = stripEventBindingClauses(constraint); + String machineConstraint = CarrierConstraintSupport.stripNonMachineClauses(constraint); return BooleanConstraintEvaluator.isCompatibleWithMachineDomain( machineConstraint, MachineDomainKeys.extractMachineDomainKey(machineName)); } - private static String stripEventBindingClauses(String constraint) { - if (constraint == null || constraint.isBlank()) { - return constraint; - } - // Event/payload binding clauses prove which event was selected — not which machine. - // Keep machineType/domain comparisons for isCompatibleWithMachineDomain. - String eventLike = "(?i)(" + EventCarrierPolicy.carrierNameAlternation() + ")"; - String stripped = constraint.replaceAll( - "\"[^\"]+\"\\s*\\.\\s*equalsIgnoreCase\\s*\\(\\s*" + eventLike + "\\s*\\)", - "true"); - stripped = stripped.replaceAll( - eventLike + "\\s*\\.\\s*equalsIgnoreCase\\s*\\(\\s*\"[^\"]+\"\\s*\\)", - "true"); - stripped = stripped.replaceAll( - "\"[^\"]+\"\\s*\\.\\s*equals\\s*\\(\\s*" + eventLike + "\\s*\\)", - "true"); - stripped = stripped.replaceAll( - eventLike + "\\s*\\.\\s*equals\\s*\\(\\s*\"[^\"]+\"\\s*\\)", - "true"); - // Switch-case / arrow constraints often use == on the payload param. - stripped = stripped.replaceAll( - eventLike + "\\s*==\\s*\"[^\"]+\"", - "true"); - stripped = stripped.replaceAll( - "\"[^\"]+\"\\s*==\\s*" + eventLike, - "true"); - stripped = stripped.replaceAll( - eventLike + "\\s*!=\\s*\"[^\"]+\"", - "true"); - stripped = stripped.replaceAll( - "\"[^\"]+\"\\s*!=\\s*" + eventLike, - "true"); - stripped = stripped.replaceAll("&&\\s*&&+", "&&"); - stripped = stripped.replaceAll("^\\s*&&\\s*", ""); - stripped = stripped.replaceAll("\\s*&&\\s*$", ""); - return stripped.trim(); - } - private String extractStateEnumType(String stateIdentifier) { if (stateIdentifier == null || stateIdentifier.isBlank()) { return stateIdentifier; @@ -452,14 +415,8 @@ public class TransitionLinkerEnricher implements AnalysisEnricher { if (colon > 0) { lower = lower.substring(0, colon); } - return lower.equals("event") - || lower.equals("e") - || lower.endsWith("event") - || lower.equals("command") - || lower.equals("commandkey") - || lower.equals("transition") - || lower.equals("action") - || lower.equals("machinetype"); + return EventCarrierPolicy.isCarrierParamName(lower) + || EventCarrierPolicy.isMachineDiscriminatorName(lower); } private static boolean hasConcreteEventEvidence(TriggerPoint trigger) { diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/matching/HeuristicEventMatchingEngine.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/matching/HeuristicEventMatchingEngine.java index 8ca83a3..8d21745 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/matching/HeuristicEventMatchingEngine.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/matching/HeuristicEventMatchingEngine.java @@ -158,13 +158,12 @@ public class HeuristicEventMatchingEngine implements EventMatchingEngine { private boolean isWildcardVariable(String eventStr) { if (eventStr == null) return false; - - if (eventStr.equals("event") || eventStr.equals("e") || - eventStr.equals("msg") || eventStr.equals("message") || - eventStr.equals("payload")) { + + if (click.kamil.springstatemachineexporter.analysis.service.EventCarrierPolicy + .isDynamicEventToken(eventStr)) { return true; } - + if (eventStr.contains(".valueOf(") || eventStr.contains("valueOf (")) { return true; } @@ -172,7 +171,7 @@ public class HeuristicEventMatchingEngine implements EventMatchingEngine { if (eventStr.contains(" ? ") && eventStr.contains(" : ")) { return true; } - + return false; } diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/resolver/MachineEnumCanonicalizer.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/resolver/MachineEnumCanonicalizer.java index 79c2ecc..269d03f 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/resolver/MachineEnumCanonicalizer.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/resolver/MachineEnumCanonicalizer.java @@ -681,9 +681,8 @@ public final class MachineEnumCanonicalizer { if (eventStr.contains("${")) { return true; } - if (eventStr.equals("event") || eventStr.equals("e") - || eventStr.equals("msg") || eventStr.equals("message") - || eventStr.equals("payload")) { + if (click.kamil.springstatemachineexporter.analysis.service.EventCarrierPolicy + .isDynamicEventToken(eventStr)) { return true; } if (eventStr.contains(".valueOf(") || eventStr.contains("valueOf (")) { @@ -1199,11 +1198,8 @@ public final class MachineEnumCanonicalizer { .matcher(constraint); while (matcher.find()) { String param = matcher.group(2); - if ("event".equals(param) - || "eventString".equals(param) - || "actionKey".equals(param) - || "action".equals(param) - || "commandKey".equals(param)) { + if (click.kamil.springstatemachineexporter.analysis.service.EventCarrierPolicy + .isCarrierParamName(param)) { literals.add(matcher.group(1)); } } diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java index ffa7491..38e99ab 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java @@ -12,7 +12,6 @@ import click.kamil.springstatemachineexporter.analysis.model.CallEdge; import click.kamil.springstatemachineexporter.analysis.model.EntryPoint; import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint; import click.kamil.springstatemachineexporter.ast.common.CodebaseContext; -import click.kamil.springstatemachineexporter.analysis.resolver.BooleanConstraintEvaluator; import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver; import click.kamil.springstatemachineexporter.analysis.resolver.MachineEnumCanonicalizer; import lombok.extern.slf4j.Slf4j; @@ -144,7 +143,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine { && resolvedTp.getConstraint() != null && constraintBindings != null && !constraintBindings.isEmpty() - && !BooleanConstraintEvaluator.isCompatibleWithKnownBindings( + && CarrierConstraintSupport.contradictsCarrierBindings( resolvedTp.getConstraint(), constraintBindings)) { continue; } diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupport.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupport.java new file mode 100644 index 0000000..6ed6837 --- /dev/null +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupport.java @@ -0,0 +1,89 @@ +package click.kamil.springstatemachineexporter.analysis.service; + +import click.kamil.springstatemachineexporter.analysis.resolver.BooleanConstraintEvaluator; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * Carrier-aware constraint helpers shared by call-graph filtering and transition linking. + * Payload/event binding clauses are not machine-domain evidence. + */ +public final class CarrierConstraintSupport { + + private CarrierConstraintSupport() { + } + + /** + * Removes equals / {@code ==} / {@code !=} clauses whose parameter is an event/payload carrier, + * leaving machine-domain discriminators for {@link BooleanConstraintEvaluator#isCompatibleWithMachineDomain}. + */ + public static String stripNonMachineClauses(String constraint) { + if (constraint == null || constraint.isBlank()) { + return constraint; + } + String eventLike = "(?i)(" + EventCarrierPolicy.carrierNameAlternation() + ")"; + String stripped = constraint.replaceAll( + "\"[^\"]+\"\\s*\\.\\s*equalsIgnoreCase\\s*\\(\\s*" + eventLike + "\\s*\\)", + "true"); + stripped = stripped.replaceAll( + eventLike + "\\s*\\.\\s*equalsIgnoreCase\\s*\\(\\s*\"[^\"]+\"\\s*\\)", + "true"); + stripped = stripped.replaceAll( + "\"[^\"]+\"\\s*\\.\\s*equals\\s*\\(\\s*" + eventLike + "\\s*\\)", + "true"); + stripped = stripped.replaceAll( + eventLike + "\\s*\\.\\s*equals\\s*\\(\\s*\"[^\"]+\"\\s*\\)", + "true"); + stripped = stripped.replaceAll( + eventLike + "\\s*==\\s*\"[^\"]+\"", + "true"); + stripped = stripped.replaceAll( + "\"[^\"]+\"\\s*==\\s*" + eventLike, + "true"); + stripped = stripped.replaceAll( + eventLike + "\\s*!=\\s*\"[^\"]+\"", + "true"); + stripped = stripped.replaceAll( + "\"[^\"]+\"\\s*!=\\s*" + eventLike, + "true"); + stripped = stripped.replaceAll("&&\\s*&&+", "&&"); + stripped = stripped.replaceAll("^\\s*&&\\s*", ""); + stripped = stripped.replaceAll("\\s*&&\\s*$", ""); + return stripped.trim(); + } + + /** + * True when the constraint contradicts entry/path bindings on overlapping carrier keys. + * Unrelated locals (e.g. {@code command} vs binding {@code commandKey}) are ignored. + */ + public static boolean contradictsCarrierBindings(String constraint, Map bindings) { + if (constraint == null || constraint.isBlank() || bindings == null || bindings.isEmpty()) { + return false; + } + Map carrierBindings = new LinkedHashMap<>(); + for (Map.Entry entry : bindings.entrySet()) { + String key = entry.getKey(); + if (key == null || !EventCarrierPolicy.isCarrierParamName(key)) { + continue; + } + if (!constraintMentionsIdent(constraint, key)) { + continue; + } + carrierBindings.put(key, entry.getValue()); + } + if (carrierBindings.isEmpty()) { + return false; + } + return !BooleanConstraintEvaluator.isCompatibleWithKnownBindings(constraint, carrierBindings); + } + + private static boolean constraintMentionsIdent(String constraint, String ident) { + if (constraint == null || ident == null || ident.isBlank()) { + return false; + } + Pattern word = Pattern.compile("(?i)\\b" + Pattern.quote(ident) + "\\b"); + return word.matcher(constraint).find(); + } +} diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicy.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicy.java index ff4be91..f87246f 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicy.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicy.java @@ -43,6 +43,14 @@ public final class EventCarrierPolicy { "sourcestate", "fromstate"); + /** Bare unresolved trigger tokens (not FQNs / expressions). */ + private static final Set DYNAMIC_EVENT_TOKENS = Set.of( + "event", + "e", + "message", + "msg", + "payload"); + private EventCarrierPolicy() { } @@ -71,6 +79,17 @@ public final class EventCarrierPolicy { return isCarrierParamName(name) || isMachineDiscriminatorName(name); } + /** + * Bare identifier used as an unresolved trigger event expression + * ({@code event}, {@code message}, {@code payload}, …). + */ + public static boolean isDynamicEventToken(String eventStr) { + if (eventStr == null || eventStr.isBlank()) { + return false; + } + return DYNAMIC_EVENT_TOKENS.contains(eventStr.toLowerCase(Locale.ROOT)); + } + /** Clear state-variable / accessor names used for positive source-state inference. */ public static boolean isStateAccessorName(String name) { if (name == null || name.isBlank()) { @@ -84,7 +103,7 @@ public final class EventCarrierPolicy { } /** - * Messaging {@code @Payload} or unannotated String body that looks like an event carrier. + * Messaging {@code @Payload}, conventional carrier name, or the sole unannotated String body. */ public static boolean isMessagingPayloadParameter(EntryPoint entryPoint, EntryPoint.Parameter parameter) { if (entryPoint == null || parameter == null || !isMessagingEntryPoint(entryPoint)) { @@ -100,7 +119,41 @@ public final class EventCarrierPolicy { if (!isStringType(parameter.getType())) { return false; } - return isCarrierParamName(parameter.getName()); + if (isCarrierParamName(parameter.getName())) { + return true; + } + return isSoleUnannotatedStringMessagingBody(entryPoint, parameter); + } + + /** + * Unannotated {@code String} body that is the only such param on a messaging entry — + * treat as carrier even when named {@code cmd}. + */ + public static boolean isSoleUnannotatedStringMessagingBody( + EntryPoint entryPoint, EntryPoint.Parameter parameter) { + if (entryPoint == null || parameter == null || !isMessagingEntryPoint(entryPoint)) { + return false; + } + if (parameter.getAnnotations() != null && !parameter.getAnnotations().isEmpty()) { + return false; + } + if (!isStringType(parameter.getType())) { + return false; + } + if (entryPoint.getParameters() == null) { + return false; + } + int unannotatedStringBodies = 0; + for (EntryPoint.Parameter candidate : entryPoint.getParameters()) { + if (candidate == null) { + continue; + } + boolean unannotated = candidate.getAnnotations() == null || candidate.getAnnotations().isEmpty(); + if (unannotated && isStringType(candidate.getType())) { + unannotatedStringBodies++; + } + } + return unannotatedStringBodies == 1; } /** @@ -148,24 +201,16 @@ public final class EventCarrierPolicy { } /** - * Alternation for regex consumers (linker constraint stripping). Names are already lowercased - * where case-insensitive flags are used by the caller. + * Alternation for carrier-clause regex stripping ({@link CarrierConstraintSupport}). + * Includes camelCase aliases so source that uses {@code commandKey} matches under {@code (?i)}. */ - public static String carrierNameAlternation() { - return Stream.concat( - CARRIER_NAMES.stream(), - Stream.of("commandKey")) + static String carrierNameAlternation() { + return Stream.concat(CARRIER_NAMES.stream(), Stream.of("commandKey", "eventString", "actionKey")) .distinct() .sorted() .collect(Collectors.joining("|")); } - public static String routingDiscriminantAlternation() { - return Stream.concat(CARRIER_NAMES.stream(), MACHINE_DISCRIMINATOR_NAMES.stream()) - .sorted() - .collect(Collectors.joining("|")); - } - private static boolean hasAnnotation(EntryPoint.Parameter parameter, String simpleName) { if (parameter.getAnnotations() == null || simpleName == null) { return false; diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java index 91cd431..0796e18 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java @@ -800,11 +800,38 @@ public class GenericEventDetector { if (hasPayloadAnnotation(param)) { return true; } - return EventCarrierPolicy.isCarrierParamName(param.getName().getIdentifier()); + if (EventCarrierPolicy.isCarrierParamName(param.getName().getIdentifier())) { + return true; + } + // Sole unannotated String param on the method — same rule as messaging body carrier. + return countUnannotatedStringParams(method) == 1; } return false; } + private static int countUnannotatedStringParams(MethodDeclaration method) { + int count = 0; + for (Object paramObj : method.parameters()) { + if (!(paramObj instanceof SingleVariableDeclaration param)) { + continue; + } + if (hasPayloadAnnotation(param)) { + continue; + } + boolean unannotated = true; + for (Object modifier : param.modifiers()) { + if (modifier instanceof Annotation) { + unannotated = false; + break; + } + } + if (unannotated && isStringType(param.getType())) { + count++; + } + } + return count; + } + private static boolean isStringType(org.eclipse.jdt.core.dom.Type type) { if (type == null) { return false; diff --git a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupportTest.java b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupportTest.java new file mode 100644 index 0000000..22092be --- /dev/null +++ b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/CarrierConstraintSupportTest.java @@ -0,0 +1,46 @@ +package click.kamil.springstatemachineexporter.analysis.service; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class CarrierConstraintSupportTest { + + @Test + void stripNonMachineClausesRemovesPayloadEquals() { + String stripped = CarrierConstraintSupport.stripNonMachineClauses( + "\"PAY\".equalsIgnoreCase(message) && message == \"PAY\""); + assertThat(stripped).isEqualToIgnoringWhitespace("true && true"); + } + + @Test + void stripNonMachineClausesKeepsMachineDomainClauses() { + String stripped = CarrierConstraintSupport.stripNonMachineClauses( + "\"ORDER\".equalsIgnoreCase(machineType) && message == \"PAY\""); + assertThat(stripped).contains("machineType"); + assertThat(stripped).doesNotContain("message == "); + } + + @Test + void contradictsWhenCarrierBindingConflictsWithConstraint() { + assertThat(CarrierConstraintSupport.contradictsCarrierBindings( + "message == \"SHIP\"", + Map.of("message", "PAY"))).isTrue(); + } + + @Test + void doesNotContradictWhenCarrierBindingMatchesConstraint() { + assertThat(CarrierConstraintSupport.contradictsCarrierBindings( + "\"PAY\".equalsIgnoreCase(message) && message == \"PAY\"", + Map.of("message", "PAY"))).isFalse(); + } + + @Test + void doesNotContradictWhenConstraintLocalsDoNotOverlapCarrierBindings() { + assertThat(CarrierConstraintSupport.contradictsCarrierBindings( + "command == ORDER_PAY", + Map.of("commandKey", "order.pay"))).isFalse(); + } +} diff --git a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicyTest.java b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicyTest.java index ba94c8e..e985eb1 100644 --- a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicyTest.java +++ b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/analysis/service/EventCarrierPolicyTest.java @@ -4,6 +4,7 @@ import click.kamil.springstatemachineexporter.analysis.model.EntryPoint; import org.junit.jupiter.api.Test; import java.util.List; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -19,6 +20,15 @@ class EventCarrierPolicyTest { assertThat(EventCarrierPolicy.isCarrierParamName("cmd")).isFalse(); } + @Test + void dynamicEventTokensMatchBareUnresolvedTriggers() { + assertThat(EventCarrierPolicy.isDynamicEventToken("event")).isTrue(); + assertThat(EventCarrierPolicy.isDynamicEventToken("message")).isTrue(); + assertThat(EventCarrierPolicy.isDynamicEventToken("payload")).isTrue(); + assertThat(EventCarrierPolicy.isDynamicEventToken("OrderEvent.PAY")).isFalse(); + assertThat(EventCarrierPolicy.isDynamicEventToken("cmd")).isFalse(); + } + @Test void machineDiscriminatorsAreRoutingButNotCarriers() { assertThat(EventCarrierPolicy.isMachineDiscriminatorName("machineType")).isTrue(); @@ -55,6 +65,54 @@ class EventCarrierPolicyTest { entryPoint, entryPoint.getParameters().get(0))).isTrue(); } + @Test + void soleUnannotatedStringMessagingBodyIsCarrierEvenWhenNamedCmd() { + EntryPoint entryPoint = EntryPoint.builder() + .type(EntryPoint.Type.JMS) + .name("JMS: q") + .className("com.example.L") + .methodName("onMessage") + .parameters(List.of(EntryPoint.Parameter.builder() + .name("cmd") + .type("String") + .annotations(List.of()) + .build())) + .build(); + + assertThat(EventCarrierPolicy.isSoleUnannotatedStringMessagingBody( + entryPoint, entryPoint.getParameters().get(0))).isTrue(); + assertThat(EventCarrierPolicy.isMessagingPayloadParameter( + entryPoint, entryPoint.getParameters().get(0))).isTrue(); + } + + @Test + void twoUnannotatedStringBodiesAreNotAutoCarriersBySoleBodyRule() { + EntryPoint entryPoint = EntryPoint.builder() + .type(EntryPoint.Type.JMS) + .name("JMS: q") + .className("com.example.L") + .methodName("onMessage") + .parameters(List.of( + EntryPoint.Parameter.builder() + .name("cmd") + .type("String") + .annotations(List.of()) + .build(), + EntryPoint.Parameter.builder() + .name("extra") + .type("String") + .annotations(List.of()) + .build())) + .build(); + + assertThat(EventCarrierPolicy.isSoleUnannotatedStringMessagingBody( + entryPoint, entryPoint.getParameters().get(0))).isFalse(); + assertThat(EventCarrierPolicy.isMessagingPayloadParameter( + entryPoint, entryPoint.getParameters().get(0))).isFalse(); + assertThat(EventCarrierPolicy.isMessagingPayloadParameter( + entryPoint, entryPoint.getParameters().get(1))).isFalse(); + } + @Test void unannotatedMessagingStringUsesCarrierNameConvention() { EntryPoint entryPoint = EntryPoint.builder() @@ -72,12 +130,4 @@ class EventCarrierPolicyTest { assertThat(EventCarrierPolicy.isMessagingPayloadParameter( entryPoint, entryPoint.getParameters().get(0))).isTrue(); } - - @Test - void carrierNameAlternationIsNonEmptyForLinkerRegex() { - assertThat(EventCarrierPolicy.carrierNameAlternation()) - .contains("message") - .contains("payload") - .contains("event"); - } }