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);
}
}
}