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