Added Android code
[wl-app.git] / Android / r2-streamer / r2-server / src / main / java / org / readium / r2_streamer / server / handler / SearchQueryHandler.java
1 package org.readium.r2_streamer.server.handler;
2
3 //import android.support.annotation.Nullable;
4 //import android.util.Log;
5
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;
14
15 import org.jsoup.Jsoup;
16 import org.jsoup.nodes.Document;
17 import org.jsoup.nodes.Element;
18
19 import java.util.Map;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
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;
31
32 /**
33  * Created by Shrikant Badwaik on 17-Feb-17.
34  */
35
36 public class SearchQueryHandler extends DefaultHandler {
37     private static final String TAG = "SearchQueryHandler";
38     private Response response;
39
40     public SearchQueryHandler() {
41     }
42
43     @Override
44     public String getText() {
45         return ResponseStatus.FAILURE_RESPONSE;
46     }
47
48     @Override
49     public String getMimeType() {
50         return "application/json";
51     }
52
53     @Override
54     public IStatus getStatus() {
55         return Status.NOT_ACCEPTABLE;
56     }
57
58     @Override
59     public Response get(UriResource uriResource, Map<String, String> urlParams, IHTTPSession session) {
60         Method method = session.getMethod();
61         String uri = session.getUri();
62
63         //Log.d(TAG, "Method: " + method + ", Url: " + uri);
64
65         try {
66             EpubFetcher fetcher = uriResource.initParameter(EpubFetcher.class);
67
68             String queryParameter = session.getQueryParameterString();
69             int startIndex = queryParameter.indexOf("=");
70             String searchQueryPath = queryParameter.substring(startIndex + 1);
71
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", " ");
77                 }
78                 Pattern pattern = Pattern.compile(searchQueryPath, Pattern.CASE_INSENSITIVE);
79                 Matcher matcher = pattern.matcher(htmlText);
80                 while (matcher.find()) {
81                     int start = matcher.start();
82
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);
88
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);
96
97                     String title = parseChapterTitle(htmlText);
98                     if (title != null) {
99                         searchResult.setTitle(title);
100                     } else {
101                         searchResult.setTitle("Title not available");
102                     }
103                     searchQueryResults.searchResultList.add(searchResult);
104                 }
105             }
106             ObjectMapper objectMapper = new ObjectMapper();
107             String json = objectMapper.writeValueAsString(searchQueryResults);
108             response = NanoHTTPD.newFixedLengthResponse(Status.OK, getMimeType(), json);
109             return response;
110         } catch (EpubFetcherException | JsonProcessingException e) {
111             e.printStackTrace();
112             return NanoHTTPD.newFixedLengthResponse(Status.INTERNAL_ERROR, getMimeType(), ResponseStatus.FAILURE_RESPONSE);
113         }
114     }
115
116     //@Nullable
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();
122         } else {
123             Element h2Element = document.select("h2").first();
124             if (h2Element != null) {
125                 return h2Element.text();
126             } else {
127                 Element titleElement = document.select("title").first();
128                 if (titleElement != null) {
129                     return titleElement.text();
130                 }
131             }
132         }
133         return null;
134     }
135
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);
140         } else {
141             return htmlString.substring(0, start);
142         }
143     }
144
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);
149         } else {
150             return htmlString.substring(beginIndex, beginIndex + 20);
151         }
152     }
153 }