diff --git a/src/main/software/amazon/event/ruler/ACFinder.java b/src/main/software/amazon/event/ruler/ACFinder.java index b23d9ec..367e778 100644 --- a/src/main/software/amazon/event/ruler/ACFinder.java +++ b/src/main/software/amazon/event/ruler/ACFinder.java @@ -78,7 +78,7 @@ private static void tryStep(final ACTask task, final SubRuleContext.Generator su } } - private static void tryMustNotExistMatch(final Set candidateSubRuleIds, final NameState nameState, + private static void tryMustNotExistMatch(final Set candidateSubRuleIds, final NameState nameState, final ACTask task, int nextKeyIndex, final ArrayMembership arrayMembership, final SubRuleContext.Generator subRuleContextGenerator) { if (!nameState.hasKeyTransitions()) { @@ -94,7 +94,7 @@ private static void tryMustNotExistMatch(final Set candidateSubRuleIds, } // Move from a state. Give all the remaining event fields a chance to transition from it. - private static void moveFrom(final Set candidateSubRuleIdsForNextStep, final NameState nameState, + private static void moveFrom(final Set candidateSubRuleIdsForNextStep, final NameState nameState, int fieldIndex, final ACTask task, final ArrayMembership arrayMembership, final SubRuleContext.Generator subRuleContextGenerator) { /* @@ -120,12 +120,12 @@ private static void moveFrom(final Set candidateSubRuleIdsForNextStep, f } } - private static void moveFromWithPriorCandidates(final Set candidateSubRuleIds, + private static void moveFromWithPriorCandidates(final Set candidateSubRuleIds, final NameState fromState, final Patterns fromPattern, final int fieldIndex, final ACTask task, final ArrayMembership arrayMembership, final SubRuleContext.Generator subRuleContextGenerator) { - Set candidateSubRuleIdsForNextStep = calculateCandidateSubRuleIdsForNextStep(candidateSubRuleIds, + Set candidateSubRuleIdsForNextStep = calculateCandidateSubRuleIdsForNextStep(candidateSubRuleIds, fromState, fromPattern); // If there are no more candidate sub-rules, there is no need to proceed further. @@ -145,12 +145,12 @@ private static void moveFromWithPriorCandidates(final Set candidateSubRu * @return The set of candidate sub-rule IDs for the next step. Null means there are no candidates and thus, there * is no point to evaluating subsequent steps. */ - private static Set calculateCandidateSubRuleIdsForNextStep(final Set currentCandidateSubRuleIds, + private static Set calculateCandidateSubRuleIdsForNextStep(final Set currentCandidateSubRuleIds, final NameState fromState, final Patterns fromPattern) { // These are all the sub-rules that use the matched pattern to transition to the next NameState. Note that they // are not all candidates as they may have required different values for previously evaluated fields. - Set subRuleIds = fromState.getNonTerminalSubRuleIdsForPattern(fromPattern); + Set subRuleIds = fromState.getNonTerminalSubRuleIdsForPattern(fromPattern); // If no sub-rules used the matched pattern to transition to the next NameState, then there are no matches to be // found by going further. @@ -166,12 +166,12 @@ private static Set calculateCandidateSubRuleIdsForNextStep(final Set candidateSubRuleIdsForNextStep = new HashSet<>(); + Set candidateSubRuleIdsForNextStep = new HashSet<>(); intersection(subRuleIds, currentCandidateSubRuleIds, candidateSubRuleIdsForNextStep); return candidateSubRuleIdsForNextStep; } - private static void addNameState(Set candidateSubRuleIds, NameState nameState, Patterns pattern, + private static void addNameState(Set candidateSubRuleIds, NameState nameState, Patterns pattern, ACTask task, int nextKeyIndex, final ArrayMembership arrayMembership, final SubRuleContext.Generator subRuleContextGenerator) { // one of the matches might imply a rule match diff --git a/src/main/software/amazon/event/ruler/ACStep.java b/src/main/software/amazon/event/ruler/ACStep.java index a9f72a0..e628e03 100644 --- a/src/main/software/amazon/event/ruler/ACStep.java +++ b/src/main/software/amazon/event/ruler/ACStep.java @@ -8,10 +8,10 @@ class ACStep { final int fieldIndex; final NameState nameState; - final Set candidateSubRuleIds; + final Set candidateSubRuleIds; final ArrayMembership membershipSoFar; - ACStep(final int fieldIndex, final NameState nameState, final Set candidateSubRuleIds, + ACStep(final int fieldIndex, final NameState nameState, final Set candidateSubRuleIds, final ArrayMembership arrayMembership) { this.fieldIndex = fieldIndex; this.nameState = nameState; diff --git a/src/main/software/amazon/event/ruler/ACTask.java b/src/main/software/amazon/event/ruler/ACTask.java index 2a2fa5f..90b45ca 100644 --- a/src/main/software/amazon/event/ruler/ACTask.java +++ b/src/main/software/amazon/event/ruler/ACTask.java @@ -44,7 +44,7 @@ ACStep nextStep() { /* * Add a step to the queue for later consideration */ - void addStep(final int fieldIndex, final NameState nameState, final Set candidateSubRuleIds, + void addStep(final int fieldIndex, final NameState nameState, final Set candidateSubRuleIds, final ArrayMembership membershipSoFar) { stepQueue.add(new ACStep(fieldIndex, nameState, candidateSubRuleIds, membershipSoFar)); } @@ -57,21 +57,21 @@ List getMatchedRules() { return new ArrayList<>(matchingRules); } - void collectRules(final Set candidateSubRuleIds, final NameState nameState, final Patterns pattern, + void collectRules(final Set candidateSubRuleIds, final NameState nameState, final Patterns pattern, final SubRuleContext.Generator subRuleContextGenerator) { - Set terminalSubRuleIds = nameState.getTerminalSubRuleIdsForPattern(pattern); + Set terminalSubRuleIds = nameState.getTerminalSubRuleIdsForPattern(pattern); if (terminalSubRuleIds == null) { return; } // If no candidates, that means we're on the first step, so all sub-rules are candidates. if (candidateSubRuleIds == null || candidateSubRuleIds.isEmpty()) { - for (Double terminalSubRuleId : terminalSubRuleIds) { - matchingRules.add(subRuleContextGenerator.getNameForGeneratedId(terminalSubRuleId)); + for (SubRuleContext terminalSubRuleId : terminalSubRuleIds) { + matchingRules.add(terminalSubRuleId.getRuleName()); } } else { intersection(candidateSubRuleIds, terminalSubRuleIds, matchingRules, - id -> subRuleContextGenerator.getNameForGeneratedId(id)); + SubRuleContext::getRuleName); } } } diff --git a/src/main/software/amazon/event/ruler/Finder.java b/src/main/software/amazon/event/ruler/Finder.java index 754b62c..2bb31db 100644 --- a/src/main/software/amazon/event/ruler/Finder.java +++ b/src/main/software/amazon/event/ruler/Finder.java @@ -83,7 +83,7 @@ private static List find(final Task task, final SubRuleContext.Generator } // Move from a state. Give all the remaining tokens a chance to transition from it - private static void moveFrom(final Set candidateSubRuleIdsForNextStep, final NameState nameState, + private static void moveFrom(final Set candidateSubRuleIdsForNextStep, final NameState nameState, final int tokenIndex, final Task task, final SubRuleContext.Generator subRuleContextGenerator) { /* @@ -111,11 +111,11 @@ private static void moveFrom(final Set candidateSubRuleIdsForNextStep, f } } - private static void moveFromWithPriorCandidates(final Set candidateSubRuleIds, + private static void moveFromWithPriorCandidates(final Set candidateSubRuleIds, final NameState fromState, final Patterns fromPattern, final int tokenIndex, final Task task, final SubRuleContext.Generator subRuleContextGenerator) { - Set candidateSubRuleIdsForNextStep = calculateCandidateSubRuleIdsForNextStep(candidateSubRuleIds, + Set candidateSubRuleIdsForNextStep = calculateCandidateSubRuleIdsForNextStep(candidateSubRuleIds, fromState, fromPattern); // If there are no more candidate sub-rules, there is no need to proceed further. @@ -135,12 +135,12 @@ private static void moveFromWithPriorCandidates(final Set candidateSubRu * @return The set of candidate sub-rule IDs for the next step. Null means there are no candidates and thus, there * is no point to evaluating subsequent steps. */ - private static Set calculateCandidateSubRuleIdsForNextStep(final Set currentCandidateSubRuleIds, + private static Set calculateCandidateSubRuleIdsForNextStep(final Set currentCandidateSubRuleIds, final NameState fromState, final Patterns fromPattern) { // These are all the sub-rules that use the matched pattern to transition to the next NameState. Note that they // are not all candidates as they may have required different values for previously evaluated fields. - Set subRuleIds = fromState.getNonTerminalSubRuleIdsForPattern(fromPattern); + Set subRuleIds = fromState.getNonTerminalSubRuleIdsForPattern(fromPattern); // If no sub-rules used the matched pattern to transition to the next NameState, then there are no matches to be // found by going further. @@ -156,7 +156,7 @@ private static Set calculateCandidateSubRuleIdsForNextStep(final Set candidateSubRuleIdsForNextStep = new HashSet<>(); + Set candidateSubRuleIdsForNextStep = new HashSet<>(); intersection(subRuleIds, currentCandidateSubRuleIds, candidateSubRuleIdsForNextStep); return candidateSubRuleIdsForNextStep; } @@ -193,7 +193,7 @@ private static void tryValueMatching(final Task task, final Step step, } } - private static void tryNameMatching(final Set candidateSubRuleIds, final NameState nameState, + private static void tryNameMatching(final Set candidateSubRuleIds, final NameState nameState, final Task task, final int keyIndex, final SubRuleContext.Generator subRuleContextGenerator) { if (!nameState.hasKeyTransitions()) { @@ -208,7 +208,7 @@ private static void tryNameMatching(final Set candidateSubRuleIds, final } } - private static void addNameState(Set candidateSubRuleIds, NameState nameState, Patterns pattern, Task task, + private static void addNameState(Set candidateSubRuleIds, NameState nameState, Patterns pattern, Task task, int nextKeyIndex, final SubRuleContext.Generator subRuleContextGenerator) { // one of the matches might imply a rule match task.collectRules(candidateSubRuleIds, nameState, pattern, subRuleContextGenerator); diff --git a/src/main/software/amazon/event/ruler/GenericMachine.java b/src/main/software/amazon/event/ruler/GenericMachine.java index bb4e40c..0c76519 100644 --- a/src/main/software/amazon/event/ruler/GenericMachine.java +++ b/src/main/software/amazon/event/ruler/GenericMachine.java @@ -255,7 +255,7 @@ public void deletePatternRule(final T name, final Map> na Collections.sort(keys); synchronized(this) { final List deletedKeys = new ArrayList<>(); - final Set candidateSubRuleIds = new HashSet<>(); + final Set candidateSubRuleIds = new HashSet<>(); deleteStep(getStartState(), keys, 0, namevals, name, deletedKeys, candidateSubRuleIds); // check and delete the key from filedUsed ... checkAndDeleteUsedFields(deletedKeys); @@ -272,15 +272,15 @@ public void deleteRule(final T name, final Map> namevals) { deletePatternRule(name, patternMap); } - private Set deleteStep(final NameState state, + private Set deleteStep(final NameState state, final List keys, final int keyIndex, final Map> patterns, final T ruleName, final List deletedKeys, - final Set candidateSubRuleIds) { + final Set candidateSubRuleIds) { - final Set deletedSubRuleIds = new HashSet<>(); + final Set deletedSubRuleIds = new HashSet<>(); final String key = keys.get(keyIndex); ByteMachine byteMachine = state.getTransitionOn(key); NameMatcher nameMatcher = state.getKeyTransitionOn(key); @@ -309,7 +309,7 @@ private Set deleteStep(final NameState state, boolean isTerminal = nextKeyIndex == keys.size(); // Trim the candidate sub-rule ID set to contain only the sub-rule IDs present in the next NameState. - Set nextNameStateSubRuleIds = isTerminal ? + Set nextNameStateSubRuleIds = isTerminal ? nextNameState.getTerminalSubRuleIdsForPattern(pattern) : nextNameState.getNonTerminalSubRuleIdsForPattern(pattern); // If no sub-rule IDs are found for next NameState, then we have no candidates, and will return below @@ -319,9 +319,9 @@ private Set deleteStep(final NameState state, // If candidate set is empty, we are at first NameState, so initialize to next NameState's sub-rule IDs. // When initializing, ensure that sub-rule IDs match the provided rule name for deletion. } else if (candidateSubRuleIds.isEmpty()) { - for (Double nextNameStateSubRuleId : nextNameStateSubRuleIds) { + for (SubRuleContext nextNameStateSubRuleId : nextNameStateSubRuleIds) { if (Objects.equals(ruleName, - subRuleContextGenerator.getNameForGeneratedId(nextNameStateSubRuleId))) { + nextNameStateSubRuleId.getRuleName())) { candidateSubRuleIds.add(nextNameStateSubRuleId); } } @@ -331,9 +331,9 @@ private Set deleteStep(final NameState state, } if (isTerminal) { - for (Double candidateSubRuleId : candidateSubRuleIds) { + for (SubRuleContext candidateSubRuleId : candidateSubRuleIds) { if (nextNameState.deleteSubRule( - subRuleContextGenerator.getNameForGeneratedId(candidateSubRuleId), candidateSubRuleId, + candidateSubRuleId.getRuleName(), candidateSubRuleId, pattern, true)) { deletedSubRuleIds.add(candidateSubRuleId); // Only delete the pattern if the pattern does not transition to the next NameState. @@ -351,8 +351,8 @@ private Set deleteStep(final NameState state, deletedSubRuleIds.addAll(deleteStep(nextNameState, keys, nextKeyIndex, patterns, ruleName, deletedKeys, new HashSet<>(candidateSubRuleIds))); - for (double deletedSubRuleId : deletedSubRuleIds) { - nextNameState.deleteSubRule(subRuleContextGenerator.getNameForGeneratedId(deletedSubRuleId), + for (SubRuleContext deletedSubRuleId : deletedSubRuleIds) { + nextNameState.deleteSubRule(deletedSubRuleId.getRuleName(), deletedSubRuleId, pattern, false); } @@ -519,7 +519,7 @@ private void addStep(final List keys, boolean isTerminal = i + 1 == keys.size(); for (Patterns pattern : patterns.get(keys.get(i))) { for (NameState nameState : nameStates[i]) { - nameState.addSubRule(ruleName, context.getId(), pattern, isTerminal); + nameState.addSubRule(ruleName, context, pattern, isTerminal); } } } @@ -541,7 +541,7 @@ private void addStep(final List keys, * keyIndex and greater. If keyIndex==0 and the returned set is empty, then the keys and patterns being * added represent a new sub-rule. */ - private Set addStep(final NameState state, + private Set addStep(final NameState state, final List keys, final int keyIndex, final Map> patterns, @@ -595,8 +595,8 @@ private Set addStep(final NameState state, // rule+pattern for the given key are returned up the recursion stack as our "candidates". At each level of the // stack, we remove any candidates if they did not have the same rule+pattern for that level's key. If our // candidate set becomes empty, we know we are adding a new rule. - Set candidateSubRuleIds = null; - Set candidateSubRuleIdsForThisKey = null; + Set candidateSubRuleIds = null; + Set candidateSubRuleIdsForThisKey = null; final int nextKeyIndex = keyIndex + 1; boolean isTerminal = nextKeyIndex == keys.size(); for (NameState nameState : nameStates) { @@ -606,8 +606,8 @@ private Set addStep(final NameState state, if (isTerminal) { candidateSubRuleIds = new HashSet<>(); for (Patterns pattern : patterns.get(key)) { - Set subRuleIdsForPattern = nameState.getTerminalSubRuleIdsForPattern(pattern); - Set subRuleIdsForName = subRuleContextGenerator.getIdsGeneratedForName(ruleName); + Set subRuleIdsForPattern = nameState.getTerminalSubRuleIdsForPattern(pattern); + Set subRuleIdsForName = subRuleContextGenerator.getIdsGeneratedForName(ruleName); if (subRuleIdsForPattern != null && subRuleIdsForName != null) { intersection(subRuleIdsForPattern, subRuleIdsForName, candidateSubRuleIds); } @@ -632,7 +632,7 @@ private Set addStep(final NameState state, candidateSubRuleIdsForThisKey = new HashSet<>(); for (Patterns pattern : patternsForThisKey) { - Set nonTerminalSubRuleIds = nameState.getNonTerminalSubRuleIdsForPattern(pattern); + Set nonTerminalSubRuleIds = nameState.getNonTerminalSubRuleIdsForPattern(pattern); if (nonTerminalSubRuleIds != null) { candidateSubRuleIdsForThisKey.addAll(nonTerminalSubRuleIds); } diff --git a/src/main/software/amazon/event/ruler/NameState.java b/src/main/software/amazon/event/ruler/NameState.java index 484e17f..e346f8f 100644 --- a/src/main/software/amazon/event/ruler/NameState.java +++ b/src/main/software/amazon/event/ruler/NameState.java @@ -36,13 +36,13 @@ class NameState { private final Map> patternToRules = new ConcurrentHashMap<>(); // All terminal sub-rule IDs, keyed by pattern, that led to this NameState. - private final Map> patternToTerminalSubRuleIds = new ConcurrentHashMap<>(); + private final Map> patternToTerminalSubRuleIds = new ConcurrentHashMap<>(); // All non-terminal sub-rule IDs, keyed by pattern, that led to this NameState. - private final Map> patternToNonTerminalSubRuleIds = new ConcurrentHashMap<>(); + private final Map> patternToNonTerminalSubRuleIds = new ConcurrentHashMap<>(); // All sub-rule IDs mapped to the number of times that sub-rule has been added to this NameState. - private final Map subRuleIdToCount = new ConcurrentHashMap<>(); + private final Map subRuleIdToCount = new ConcurrentHashMap<>(); ByteMachine getTransitionOn(final String token) { return valueTransitions.get(token); @@ -90,7 +90,7 @@ Set getNonTerminalPatterns() { * @param pattern The pattern that the rules must use to get to this NameState. * @return The sub-rules, could be null if none for pattern. */ - Set getTerminalSubRuleIdsForPattern(Patterns pattern) { + Set getTerminalSubRuleIdsForPattern(Patterns pattern) { return patternToTerminalSubRuleIds.get(pattern); } @@ -105,7 +105,7 @@ Set getTerminalSubRuleIdsForPattern(Patterns pattern) { * @param pattern The pattern that the rules must use to get to this NameState. * @return The sub-rule IDs, could be null if none for pattern. */ - Set getNonTerminalSubRuleIdsForPattern(Patterns pattern) { + Set getNonTerminalSubRuleIdsForPattern(Patterns pattern) { return patternToNonTerminalSubRuleIds.get(pattern); } @@ -118,7 +118,7 @@ Set getNonTerminalSubRuleIdsForPattern(Patterns pattern) { * @param isTerminal True indicates that the sub-rule is using pattern to match on the final event field. * @return True if and only if the sub-rule was found and deleted. */ - boolean deleteSubRule(final Object rule, final double subRuleId, final Patterns pattern, final boolean isTerminal) { + boolean deleteSubRule(final Object rule, final SubRuleContext subRuleId, final Patterns pattern, final boolean isTerminal) { deleteFromPatternToSetMap(patternToRules, pattern, rule); Map patternToSubRules = isTerminal ? patternToTerminalSubRuleIds : patternToNonTerminalSubRuleIds; boolean deleted = deleteFromPatternToSetMap(patternToSubRules, pattern, subRuleId); @@ -175,12 +175,11 @@ boolean isEmpty() { * @param pattern The pattern used by the sub-rule to transition to this NameState. * @param isTerminal True indicates that the sub-rule is using pattern to match on the final event field. */ - void addSubRule(final Object rule, final double subRuleId, final Patterns pattern, final boolean isTerminal) { + void addSubRule(final Object rule, final SubRuleContext subRuleId, final Patterns pattern, final boolean isTerminal) { addToPatternToSetMap(patternToRules, pattern, rule); Map patternToSubRules = isTerminal ? patternToTerminalSubRuleIds : patternToNonTerminalSubRuleIds; if (addToPatternToSetMap(patternToSubRules, pattern, subRuleId)) { - Integer count = subRuleIdToCount.get(subRuleId); - subRuleIdToCount.put(subRuleId, count == null ? 1 : count + 1); + subRuleIdToCount.compute(subRuleId, (k, count) -> count == null ? 1 : count + 1); } } @@ -310,11 +309,11 @@ public void gatherObjects(Set objectSet, int maxObjectCount) { for (Map.Entry> mustNotExistEntry : mustNotExistMatchers.entrySet()) { mustNotExistEntry.getValue().getNextState().gatherObjects(objectSet, maxObjectCount); } - for (Map.Entry> entry : patternToTerminalSubRuleIds.entrySet()) { + for (Map.Entry> entry : patternToTerminalSubRuleIds.entrySet()) { objectSet.add(entry.getKey()); objectSet.addAll(entry.getValue()); } - for (Map.Entry> entry : patternToNonTerminalSubRuleIds.entrySet()) { + for (Map.Entry> entry : patternToNonTerminalSubRuleIds.entrySet()) { objectSet.add(entry.getKey()); objectSet.addAll(entry.getValue()); } diff --git a/src/main/software/amazon/event/ruler/Step.java b/src/main/software/amazon/event/ruler/Step.java index 5e6099a..7446b3e 100644 --- a/src/main/software/amazon/event/ruler/Step.java +++ b/src/main/software/amazon/event/ruler/Step.java @@ -14,9 +14,9 @@ class Step { final int keyIndex; final NameState nameState; - final Set candidateSubRuleIds; + final Set candidateSubRuleIds; - Step(final int keyIndex, final NameState nameState, final Set candidateSubRuleIds) { + Step(final int keyIndex, final NameState nameState, final Set candidateSubRuleIds) { this.keyIndex = keyIndex; this.nameState = nameState; this.candidateSubRuleIds = candidateSubRuleIds; diff --git a/src/main/software/amazon/event/ruler/SubRuleContext.java b/src/main/software/amazon/event/ruler/SubRuleContext.java index a3ee643..9175925 100644 --- a/src/main/software/amazon/event/ruler/SubRuleContext.java +++ b/src/main/software/amazon/event/ruler/SubRuleContext.java @@ -11,30 +11,34 @@ * A sub-rule refers to name/value pairs, usually represented by Map of String to List of Patterns, that compose a rule. * In the case of $or, one rule will have multiple name/value pairs, and this is why we use the "sub-rule" terminology. */ -public class SubRuleContext { +public final class SubRuleContext { - private final double id; + private final long id; + private final Object ruleName; - private SubRuleContext(double id) { + SubRuleContext(long id, Object ruleName) { this.id = id; + this.ruleName = ruleName; } - public double getId() { - return id; + public Object getRuleName() { + return ruleName; } @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof SubRuleContext)) { - return false; + public boolean equals(Object obj) { + if (this == obj) { + return true; } - SubRuleContext otherContext = (SubRuleContext) o; - return id == otherContext.id; + if (obj instanceof SubRuleContext) { + return id == ((SubRuleContext) obj).id; + } + return false; } @Override public int hashCode() { - return Double.hashCode(id); + return Long.hashCode(id); } /** @@ -42,32 +46,17 @@ public int hashCode() { */ static final class Generator { - private double nextId = -Double.MAX_VALUE; - - private final Map> nameToIds = new ConcurrentHashMap<>(); - private final Map idToName = new ConcurrentHashMap<>(); + private final Map> nameToContext = new ConcurrentHashMap<>(); + private long nextId; public SubRuleContext generate(Object ruleName) { - assert nextId < Double.MAX_VALUE : "SubRuleContext.Generator's nextId reached Double.MAX_VALUE - " + - "this required the equivalent of calling generate() at 6 billion TPS for 100 years"; - - SubRuleContext subRuleContext = new SubRuleContext(nextId); - if (!nameToIds.containsKey(ruleName)) { - nameToIds.put(ruleName, new HashSet<>()); - } - nameToIds.get(ruleName).add(nextId); - idToName.put(nextId, ruleName); - - nextId = Math.nextUp(nextId); + SubRuleContext subRuleContext = new SubRuleContext(nextId++, ruleName); + nameToContext.computeIfAbsent(ruleName, k -> new HashSet<>()).add(subRuleContext); return subRuleContext; } - public Set getIdsGeneratedForName(Object ruleName) { - return nameToIds.get(ruleName); - } - - public Object getNameForGeneratedId(Double id) { - return idToName.get(id); + public Set getIdsGeneratedForName(Object ruleName) { + return nameToContext.get(ruleName); } } } diff --git a/src/main/software/amazon/event/ruler/Task.java b/src/main/software/amazon/event/ruler/Task.java index 95b7af9..c13cc03 100644 --- a/src/main/software/amazon/event/ruler/Task.java +++ b/src/main/software/amazon/event/ruler/Task.java @@ -80,21 +80,21 @@ List getMatchedRules() { return new ArrayList<>(matchingRules); } - void collectRules(final Set candidateSubRuleIds, final NameState nameState, final Patterns pattern, + void collectRules(final Set candidateSubRuleIds, final NameState nameState, final Patterns pattern, final SubRuleContext.Generator subRuleContextGenerator) { - Set terminalSubRuleIds = nameState.getTerminalSubRuleIdsForPattern(pattern); + Set terminalSubRuleIds = nameState.getTerminalSubRuleIdsForPattern(pattern); if (terminalSubRuleIds == null) { return; } // If no candidates, that means we're on the first step, so all sub-rules are candidates. if (candidateSubRuleIds == null || candidateSubRuleIds.isEmpty()) { - for (Double terminalSubRuleId : terminalSubRuleIds) { - matchingRules.add(subRuleContextGenerator.getNameForGeneratedId(terminalSubRuleId)); + for (SubRuleContext terminalSubRuleId : terminalSubRuleIds) { + matchingRules.add(terminalSubRuleId.getRuleName()); } } else { intersection(candidateSubRuleIds, terminalSubRuleIds, matchingRules, - id -> subRuleContextGenerator.getNameForGeneratedId(id)); + SubRuleContext::getRuleName); } } } diff --git a/src/test/software/amazon/event/ruler/NameStateTest.java b/src/test/software/amazon/event/ruler/NameStateTest.java index b934139..c9a0c57 100644 --- a/src/test/software/amazon/event/ruler/NameStateTest.java +++ b/src/test/software/amazon/event/ruler/NameStateTest.java @@ -15,40 +15,45 @@ public class NameStateTest { + final SubRuleContext c1 = new SubRuleContext(1, "c1"); + final SubRuleContext c2 = new SubRuleContext(2, "c2"); + final SubRuleContext c3 = new SubRuleContext(3, "c3"); + final SubRuleContext c4 = new SubRuleContext(4, "c4"); + @Test public void testAddSubRule() { NameState nameState = new NameState(); - nameState.addSubRule("rule1", 1.0, Patterns.exactMatch("a"), true); - nameState.addSubRule("rule1", 2.0, Patterns.exactMatch("b"), true); - nameState.addSubRule("rule2", 3.0, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule1", c1, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule1", c2, Patterns.exactMatch("b"), true); + nameState.addSubRule("rule2", c3, Patterns.exactMatch("a"), true); - assertEquals(new HashSet<>(asList(1.0, 3.0)), + assertEquals(new HashSet<>(asList(c1, c3)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); - assertEquals(new HashSet<>(Collections.singletonList(2.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); + assertEquals(new HashSet<>(Collections.singletonList(c2)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); assertNull(nameState.getNonTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); } @Test public void testDeleteSubRule() { NameState nameState = new NameState(); - nameState.addSubRule("rule1", 1.0, Patterns.exactMatch("a"), true); - nameState.addSubRule("rule2", 2.0, Patterns.exactMatch("b"), true); - - assertEquals(new HashSet<>(Collections.singletonList(1.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); - assertEquals(new HashSet<>(Collections.singletonList(2.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); - nameState.deleteSubRule("rule1", 1.0, Patterns.exactMatch("b"), true); - assertEquals(new HashSet<>(Collections.singletonList(1.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); - assertEquals(new HashSet<>(Collections.singletonList(2.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); - nameState.deleteSubRule("rule2", 2.0, Patterns.exactMatch("b"), true); - assertEquals(new HashSet<>(Collections.singletonList(1.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); + nameState.addSubRule("rule1", c1, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule2", c2, Patterns.exactMatch("b"), true); + + assertEquals(new HashSet<>(Collections.singletonList(c1)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); + assertEquals(new HashSet<>(Collections.singletonList(c2)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); + nameState.deleteSubRule("rule1", c1, Patterns.exactMatch("b"), true); + assertEquals(new HashSet<>(Collections.singletonList(c1)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); + assertEquals(new HashSet<>(Collections.singletonList(c2)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); + nameState.deleteSubRule("rule2", c2, Patterns.exactMatch("b"), true); + assertEquals(new HashSet<>(Collections.singletonList(c1)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); assertNull(nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); - nameState.deleteSubRule("rule2", 2.0, Patterns.exactMatch("a"), true); - assertEquals(new HashSet<>(Collections.singletonList(1.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); + nameState.deleteSubRule("rule2", c2, Patterns.exactMatch("a"), true); + assertEquals(new HashSet<>(Collections.singletonList(c1)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); assertNull(nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); - nameState.deleteSubRule("rule1", 1.0, Patterns.exactMatch("a"), false); - assertEquals(new HashSet<>(Collections.singletonList(1.0)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); + nameState.deleteSubRule("rule1", c1, Patterns.exactMatch("a"), false); + assertEquals(new HashSet<>(Collections.singletonList(c1)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); assertNull(nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); - nameState.deleteSubRule("rule1", 1.0, Patterns.exactMatch("a"), true); + nameState.deleteSubRule("rule1", c1, Patterns.exactMatch("a"), true); assertNull(nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); assertNull(nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("b"))); } @@ -56,10 +61,10 @@ public void testDeleteSubRule() { @Test public void testGetTerminalPatterns() { NameState nameState = new NameState(); - nameState.addSubRule("rule1", 1.0, Patterns.exactMatch("a"), true); - nameState.addSubRule("rule1", 2.0, Patterns.exactMatch("b"), false); - nameState.addSubRule("rule2", 3.0, Patterns.exactMatch("a"), false); - nameState.addSubRule("rule3", 4.0, Patterns.exactMatch("c"), true); + nameState.addSubRule("rule1", c1, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule1", c2, Patterns.exactMatch("b"), false); + nameState.addSubRule("rule2", c3, Patterns.exactMatch("a"), false); + nameState.addSubRule("rule3", c4, Patterns.exactMatch("c"), true); Set expectedPatterns = new HashSet<>(Arrays.asList( Patterns.exactMatch("a"), Patterns.exactMatch("c"))); @@ -69,10 +74,10 @@ public void testGetTerminalPatterns() { @Test public void testGetNonTerminalPatterns() { NameState nameState = new NameState(); - nameState.addSubRule("rule1", 1.0, Patterns.exactMatch("a"), false); - nameState.addSubRule("rule1", 2.0, Patterns.exactMatch("b"), true); - nameState.addSubRule("rule2", 3.0, Patterns.exactMatch("a"), true); - nameState.addSubRule("rule3", 4.0, Patterns.exactMatch("c"), false); + nameState.addSubRule("rule1", c1, Patterns.exactMatch("a"), false); + nameState.addSubRule("rule1", c2, Patterns.exactMatch("b"), true); + nameState.addSubRule("rule2", c3, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule3", c4, Patterns.exactMatch("c"), false); Set expectedPatterns = new HashSet<>(Arrays.asList( Patterns.exactMatch("a"), Patterns.exactMatch("c"))); @@ -82,33 +87,33 @@ public void testGetNonTerminalPatterns() { @Test public void testGetTerminalSubRuleIdsForPattern() { NameState nameState = new NameState(); - nameState.addSubRule("rule1", 1.0, Patterns.exactMatch("a"), false); - nameState.addSubRule("rule1", 2.0, Patterns.exactMatch("a"), true); - nameState.addSubRule("rule2", 3.0, Patterns.exactMatch("b"), false); - nameState.addSubRule("rule3", 4.0, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule1", c1, Patterns.exactMatch("a"), false); + nameState.addSubRule("rule1", c2, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule2", c3, Patterns.exactMatch("b"), false); + nameState.addSubRule("rule3", c4, Patterns.exactMatch("a"), true); - assertEquals(new HashSet<>(Arrays.asList(2.0, 4.0)), + assertEquals(new HashSet<>(Arrays.asList(c2, c4)), nameState.getTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); } @Test public void testGetNonTerminalSubRuleIdsForPattern() { NameState nameState = new NameState(); - nameState.addSubRule("rule1", 1.0, Patterns.exactMatch("a"), true); - nameState.addSubRule("rule1", 2.0, Patterns.exactMatch("a"), false); - nameState.addSubRule("rule2", 3.0, Patterns.exactMatch("a"), false); - nameState.addSubRule("rule3", 4.0, Patterns.exactMatch("b"), false); + nameState.addSubRule("rule1", c1, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule1", c2, Patterns.exactMatch("a"), false); + nameState.addSubRule("rule2", c3, Patterns.exactMatch("a"), false); + nameState.addSubRule("rule3", c4, Patterns.exactMatch("b"), false); - assertEquals(new HashSet<>(Arrays.asList(2.0, 3.0)), + assertEquals(new HashSet<>(Arrays.asList(c2, c3)), nameState.getNonTerminalSubRuleIdsForPattern(Patterns.exactMatch("a"))); } @Test public void testContainsRule() { NameState nameState = new NameState(); - nameState.addSubRule("rule1", 1.0, Patterns.exactMatch("a"), true); - nameState.addSubRule("rule2", 2.0, Patterns.exactMatch("a"), false); - nameState.addSubRule("rule1", 2.0, Patterns.exactMatch("b"), false); + nameState.addSubRule("rule1", c1, Patterns.exactMatch("a"), true); + nameState.addSubRule("rule2", c2, Patterns.exactMatch("a"), false); + nameState.addSubRule("rule1", c2, Patterns.exactMatch("b"), false); assertTrue(nameState.containsRule("rule1", Patterns.exactMatch("a"))); assertTrue(nameState.containsRule("rule2", Patterns.exactMatch("a"))); diff --git a/src/test/software/amazon/event/ruler/SubRuleContextTest.java b/src/test/software/amazon/event/ruler/SubRuleContextTest.java index e78b601..ff97789 100644 --- a/src/test/software/amazon/event/ruler/SubRuleContextTest.java +++ b/src/test/software/amazon/event/ruler/SubRuleContextTest.java @@ -7,45 +7,31 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; public class SubRuleContextTest { private static final String NAME = "name"; @Test - public void testGenerate() { - SubRuleContext.Generator generatorA = new SubRuleContext.Generator(); - SubRuleContext contextA1 = generatorA.generate(NAME); - SubRuleContext contextA2 = generatorA.generate(NAME); - - SubRuleContext.Generator generatorB = new SubRuleContext.Generator(); - SubRuleContext contextB1 = generatorB.generate(NAME); - SubRuleContext contextB2 = generatorB.generate(NAME); - SubRuleContext contextB3 = generatorB.generate(NAME); - - SubRuleContext contextA3 = generatorA.generate(NAME); - - double expected1 = -Double.MAX_VALUE; - double expected2 = Math.nextUp(expected1); - double expected3 = Math.nextUp(expected2); - assertTrue(expected1 < expected2); - assertTrue(expected2 < expected3); - assertEquals(expected1, contextA1.getId(), 0.0); - assertEquals(expected1, contextB1.getId(), 0.0); - assertEquals(expected2, contextA2.getId(), 0.0); - assertEquals(expected2, contextB2.getId(), 0.0); - assertEquals(expected3, contextA3.getId(), 0.0); - assertEquals(expected3, contextB3.getId(), 0.0); + public void testPerformance() { + long start = System.nanoTime(); + + for (int i = 0; i < 10_000_000; i++) { + SubRuleContext.Generator generator = new SubRuleContext.Generator(); + SubRuleContext c = generator.generate(NAME); +// assertEquals(NAME, generator.getNameForGeneratedId(c.getId())); + assertEquals(NAME, c.getRuleName()); + } + System.out.println( (System.nanoTime() - start) / 1000_000 + "ms"); } @Test public void testGetters() { SubRuleContext.Generator generator = new SubRuleContext.Generator(); SubRuleContext context = generator.generate(NAME); - assertEquals(NAME, generator.getNameForGeneratedId(context.getId())); - Set expectedIds = new HashSet<>(); - expectedIds.add(context.getId()); + assertEquals(NAME, context.getRuleName()); + Set expectedIds = new HashSet<>(); + expectedIds.add(context); assertEquals(expectedIds, generator.getIdsGeneratedForName(NAME)); }