/* * ModeShape (http://www.modeshape.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.modeshape.jcr.query.parse; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.junit.Before; import org.junit.Test; import org.modeshape.common.text.ParsingException; import org.modeshape.jcr.query.model.Column; import org.modeshape.jcr.query.model.FullTextSearch.CompoundTerm; import org.modeshape.jcr.query.model.FullTextSearch.Conjunction; import org.modeshape.jcr.query.model.FullTextSearch.Disjunction; import org.modeshape.jcr.query.model.FullTextSearch.NegationTerm; import org.modeshape.jcr.query.model.FullTextSearch.SimpleTerm; import org.modeshape.jcr.query.model.FullTextSearch.Term; public class FullTextSearchParserTest { private FullTextSearchParser parser; @Before public void beforeEach() { parser = new FullTextSearchParser(); } @Test public void shouldHaveLocationAndScoresButNoColumns() { List<? extends Column> columns = FullTextSearchParser.FULL_TEXT_COLUMNS; assertThat(columns.size(), is(1)); Column column1 = columns.get(0); assertThat(column1.getColumnName(), is("jcr:score")); } @Test( expected = IllegalArgumentException.class ) public void shouldFailToParseNullString() { parser.parse((String)null); } @Test( expected = ParsingException.class ) public void shouldFailToParseEmptyString() { parser.parse(""); } @Test( expected = ParsingException.class ) public void shouldFailToParseBlankString() { parser.parse(" "); } @Test public void shouldParseStringWithOneUnquotedTerm() { Term result = parser.parse("term1"); assertSimpleTerm(result, "term1", false, false); } @Test public void shouldParseStringWithOneSingleQuotedTermWithOneWord() { Term result = parser.parse("'term1'"); assertSimpleTerm(result, "term1", false, false); } @Test public void shouldParseStringWithOneSingleQuotedTermWithMultipleWords() { Term result = parser.parse("'term1 has two words'"); assertSimpleTerm(result, "term1 has two words", false, true); } @Test public void shouldParseStringWithOneDoubleQuotedTermWithOneWord() { Term result = parser.parse("\"term1\""); assertSimpleTerm(result, "term1", false, false); } @Test public void shouldParseStringWithOneDoubleQuotedTermWithMultipleWords() { Term result = parser.parse("\"term1 has two words\""); assertSimpleTerm(result, "term1 has two words", false, true); } @Test public void shouldParseStringWithMultipleUnquotedTerms() { Term result = parser.parse("term1 term2 term3"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Conjunction.class))); Conjunction conjunction = (Conjunction)result; assertHasSimpleTerms(conjunction, "term1", "term2", "term3"); } @Test public void shouldParseStringWithMultipleUnquotedTermsWithNegatedTerms() { Term result = parser.parse("term1 term2 -term3"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Conjunction.class))); Conjunction conjunction = (Conjunction)result; assertHasSimpleTerms(conjunction, "term1", "term2", "-term3"); } @Test public void shouldParseStringWithMultipleQuotedAndUnquotedTermsWithNegatedTerms() { Term result = parser.parse("term1 \"term2 and 2a\" -term3 -'term 4'"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Conjunction.class))); Conjunction conjunction = (Conjunction)result; assertHasSimpleTerms(conjunction, "term1", "term2 and 2a", "-term3", "-term 4"); } @Test public void shouldParseStringWithMultipleUnquotedORedTerms() { Term result = parser.parse("term1 OR term2 OR term3"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Disjunction.class))); Disjunction disjunction = (Disjunction)result; assertHasSimpleTerms(disjunction, "term1", "term2", "term3"); } @Test public void shouldParseStringWithMultipleUnquotedORedTermsWithNegatedTerms() { Term result = parser.parse("term1 OR term2 OR -term3"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Disjunction.class))); Disjunction disjunction = (Disjunction)result; assertHasSimpleTerms(disjunction, "term1", "term2", "-term3"); } @Test public void shouldParseStringWithMultipleUnquotedANDedTermsORedTogether() { Term result = parser.parse("term1 term2 OR -term3 -term4"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Disjunction.class))); Disjunction disjunction = (Disjunction)result; assertThat(disjunction.getTerms().size(), is(2)); Conjunction conjunction1 = (Conjunction)disjunction.getTerms().get(0); Conjunction conjunction2 = (Conjunction)disjunction.getTerms().get(1); assertHasSimpleTerms(conjunction1, "term1", "term2"); assertHasSimpleTerms(conjunction2, "-term3", "term4"); } @Test public void shouldParseStringWithTwoANDedUnquotedTermsORedWithMultipleUnquotedTerms() { Term result = parser.parse("term1 term2 OR -term3 OR -term4 OR term5"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Disjunction.class))); Disjunction disjunction = (Disjunction)result; assertThat(disjunction.getTerms().size(), is(4)); Conjunction conjunction1 = (Conjunction)disjunction.getTerms().get(0); Term term3 = disjunction.getTerms().get(1); Term term4 = disjunction.getTerms().get(2); Term term5 = disjunction.getTerms().get(3); assertHasSimpleTerms(conjunction1, "term1", "term2"); assertSimpleTerm(term3, "term3", true, false); assertSimpleTerm(term4, "term4", true, false); assertSimpleTerm(term5, "term5", false, false); } @Test public void shouldParseStringWithWildcardCharactersAtEndOfSingleTerm() { Term result = parser.parse("term*"); assertSimpleTerm(result, "term*", false, false); } @Test public void shouldParseStringWithWildcardCharactersAtBeginningOfSingleTerm() { Term result = parser.parse("*term"); assertSimpleTerm(result, "*term", false, false); } @Test public void shouldParseStringWithWildcardCharactersInsideSingleTerm() { Term result = parser.parse("te*rm"); assertSimpleTerm(result, "te*rm", false, false); } @Test public void shouldParseStringWithWildcardCharactersInMultipleTerms() { Term result = parser.parse("term* term? *term*"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Conjunction.class))); Conjunction conjunction = (Conjunction)result; assertHasSimpleTerms(conjunction, "term*", "term?", "*term*"); } @Test public void shouldParseStringWithWildcardCharactersInSingleQuotedTerm() { Term result = parser.parse("'term* term? *term*'"); assertSimpleTerm(result, "term* term? *term*", false, true); } @Test public void shouldParseStringWithSqlStyleWildcardCharactersInMultipleTerms() { Term result = parser.parse("term% term_ %term_"); assertThat(result, is(notNullValue())); assertThat(result, is(instanceOf(Conjunction.class))); Conjunction conjunction = (Conjunction)result; assertHasSimpleTerms(conjunction, "term%", "term_", "%term_"); } @Test public void shouldParseStringWithSqlStyleWildcardCharactersInSingleQuotedTerm() { Term result = parser.parse("'term% term_ %term_'"); assertSimpleTerm(result, "term% term_ %term_", false, true); } @Test public void shouldParseStringWithEscapedWildcardCharacterInSingleTerm() { Term result = parser.parse("term\\*"); assertSimpleTerm(result, "term\\*", false, false); } public static void assertHasSimpleTerms( CompoundTerm compoundTerm, String... terms ) { List<Term> expectedTerms = new ArrayList<Term>(); for (String term : terms) { if (term.startsWith("-")) { term = term.substring(1); expectedTerms.add(new NegationTerm(new SimpleTerm(term))); } else { expectedTerms.add(new SimpleTerm(term)); } } assertHasTerms(compoundTerm, expectedTerms.toArray(new Term[expectedTerms.size()])); } public static void assertSimpleTerm( Term term, String value, boolean excluded, boolean quotingRequired ) { assertThat(term, is(notNullValue())); if (excluded) { assertThat(term, is(instanceOf(NegationTerm.class))); NegationTerm negationTerm = (NegationTerm)term; Term negated = negationTerm.getNegatedTerm(); assertThat(negated, is(instanceOf(SimpleTerm.class))); SimpleTerm simpleTerm = (SimpleTerm)negated; assertThat(simpleTerm.getValue(), is(value)); assertThat(simpleTerm.isQuotingRequired(), is(quotingRequired)); } else { assertThat(term, is(instanceOf(SimpleTerm.class))); SimpleTerm simpleTerm = (SimpleTerm)term; assertThat(simpleTerm.getValue(), is(value)); assertThat(simpleTerm.isQuotingRequired(), is(quotingRequired)); } } public static void assertHasTerms( CompoundTerm compoundTerm, Term... terms ) { Iterator<Term> iterator = compoundTerm.iterator(); for (int i = 0; i != 0; i++) { Term expected = terms[i]; assertThat(iterator.hasNext(), is(true)); Term term = iterator.next(); assertThat(term, is(expected)); } } }