private void doTransitionOn()

in src/main/software/amazon/event/ruler/ByteMachine.java [461:570]


    private void doTransitionOn(final String valString, final Set<NameStateWithPattern> transitionTo,
                                TransitionValueType valueType) {
        final Map<NameState, List<Patterns>> failedAnythingButs = new HashMap<>();
        final byte[] val = valString.getBytes(StandardCharsets.UTF_8);

        // we need to add the name state for key existence
        addExistenceMatch(transitionTo);

        // attempt to harvest the possible suffix match
        addSuffixMatch(val, transitionTo, failedAnythingButs);

        if (startStateMatch != null) {
            transitionTo.add(new NameStateWithPattern(startStateMatch.getNextNameState(), startStateMatch.getPattern()));
        }

        // we have to do old-school indexing rather than "for (byte b : val)" because there is some special-casing
        // on transitions on the last byte in the value array
        ByteTransition trans = startState;
        for (int valIndex = 0; valIndex < val.length; valIndex++) {
            final ByteTransition nextTrans = getTransition(trans, val[valIndex]);

            attemptAddShortcutTransitionMatch(nextTrans, valString, EXACT, transitionTo);

            if (!nextTrans.isShortcutTrans()) {

                // process any matches hanging off this transition
                for (ByteMatch match : nextTrans.getMatches()) {
                    switch (match.getPattern().type()) {
                        case EXACT:
                        case EQUALS_IGNORE_CASE:
                        case WILDCARD:
                            if (valIndex == (val.length - 1)) {
                                transitionTo.add(new NameStateWithPattern(match.getNextNameState(), match.getPattern()));
                            }
                            break;
                        case NUMERIC_EQ:
                            // only matches at last character
                            if (valueType == TransitionValueType.NUMERIC && valIndex == (val.length - 1)) {
                                transitionTo.add(new NameStateWithPattern(match.getNextNameState(), match.getPattern()));
                            }
                            break;

                        case PREFIX:
                        case PREFIX_EQUALS_IGNORE_CASE:
                            transitionTo.add(new NameStateWithPattern(match.getNextNameState(), match.getPattern()));
                            break;
                        case ANYTHING_BUT_SUFFIX:
                        case SUFFIX:
                        case SUFFIX_EQUALS_IGNORE_CASE:
                        case EXISTS:
                            // we already harvested these matches via separate functions due to special matching
                            // requirements, so just ignore them here.
                            break;

                        case NUMERIC_RANGE:
                            // as soon as you see the match, you've matched
                            Range range = (Range) match.getPattern();
                            if ((valueType == TransitionValueType.NUMERIC && !range.isCIDR) ||
                                    (valueType != TransitionValueType.NUMERIC && range.isCIDR)) {
                                transitionTo.add(new NameStateWithPattern(match.getNextNameState(), match.getPattern()));
                            }
                            break;

                        case ANYTHING_BUT:
                            AnythingBut anythingBut = (AnythingBut) match.getPattern();
                            // only applies if at last character
                            if (valIndex == (val.length - 1) &&
                                    anythingBut.isNumeric() == (valueType == TransitionValueType.NUMERIC)) {
                                addToAnythingButsMap(failedAnythingButs, match.getNextNameState(), match.getPattern());
                            }
                            break;
                        case ANYTHING_BUT_IGNORE_CASE:
                        case ANYTHING_BUT_WILDCARD:
                            // only applies if at last character
                            if (valIndex == (val.length - 1)) {
                                addToAnythingButsMap(failedAnythingButs, match.getNextNameState(), match.getPattern());
                            }
                            break;
                        case ANYTHING_BUT_PREFIX:
                            addToAnythingButsMap(failedAnythingButs, match.getNextNameState(), match.getPattern());
                            break;

                        default:
                            throw new RuntimeException("Not implemented yet");

                    }
                }
            }

            trans = nextTrans.getTransitionForNextByteStates();
            if (trans == null) {
                break;
            }
        }

        // This may look like premature optimization, but the first "if" here yields roughly 10x performance
        // improvement. We exclude CIDR because the value will have been transformed, causing the anythingBut to always
        // match. Wait for NUMERIC or STRING matching to harvest anythingBut matches.
        if (!anythingButs.isEmpty() && valueType != TransitionValueType.CIDR) {
            for (Map.Entry<NameState, List<Patterns>> entry : anythingButs.entrySet()) {
                boolean failedAnythingButsContainsKey = failedAnythingButs.containsKey(entry.getKey());
                for (Patterns pattern : entry.getValue()) {
                    if (!failedAnythingButsContainsKey ||
                            !failedAnythingButs.get(entry.getKey()).contains(pattern)) {
                        transitionTo.add(new NameStateWithPattern(entry.getKey(), pattern));
                    }
                }
            }
        }
    }