/* Copyright (2007-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 no.sesat.search.result.BasicResultList;
import no.sesat.search.result.BasicResultItem;
import no.sesat.search.mode.config.YahooMediaCommandConfig;
import java.util.Map;
import java.text.MessageFormat;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.net.SocketTimeoutException;
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;
/**
* Command for searching images and videos using Yahoo! as a provider.
*
* Yahoo API documentation can be found here:
* https://dev.sesat.no/confluence/display/TECHDEV/Yahoo+Media+Search
*
* @version $Id$
*/
public final class YahooMediaSearchCommand extends AbstractYahooSearchCommand {
private static final Logger LOG = Logger.getLogger(YahooMediaSearchCommand.class);
private static final String COMMAND_URL_PATTERN =
"/std_xmls_a00?type=any&query={0}&offset={1}&custid1={2}&hits={3}&ocr={4}&catalog={5}&encoding=utf-8";
private static final String ERR_FAILED_CREATING_URL = "Failed to encode URL";
private static final String RESULT_HEADER_ELEMENT = "GRP";
private static final String TOTAL_HITS_ATTR = "TOT";
private static final String RESULT_ELEMENT = "RES";
private static final String URL_ENCODING = "UTF-8";
private static final String YAHOO_SIZE_PARAM = "dimensions";
private static final String SIZE_PARAM = "sz";
private static final String OCR_PARAM = "ocr";
private static final String FIELD_THUMB_HEIGHT = "thumb_height";
private static final String FIELD_THUMB_WIDTH = "thumb_width";
private static final String ATTRIBUTE_THUMB_GEO = "TGEO";
/**
* provides a mapping betweeen sizes defined by us
* and sizes defined by yahoo. Currently one to one.
*/
private static enum ImageMapping {
SMALL ("small"),
MEDIUM ("medium"),
LARGE ("large"),
WALLPAPER ("wallpaper"),
WIDEWALLPAPER ("widewallpaper");
private final String sizes;
ImageMapping(final String sizes) {
this.sizes = sizes;
}
/**
* Getter for property 'sizes'.
*
* @return Value for property 'sizes'.
*/
public String getSizes() {
return sizes;
}
}
/**
* Create new yahoo media command.
*
* @param cxt Context to execute in.
*/
public YahooMediaSearchCommand(final Context cxt) {
super(cxt);
setXmlRestful(
new AbstractXmlRestful(cxt) {
public String createRequestURL() {
String query = YahooMediaSearchCommand.this.getTransformedQuery();
final YahooMediaCommandConfig cfg = (YahooMediaCommandConfig) cxt.getSearchConfiguration();
if (cfg.getSite().length() > 0) {
query += " +site:" + cfg.getSite();
}
try {
final String ocr = YahooMediaSearchCommand.this.getSingleParameter(OCR_PARAM) != null
? YahooMediaSearchCommand.this.getSingleParameter(OCR_PARAM)
: cfg.getOcr();
String url = MessageFormat.format(
COMMAND_URL_PATTERN,
URLEncoder.encode(query, URL_ENCODING),
YahooMediaSearchCommand.this.getOffset(),
YahooMediaSearchCommand.this.getPartnerId(),
cfg.getResultsToReturn(),
ocr,
cfg.getCatalog());
if (YahooMediaSearchCommand.this.getSingleParameter(SIZE_PARAM) != null
&& !YahooMediaSearchCommand.this.getSingleParameter(SIZE_PARAM).equals("")) {
final ImageMapping mapping = ImageMapping.valueOf(
YahooMediaSearchCommand.this.getSingleParameter(SIZE_PARAM).toUpperCase());
if (mapping != null) {
url += "&" + YAHOO_SIZE_PARAM + "=" + mapping.getSizes();
}
}
return url;
} catch (final UnsupportedEncodingException e) {
throw new SearchCommandException(ERR_FAILED_CREATING_URL, e);
}
}
});
}
public ResultList<ResultItem> execute() {
try {
final Document doc = getXmlRestful().getXmlResult();
final ResultList<ResultItem> searchResult = new BasicResultList<ResultItem>();
if (doc != null) {
searchResult.setHitCount(0);
final Element searchResponseE = doc.getDocumentElement();
final Element resultHeaderE = (Element) searchResponseE.getElementsByTagName(RESULT_HEADER_ELEMENT).item(0);
if (resultHeaderE != null) {
searchResult.setHitCount(Integer.parseInt(resultHeaderE.getAttribute(TOTAL_HITS_ATTR)));
final NodeList list = searchResponseE.getElementsByTagName(RESULT_ELEMENT);
for (int i = 0; i < list.getLength(); ++i) {
final Element listing = (Element) list.item(i);
searchResult.addResult(createItem(listing));
}
}
}
searchResult.addField("generatedQuery", getQueryRepresentation());
return searchResult;
} catch (SocketTimeoutException ste) {
LOG.error(getSearchConfiguration().getId() + " --> " + ste.getMessage());
return new BasicResultList<ResultItem>();
} catch (final IOException e) {
throw new SearchCommandException(e);
} catch (final SAXException e) {
throw new SearchCommandException(e);
}
}
protected ResultItem createItem(final Element listing) {
final BasicResultItem item = new BasicResultItem();
for (final Map.Entry<String,String> entry : context.getSearchConfiguration().getResultFieldMap().entrySet()){
// Special case for thumb width & height.
if (entry.getKey().equals(FIELD_THUMB_HEIGHT)) {
final String geometry = listing.getAttribute(ATTRIBUTE_THUMB_GEO);
final String height = geometry.substring(geometry.indexOf("x") + 1);
item.addField(entry.getValue(), height);
} else if (entry.getKey().equals(FIELD_THUMB_WIDTH)) {
final String geometry = listing.getAttribute(ATTRIBUTE_THUMB_GEO);
final String width = geometry.substring(0, geometry.indexOf("x"));
item.addField(entry.getValue(), width);
} else {
final String field = listing.getAttribute(entry.getKey().toUpperCase());
if (!"".equals(field)) {
item.addField(entry.getValue(), field);
}
}
}
return item;
}
}