org.apache.solr.search.TestSolrCoreParser.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.solr.search.TestSolrCoreParser.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.solr.search;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.analysis.MockTokenFilter;
import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.xml.CoreParser;
import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.spans.SpanBoostQuery;
import org.apache.lucene.search.spans.SpanNearQuery;
import org.apache.lucene.search.spans.SpanOrQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;

public class TestSolrCoreParser extends LuceneTestCase {

    private SolrCoreParser solrCoreParser;

    private CoreParser solrCoreParser() {
        if (solrCoreParser == null) {
            final String defaultField = "contents";
            final Analyzer analyzer = new MockAnalyzer(random(), MockTokenizer.WHITESPACE, true,
                    MockTokenFilter.ENGLISH_STOPSET);
            final SolrQueryRequest req = null;
            solrCoreParser = new SolrCoreParser(defaultField, analyzer, req);
            {
                final NamedList<String> args = new NamedList<>();
                args.add("HelloQuery", HelloQueryBuilder.class.getCanonicalName());
                args.add("GoodbyeQuery", GoodbyeQueryBuilder.class.getCanonicalName());
                args.add("HandyQuery", HandyQueryBuilder.class.getCanonicalName());
                args.add("ApacheLuceneSolr", ApacheLuceneSolrNearQueryBuilder.class.getCanonicalName());
                args.add("ChooseOneWord", ChooseOneWordQueryBuilder.class.getCanonicalName());
                solrCoreParser.init(args);
            }
        }
        return solrCoreParser;
    }

    private Query parseXmlString(String xml) throws IOException, ParserException {
        final byte[] xmlBytes = xml.getBytes(StandardCharsets.UTF_8);
        final InputStream xmlStream = new ByteArrayInputStream(xmlBytes);
        return solrCoreParser().parse(xmlStream);
    }

    private Query parseHandyQuery(String lhsXml, String rhsXml) throws IOException, ParserException {
        final String xml = "<HandyQuery>" + "<Left>" + lhsXml + "</Left>" + "<Right>" + rhsXml + "</Right>"
                + "</HandyQuery>";
        return parseXmlString(xml);
    }

    public void testHello() throws IOException, ParserException {
        final Query query = parseXmlString("<HelloQuery/>");
        assertTrue(query instanceof MatchAllDocsQuery);
    }

    public void testGoodbye() throws IOException, ParserException {
        final Query query = parseXmlString("<GoodbyeQuery/>");
        assertTrue(query instanceof MatchNoDocsQuery);
    }

    public void testApacheLuceneSolr() throws IOException, ParserException {
        final String fieldName = "contents";
        final Query query = parseXmlString("<ApacheLuceneSolr fieldName='" + fieldName + "'/>");
        checkApacheLuceneSolr(query, fieldName);
    }

    private static void checkApacheLuceneSolr(Query query, String fieldName) {
        assertTrue(query instanceof SpanNearQuery);
        final SpanNearQuery snq = (SpanNearQuery) query;
        assertEquals(fieldName, snq.getField());
        assertEquals(42, snq.getSlop());
        assertFalse(snq.isInOrder());
        assertEquals(3, snq.getClauses().length);
        assertTrue(snq.getClauses()[0] instanceof SpanTermQuery);
        assertTrue(snq.getClauses()[1] instanceof SpanTermQuery);
        assertTrue(snq.getClauses()[2] instanceof SpanTermQuery);
    }

    // test custom query (HandyQueryBuilder) wrapping a Query
    public void testHandyQuery() throws IOException, ParserException {
        final String lhsXml = "<HelloQuery/>";
        final String rhsXml = "<GoodbyeQuery/>";
        final Query query = parseHandyQuery(lhsXml, rhsXml);
        assertTrue(query instanceof BooleanQuery);
        final BooleanQuery bq = (BooleanQuery) query;
        assertEquals(2, bq.clauses().size());
        assertTrue(bq.clauses().get(0).getQuery() instanceof MatchAllDocsQuery);
        assertTrue(bq.clauses().get(1).getQuery() instanceof MatchNoDocsQuery);
    }

    private static SpanQuery unwrapSpanBoostQuery(Query query) {
        assertTrue(query instanceof SpanBoostQuery);
        final SpanBoostQuery spanBoostQuery = (SpanBoostQuery) query;
        return spanBoostQuery.getQuery();
    }

