private void calculateNextStates()

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


    private void calculateNextStates(final SimpleState state,
                                     final Map<Set<Position>, SimpleState> stateMap,
                                     final Position[] positions)
    {
        Map<TopicWord, Set<Position>> transitions = new HashMap<>();

        for(Position pos : state._positions)
        {
            if(pos.isSelfTransition())
            {
                Set<Position> dest = transitions.get(TopicWord.ANY_WORD);
                if(dest == null)
                {
                    dest = new HashSet<>();
                    transitions.put(TopicWord.ANY_WORD,dest);
                }
                dest.add(pos);
            }

            final int nextPos = pos.getPosition() + 1;
            Position nextPosition = nextPos == positions.length ? ERROR_POSITION : positions[nextPos];

            Set<Position> dest = transitions.get(pos.getWord());
            if(dest == null)
            {
                dest = new HashSet<>();
                transitions.put(pos.getWord(),dest);
            }
            dest.add(nextPosition);

        }

        Set<Position> anyWordTransitions = transitions.get(TopicWord.ANY_WORD);
        if(anyWordTransitions != null)
        {
            for(Set<Position> dest : transitions.values())
            {
                dest.addAll(anyWordTransitions);
            }
        }

        state._nextState = new HashMap<>();

        for(Map.Entry<TopicWord,Set<Position>> dest : transitions.entrySet())
        {

            if(dest.getValue().size()>1)
            {
                dest.getValue().remove(ERROR_POSITION);
            }
            Position loopingTerminal = null;
            for(Position destPos : dest.getValue())
            {
                if(destPos.isSelfTransition() && destPos.isEndState())
                {
                    loopingTerminal = destPos;
                    break;
                }
            }

            if(loopingTerminal!=null)
            {
                dest.setValue(Set.of(loopingTerminal));
            }
            else
            {
                Position anyLoop = null;
                for(Position destPos : dest.getValue())
                {
                    if(destPos.isFollowedByAnyLoop())
                    {
                        if(anyLoop == null || anyLoop.getPosition() < destPos.getPosition())
                        {
                            anyLoop = destPos;
                        }
                    }
                }
                if(anyLoop != null)
                {
                    Collection<Position> removals = new ArrayList<>();
                    for(Position destPos : dest.getValue())
                    {
                        if(destPos.getPosition() < anyLoop.getPosition())
                        {
                            removals.add(destPos);
                        }
                    }
                    dest.getValue().removeAll(removals);
                }
            }

            SimpleState stateForEntry = stateMap.get(dest.getValue());
            if(stateForEntry == null)
            {
                stateForEntry = new SimpleState();
                stateForEntry._positions = dest.getValue();
                stateMap.put(dest.getValue(),stateForEntry);
                calculateNextStates(stateForEntry,
                                    stateMap,
                                    positions);
            }
            state._nextState.put(dest.getKey(),stateForEntry);



        }

        // remove redundant transitions
        SimpleState anyWordState = state._nextState.get(TopicWord.ANY_WORD);
        if(anyWordState != null)
        {
            List<TopicWord> removeList = new ArrayList<>();
            for(Map.Entry<TopicWord,SimpleState> entry : state._nextState.entrySet())
            {
                if(entry.getValue() == anyWordState && entry.getKey() != TopicWord.ANY_WORD)
                {
                    removeList.add(entry.getKey());
                }
            }
            for(TopicWord removeKey : removeList)
            {
                state._nextState.remove(removeKey);
            }
        }


    }