private TopicMatcherDFAState createStateMachine()

in broker-core/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java [134:289]


    private TopicMatcherDFAState createStateMachine(String bindingKey, TopicMatcherResult result)
    {
        List<TopicWord> wordList = createTopicWordList(bindingKey);
        int wildCards = 0;
        for(TopicWord word : wordList)
        {
            if(word == TopicWord.WILDCARD_WORD)
            {
                wildCards++;
            }
        }
        if(wildCards == 0)
        {
            TopicMatcherDFAState[] states = new TopicMatcherDFAState[wordList.size()+1];
            states[states.length-1] = new TopicMatcherDFAState(Map.of(), Set.of(result));
            for(int i = states.length-2; i >= 0; i--)
            {
                states[i] = new TopicMatcherDFAState(Map.of(wordList.get(i),states[i+1]), Set.of());

            }
            return states[0];
        }
        else if(wildCards == wordList.size())
        {
            Map<TopicWord,TopicMatcherDFAState> stateMap = new HashMap<>();
            TopicMatcherDFAState state = new TopicMatcherDFAState(stateMap, Set.of(result));
            stateMap.put(TopicWord.ANY_WORD, state);
            return state;
        }


        int positionCount = wordList.size() - wildCards;

        Position[] positions = new Position[positionCount+1];

        int lastWord;

        if(wordList.get(wordList.size()-1)== TopicWord.WILDCARD_WORD)
        {
            lastWord = wordList.size()-1;
            positions[positionCount] = new Position(positionCount, TopicWord.ANY_WORD, true, true);
        }
        else
        {
            lastWord = wordList.size();
            positions[positionCount] = new Position(positionCount, TopicWord.ANY_WORD, false, true);
        }


        int pos = 0;
        int wordPos = 0;


        while(wordPos < lastWord)
        {
            TopicWord word = wordList.get(wordPos++);

            if(word == TopicWord.WILDCARD_WORD)
            {
                int nextWordPos = wordPos++;
                word = wordList.get(nextWordPos);

                positions[pos] = new Position(pos++,word,true,false);
            }
            else
            {
                positions[pos] = new Position(pos++,word,false,false);
            }

        }


        for(int p = 0; p<positionCount; p++)
        {
            boolean followedByWildcards = true;

            int n = p;
            while(followedByWildcards && n<(positionCount+1))
            {

                if(positions[n].isSelfTransition())
                {
                    break;
                }
                else if(positions[n].getWord() !=TopicWord.ANY_WORD)
                {
                    followedByWildcards = false;
                }
                n++;
            }


            positions[p].setFollowedByAnyLoop(followedByWildcards && (n!= positionCount+1));
        }


        // from each position you transition to a set of other positions.
        // we approach this by examining steps of increasing length - so we
        // look how far we can go from the start position in 1 word, 2 words, etc...

        Map<Set<Position>, SimpleState> stateMap = new HashMap<>();


        SimpleState state = new SimpleState();
        state._positions = Set.of(positions[0]);
        stateMap.put(state._positions, state);

        calculateNextStates(state, stateMap, positions);

        SimpleState[] simpleStates = stateMap.values().toArray(new SimpleState[stateMap.size()]);
        HashMap<TopicWord, TopicMatcherDFAState>[] dfaStateMaps = new HashMap[simpleStates.length];
        Map<SimpleState, TopicMatcherDFAState> simple2DFAMap = new HashMap<>();

        for(int i = 0; i < simpleStates.length; i++)
        {

            Collection<TopicMatcherResult> results;
            boolean endState = false;

            for(Position p : simpleStates[i]._positions)
            {
                if(p.isEndState())
                {
                    endState = true;
                    break;
                }
            }

            if(endState)
            {
                results = Set.of(result);
            }
            else
            {
                results = Set.of();
            }

            dfaStateMaps[i] = new HashMap<>();
            simple2DFAMap.put(simpleStates[i], new TopicMatcherDFAState(dfaStateMaps[i],results));

        }
        for(int i = 0; i < simpleStates.length; i++)
        {
            SimpleState simpleState = simpleStates[i];

            Map<TopicWord, SimpleState> nextSimpleStateMap = simpleState._nextState;
            for(Map.Entry<TopicWord, SimpleState> stateMapEntry : nextSimpleStateMap.entrySet())
            {
                dfaStateMaps[i].put(stateMapEntry.getKey(), simple2DFAMap.get(stateMapEntry.getValue()));
            }

        }

        return simple2DFAMap.get(state);

    }