/* * 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; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.SocketTimeoutException; import java.net.URLEncoder; import java.text.MessageFormat; import java.util.Map; import no.sesat.search.mode.config.YahooWebCommandConfig; import no.sesat.search.result.BasicResultList; import no.sesat.search.result.BasicResultItem; import no.sesat.search.result.ResultItem; import no.sesat.search.result.ResultList; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * Search against Yahoo! Contextual Web Service. * http://developer.yahoo.com/search/web/V1/contextSearch.html * * * @version $Id$ */ public class YahooWebSearchCommand extends AbstractYahooSearchCommand { // Constants ----------------------------------------------------- private static final Logger LOG = Logger.getLogger(YahooWebSearchCommand.class); private static final String ERR_FAILED_CREATING_URL = "Failed to create command url"; private static final String COMMAND_URL_PATTERN = "/WebSearchService/V1/webSearch?appid={0}&query={1}&context={2}&" + "results={3}&start={4}&" + "format={5}&{6}{7}language={8}&{9}{10}"; private static final String TOTALHITS_ATTRIBUTE ="totalResultsAvailable"; private static final String RESULT_ELEMENT = "Result"; // Attributes ---------------------------------------------------- // Static -------------------------------------------------------- // Constructors -------------------------------------------------- /** * Create new command. * * @param cxt The context to execute in. */ public YahooWebSearchCommand(final Context cxt) { super(cxt); setXmlRestful( new AbstractXmlRestful(cxt) { public String createRequestURL() { final YahooWebCommandConfig conf = YahooWebSearchCommand.this.getSearchConfiguration(); final String wrappedTransformedQuery = YahooWebSearchCommand.this.getTransformedQuery() + ' ' + YahooWebSearchCommand.this.getFilter(); final String site = null != conf.getSite() ? "site=" + conf.getSite() : null != cxt.getDataModel().getParameters().getValue("site") ? "site=" + cxt.getDataModel().getParameters().getValue("site").getUtf8UrlEncoded() : ""; try { return MessageFormat.format( COMMAND_URL_PATTERN, conf.getAppid(), URLEncoder.encode(wrappedTransformedQuery, "UTF-8"), URLEncoder.encode(wrappedTransformedQuery, "UTF-8"), conf.getResultsToReturn(), YahooWebSearchCommand.this.getOffset(), conf.getFormat(), conf.getAdult() ? "adult_ok=1&" : "", conf.getSimilar() ? "similar_ok=1&" : "", conf.getLanguage(), null != conf.getCountry() ? "country=" + conf.getCountry() + "&" : "", site); } catch (UnsupportedEncodingException ex) { throw new SearchCommandException(ERR_FAILED_CREATING_URL, ex); } } }); } // Public -------------------------------------------------------- public ResultList<ResultItem> execute() { try { final ResultList<ResultItem> searchResult = new BasicResultList<ResultItem>(); if(getTransformedQuery().trim().length() > 0 || getFilter().trim().length() > 0 || "*".equals(getQuery().getQueryString())){ final Document doc = getXmlRestful().getXmlResult(); if (doc != null) { final Element searchResponseE = doc.getDocumentElement(); final String totalHitsStr = searchResponseE.getAttribute(TOTALHITS_ATTRIBUTE); int totalHits; try { totalHits = Integer.parseInt(totalHitsStr); }catch(NumberFormatException e) { totalHits = Integer.MAX_VALUE; } searchResult.setHitCount(totalHits); // build results final NodeList list = searchResponseE.getElementsByTagName(RESULT_ELEMENT); for (int i = 0; i < list.getLength(); ++i) { final Element listing = (Element) list.item(i); final BasicResultItem item = createItem(listing); searchResult.addResult(item); } } } return searchResult; } catch (SocketTimeoutException ste) { LOG.error(getSearchConfiguration().getId() + " --> " + ste.getMessage()); return new BasicResultList<ResultItem>(); } catch (IOException e) { throw new SearchCommandException(e); } catch (SAXException e) { throw new SearchCommandException(e); } } /** Assured that associated SearchConfiguration is always of this type. **/ @Override public YahooWebCommandConfig getSearchConfiguration() { return (YahooWebCommandConfig)super.getSearchConfiguration(); } @Override public String getTransformedQuery() { final String tq = super.getTransformedQuery(); if(tq == null) { LOG.debug("transformedQuery is null, using \"\""); return ""; } return tq; } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- /** * * @param result * @return */ protected BasicResultItem createItem(final Element result) { final BasicResultItem item = new BasicResultItem(); for (final Map.Entry<String,String> entry : getSearchConfiguration().getResultFieldMap().entrySet()){ final Element fieldE = (Element) result.getElementsByTagName(entry.getKey()).item(0); if(null != fieldE && fieldE.getChildNodes().getLength() >0){ item.addField(entry.getValue(), fieldE.getFirstChild().getNodeValue()); } } return item; } @Override protected String getFilter() { return super.getFilter(); } @Override protected int getOffset() { return super.getOffset(); } @Override protected String getParameter(String paramName) { return super.getParameter(paramName); } // Private ------------------------------------------------------- // Inner classes ------------------------------------------------- }