private Set deleteStep()

in src/main/software/amazon/event/ruler/GenericMachine.java [275:371]


    private Set<SubRuleContext> deleteStep(final NameState state,
                                   final List<String> keys,
                                   final int keyIndex,
                                   final Map<String, List<Patterns>> patterns,
                                   final T ruleName,
                                   final List<String> deletedKeys,
                                   final Set<SubRuleContext> candidateSubRuleIds) {

        final Set<SubRuleContext> deletedSubRuleIds = new HashSet<>();
        final String key = keys.get(keyIndex);
        ByteMachine byteMachine = state.getTransitionOn(key);
        NameMatcher<NameState> nameMatcher = state.getKeyTransitionOn(key);

        // matchers are null, we have nothing to delete.
        if (byteMachine == null && nameMatcher == null) {
            return deletedSubRuleIds;
        }

        for (Patterns pattern : patterns.get(key)) {
            NameState nextNameState = null;
            if (isNamePattern(pattern)) {
                if (nameMatcher != null) {
                    nextNameState = nameMatcher.findPattern(pattern);
                }
            } else {
                if (byteMachine != null) {
                    nextNameState = byteMachine.findPattern(pattern);
                }
            }

            if (nextNameState != null) {
                // If this was the last step, then reaching the last state means the rule matched, and we should delete
                // the rule from the next NameState.
                final int nextKeyIndex = keyIndex + 1;
                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<SubRuleContext> 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
                // without further recursion through the keys.
                if (nextNameStateSubRuleIds == null) {
                    candidateSubRuleIds.clear();
                    // 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 (SubRuleContext nextNameStateSubRuleId : nextNameStateSubRuleIds) {
                        if (Objects.equals(ruleName,
                                nextNameStateSubRuleId.getRuleName())) {
                            candidateSubRuleIds.add(nextNameStateSubRuleId);
                        }
                    }
                    // Have already initialized candidate set. Just retain the candidates present in the next NameState.
                } else {
                    candidateSubRuleIds.retainAll(nextNameStateSubRuleIds);
                }

                if (isTerminal) {
                    for (SubRuleContext candidateSubRuleId : candidateSubRuleIds) {
                        if (nextNameState.deleteSubRule(
                                candidateSubRuleId.getRuleName(), candidateSubRuleId,
                                pattern, true)) {
                            deletedSubRuleIds.add(candidateSubRuleId);
                            // Only delete the pattern if the pattern does not transition to the next NameState.
                            if (!doesNameStateContainPattern(nextNameState, pattern) &&
                                    deletePattern(state, key, pattern)) {
                                deletedKeys.add(key);
                                state.removeNextNameState(key);
                            }
                        }
                    }
                } else {
                    if (candidateSubRuleIds.isEmpty()) {
                        return deletedSubRuleIds;
                    }
                    deletedSubRuleIds.addAll(deleteStep(nextNameState, keys, nextKeyIndex, patterns, ruleName,
                            deletedKeys, new HashSet<>(candidateSubRuleIds)));

                    for (SubRuleContext deletedSubRuleId : deletedSubRuleIds) {
                        nextNameState.deleteSubRule(deletedSubRuleId.getRuleName(),
                                deletedSubRuleId, pattern, false);
                    }

                    // Unwinding the key recursion, so we aren't on a rule match. Only delete the pattern if the pattern
                    // does not transition to the next NameState.
                    if (!doesNameStateContainPattern(nextNameState, pattern) && deletePattern(state, key, pattern)) {
                        deletedKeys.add(key);
                        state.removeNextNameState(key);
                    }
                }
            }

        }

        return deletedSubRuleIds;
    }