blob: 330cbdb5719e7c53eba1f886b375099a79226b8c [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
Akron394607a2017-05-29 13:27:37 +020046 for (String field : new String[] {
47 "ID",
48 "UID",
49 "textSigle",
50 "corpusID",
51 "author",
52 "title",
53 "subTitle",
54 "textClass",
55 "pubPlace",
56 "pubDate",
57 // "foundries",
Akron3e0403f2015-06-24 20:59:13 +020058 // "tokenization",
Akron12f1f5b2015-06-24 15:56:52 +020059 // New:
Akron394607a2017-05-29 13:27:37 +020060 "availability",
61 "layerInfos",
62 "docSigle",
63 "corpusSigle"
64 }) {
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000065 fields.add(field);
66 };
67
68 // Classes used for highlights
69 highlights = new HashSet<Integer>(3);
Nils Diewaldbb33da22015-03-04 16:24:25 +000070 context = new SearchContext();
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000071 };
72
73
74 public KrillMeta () {};
75
Nils Diewaldbb33da22015-03-04 16:24:25 +000076
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000077 public KrillMeta (JsonNode json) {
78 this.fromJson(json);
79 };
80
Nils Diewaldbb33da22015-03-04 16:24:25 +000081
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000082 public KrillMeta (String json) {
83 try {
84 this.fromJson(json);
85 }
86 catch (QueryException q) {
87 this.addError(q.getErrorCode(), q.getMessage());
88 };
89 };
90
Nils Diewaldbb33da22015-03-04 16:24:25 +000091
Nils Diewaldf5ab4b22015-02-25 20:55:16 +000092 public KrillMeta fromJson (String json) throws QueryException {
93 JsonNode jsonN;
94 try {
95 // Read Json string
96 jsonN = new ObjectMapper().readValue(json, JsonNode.class);
97 }
98
99 // Something went wrong
100 catch (IOException e) {
101 String msg = e.getMessage();
102 log.warn("Unable to parse JSON: " + msg.split("\n")[0]);
103 throw new QueryException(621, "Unable to parse JSON");
104 };
105
106 // Deserialize from node
107 return this.fromJson(jsonN);
108 };
109
110
111 public KrillMeta fromJson (JsonNode json) {
112 // The object type of meta is undefined in KoralQuery,
113 // so it may or may have no @type
114
115 // The query is nested in a parent query
116 if (!json.has("@type") && json.has("meta"))
117 json = json.get("meta");
118
119 // Defined cutOff
120 // <legacy>
121 if (json.has("cutOff"))
122 this.setCutOff(json.get("cutOff").asBoolean());
123 // </legacy>
124
125 // Defined count
126 if (json.has("count"))
127 this.setCount(json.get("count").asInt());
128
129 // Defined startIndex
130 if (json.has("startIndex"))
131 this.setStartIndex(json.get("startIndex").asInt());
132
133 // Defined startPage
134 if (json.has("startPage"))
135 this.setStartPage(json.get("startPage").asInt());
136
137 // Defined timeout
138 if (json.has("timeout"))
139 this.setTimeOut(json.get("timeout").asLong());
140
141 // Defined resource count
142 if (json.has("itemsPerResource"))
143 this.setItemsPerResource(json.get("itemsPerResource").asInt());
144
145 // Defined context
146 if (json.has("context"))
147 this.context.fromJson(json.get("context"));
148
149 // Defined highlights
150 if (json.has("highlight")) {
151
152 // Add highlights
153 if (json.get("highlight").isArray()) {
154 for (JsonNode highlight : (JsonNode) json.get("highlight")) {
155 this.addHighlight(highlight.asInt());
156 };
157 }
158 else
159 this.addHighlight(json.get("highlight").asInt());
160 };
Nils Diewaldbb33da22015-03-04 16:24:25 +0000161
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000162 // Defined fields to lift from the index
163 if (json.has("fields")) {
Nils Diewaldbb33da22015-03-04 16:24:25 +0000164
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000165 // Remove default fields
166 this.fields.clear();
Nils Diewaldbb33da22015-03-04 16:24:25 +0000167
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000168 // Add fields
169 if (json.get("fields").isArray()) {
170 for (JsonNode field : (JsonNode) json.get("fields")) {
171 this.addField(field.asText());
172 };
173 }
174 else
175 this.addField(json.get("fields").asText());
176 };
177
178 return this;
179 };
180
181
182 public short getCount () {
183 return this.count;
184 };
185
Nils Diewaldbb33da22015-03-04 16:24:25 +0000186
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000187 public KrillMeta setCount (int value) {
188 // Todo: Maybe update startIndex with known startPage!
189 this.setCount((short) value);
190 return this;
191 };
192
Nils Diewaldbb33da22015-03-04 16:24:25 +0000193
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000194 public KrillMeta setCount (short value) {
195 if (value > 0)
196 this.count = (value <= this.countMax) ? value : this.countMax;
197 return this;
198 };
199
Nils Diewaldbb33da22015-03-04 16:24:25 +0000200
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000201 public short getCountMax () {
202 return this.countMax;
203 };
204
205
206 public int getStartIndex () {
207 return this.startIndex;
208 };
Nils Diewaldbb33da22015-03-04 16:24:25 +0000209
210
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000211 public KrillMeta setStartIndex (int value) {
212 this.startIndex = (value >= 0) ? value : 0;
213 return this;
214 };
215
Nils Diewaldbb33da22015-03-04 16:24:25 +0000216
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000217 public KrillMeta setStartPage (int value) {
218 if (value >= 0)
219 this.setStartIndex((value * this.getCount()) - this.getCount());
220 else
221 this.startIndex = 0;
222 return this;
223 };
224
225
226 public long getTimeOut () {
227 return this.timeout;
228 };
229
Nils Diewaldbb33da22015-03-04 16:24:25 +0000230
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000231 public void setTimeOut (long timeout) {
232 this.timeout = timeout;
233 };
234
Nils Diewaldbb33da22015-03-04 16:24:25 +0000235
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000236 public KrillMeta setItemsPerResource (short value) {
237 if (value >= 0)
238 this.itemsPerResource = value;
239 return this;
240 };
241
Nils Diewaldbb33da22015-03-04 16:24:25 +0000242
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000243 public KrillMeta setItemsPerResource (int value) {
244 return this.setItemsPerResource((short) value);
245 };
246
Nils Diewaldbb33da22015-03-04 16:24:25 +0000247
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000248 public short getItemsPerResource () {
249 return this.itemsPerResource;
250 };
251
252
253 public SearchContext getContext () {
254 return this.context;
255 };
256
Nils Diewaldbb33da22015-03-04 16:24:25 +0000257
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000258 public KrillMeta setContext (SearchContext context) {
259 this.context = context;
260 return this;
261 };
262
263
264 // Get set of fields
265 /**
266 * Get the fields as a set
267 */
268 public HashSet<String> getFields () {
269 return this.fields;
270 };
271
272
273 /**
274 * Add a field to the set of fields to retrieve.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000275 *
276 * @param field
277 * The field to retrieve.
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000278 * @return The {@link Krill} object for chaining.
279 */
280 public KrillMeta addField (String field) {
281 this.fields.add(field);
282 return this;
283 };
284
285
286 /**
287 * Add class numbers to highlight in KWIC view.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000288 *
289 * @param classNumber
290 * The number of a class to highlight.
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000291 * @return The {@link Krill} object for chaining.
292 */
293 public KrillMeta addHighlight (int classNumber) {
294 this.highlights.add(classNumber);
295 return this;
296 };
297
298
299 @Deprecated
300 public boolean doCutOff () {
301 return this.cutOff;
302 };
303
Nils Diewaldbb33da22015-03-04 16:24:25 +0000304
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000305 @Deprecated
306 public KrillMeta setCutOff (boolean cutOff) {
307 this.cutOff = cutOff;
308 return this;
309 };
310
311
312 // TODO:
313 // This limits the search results with offset
314 // Maybe can be deprecated!
315 @Deprecated
316 public int getLimit () {
317 return this.limit;
318 };
319
Nils Diewaldbb33da22015-03-04 16:24:25 +0000320
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000321 // TODO:
322 // This limits the search results with offset
323 // Maybe can be deprecated!
324 @Deprecated
325 public KrillMeta setLimit (int limit) {
326 if (limit > 0)
327 this.limit = limit;
328 return this;
329 };
330
331
332 @Override
333 public JsonNode toJsonNode () {
334 ObjectMapper mapper = new ObjectMapper();
Nils Diewaldbb33da22015-03-04 16:24:25 +0000335 ObjectNode json = mapper.createObjectNode();
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000336 // json.put("@type", "koral:meta");
337
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000338 // <legacy>
339 // Add cutOff attribute
340 if (this.cutOff)
341 json.put("cutOff", this.doCutOff());
342
343 // Add limit attribute
344 if (this.limit > 0)
Nils Diewaldbb33da22015-03-04 16:24:25 +0000345 json.put("limit", this.getLimit());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000346 // </legacy>
347
348 // Add count attribute
Nils Diewaldbb33da22015-03-04 16:24:25 +0000349 json.put("count", this.getCount());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000350
351 // Add startindex attribute
352 json.put("startIndex", this.getStartIndex());
353
354 // Add timeout attribute
Nils Diewaldbb33da22015-03-04 16:24:25 +0000355 json.put("timeout", this.getTimeOut());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000356
357 // Add context attribute
Nils Diewaldbb33da22015-03-04 16:24:25 +0000358 json.put("context", this.getContext().toJsonNode());
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000359
360 // Add fields attribute
Akronb1166442015-06-27 00:34:19 +0200361 ArrayNode fieldNode = mapper.createArrayNode();
362 Iterator<String> field = this.fields.iterator();
363 while (field.hasNext())
364 fieldNode.add(field.next());
Nils Diewaldbb33da22015-03-04 16:24:25 +0000365 json.put("fields", fieldNode);
Nils Diewaldf5ab4b22015-02-25 20:55:16 +0000366
367 // Add itemsPerResource attribute
368 if (this.itemsPerResource > 0)
369 json.put("itemsPerResource", (int) this.getItemsPerResource());
370
371 // Add highlight attribute
372 if (!this.highlights.isEmpty()) {
373 ArrayNode highlightNode = mapper.createArrayNode();
374 highlightNode.addPOJO(this.highlights);
375 json.put("highlight", highlightNode);
376 };
377
378 return json;
379 };
380};