/** * */ package querqy.rewrite.commonrules.model; import java.util.LinkedList; import java.util.List; import querqy.ComparableCharSequence; import querqy.CompoundCharSequence; import querqy.trie.State; import querqy.trie.States; import querqy.trie.TrieMap; /** * @author René Kriegler, @renekrie * */ public class TrieMapRulesCollectionBuilder implements RulesCollectionBuilder { final TrieMap<List<Instructions>> map = new TrieMap<>(); final boolean ignoreCase; public TrieMapRulesCollectionBuilder(boolean ignoreCase) { this.ignoreCase = ignoreCase; } /* (non-Javadoc) * @see querqy.rewrite.commonrules.model.RulesCollectionBuilder#addRule(querqy.rewrite.commonrules.model.Input, querqy.rewrite.commonrules.model.Instructions) */ @Override public void addRule(Input input, Instructions instructions) { List<Term> inputTerms = input.getInputTerms(); switch (inputTerms.size()) { case 0: { if (!(input.requiresLeftBoundary && input.requiresRightBoundary)) { throw new IllegalArgumentException("Empty input!"); } ComparableCharSequence seq = new CompoundCharSequence(" ", TrieMapRulesCollection.BOUNDARY_WORD, TrieMapRulesCollection.BOUNDARY_WORD); States<List<Instructions>> states = map.get(seq); State<List<Instructions>> state = states.getStateForCompleteSequence(); if (state.value != null) { state.value.add(instructions); } else { List<Instructions> instructionsList = new LinkedList<>(); instructionsList.add(instructions); map.put(seq, instructionsList); } } break; case 1: { Term term = inputTerms.get(0); boolean isPrefix = term instanceof PrefixTerm; for (ComparableCharSequence seq: term.getCharSequences(ignoreCase)) { seq = applyBoundaries(seq, input.requiresLeftBoundary, input.requiresRightBoundary); States<List<Instructions>> states = map.get(seq); if (isPrefix) { boolean added = false; List<State<List<Instructions>>> prefixes = states.getPrefixes(); if (prefixes != null) { for (State<List<Instructions>> state: prefixes) { if (state.isFinal() && state.index == (seq.length() - 1) && state.value != null) { state.value.add(instructions); added = true; break; } } } if (!added) { List<Instructions> instructionsList = new LinkedList<>(); instructionsList.add(instructions); map.putPrefix(seq, instructionsList); } } else { State<List<Instructions>> state = states.getStateForCompleteSequence(); if (state.value != null) { state.value.add(instructions); } else { List<Instructions> instructionsList = new LinkedList<>(); instructionsList.add(instructions); map.put(seq, instructionsList); } } } } break; default: Term lastTerm = input.inputTerms.get(input.inputTerms.size() -1); boolean isPrefix = lastTerm instanceof PrefixTerm; for (ComparableCharSequence seq : input.getInputSequences(ignoreCase)) { seq = applyBoundaries(seq, input.requiresLeftBoundary, input.requiresRightBoundary); States<List<Instructions>> states = map.get(seq); if (isPrefix) { boolean added = false; List<State<List<Instructions>>> prefixes = states.getPrefixes(); if (prefixes != null) { for (State<List<Instructions>> state: prefixes) { if (state.isFinal() && state.index == (seq.length() - 1) && state.value != null) { state.value.add(instructions); added = true; break; } } } if (!added) { List<Instructions> instructionsList = new LinkedList<>(); instructionsList.add(instructions); map.putPrefix(seq, instructionsList); } } else { State<List<Instructions>> state = states.getStateForCompleteSequence(); if (state.value != null) { state.value.add(instructions); } else { List<Instructions> instructionsList = new LinkedList<>(); instructionsList.add(instructions); map.put(seq, instructionsList); } } } } } ComparableCharSequence applyBoundaries(ComparableCharSequence seq, boolean requiresLeftBoundary, boolean requiresRightBoundary) { if (requiresLeftBoundary == requiresRightBoundary) { if (requiresLeftBoundary) { return new CompoundCharSequence(" ", TrieMapRulesCollection.BOUNDARY_WORD, seq, TrieMapRulesCollection.BOUNDARY_WORD); } else { return seq; } } else if (requiresLeftBoundary) { return new CompoundCharSequence(" ", TrieMapRulesCollection.BOUNDARY_WORD, seq); } else { return new CompoundCharSequence(" ", seq, TrieMapRulesCollection.BOUNDARY_WORD); } } /* (non-Javadoc) * @see querqy.rewrite.commonrules.model.RulesCollectionBuilder#build() */ @Override public RulesCollection build() { return new TrieMapRulesCollection(map, ignoreCase); } }