    // test custom query (HandyQueryBuilder) wrapping a SpanQuery
    public void testHandySpanQuery() throws IOException, ParserException {
        final String lhsXml = "<SpanOr fieldName='contents'>" + "<SpanTerm>rain</SpanTerm>"
                + "<SpanTerm>spain</SpanTerm>" + "<SpanTerm>plain</SpanTerm>" + "</SpanOr>";
        final String rhsXml = "<SpanNear fieldName='contents' slop='2' inOrder='true'>"
                + "<SpanTerm>sunny</SpanTerm>" + "<SpanTerm>sky</SpanTerm>" + "</SpanNear>";
        final Query query = parseHandyQuery(lhsXml, rhsXml);
        final BooleanQuery bq = (BooleanQuery) query;
        assertEquals(2, bq.clauses().size());
        for (int ii = 0; ii < bq.clauses().size(); ++ii) {
            final Query clauseQuery = bq.clauses().get(ii).getQuery();
            switch (ii) {
            case 0:
                assertTrue(unwrapSpanBoostQuery(clauseQuery) instanceof SpanOrQuery);
                break;
            case 1:
                assertTrue(unwrapSpanBoostQuery(clauseQuery) instanceof SpanNearQuery);
                break;
            default:
                fail("unexpected clause index " + ii);
            }
        }
    }

    private static String composeChooseOneWordQueryXml(String fieldName, String... termTexts) {
        final StringBuilder sb = new StringBuilder("<ChooseOneWord fieldName='" + fieldName + "'>");
        for (String termText : termTexts) {
            sb.append("<Word>").append(termText).append("</Word>");
        }
        sb.append("</ChooseOneWord>");
        return sb.toString();
    }

    // test custom queries being wrapped in a Query or SpanQuery
    public void testCustomQueryWrapping() throws IOException, ParserException {
        final boolean span = random().nextBoolean();
        // the custom queries
        final String fieldName = "contents";
        final String[] randomTerms = new String[] { "bumble", "honey", "solitary" };
        final String randomQuery = composeChooseOneWordQueryXml(fieldName, randomTerms);
        final String apacheLuceneSolr = "<ApacheLuceneSolr fieldName='" + fieldName + "'/>";
        // the wrapping query
        final String parentQuery = (span ? "SpanOr" : "BooleanQuery");
        final String subQueryPrefix = (span ? "" : "<Clause occurs='must'>");
        final String subQuerySuffix = (span ? "" : "</Clause>");
        final String xml = "<" + parentQuery + ">" + subQueryPrefix + randomQuery + subQuerySuffix + subQueryPrefix
                + apacheLuceneSolr + subQuerySuffix + "</" + parentQuery + ">";
        // the test
        final Query query = parseXmlString(xml);
        if (span) {
            assertTrue(unwrapSpanBoostQuery(query) instanceof SpanOrQuery);
            final SpanOrQuery soq = (SpanOrQuery) unwrapSpanBoostQuery(query);
            assertEquals(2, soq.getClauses().length);
            checkChooseOneWordQuery(span, soq.getClauses()[0], fieldName, randomTerms);
            checkApacheLuceneSolr(soq.getClauses()[1], fieldName);
        } else {
            assertTrue(query instanceof BooleanQuery);
            final BooleanQuery bq = (BooleanQuery) query;
            assertEquals(2, bq.clauses().size());
            checkChooseOneWordQuery(span, bq.clauses().get(0).getQuery(), fieldName, randomTerms);
            checkApacheLuceneSolr(bq.clauses().get(1).getQuery(), fieldName);
        }
    }

    private static void checkChooseOneWordQuery(boolean span, Query query, String fieldName,
            String... expectedTermTexts) {
        final Term term;
        if (span) {
            assertTrue(query instanceof SpanTermQuery);
            final SpanTermQuery stq = (SpanTermQuery) query;
            term = stq.getTerm();
        } else {
            assertTrue(query instanceof TermQuery);
            final TermQuery tq = (TermQuery) query;
            term = tq.getTerm();
        }
        final String text = term.text();
        boolean foundExpected = false;
        for (String expected : expectedTermTexts) {
            foundExpected |= expected.equals(text);
        }
        assertEquals(fieldName, term.field());
        assertTrue("expected term text (" + text + ") not found in (" + expectedTermTexts + ")", foundExpected);
    }

}