package com.epam.wilma.message.search.web.controller;
/*==========================================================================
Copyright 2013-2017 EPAM Systems
This file is part of Wilma.
Wilma is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Wilma 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wilma. If not, see <http://www.gnu.org/licenses/>.
===========================================================================*/
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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 com.epam.wilma.message.search.domain.IndexStatus;
import com.epam.wilma.message.search.domain.exception.QueryCannotBeParsedException;
import com.epam.wilma.message.search.lucene.LuceneEngine;
import com.epam.wilma.message.search.web.support.FileChecker;
import com.epam.wilma.message.search.web.support.FileZipper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
/**
* Controller for message searching.
* @author Tamas_Bihari
*
*/
@Controller
public class SearchController {
private static final String QUERY_ERROR_MESSAGE = "This query is not valid.";
private static final String ZIP_CONTENT_TYPE = "application/zip";
private static final String FILES = "files";
private final Logger logger = LoggerFactory.getLogger(SearchController.class);
@Autowired
private LuceneEngine luceneEngine;
@Autowired
private FileZipper fileZipper;
@Autowired
private FileChecker fileChecker;
@Autowired
private IndexStatus indexStatus;
/**
* Searches for an expression using {@link LuceneEngine} and sends back matched files in a compressed ZIP file.
* @param searchedText the expression that will be searched
* @param resp is the HTTP response for the request
*/
@RequestMapping(value = "/search", method = RequestMethod.GET)
public void searchAndZip(@RequestParam("text") final String searchedText, final HttpServletResponse resp) {
if (searchedText != null && !"".equals(searchedText)) {
List<List<String>> searchResult;
try {
searchResult = searchForText(searchedText);
} catch (QueryCannotBeParsedException e) {
logger.warn("Invalid query");
searchResult = new ArrayList<List<String>>();
}
zipSearchResult(searchedText, resp, searchResult);
}
}
/**
* Searches for an expression using {@link LuceneEngine} and sends back matched files' name.
* @param searchedText the expression that will be searched
* @param session is the actual HTTP session
* @return list of hits as a JSON response
*/
@ResponseBody
@RequestMapping(value = "/search", method = RequestMethod.POST)
public ResponseEntity<String> searchForFiles(@RequestParam("searchedText") final String searchedText, final HttpSession session) {
List<List<String>> searchResult = new ArrayList<List<String>>();
ResponseEntity<String> result;
HttpHeaders responseHeaders = setHeadersForJSON();
try {
searchResult = searchForText(searchedText);
addResultToSession(searchResult, session);
if (!indexStatus.isReady()) {
result = new ResponseEntity<String>(getJson(searchResult), responseHeaders, HttpStatus.PARTIAL_CONTENT);
} else {
result = new ResponseEntity<String>(getJson(searchResult), responseHeaders, HttpStatus.CREATED);
}
} catch (QueryCannotBeParsedException e) {
logger.warn("Invalid query");
result = new ResponseEntity<String>(QUERY_ERROR_MESSAGE, HttpStatus.BAD_REQUEST);
}
return result;
}
private List<List<String>> searchForText(final String searchedText) {
List<String> searchResult = new ArrayList<>();
logger.info("Searching with GET for text:" + searchedText);
searchResult = luceneEngine.search(searchedText);
return fileChecker.checkFilesExistsWithPairs(searchResult);
}
private void zipSearchResult(final String searchedText, final HttpServletResponse resp, final List<List<String>> searchResult) {
try {
ServletOutputStream output = resp.getOutputStream();
resp.setContentType(ZIP_CONTENT_TYPE);
fileZipper.createZipWithFiles(searchResult, output);
} catch (IOException e) {
logger.info("Searching for '" + searchedText + "' failed, response's output stream can not get!", e);
}
}
private HttpHeaders setHeadersForJSON() {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
return responseHeaders;
}
private void addResultToSession(final List<List<String>> searchResult, final HttpSession session) {
session.setAttribute("searchResult", searchResult);
}
private String getJson(final Object object) {
Gson gson = new Gson();
JsonObject jsonObject = new JsonObject();
jsonObject.add(FILES, gson.toJsonTree(object));
String json = gson.toJson(jsonObject);
return json;
}
}