blob: c6bb0a405ef0dd17831c27aaf9b40e1cea811be4 [file] [log] [blame]
Nils Diewaldf5ab4b22015-02-25 20:55:16 +00001package de.ids_mannheim.korap;
2
3import java.io.*;
4import java.util.*;
5
6import com.fasterxml.jackson.databind.JsonNode;
7import com.fasterxml.jackson.databind.ObjectMapper;
8import com.fasterxml.jackson.databind.node.*;
9
Nils Diewald65449ff2015-02-27 17:57:29 +000010import de.ids_mannheim.korap.response.SearchContext;
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000011import de.ids_mannheim.korap.util.QueryException;
12import de.ids_mannheim.korap.response.Notifications;
13
14import org.slf4j.Logger;
15import org.slf4j.LoggerFactory;
16
17// Todo: Set timeout default value per config file
Akron98b78542015-08-06 21:43:08 +020018public final class KrillMeta extends Notifications {
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000019 // <legacy>
20 private boolean cutOff = false;
21 // </legacy>
22
23 private int limit = 0;
24 private short count = 25, countMax = 50;
25 private int startIndex = 0;
26 private short itemsPerResource = 0;
27 private SearchContext context;
28
29 private HashSet<String> fields;
Nils Diewaldbb33da22015-03-04 16:24:25 +000030 HashSet<Integer> highlights;
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000031
32 // Timeout search after milliseconds
33 private long timeout = (long) 120_000;
34 // private long timeoutStart = Long.MIN_VALUE;
35
36 // Logger
37 private final static Logger log = LoggerFactory.getLogger(Krill.class);
38
39 {
40 fields = new HashSet<String>(16);
41
Akron12f1f5b2015-06-24 15:56:52 +020042 // TODO: Support @all
43
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000044 // Lift following fields per default
45 // These fields are chosen for <legacy /> reasons
Akron640458c2015-06-25 12:36:15 +020046 for (String field : new String[] { "ID", "UID", "textSigle",
47 "corpusID", "author", "title", "subTitle", "textClass",
48 "pubPlace", "pubDate",
Akron3e0403f2015-06-24 20:59:13 +020049 // "foundries",
50 // "tokenization",
Akron12f1f5b2015-06-24 15:56:52 +020051 // New:
Akron640458c2015-06-25 12:36:15 +020052 "layerInfos", "docSigle", "corpusSigle", }) {
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000053 fields.add(field);
54 };
55
56 // Classes used for highlights
57 highlights = new HashSet<Integer>(3);
Nils Diewaldbb33da22015-03-04 16:24:25 +000058 context = new SearchContext();
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000059 };
60
61
62 public KrillMeta () {};
63
Nils Diewaldbb33da22015-03-04 16:24:25 +000064
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000065 public KrillMeta (JsonNode json) {
66 this.fromJson(json);
67 };
68
Nils Diewaldbb33da22015-03-04 16:24:25 +000069
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000070 public KrillMeta (String json) {
71 try {
72 this.fromJson(json);
73 }
74 catch (QueryException q) {
75 this.addError(q.getErrorCode(), q.getMessage());
76 };
77 };
78
Nils Diewaldbb33da22015-03-04 16:24:25 +000079
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000080 public KrillMeta fromJson (String json) throws QueryException {
81 JsonNode jsonN;
82 try {
83 // Read Json string
84 jsonN = new ObjectMapper().readValue(json, JsonNode.class);
85 }
86
87 // Something went wrong
88 catch (IOException e) {
89 String msg = e.getMessage();
90 log.warn("Unable to parse JSON: " + msg.split("\n")[0]);
91 throw new QueryException(621, "Unable to parse JSON");
92 };
93
94 // Deserialize from node
95 return this.fromJson(jsonN);
96 };
97
98
99 public KrillMeta fromJson (JsonNode json) {
100 // The object type of meta is undefined in KoralQuery,
101 // so it may or may have no @type
102
103 // The query is nested in a parent query
104 if (!json.has("@type") && json.has("meta"))
105 json = json.get("meta");
106
107 // Defined cutOff
108 // <legacy>
109 if (json.has("cutOff"))
110 this.setCutOff(json.get("cutOff").asBoolean());
111 // </legacy>
112
113 // Defined count
114 if (json.has("count"))
115 this.setCount(json.get("count").asInt());
116
117 // Defined startIndex
118 if (json.has("startIndex"))
119 this.setStartIndex(json.get("startIndex").asInt());
120
121 // Defined startPage
122 if (json.has("startPage"))
123 this.setStartPage(json.get("startPage").asInt());
124
125 // Defined timeout
126 if (json.has("timeout"))
127 this.setTimeOut(json.get("timeout").asLong());
128
129 // Defined resource count
130 if (json.has("itemsPerResource"))
131 this.setItemsPerResource(json.get("itemsPerResource").asInt());
132
133 // Defined context
134 if (json.has("context"))
135 this.context.fromJson(json.get("context"));
136
137 // Defined highlights
138 if (json.has("highlight")) {
139
140 // Add highlights
141 if (json.get("highlight").isArray()) {
142 for (JsonNode highlight : (JsonNode) json.get("highlight")) {
143 this.addHighlight(highlight.asInt());
144 };
145 }
146 else
147 this.addHighlight(json.get("highlight").asInt());
148 };
Nils Diewaldbb33da22015-03-04 16:24:25 +0000149
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000150 // Defined fields to lift from the index
151 if (json.has("fields")) {
Nils Diewaldbb33da22015-03-04 16:24:25 +0000152
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000153 // Remove default fields
154 this.fields.clear();
Nils Diewaldbb33da22015-03-04 16:24:25 +0000155
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000156 // Add fields
157 if (json.get("fields").isArray()) {
158 for (JsonNode field : (JsonNode) json.get("fields")) {
159 this.addField(field.asText());
160 };
161 }
162 else
163 this.addField(json.get("fields").asText());
164 };
165
166 return this;
167 };
168
169
170 public short getCount () {
171 return this.count;
172 };
173
Nils Diewaldbb33da22015-03-04 16:24:25 +0000174
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000175 public KrillMeta setCount (int value) {
176 // Todo: Maybe update startIndex with known startPage!
177 this.setCount((short) value);
178 return this;
179 };
180
Nils Diewaldbb33da22015-03-04 16:24:25 +0000181
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000182 public KrillMeta setCount (short value) {
183 if (value > 0)
184 this.count = (value <= this.countMax) ? value : this.countMax;
185 return this;
186 };
187
Nils Diewaldbb33da22015-03-04 16:24:25 +0000188
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000189 public short getCountMax () {
190 return this.countMax;
191 };
192
193
194 public int getStartIndex () {
195 return this.startIndex;
196 };
Nils Diewaldbb33da22015-03-04 16:24:25 +0000197
198
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000199 public KrillMeta setStartIndex (int value) {
200 this.startIndex = (value >= 0) ? value : 0;
201 return this;
202 };
203
Nils Diewaldbb33da22015-03-04 16:24:25 +0000204
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000205 public KrillMeta setStartPage (int value) {
206 if (value >= 0)
207 this.setStartIndex((value * this.getCount()) - this.getCount());
208 else
209 this.startIndex = 0;
210 return this;
211 };
212
213
214 public long getTimeOut () {
215 return this.timeout;
216 };
217
Nils Diewaldbb33da22015-03-04 16:24:25 +0000218
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000219 public void setTimeOut (long timeout) {
220 this.timeout = timeout;
221 };
222
Nils Diewaldbb33da22015-03-04 16:24:25 +0000223
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000224 public KrillMeta setItemsPerResource (short value) {
225 if (value >= 0)
226 this.itemsPerResource = value;
227 return this;
228 };
229
Nils Diewaldbb33da22015-03-04 16:24:25 +0000230
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000231 public KrillMeta setItemsPerResource (int value) {
232 return this.setItemsPerResource((short) value);
233 };
234
Nils Diewaldbb33da22015-03-04 16:24:25 +0000235
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000236 public short getItemsPerResource () {
237 return this.itemsPerResource;
238 };
239
240
241 public SearchContext getContext () {
242 return this.context;
243 };
244
Nils Diewaldbb33da22015-03-04 16:24:25 +0000245
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000246 public KrillMeta setContext (SearchContext context) {
247 this.context = context;
248 return this;
249 };
250
251
252 // Get set of fields
253 /**
254 * Get the fields as a set
255 */
256 public HashSet<String> getFields () {
257 return this.fields;
258 };
259
260
261 /**
262 * Add a field to the set of fields to retrieve.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000263 *
264 * @param field
265 * The field to retrieve.
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000266 * @return The {@link Krill} object for chaining.
267 */
268 public KrillMeta addField (String field) {
269 this.fields.add(field);
270 return this;
271 };
272
273
274 /**
275 * Add class numbers to highlight in KWIC view.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000276 *
277 * @param classNumber
278 * The number of a class to highlight.
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000279 * @return The {@link Krill} object for chaining.
280 */
281 public KrillMeta addHighlight (int classNumber) {
282 this.highlights.add(classNumber);
283 return this;
284 };
285
286
287 @Deprecated
288 public boolean doCutOff () {
289 return this.cutOff;
290 };
291
Nils Diewaldbb33da22015-03-04 16:24:25 +0000292
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000293 @Deprecated
294 public KrillMeta setCutOff (boolean cutOff) {
295 this.cutOff = cutOff;
296 return this;
297 };
298
299
300 // TODO:
301 // This limits the search results with offset
302 // Maybe can be deprecated!
303 @Deprecated
304 public int getLimit () {
305 return this.limit;
306 };
307
Nils Diewaldbb33da22015-03-04 16:24:25 +0000308
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000309 // TODO:
310 // This limits the search results with offset
311 // Maybe can be deprecated!
312 @Deprecated
313 public KrillMeta setLimit (int limit) {
314 if (limit > 0)
315 this.limit = limit;
316 return this;
317 };
318
319
320 @Override
321 public JsonNode toJsonNode () {
322 ObjectMapper mapper = new ObjectMapper();
Nils Diewaldbb33da22015-03-04 16:24:25 +0000323 ObjectNode json = mapper.createObjectNode();
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000324 // json.put("@type", "koral:meta");
325
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000326 // <legacy>
327 // Add cutOff attribute
328 if (this.cutOff)
329 json.put("cutOff", this.doCutOff());
330
331 // Add limit attribute
332 if (this.limit > 0)
Nils Diewaldbb33da22015-03-04 16:24:25 +0000333 json.put("limit", this.getLimit());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000334 // </legacy>
335
336 // Add count attribute
Nils Diewaldbb33da22015-03-04 16:24:25 +0000337 json.put("count", this.getCount());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000338
339 // Add startindex attribute
340 json.put("startIndex", this.getStartIndex());
341
342 // Add timeout attribute
Nils Diewaldbb33da22015-03-04 16:24:25 +0000343 json.put("timeout", this.getTimeOut());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000344
345 // Add context attribute
Nils Diewaldbb33da22015-03-04 16:24:25 +0000346 json.put("context", this.getContext().toJsonNode());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000347
348 // Add fields attribute
Akronb1166442015-06-27 00:34:19 +0200349 ArrayNode fieldNode = mapper.createArrayNode();
350 Iterator<String> field = this.fields.iterator();
351 while (field.hasNext())
352 fieldNode.add(field.next());
Nils Diewaldbb33da22015-03-04 16:24:25 +0000353 json.put("fields", fieldNode);
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000354
355 // Add itemsPerResource attribute
356 if (this.itemsPerResource > 0)
357 json.put("itemsPerResource", (int) this.getItemsPerResource());
358
359 // Add highlight attribute
360 if (!this.highlights.isEmpty()) {
361 ArrayNode highlightNode = mapper.createArrayNode();
362 highlightNode.addPOJO(this.highlights);
363 json.put("highlight", highlightNode);
364 };
365
366 return json;
367 };
368};