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