package querqy.rewrite.commonrules.model; import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Before; import org.junit.Test; import querqy.model.ExpandedQuery; import querqy.model.InputSequenceElement; import querqy.model.Term; import querqy.rewrite.QueryRewriter; public class RulesCollectionTest { @Before public void setUp() throws Exception { } @Test public void testSingeInputSingleInstruction() { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test"; Input input = new Input(inputTerms(null, s1), false, false); Instructions instructions = instructions("instruction1"); builder.addRule(input, instructions); RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s1)); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions), termMatches(s1), 0, 1))); } @Test public void testSingleInputTwoInstructionsFromSameRule() { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test"; Input input = new Input(inputTerms(null, s1), false, false); Instructions instructions = instructions("instruction1", "instruction2"); builder.addRule(input, instructions); RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s1)); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions), termMatches(s1), 0, 1))); } @Test public void testSameInputTwoInstructionsFromDiffentRules() { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test"; Input input = new Input(inputTerms(null, s1), false, false); Instructions instructions1 = instructions("instruction1"); builder.addRule(input, instructions1); Instructions instructions2 = instructions("instruction2"); builder.addRule(input, instructions2); RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s1)); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions1, instructions2), termMatches(s1), 0, 1))); } @Test public void testTwoInputsOneInstructionsPerInput() { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test1"; String s2 = "test2"; Input input1 = new Input(inputTerms(null, s1), false, false); Input input2 = new Input(inputTerms(null, s2), false, false); Instructions instructions1 = instructions("instruction1"); builder.addRule(input1, instructions1); Instructions instructions2 = instructions("instruction2"); builder.addRule(input2, instructions2); // Input is just s1 RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s1)); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions1), termMatches(s1), 0, 1))); // Input is just s2 sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s2)); actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions2), termMatches(s2), 0, 1))); // Input is s2 s1 sequence.nextPosition(); sequence.addElement(new Term(null, s1)); actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains( new Action(Arrays.asList(instructions2), termMatches(s2), 0, 1), new Action(Arrays.asList(instructions1), termMatches(s1), 1, 2)) ); } @Test public void testCompoundAndInterlacedInput() throws Exception { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test1"; String s2 = "test2"; String s3 = "test3"; Input input1 = new Input(inputTerms(null, s1, s2), false, false); Input input2 = new Input(inputTerms(null, s2, s3), false, false); Instructions instructions1 = instructions("instruction1"); builder.addRule(input1, instructions1); Instructions instructions2 = instructions("instruction2"); builder.addRule(input2, instructions2); // Input is just s1 RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s1)); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertTrue(actions.isEmpty()); // Input is s1 s2 sequence.nextPosition(); sequence.addElement(new Term(null, s2)); actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains( new Action(Arrays.asList(instructions1), termMatches(s1, s2), 0, 2)) ); // Input is s1 s2 s3 sequence.nextPosition(); sequence.addElement(new Term(null, s3)); actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains( new Action(Arrays.asList(instructions1), termMatches(s1, s2), 0, 2), new Action(Arrays.asList(instructions2), termMatches(s2, s3), 1, 3) ) ); } @Test public void testTwoMatchingInputsOnePartial() throws Exception { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test1"; String s2 = "test2"; Input input1 = new Input(inputTerms(null, s1, s2), false, false); Input input2 = new Input(inputTerms(null, s2), false, false); Instructions instructions1 = instructions("instruction1"); Instructions instructions2 = instructions("instruction2"); builder.addRule(input2, instructions2); builder.addRule(input1, instructions1); // Input is s1 s2 RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s1)); sequence.nextPosition(); sequence.addElement(new Term(null, s2)); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains( new Action(Arrays.asList(instructions1), termMatches(s1, s2), 0, 2), new Action(Arrays.asList(instructions2), termMatches(s2), 1, 2) ) ); } @Test public void testMultipleTermsPerPosition() throws Exception { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test1"; String s2 = "test2"; Input input1 = new Input(inputTerms(null, s1), false, false); Input input2 = new Input(inputTerms(null, s2), false, false); Instructions instructions1 = instructions("instruction1"); builder.addRule(input1, instructions1); Instructions instructions2 = instructions("instruction2"); builder.addRule(input2, instructions2); // Input is just s1 RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(new Term(null, s1)); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions1), termMatches(s1), 0, 1))); sequence.addElement(new Term(null, s2)); actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions1), termMatches(s1), 0, 1), new Action(Arrays.asList(instructions2), termMatches(s2), 0, 1))); } @Test public void testMultipleTermsWithFieldNamesPerPosition() throws Exception { RulesCollectionBuilder builder = new TrieMapRulesCollectionBuilder(false); String s1 = "test1"; String s2 = "test2"; Input input1 = new Input( Arrays.asList( new querqy.rewrite.commonrules.model.Term(s1.toCharArray(), 0, s1.length(), Arrays.asList("f11", "f12")), new querqy.rewrite.commonrules.model.Term(s2.toCharArray(), 0, s2.length(), Arrays.asList("f21", "f22")) ), false, false); Instructions instructions1 = instructions("instruction1"); builder.addRule(input1, instructions1); Term term11 = new Term(null, "f11", s1); Term term12 = new Term(null, "f12", s1); Term term21 = new Term(null, "f21", s2); Term term22 = new Term(null, "f22", s2); // Input is just s1 RulesCollection rulesCollection = builder.build(); PositionSequence<InputSequenceElement> sequence = new PositionSequence<>(); sequence.nextPosition(); sequence.addElement(term11); sequence.addElement(term21); List<Action> actions = rulesCollection.getRewriteActions(sequence); assertTrue(actions.isEmpty()); sequence.nextPosition(); sequence.addElement(term12); actions = rulesCollection.getRewriteActions(sequence); assertTrue(actions.isEmpty()); sequence.addElement(term22); actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions1), new TermMatches(Arrays.asList(new TermMatch(term11), new TermMatch(term22))), 0, 2))); sequence.clear(); actions = rulesCollection.getRewriteActions(sequence); assertTrue(actions.isEmpty()); sequence.nextPosition(); sequence.addElement(term12); sequence.nextPosition(); sequence.addElement(term21); actions = rulesCollection.getRewriteActions(sequence); assertThat(actions, contains(new Action(Arrays.asList(instructions1), new TermMatches(Arrays.asList(new TermMatch(term12), new TermMatch(term21))), 0, 2))); } List<querqy.rewrite.commonrules.model.Term> inputTerms(List<String> fieldNames, String... values) { List<querqy.rewrite.commonrules.model.Term> result = new LinkedList<>(); for (String value : values) { char[] chars = value.toCharArray(); result.add(new querqy.rewrite.commonrules.model.Term(chars, 0, chars.length, fieldNames)); } return result; } TermMatches termMatches(String... values) { TermMatches result = new TermMatches(); for (String value : values) { result.add(new TermMatch(new Term(null, value))); } return result; } List<Term> termsWithFieldname(String fieldName, String... values) { List<Term> result = new LinkedList<>(); for (String value : values) { result.add(new Term(null, fieldName, value)); } return result; } Instructions instructions(String... names) { List<Instruction> instructions = new LinkedList<>(); for (String name : names) { instructions.add(new SimpleInstruction(name)); } return new Instructions(instructions); } static class SimpleInstruction implements Instruction { final String name; public SimpleInstruction(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; SimpleInstruction other = (SimpleInstruction) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "SimpleInstruction [name=" + name + "]"; } @Override public void apply(PositionSequence<Term> sequence, TermMatches termsMatches, int startPosition, int endPosition, ExpandedQuery expandedQuery, Map<String, Object> context) { } @Override public Set<Term> getGenerableTerms() { return QueryRewriter.EMPTY_GENERABLE_TERMS; } } }