Java tutorial
/* Copyright (2005-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/>. * * AbstractFast4SearchCommand.java * * Created on 14 March 2006, 19:51 * */ package no.sesat.search.mode.command; import no.fast.ds.search.BaseParameter; import no.fast.ds.search.ConfigurationException; import no.fast.ds.search.FastSearchEngineFactory; import no.fast.ds.search.IDocumentSummary; import no.fast.ds.search.IDocumentSummaryField; import no.fast.ds.search.IFastSearchEngine; import no.fast.ds.search.IFastSearchEngineFactory; import no.fast.ds.search.IModifier; import no.fast.ds.search.INavigator; import no.fast.ds.search.IQuery; import no.fast.ds.search.IQueryResult; import no.fast.ds.search.IQueryTransformation; import no.fast.ds.search.IQueryTransformations; import no.fast.ds.search.ISearchParameters; import no.fast.ds.search.Query; import no.fast.ds.search.SearchEngineException; import no.fast.ds.search.SearchParameter; import no.fast.ds.search.SearchParameters; import no.sesat.search.datamodel.generic.StringDataObject; import no.sesat.search.mode.config.FastCommandConfig; import no.sesat.search.result.BasicResultItem; import no.sesat.search.result.FastSearchResult; import no.sesat.search.result.Modifier; import no.sesat.search.result.Navigator; import no.sesat.search.site.config.SiteConfiguration; import no.sesat.search.result.BasicWeightedSuggestion; import no.sesat.search.result.ModifierDateComparator; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import java.io.IOException; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import no.sesat.search.result.ResultItem; import no.sesat.search.result.ResultList; import no.sesat.search.result.WeightedSuggestion; /** * Handles the basic implementation of the FAST 4 search. * * Includes support for * - faceted search (modifiers or navigators), * - relevant queries, proper name and spelling suggestions. * * @version $Id$ */ public abstract class AbstractFast4SearchCommand extends AbstractSearchCommand { // Constants ----------------------------------------------------- private static final Logger LOG = Logger.getLogger(AbstractFast4SearchCommand.class); private static final String ERR_FAST_FAILURE = " suffered from a FAST error "; private static final String ERR_EXECUTE_FAILURE = "execute() failed"; private static final String DEBUG_FAST_SEARCH_ENGINE = "Creating Fast Engine to "; private static final String DEBUG_EXECUTE_QR_URL = "execute() QueryServerURL="; private static final String DEBUG_EXECUTE_COLLECTIONS = "execute() Collections="; private static final String DEBUG_EXECUTE_QUERY = "execute() Query="; private static final String DEBUG_EXECUTE_FILTER = "execute() Filter="; private static final String COLLAPSE_PARAMETER = "collapse"; // Attributes ---------------------------------------------------- private final Map<String, Navigator> navigators; // Deprecated code. I cannot see how anybody is using it. Much related below is also commented out. // private final Map<String, String[]> navigatedValues = new HashMap<String, String[]>(); private final String queryServerUrl; // Static -------------------------------------------------------- private static final Map<String, IFastSearchEngine> SEARCH_ENGINES = new ConcurrentHashMap<String, IFastSearchEngine>(); private static transient IFastSearchEngineFactory engineFactory; static { try { engineFactory = FastSearchEngineFactory.newInstance(); } catch (ConfigurationException e) { LOG.fatal(e.getMessage(), e); // Who exactly is expected to catch from a static constructor? throw new SearchCommandException(e); } } // Constructors -------------------------------------------------- /** * Creates a new instance of AbstractFast4SearchCommand * @param cxt the context the search command must work within. */ public AbstractFast4SearchCommand(final Context cxt) { super(cxt); final FastCommandConfig conf = (FastCommandConfig) cxt.getSearchConfiguration(); final SiteConfiguration siteConf = cxt.getDataModel().getSite().getSiteConfiguration(); queryServerUrl = siteConf.getProperty(conf.getQueryServerUrl()); navigators = conf.getNavigators(); } // Public -------------------------------------------------------- /** Return all our configured navigator's field:value pairs in one string in filter syntax. * Commas in the navigator's parameter value are treated as separators between optional selected navigator items. * * @deprecated @todo extract to a query transformer, FastNavigationQueryTransformer * * @return field:value filter string. */ public Collection<String> createNavigationFilterStrings() { Collection<String> filterStrings = new ArrayList<String>(); // for (final Iterator iterator = navigatedValues.keySet().iterator(); iterator.hasNext();) { // final String field = (String) iterator.next(); // // final String modifiers[] = navigatedValues.get(field); // // for (int i = 0; i < modifiers.length; i++) { // if (!field.equals("contentsource") || !modifiers[i].equals("Norske nyheter")) { // if ("adv".equals(getSearchConfiguration().getFiltertype())) // filterStrings.add(" AND " + field + ":\"" + modifiers[i] + "\""); // else // filterStrings.add("+" + field + ":\"" + modifiers[i] + "\""); // } // } // } for (final Navigator navigator : getNavigators().values()) { filterStrings = createNavigationFilterStrings(filterStrings, navigator); } return filterStrings; } /** * set the IFastSearchEngineFactory to use when getting, or creating, IFastSearchEngines. * @param factory */ public static void setSearchEngineFactory(final IFastSearchEngineFactory factory) { engineFactory = factory; } // Z implementation ---------------------------------------------- // SearchCommand overrides ---------------------------------------------- /** * Assured associated search configuration will always be of this type. * */ @Override public FastCommandConfig getSearchConfiguration() { return (FastCommandConfig) super.getSearchConfiguration(); } public ResultList<ResultItem> execute() { try { final IFastSearchEngine engine = getSearchEngine(); final IQuery fastQuery = createQuery(); IQueryResult result = null; try { LOG.debug(DEBUG_EXECUTE_QR_URL + queryServerUrl); LOG.debug(DEBUG_EXECUTE_COLLECTIONS + getSearchConfiguration().getCollections()); LOG.debug(DEBUG_EXECUTE_QUERY + fastQuery.getQueryString()); LOG.debug(DEBUG_EXECUTE_FILTER + getSearchConfiguration().getCollectionFilterString()); result = engine.search(fastQuery); } catch (SocketTimeoutException ste) { LOG.error(getSearchConfiguration().getName() + " --> " + ste.getMessage()); return new FastSearchResult<ResultItem>(); } catch (IOException ioe) { LOG.error(getSearchConfiguration().getName() + ERR_FAST_FAILURE, ioe); return new FastSearchResult<ResultItem>(); } catch (SearchEngineException fe) { LOG.error(getSearchConfiguration().getName() + ERR_FAST_FAILURE + '[' + fe.getErrorCode() + ']', fe); return new FastSearchResult<ResultItem>(); } DUMP.info(fastQuery.toString()); final FastSearchResult<ResultItem> searchResult = collectResults(result); if (getSearchConfiguration().isSpellcheck()) { collectSpellingSuggestions(result, searchResult); } if (getSearchConfiguration().isRelevantQueries() && null == getParameter("qs")) { collectRelevantQueries(result, searchResult); } if (getNavigators() != null) { collectModifiers(result, searchResult); } final String collapseId = getParameter(COLLAPSE_PARAMETER); if (getSearchConfiguration().isCollapsing() && getSearchConfiguration().isExpansion()) { if (collapseId != null && !collapseId.equals("")) { if (searchResult.getResults().size() > 0) { final ResultItem itm = searchResult.getResults().get(0); final URL url = new URL(itm.getField("url")); searchResult.addField("collapsedDomain", url.getHost()); } } } return searchResult; } catch (ConfigurationException e) { LOG.error(ERR_EXECUTE_FAILURE, e); throw new SearchCommandException(e); } catch (MalformedURLException e) { LOG.error(ERR_EXECUTE_FAILURE, e); throw new SearchCommandException(e); } } /** * @deprecated does nothing. here only to maintain API. */ public void addNavigatedTo(final String navigatorKey) { } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- /** * Get the navigators from the command's SearchConfiguration. * @return the navigators */ protected Map<String, Navigator> getNavigators() { return navigators; } @Override protected int getResultsToReturn() { return getSearchConfiguration().getResultsToReturn(); } /** * Get, or create, the IFastSearchEngine responsible for connecting to and fetching the results from the fsat index. * @return the IFastSearchEngine * @throws ConfigurationException * @throws MalformedURLException index url is malformed */ protected IFastSearchEngine getSearchEngine() throws ConfigurationException, MalformedURLException { try { if (!SEARCH_ENGINES.containsKey(queryServerUrl)) { LOG.debug(DEBUG_FAST_SEARCH_ENGINE + getSearchConfiguration().getQueryServerUrl() + "-->" + queryServerUrl); final IFastSearchEngine engine = engineFactory.createSearchEngine(queryServerUrl); SEARCH_ENGINES.put(queryServerUrl, engine); } return SEARCH_ENGINES.get(queryServerUrl); } catch (MalformedURLException e) { LOG.error("Malformed URL is: " + queryServerUrl); throw (e); } } protected String getSortBy() { return getSearchConfiguration().getSortBy(); } /** Add additional fast search parameters. * iSearchParameters.setParameter(new SearchParameter(...)); * * @param iSearchParameters live list of parameters being built and eventually used in the fast query. */ protected void setAdditionalParameters(final ISearchParameters iSearchParameters) { for (Map.Entry<String, String> entry : getSearchConfiguration().getSearchParameterMap().entrySet()) { iSearchParameters.setParameter(new SearchParameter(entry.getKey(), entry.getValue())); } } // Private ------------------------------------------------------- @SuppressWarnings("unchecked") private void collectSpellingSuggestions(final IQueryResult result, final FastSearchResult searchResult) { final IQueryTransformations qTransforms = result.getQueryTransformations(false); if (qTransforms.getSuggestions().size() > 0) { for (IQueryTransformation transformation : (Collection<IQueryTransformation>) qTransforms .getAllQueryTransformations()) { if (transformation.getName().equals("FastQT_SpellCheck") && transformation.getAction().equals("nop")) { final String custom = transformation.getCustom(); final WeightedSuggestion suggestion = createSpellingSuggestion(custom); searchResult.addSpellingSuggestion(suggestion); } if (transformation.getName().equals("FastQT_ProperName")) { String custom = transformation.getCustom(); WeightedSuggestion suggestion = createProperNameSuggestion(custom); if (suggestion != null) { searchResult.addSpellingSuggestion(suggestion); } } } } if ("42".equals(datamodel.getQuery().getString())) { final WeightedSuggestion egg = BasicWeightedSuggestion.instanceOf("42", "Meningen med livet", "Meningen med livet", 1000); searchResult.addSpellingSuggestion(egg); } if ("kvasir".equalsIgnoreCase(datamodel.getQuery().getString())) { final WeightedSuggestion egg = BasicWeightedSuggestion.instanceOf("kvasir", "sesam", "sesam", 1000); searchResult.addSpellingSuggestion(egg); } if ("meningen med livet".equalsIgnoreCase(datamodel.getQuery().getString())) { final WeightedSuggestion egg = BasicWeightedSuggestion.instanceOf("meningen med livet", "42", "42", 1000); searchResult.addSpellingSuggestion(egg); } } private WeightedSuggestion createSpellingSuggestion(final String custom) { final int suggestionIndex = custom.indexOf("->"); final int qualityIndex = custom.indexOf("Quality:"); LOG.debug("Custom is " + custom); final String orig = custom.substring(0, suggestionIndex); final String string = custom.substring(suggestionIndex + 2, qualityIndex - 2); final String quality = custom.substring(qualityIndex + 9, qualityIndex + 12); return BasicWeightedSuggestion.instanceOf(orig, string, string, Integer.parseInt(quality)); } private FastSearchResult<ResultItem> collectResults(final IQueryResult result) { if (LOG.isDebugEnabled()) { LOG.debug( getSearchConfiguration().getName() + " Collecting results. There are " + result.getDocCount()); LOG.debug(getSearchConfiguration().getName() + " Number of results to collect: " + getSearchConfiguration().getResultsToReturn()); } final FastSearchResult<ResultItem> searchResult = new FastSearchResult<ResultItem>(); final int cnt = getOffset(); final int maxIndex = Math.min(cnt + getResultsToReturn(), result.getDocCount()); searchResult.setHitCount(result.getDocCount()); for (int i = cnt; i < maxIndex; i++) { final IDocumentSummary document = result.getDocument(i + 1); //catch nullpointerException because of unaccurate doccount try { final ResultItem item = createResultItem(document); searchResult.addResult(item); } catch (NullPointerException e) { LOG.debug("Error finding document", e); return searchResult; } } return searchResult; } private ResultItem createResultItem(final IDocumentSummary document) { ResultItem item = new BasicResultItem(); for (final Map.Entry<String, String> entry : getSearchConfiguration().getResultFieldMap().entrySet()) { final IDocumentSummaryField summary = document.getSummaryField(entry.getKey()); if (summary != null) { item = item.addField(entry.getValue(), summary.getSummary()); } } if (getSearchConfiguration().isCollapsing() && getSearchConfiguration().isExpansion()) { final String currCollapseId = getParameter(COLLAPSE_PARAMETER); if (currCollapseId == null || currCollapseId.equals("")) { final String moreHits = document.getSummaryField("morehits").getSummary(); if (moreHits.equals("1")) { item = item.addField("moreHits", "true").addField("collapseParameter", COLLAPSE_PARAMETER) .addField("collapseId", document.getSummaryField("collapseid").getSummary()); } } } return item; } private IQuery createQuery() { final ISearchParameters params = new SearchParameters(); params.setParameter(new SearchParameter(BaseParameter.LEMMATIZE, getSearchConfiguration().isLemmatise())); params.setParameter( new SearchParameter("sesat:uniqueId", context.getDataModel().getParameters().getUniqueId())); if (getSearchConfiguration().isSpellcheck()) { params.setParameter(new SearchParameter(BaseParameter.SPELL, "suggest")); params.setParameter(new SearchParameter("qtf_spellcheck:addconsidered", "1")); params.setParameter(new SearchParameter("qtf_spellcheck:consideredverbose", "1")); } if (getSearchConfiguration().getName() != null && getSearchConfiguration().getName().equals("relevantQueries")) { params.setParameter(new SearchParameter("sources", "alone")); } String kwString = ""; String queryString = getTransformedQuery(); if (getSearchConfiguration().isKeywordClusteringEnabled()) { if (null != getParameter("kw")) { kwString = getParameter("kw"); } if (!kwString.equals("")) { queryString += " " + kwString; } } // TODO: This is a little bit messy // Set filter, the filtertype may be adv final StringBuilder filter = new StringBuilder(getSearchConfiguration().getCollectionFilterString()); if (!getSearchConfiguration().isIgnoreNavigation() && getNavigators() != null) { final Collection<String> navStrings = createNavigationFilterStrings(); filter.append(' '); filter.append(' ').append(StringUtils.join(navStrings.iterator(), " ")); } if (getSearchConfiguration().getOffensiveScoreLimit() > 0) { filter.append(' ').append("-ocfscore:>").append(getSearchConfiguration().getOffensiveScoreLimit()); } if (getSearchConfiguration().getSpamScoreLimit() > 0) { filter.append(' ').append("+spamscore:<").append(getSearchConfiguration().getSpamScoreLimit()); } final String collapseId = getParameter(COLLAPSE_PARAMETER); if (getSearchConfiguration().isCollapsing()) { if (null == collapseId || "".equals(collapseId) || !getSearchConfiguration().isExpansion()) { params.setParameter(new SearchParameter(BaseParameter.COLLAPSING, true)); } else { params.setParameter(new SearchParameter(BaseParameter.COLLAPSING, false)); filter.append(" +collapseid:").append(collapseId); } } if (getSearchConfiguration().getFilter() != null && getSearchConfiguration().getFilter().length() > 0) { // TODO create NowMacroFilterQueryTransfomer to do this instead final Calendar c = Calendar.getInstance(); final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); final String updatedFilter = getSearchConfiguration().getFilter().replaceAll("\\{NOW\\}", sdf.format(c.getTime())); filter.append(' ' + updatedFilter); } // Init dynamic filters final String superFilter = null == getFilter() ? "" : getFilter(); LOG.debug("createQuery: superFilter=" + superFilter); params.setParameter(new SearchParameter("filtertype", "adv".equals(getSearchConfiguration().getFiltertype()) ? "adv" : "any")); params.setParameter(new SearchParameter(BaseParameter.TYPE, getSearchConfiguration().getQueryType())); params.setParameter(new SearchParameter(BaseParameter.FILTER, filter.toString() + ' ' + superFilter)); if (getSearchConfiguration().getQtPipeline() != null && getSearchConfiguration().getQtPipeline().length() > 0) { params.setParameter( new SearchParameter(BaseParameter.QTPIPELINE, getSearchConfiguration().getQtPipeline())); } params.setParameter(new SearchParameter(BaseParameter.QUERY, queryString)); params.setParameter(new SearchParameter(BaseParameter.COLLAPSING, getSearchConfiguration().isCollapsing())); params.setParameter( new SearchParameter(BaseParameter.LANGUAGE, getSearchConfiguration().getSpellchecklanguage())); if (getNavigators() != null && getNavigators().size() > 0) { params.setParameter(new SearchParameter(BaseParameter.NAVIGATION, true)); } params.setParameter(new SearchParameter("hits", getResultsToReturn())); params.setParameter(new SearchParameter(BaseParameter.CLUSTERING, getSearchConfiguration().isClustering())); if (getSearchConfiguration().getResultView() != null && getSearchConfiguration().getResultView().length() > 0) { params.setParameter( new SearchParameter(BaseParameter.RESULT_VIEW, getSearchConfiguration().getResultView())); } // default SORT_BY is defined by configuration if (getSortBy() != null && getSortBy().length() > 0) { params.setParameter(new SearchParameter(BaseParameter.SORT_BY, getSortBy())); } // XXX Move-out. This code is specific to Norway's mobileYellowGeo mode! if (null != getParameter("c") && getParameter("c").equals("yg")) { if (getParameter("type").equals("f")) { params.setParameter(new SearchParameter("qtf_geosearch:center", '(' + getParameter("cla") + ',' + getParameter("clo"))); params.setParameter(new SearchParameter("qtf_geosearch:filterbox", "[(" + getParameter("la1") + "," + getParameter("lo1") + ");(" + getParameter("la2") + ',' + getParameter("lo2") + ")]")); params.setParameter(new SearchParameter("sortdirection", "ascending")); } else { params.setParameter(new SearchParameter("qtf_geosearch:center", '(' + getParameter("cla") + "," + getParameter("clo"))); params.setParameter(new SearchParameter("qtf_geosearch:radius", getParameter("rad"))); params.setParameter(new SearchParameter("sortdirection", "ascending")); } } // <-- END-OF move-out if (null != getParameter("rank")) { params.setParameter(new SearchParameter(BaseParameter.SORT_BY, getParameter("rank"))); } // This now uses sort order from canfiguration, old ones still here for backwards compability untill all are uppdated if (isUserSortable()) { final String sortBy = getUserSortBy(); LOG.debug("userSortBy " + sortBy); // TODO move-out to genericno. this is configuration hardcoded. if ("default".equals(sortBy)) { params.setParameter( new SearchParameter(BaseParameter.SORT_BY, getSearchConfiguration().getSortBy())); } else if ("alternative".equals(sortBy) && getSearchConfiguration().getAlternativeSortBy() != null) { params.setParameter(new SearchParameter(BaseParameter.SORT_BY, getSearchConfiguration().getAlternativeSortBy())); } else if ("standard".equals(sortBy)) { params.setParameter(new SearchParameter(BaseParameter.SORT_BY, "retriever")); } else if ("datetime".equals(sortBy)) { params.setParameter(new SearchParameter(BaseParameter.SORT_BY, "docdatetime+standard")); } else if ("-datetime".equals(sortBy)) { params.setParameter(new SearchParameter(BaseParameter.SORT_BY, "+docdatetime")); } // <-- END-OF move-out. } params.setParameter(new SearchParameter(BaseParameter.NAVIGATORS, getNavigatorsString())); setAdditionalParameters(params); return new Query(params); } private String getNavigatorsString() { final Collection<Navigator> allFlattened = new ArrayList<Navigator>(); for (Navigator navigator : getNavigators().values()) { allFlattened.addAll(flattenNavigators(new ArrayList<Navigator>(), navigator)); } return StringUtils.join(allFlattened.iterator(), ','); } private Collection<Navigator> flattenNavigators(Collection<Navigator> soFar, Navigator nav) { soFar.add(nav); // don't ask for navigators one step beyond anything not selected if (null != nav.getChildNavigator() && null != datamodel.getParameters().getValue(nav.getId())) { flattenNavigators(soFar, nav.getChildNavigator()); } return soFar; } private void collectModifiers(IQueryResult result, FastSearchResult<ResultItem> searchResult) { for (Navigator nav : getNavigators().values()) { collectModifier(nav, result, searchResult); } } private void collectModifier(final Navigator nav, final IQueryResult result, final FastSearchResult<ResultItem> searchResult) { final String navigatorKey = nav.getId(); final INavigator navigator = result.getNavigator(nav.getName()); if (null != navigator) { final Iterator iterator = navigator.modifiers(); while (iterator.hasNext()) { final IModifier modifier = (IModifier) iterator.next(); if (!"unknown".equals(modifier.getName())) { searchResult.addModifier(navigatorKey, new Modifier(modifier.getName(), modifier.getCount(), nav)); } } // live copy of list! final List<Modifier> modifiers = searchResult.getModifiers(navigatorKey); if (null != modifiers) { switch (nav.getSort()) { case DAY_MONTH_YEAR: Collections.sort(modifiers, ModifierDateComparator.DAY_MONTH_YEAR); break; case DAY_MONTH_YEAR_DESCENDING: Collections.sort(modifiers, ModifierDateComparator.DAY_MONTH_YEAR_DESCENDING); break; case YEAR_MONTH_DAY_DESCENDING: Collections.sort(modifiers, ModifierDateComparator.YEAR_MONTH_DAY_DESCENDING); break; case YEAR: Collections.sort(modifiers, ModifierDateComparator.YEAR); break; case MONTH_YEAR: Collections.sort(modifiers, ModifierDateComparator.MONTH_YEAR); break; case CUSTOM: Collections.sort(modifiers, getModifierComparator(nav)); break; case NONE: // Use the sorting the index returns break; case COUNT: /* Fall through */ default: Collections.sort(modifiers); break; } } // include any child if (null != nav.getChildNavigator()) { collectModifier(nav.getChildNavigator(), result, searchResult); } } } /** Override to provide custom modifier comparators. * This implementation always return null. * * @param nav * @return null */ protected Comparator<Modifier> getModifierComparator(final Navigator nav) { return null; } private WeightedSuggestion createProperNameSuggestion(String custom) { int suggestionIndex = custom.indexOf("->"); LOG.debug("Custom is " + custom); String orig = custom.substring(0, suggestionIndex); String string = custom.substring(suggestionIndex + 2); string = string.replaceAll("\"", ""); if (orig.equalsIgnoreCase(string)) { return null; } return BasicWeightedSuggestion.instanceOf(orig, string, string, 1000); } @SuppressWarnings("unchecked") private void collectRelevantQueries(IQueryResult result, FastSearchResult searchResult) { if (result.getQueryTransformations(false).getSuggestions().size() > 0) { for (IQueryTransformation transformation : (Collection<IQueryTransformation>) result .getQueryTransformations(false).getAllQueryTransformations()) { if (transformation.getName().equals("FastQT_Synonym") && transformation.getMessageID() == 8) { final String query = transformation.getQuery(); final String[] forWords = query.split("#!#"); for (int i = 0; i < forWords.length; i++) { final String[] forOneWord = forWords[i].split("###"); for (int j = 0; j < forOneWord.length; j++) { final String[] suggNweight = forOneWord[j].split("@"); if (!datamodel.getQuery().getString().equalsIgnoreCase(suggNweight[0])) { final WeightedSuggestion rq = BasicWeightedSuggestion.instanceOf( getQuery().getQueryString(), suggNweight[0], suggNweight[0], 2 == suggNweight.length ? Integer.valueOf(suggNweight[1]) : Integer.MIN_VALUE); searchResult.addRelevantQuery(rq); } } } } } } } private Collection<String> createNavigationFilterStrings(final Collection<String> filterStrings, final Navigator navigator) { final StringDataObject navigatedValue = datamodel.getParameters().getValue(navigator.getId()); if (null != navigatedValue) { // TODO this test should be encapsulated with the delegated filterBuilder final StringBuilder filter = new StringBuilder( "adv".equals(getSearchConfiguration().getFiltertype()) ? " AND (" : " +("); // splitting here allows for multiple navigation selections within the one navigation level. for (String navSingleValue : navigatedValue.getString().split(",")) { final String value = navigator.isBoundaryMatch() ? "^\"" + navSingleValue + "\"$" : "\"" + navSingleValue + "\""; filter.append(' ' + navigator.getField() + ':' + value); } filterStrings.add(filter.append(" )").toString()); } // include any children (if parent is selected) return null != navigatedValue && null != navigator.getChildNavigator() ? createNavigationFilterStrings(filterStrings, navigator.getChildNavigator()) : filterStrings; } // Inner classes ------------------------------------------------- }