/* Copyright (2006-2012) Schibsted ASA * This file is part of Possom. * * Possom is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Possom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Possom. If not, see <http://www.gnu.org/licenses/>. * * SynonymQueryTransformerTest.java * * Created on April 5, 2006, 9:32 P */ package no.sesat.search.query.transform; import java.util.Map; import no.sesat.search.query.AndClause; import no.sesat.search.query.AndNotClause; import no.sesat.search.query.Clause; import no.sesat.search.query.DefaultOperatorClause; import no.sesat.search.query.LeafClause; import no.sesat.search.query.NotClause; import no.sesat.search.query.UnaryClause; import no.sesat.search.query.OrClause; import no.sesat.search.query.Query; import no.sesat.search.query.XorClause; import no.sesat.commons.visitor.AbstractReflectionVisitor; import no.sesat.search.query.parser.ParseException; import no.sesat.search.query.token.Categories; import no.sesat.search.query.token.TokenEvaluationEngineTestContext; import no.sesat.search.query.token.TokenEvaluationEngine; import no.sesat.search.query.token.TokenEvaluationEngineImpl; import no.sesat.search.query.token.TokenPredicate; import org.apache.log4j.Logger; import org.testng.annotations.Test; import static org.testng.AssertJUnit.*; /** * * */ public final class SynonymQueryTransformerTest extends AbstractTransformerTestCase { private static final Logger LOG = Logger.getLogger(SynonymQueryTransformerTest.class); private final SynonymQueryTransformerConfig config = new SynonymQueryTransformerConfig(); /** * * @param testName */ public SynonymQueryTransformerTest(final String testName) { super(testName); Logger.getLogger(SynonymQueryTransformer.class).setLevel(org.apache.log4j.Level.TRACE); LOG.setLevel(org.apache.log4j.Level.TRACE); } /** * * @throws no.sesat.search.query.parser.ParseException */ @Test public void testOneWordExact() throws ParseException { final String queryString = "sch"; final TokenEvaluationEngineImpl.Context tefCxt = new TokenEvaluationEngineTestContext(queryString); final TokenEvaluationEngine tef = new TokenEvaluationEngineImpl(tefCxt); final Query query = parseQuery(tef); final Map<Clause,String> trans = applyTransformer(new SynonymQueryTransformer(config), query, Categories.STOCKMARKETTICKERS.exactPeer().name(), tefCxt, tef); final QueryBuilder builder = new QueryBuilder(query, trans); final String result = builder.getQueryString(); LOG.debug("testOneWordExact builder gave " + result); if( query.getFirstLeafClause().getPossiblePredicates().contains(Categories.STOCKMARKETTICKERS.exactPeer())){ assertEquals("(sch schibsted)", result); }else{ assertEquals("sch", result); } } /** * * @throws no.sesat.search.query.parser.ParseException */ @Test public void testOneWord() throws ParseException { final String queryString = "sch"; final TokenEvaluationEngineImpl.Context tefCxt = new TokenEvaluationEngineTestContext(queryString); final TokenEvaluationEngine tef = new TokenEvaluationEngineImpl(tefCxt); final Query query = parseQuery(tef); final Map<Clause,String> trans = applyTransformer(new SynonymQueryTransformer(config), query, Categories.STOCKMARKETTICKERS.name(), tefCxt, tef); final QueryBuilder builder = new QueryBuilder(query, trans); final String result = builder.getQueryString(); LOG.debug("testOneWord builder gave " + result); if( query.getFirstLeafClause().getKnownPredicates().contains(Categories.STOCKMARKETTICKERS)){ assertEquals("(sch schibsted)", result); }else{ assertEquals("sch", result); } } /** * * @throws no.sesat.search.query.parser.ParseException */ @Test public void testTwoWords() throws ParseException { final String queryString = "oslo sch schibsted"; final TokenEvaluationEngineImpl.Context tefCxt = new TokenEvaluationEngineTestContext(queryString); final TokenEvaluationEngine tef = new TokenEvaluationEngineImpl(tefCxt); final Query query = parseQuery(tef); final Map<Clause,String> trans = applyTransformer(new SynonymQueryTransformer(config), query, Categories.STOCKMARKETTICKERS.name(), tefCxt, tef); final QueryBuilder builder = new QueryBuilder(query, trans); final String result = builder.getQueryString(); LOG.debug("testTwoWords builder gave " + result); if( query.getFirstLeafClause().getKnownPredicates().contains(Categories.STOCKMARKETTICKERS)){ assertEquals("(oslo oslo areal) (sch schibsted) schibsted", result); }else{ assertEquals("oslo sch schibsted", result); } } /** * * @throws no.sesat.search.query.parser.ParseException */ @Test public void testTwoWordsExact() throws ParseException { // Not Exact match. Don't do expansion. final String queryString = "oslo sch schibsted"; final TokenEvaluationEngineImpl.Context tefCxt = new TokenEvaluationEngineTestContext(queryString); final TokenEvaluationEngine tef = new TokenEvaluationEngineImpl(tefCxt); final Query query = parseQuery(tef); final Map<Clause,String> trans = applyTransformer(new SynonymQueryTransformer(config), query, Categories.STOCKMARKETTICKERS.exactPeer().name(), tefCxt, tef); final QueryBuilder builder = new QueryBuilder(query, trans); final String result = builder.getQueryString(); LOG.debug("testTwoWordsExact builder gave " + result); assertEquals("oslo sch schibsted", result); } // leave this functionality broken until the alternation rotation implementation is fixed. // public void testMultiWordOriginalWithOtherTermAtEnd() throws ParseException { // // final String queryString = "schibsted asa oslo"; // final TokenEvaluationEngineImpl.Context tefCxt = new TokenEvaluationEngineTestContext(queryString); // final TokenEvaluationEngine tef = new TokenEvaluationEngineImpl(tefCxt); // // final Query query = parseQuery(tef); // final Map<Clause,String> trans = applyTransformer(new SynonymQueryTransformer(), query, // TokenPredicate.COMPANYRANK.name(), tefCxt, tef); // // final QueryBuilder builder = new QueryBuilder(query, trans); // final String result = builder.getQueryString(); // // LOG.debug("testMultiWordOriginalWithOtherTermAtEnd builder gave " + result); // if( query.getFirstLeafClause().getKnownPredicates().contains(TokenPredicate.COMPANYRANK)){ // assertEquals("(schibsted asa schasa) (oslo oslo areal)", result); // }else{ // assertEquals("schibsted asa oslo", result); // } // } private Map<Clause,String> applyTransformer( final SynonymQueryTransformer t, final Query query, final String predicateName, final TokenEvaluationEngineImpl.Context tefCxt, final TokenEvaluationEngine tef) { t.addPredicateName(predicateName); return super.applyTransformer(t,query,tefCxt,tef); } /** * */ public static final class QueryBuilder extends AbstractReflectionVisitor { private final Query query; private final Map map; private final StringBuilder sb = new StringBuilder(); /** * * @param q * @param m */ public QueryBuilder(final Query q, final Map m) { query = q; map = m; } /** * * @return */ public synchronized String getQueryString() { sb.setLength(0); visit(query.getRootClause()); return sb.toString(); } public void visitImpl(final LeafClause clause) { sb.append(map.get(clause)); } public void visitImpl(final UnaryClause clause) { clause.getFirstClause().accept(this); } public void visitImpl(final AndClause clause) { clause.getFirstClause().accept(this); sb.append(" AND "); clause.getSecondClause().accept(this); } public void visitImpl(final OrClause clause) { clause.getFirstClause().accept(this); sb.append(" OR "); clause.getSecondClause().accept(this); } public void visitImpl(final DefaultOperatorClause clause) { clause.getFirstClause().accept(this); sb.append(' '); clause.getSecondClause().accept(this); } public void visitImpl(final NotClause clause) { final String childsTerm = (String) map.get(clause.getFirstClause()); if (childsTerm != null && childsTerm.length() > 0) { sb.append("NOT "); clause.getFirstClause().accept(this); } } public void visitImpl(final AndNotClause clause) { final String childsTerm = (String) map.get(clause.getFirstClause()); if (childsTerm != null && childsTerm.length() > 0) { sb.append("ANDNOT "); clause.getFirstClause().accept(this); } } public void visitImpl(final XorClause clause) { // [TODO] we need to determine which branch in the query-tree we want to use. // Both branches to a XorClause should never be used. clause.getFirstClause().accept(this); // clause.getSecondClause().accept(this); } } private static class MapInitialisor extends AbstractReflectionVisitor { private final Map map; public MapInitialisor(final Map m) { map = m; } public void visitImpl(final LeafClause clause) { final String fullTerm = (clause.getField() == null ? "" : clause.getField() + ": ") + clause.getTerm(); map.put(clause, fullTerm); } public void visitImpl(final UnaryClause clause) { clause.getFirstClause().accept(this); } public void visitImpl(final AndClause clause) { clause.getFirstClause().accept(this); clause.getSecondClause().accept(this); } public void visitImpl(final OrClause clause) { clause.getFirstClause().accept(this); clause.getSecondClause().accept(this); } public void visitImpl(final DefaultOperatorClause clause) { clause.getFirstClause().accept(this); clause.getSecondClause().accept(this); } } }