1 package org.readium.r2_streamer.server.handler;
3 //import android.support.annotation.Nullable;
4 //import android.util.Log;
6 import org.readium.r2_streamer.fetcher.EpubFetcher;
7 import org.readium.r2_streamer.fetcher.EpubFetcherException;
8 import org.readium.r2_streamer.model.publication.link.Link;
9 import org.readium.r2_streamer.model.searcher.SearchQueryResults;
10 import org.readium.r2_streamer.model.searcher.SearchResult;
11 import org.readium.r2_streamer.server.ResponseStatus;
12 import com.fasterxml.jackson.core.JsonProcessingException;
13 import com.fasterxml.jackson.databind.ObjectMapper;
15 import org.jsoup.Jsoup;
16 import org.jsoup.nodes.Document;
17 import org.jsoup.nodes.Element;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
23 import fi.iki.elonen.NanoHTTPD;
24 import fi.iki.elonen.NanoHTTPD.IHTTPSession;
25 import fi.iki.elonen.NanoHTTPD.Method;
26 import fi.iki.elonen.NanoHTTPD.Response;
27 import fi.iki.elonen.NanoHTTPD.Response.IStatus;
28 import fi.iki.elonen.NanoHTTPD.Response.Status;
29 import fi.iki.elonen.router.RouterNanoHTTPD.DefaultHandler;
30 import fi.iki.elonen.router.RouterNanoHTTPD.UriResource;
33 * Created by Shrikant Badwaik on 17-Feb-17.
36 public class SearchQueryHandler extends DefaultHandler {
37 private static final String TAG = "SearchQueryHandler";
38 private Response response;
40 public SearchQueryHandler() {
44 public String getText() {
45 return ResponseStatus.FAILURE_RESPONSE;
49 public String getMimeType() {
50 return "application/json";
54 public IStatus getStatus() {
55 return Status.NOT_ACCEPTABLE;
59 public Response get(UriResource uriResource, Map<String, String> urlParams, IHTTPSession session) {
60 Method method = session.getMethod();
61 String uri = session.getUri();
63 //Log.d(TAG, "Method: " + method + ", Url: " + uri);
66 EpubFetcher fetcher = uriResource.initParameter(EpubFetcher.class);
68 String queryParameter = session.getQueryParameterString();
69 int startIndex = queryParameter.indexOf("=");
70 String searchQueryPath = queryParameter.substring(startIndex + 1);
72 SearchQueryResults searchQueryResults = new SearchQueryResults();
73 for (Link link : fetcher.publication.spines) {
74 String htmlText = fetcher.getData(link.getHref());
75 if (searchQueryPath.contains("%20")) {
76 searchQueryPath = searchQueryPath.replaceAll("%20", " ");
78 Pattern pattern = Pattern.compile(searchQueryPath, Pattern.CASE_INSENSITIVE);
79 Matcher matcher = pattern.matcher(htmlText);
80 while (matcher.find()) {
81 int start = matcher.start();
83 String prev = getTextBefore(start, htmlText);
84 //String prev = htmlText.substring(start - 20, start);
85 String next = getTextAfter(start, searchQueryPath, htmlText);
86 //String next = htmlText.substring(start + searchQueryPath.length(), (start + searchQueryPath.length()) + 20);
87 String match = prev.concat(searchQueryPath).concat(next);
89 SearchResult searchResult = new SearchResult();
90 searchResult.setSearchIndex(start);
91 searchResult.setResource(link.getHref());
92 searchResult.setSearchQuery(searchQueryPath);
93 searchResult.setMatchString(match);
94 searchResult.setTextBefore(prev);
95 searchResult.setTextAfter(next);
97 String title = parseChapterTitle(htmlText);
99 searchResult.setTitle(title);
101 searchResult.setTitle("Title not available");
103 searchQueryResults.searchResultList.add(searchResult);
106 ObjectMapper objectMapper = new ObjectMapper();
107 String json = objectMapper.writeValueAsString(searchQueryResults);
108 response = NanoHTTPD.newFixedLengthResponse(Status.OK, getMimeType(), json);
110 } catch (EpubFetcherException | JsonProcessingException e) {
112 return NanoHTTPD.newFixedLengthResponse(Status.INTERNAL_ERROR, getMimeType(), ResponseStatus.FAILURE_RESPONSE);
117 private String parseChapterTitle(String searchData) {
118 Document document = Jsoup.parse(searchData);
119 Element h1Element = document.select("h1").first();
120 if (h1Element != null) {
121 return h1Element.text();
123 Element h2Element = document.select("h2").first();
124 if (h2Element != null) {
125 return h2Element.text();
127 Element titleElement = document.select("title").first();
128 if (titleElement != null) {
129 return titleElement.text();
136 private String getTextBefore(int start, String htmlString) {
137 int beginIndex = start - 20;
138 if (beginIndex >= 0 && beginIndex < htmlString.length()) {
139 return htmlString.substring(beginIndex, start);
141 return htmlString.substring(0, start);
145 private String getTextAfter(int start, String searchQueryPath, String htmlString) {
146 int beginIndex = start + searchQueryPath.length();
147 if ((beginIndex + 20) > htmlString.length()) {
148 return htmlString.substring(beginIndex);
150 return htmlString.substring(beginIndex, beginIndex + 20);