/*Copyright (2008-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/>. */ package no.sesat.search.mode.command.querybuilder; import java.util.Collection; import java.util.HashSet; import no.sesat.search.mode.config.querybuilder.InfixQueryBuilderConfig; import no.sesat.search.mode.config.querybuilder.QueryBuilderConfig; import no.sesat.search.query.AndClause; import no.sesat.search.query.DefaultOperatorClause; import no.sesat.search.query.EmailClause; 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.UrlClause; /** The default QueryBuilder. * * Is not thread safe. * It does not use the QueryBuilderConfig. * It blanks out valid filters. * Largely mimics the Query tree layout replacing OperatorClauses with the RESERVED_WORDS. * Does not write infixes when the next occurring leaf is inside a NotClause. * * @todo grouping doesn't work due to a dependence on the lean of the binary tree. * * @version $Id$ */ public class InfixQueryBuilder extends AbstractQueryBuilder{ // Constants ----------------------------------------------------- //private static final Logger LOG = Logger.getLogger(InfixQueryBuilder.class); // Attributes ---------------------------------------------------- // Static -------------------------------------------------------- // Constructors -------------------------------------------------- public InfixQueryBuilder(final Context cxt, final QueryBuilderConfig config) { super(cxt, config); } // Public ------------------------------------------------------- // protected ---------------------------------------------- @Override protected InfixQueryBuilderConfig getConfig() { return (InfixQueryBuilderConfig) super.getConfig(); } @Override protected Collection<String> getWordsToEscape() { final Collection<String> words = new HashSet<String>(super.getWordsToEscape()); if(!getConfig().getAndInfix().isEmpty()){ words.add(getConfig().getAndInfix()); } if(!getConfig().getNotPrefix().isEmpty()){ words.add(getConfig().getNotPrefix()); } if(!getConfig().getOrInfix().isEmpty()){ words.add(getConfig().getOrInfix()); } return words; } protected void visitImpl(final LeafClause clause) { if(!isEmptyLeaf(clause)){ appendToQueryRepresentation(getEscapedTransformedTerm(clause)); } } /** * Adds quotes around the Email address and hard escape everything. * Since there is the @ symbols in email addresses. * * @param clause The email clause. */ protected void visitImpl(final EmailClause clause) { if(!isEmptyLeaf(clause)){ appendToQueryRepresentation(getContext().escape(getContext().getTransformedTerm(clause).toLowerCase())); } } /** * Adds quotes around the URL and hard escape everything. * Since there are so many symbols in URLs. * * @param clause The url clause. */ protected void visitImpl(final UrlClause clause) { if(!isEmptyLeaf(clause)){ appendToQueryRepresentation(getContext().escape(getContext().getTransformedTerm(clause).toLowerCase())); } } protected void visitImpl(final UnaryClause clause) { if (!isEmptyLeaf(clause)) { clause.getFirstClause().accept(this); } } protected void visitImpl(final AndClause clause) { if (!isEmptyLeaf(clause)) { final boolean unary = isEmptyLeaf(clause.getFirstClause()) || isEmptyLeaf(clause.getSecondClause()); if(getConfig().getAndGrouped() && !unary){ appendToQueryRepresentation(getConfig().getAndGroupOpen()); } clause.getFirstClause().accept(this); if((!getConfig().getSupportsNot() || !isNextLeafInsideNotClause(clause.getSecondClause())) && !unary){ appendToQueryRepresentation(' ' + getConfig().getAndInfix() + ' '); } clause.getSecondClause().accept(this); if(getConfig().getAndGrouped() && !unary){ appendToQueryRepresentation(getConfig().getAndGroupClose()); } } } protected void visitImpl(final OrClause clause) { if (!isEmptyLeaf(clause)) { final boolean unary = isEmptyLeaf(clause.getFirstClause()) || isEmptyLeaf(clause.getSecondClause()); if(getConfig().getOrGrouped() && !unary){ appendToQueryRepresentation(getConfig().getOrGroupOpen()); } clause.getFirstClause().accept(this); if((!getConfig().getSupportsNot() || !isNextLeafInsideNotClause(clause.getSecondClause())) && !unary){ appendToQueryRepresentation(' ' + getConfig().getOrInfix() + ' '); } clause.getSecondClause().accept(this); if(getConfig().getOrGrouped() && !unary){ appendToQueryRepresentation(getConfig().getOrGroupClose()); } } } protected void visitImpl(final DefaultOperatorClause clause) { if (!isEmptyLeaf(clause)) { final boolean unary = isEmptyLeaf(clause.getFirstClause()) || isEmptyLeaf(clause.getSecondClause()); if(getConfig().getDefaultGrouped() && !unary){ appendToQueryRepresentation(getConfig().getDefaultGroupOpen()); } clause.getFirstClause().accept(this); if((!getConfig().getSupportsNot() || !isNextLeafInsideNotClause(clause.getSecondClause())) && !unary){ appendToQueryRepresentation(' ' + getConfig().getDefaultInfix() + ' '); } clause.getSecondClause().accept(this); if(getConfig().getDefaultGrouped() && !unary){ appendToQueryRepresentation(getConfig().getDefaultGroupClose()); } } } protected void visitImpl(final NotClause clause) { if (getConfig().getSupportsNot() && !isEmptyLeaf(clause)) { appendToQueryRepresentation(' ' + getConfig().getNotPrefix()); if(getConfig().getNotGrouped()){ appendToQueryRepresentation(getConfig().getNotGroupOpen()); } clause.getFirstClause().accept(this); if(getConfig().getNotGrouped()){ appendToQueryRepresentation(getConfig().getNotGroupClose()); } } } // Private ------------------------------------------------------- // Inner classes ------------------------------------------------- }