package eu.europeana.service.ir.image.web.rest; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import eu.europeana.api2.web.model.json.ApiError; import eu.europeana.api2.web.model.json.abstracts.ApiResponse; import eu.europeana.service.ir.image.IRConfiguration; import eu.europeana.service.ir.image.api.ImageSearchingService; import eu.europeana.service.ir.image.exceptions.ImageSearchingException; import eu.europeana.service.ir.image.web.model.json.ImageSimilaritySearchResults; import eu.europeana.service.ir.image.web.model.json.SearchResultItem; /** * @author paolo * @author Sergiu Gordea <sergiu.gordea_at_ait.ac.at> */ @Controller public class ImageSearchingRest extends BaseRestService { private Logger log = Logger.getLogger(getClass()); @Autowired ImageSearchingService imageSearching; @Autowired IRConfiguration configuration; private static final int REQUEST_NUMBER_NOT_ACTIVE = -99; //QueryResultsMarshaller queryResultsMarshaller = new QueryResultsMarshaller(); public void setImageSearchingService(ImageSearchingService imageSearching) { this.imageSearching = imageSearching; } /** * @param configuration */ public void setConfiguration(IRConfiguration configuration) { this.configuration = configuration; } /** * @return */ public IRConfiguration getConfiguration() { return configuration; } @Override public String getComponentName() { return getConfiguration().getComponentName(); } /** * This method returns the name of the current component. This is the basic method to test if the deployment was completed correctly * and the service is able to accept answer web requests. * @return the name of the current web component */ @RequestMapping(value = "/component", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) @ResponseBody public String displayComponentName() { return getComponentName(); } /** * This method retrieves the list or similar images for the image already available in the index being identified by the given queryImageId * If start and rows parameters are used, the subset of items with the size of <code>rows<code> items starting with the <code>start<code> position will be retrieved. * * @param queryImageId - the europeanaId for the query image * @param start - start position in the result set * @param rows - size of the retrieved items set * @param wskey * @param profile * @param response * @return - the result set containing the similar items, or the appropriate error message in case of failure. See also {@link ApiResponse} */ @RequestMapping(value = "/searchById.json", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody ApiResponse searchById( @RequestParam(value = "queryImageId", required = true) String queryImageId, @RequestParam(value = "start", required = false, defaultValue="0") int start, @RequestParam(value = "rows", required = false, defaultValue="12") int rows, @RequestParam(value = "qt", required = false) String queryType, @RequestParam(value = "wskey", required = false) String wskey, @RequestParam(value = "profile", required = false, defaultValue="similarimage") String profile, HttpServletResponse response) { try { imageSearching.searchSimilar(queryImageId, queryType); return prepareSearchResults(start, rows, wskey, "/image/searchById.json"); } catch (ImageSearchingException e) { log.error("error searching by id " + queryImageId, e); // throw new WebApplicationException(e); return new ApiError(wskey, "/searchById.json", e.getMessage(), REQUEST_NUMBER_NOT_ACTIVE); } } private ApiResponse prepareSearchResults(int start, int rows, String wskey, String action) throws ImageSearchingException { ImageSimilaritySearchResults<SearchResultItem> results = new ImageSimilaritySearchResults<SearchResultItem>(wskey, action); results.setSearchResults(imageSearching.getResults(start, rows)); results.setTotalResults(imageSearching.getTotalResults()); return results; } /** * This method retrieves the list or similar images for the image embedded in the HTTP request. * If start and rows parameters are used, the subset of items with the size of <code>rows<code> items starting with the <code>start<code> position will be retrieved. * * @param queryImage the input stream used to read the image content * @param start - start position in the result set * @param rows - size of the retrieved items set * @param wskey * @param profile * @param response * @return the result set containing the similar items, or the appropriate error message in case of failure. See also {@link ApiResponse} */ @RequestMapping(value = "/searchByObj.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody ApiResponse searchByImageFile( @RequestParam(value = "imgFile", required = true) InputStream queryImage, @RequestParam(value = "start", required = false, defaultValue="0") int start, @RequestParam(value = "rows", required = false, defaultValue="12") int rows, @RequestParam(value = "qt", required = false) String queryType, @RequestParam(value = "wskey", required = false) String wskey, @RequestParam(value = "profile", required = false, defaultValue="similarimage") String profile, HttpServletResponse response ) { try { imageSearching.searchSimilar(queryImage, queryType); return prepareSearchResults(start, rows, wskey, "/image/searchByObj.json"); } catch (ImageSearchingException e) { log.error("error searching by obj ", e); // throw new WebApplicationException(e); return new ApiError(wskey, "/searchByObj.json", e.getMessage(), REQUEST_NUMBER_NOT_ACTIVE); } finally { if (queryImage != null) { try { queryImage.close(); } catch (IOException e) { log.warn("unable to close the image source input stream"); } } } } /** * This method retrieves the list or similar images for the image embedded in the HTTP request. * If start and rows parameters are used, the subset of items with the size of <code>rows<code> items starting with the <code>start<code> position will be retrieved. * @param queryImageUrl * @param start - start position in the result set * @param rows - size of the retrieved items set * @param wskey * @param profile * @param response * @return the result set containing the items, or the appropriate error message in case of failure. See also {@link ApiResponse} */ @RequestMapping(value = "/searchByUrl.json", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody ApiResponse searchByUrl( @RequestParam(value = "queryImageUrl", required = true) String queryImageUrl, @RequestParam(value = "start", required = false, defaultValue="0") int start, @RequestParam(value = "rows", required = false, defaultValue="12") int rows, @RequestParam(value = "qt", required = false) String queryType, @RequestParam(value = "wskey", required = false) String wskey, @RequestParam(value = "profile", required = false, defaultValue="similarimage") String profile, HttpServletResponse response) { //String encodedUrl = null; try { //encodedUrl = Tools.encodeUrl(queryImageUrl); //URLEncoder. imageSearching.searchSimilar(new URL(queryImageUrl), queryType); return prepareSearchResults(start, rows, wskey, "/image/searchByUrl.json"); } catch (ImageSearchingException e) { log.error("error searching by URL " + queryImageUrl, e); // throw new WebApplicationException(e1); return new ApiError(wskey, "/searchByUrl.json", e.getMessage(), REQUEST_NUMBER_NOT_ACTIVE); } catch (MalformedURLException e) { log.error("error searching by URL " + queryImageUrl, e); // throw new WebApplicationException(e); return new ApiError(wskey, "/searchByUrl.json", e.getMessage(), REQUEST_NUMBER_NOT_ACTIVE); } } }