blob: 09d20ea5f1f36c406f8d4eb4963745c475a357bb [file] [log] [blame]
Nils Diewald3a2d8022014-12-16 02:45:41 +00001var KorAP = KorAP || {};
Nils Diewald3a2d8022014-12-16 02:45:41 +00002
Nils Diewald8f4e2542014-12-19 04:42:09 +00003// TODO: Implement a working localization solution!
4// TODO: Support 'update' method to update elements on change
Nils Diewald966abf12014-12-20 02:27:45 +00005// TODO: Implement "toQuery"
Nils Diewaldd0770492014-12-19 03:55:00 +00006
7/*
Nils Diewaldd599d542015-01-08 20:41:34 +00008 Error codes:
Nils Diewaldd0770492014-12-19 03:55:00 +00009 701: "JSON-LD group has no @type attribute"
10 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000011 802: "Match type is not supported by value type"
12 804: "Unknown value type"
13 805: "Value is invalid"
14 806: "Value is not a valid date string"
15 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000016 810: "Unknown document group operation" (like 711)
17 811: "Document group expects operation" (like 703)
18 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000019 813: "Collection type is not supported" (like 713)
20*/
21
Nils Diewald3a2d8022014-12-16 02:45:41 +000022(function (KorAP) {
23 "use strict";
24
25 // Default log message
26 KorAP.log = KorAP.log || function (type, msg) {
27 console.log(type + ": " + msg);
28 };
29
30 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains)$");
31 KorAP._validRegexMatchRE = new RegExp("^(?:eq|ne)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000032 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000033 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
34 KorAP._validGroupOpRE = new RegExp("^(?:and|or)$");
Nils Diewaldf219eb82015-01-07 20:15:42 +000035 KorAP._quote = new RegExp("([\"\\\\])", 'g');
Nils Diewald3a2d8022014-12-16 02:45:41 +000036
Nils Diewalde15b7a22015-01-09 21:50:21 +000037 // Localization values
Nils Diewaldf219eb82015-01-07 20:15:42 +000038 var loc = (KorAP.Locale = KorAP.Locale || {} );
39 loc.AND = loc.AND || 'and';
40 loc.OR = loc.OR || 'or';
41 loc.DEL = loc.DEL || '×';
42 loc.EMPTY = loc.EMPTY || '⋯'
Nils Diewaldd0770492014-12-19 03:55:00 +000043
Nils Diewaldd599d542015-01-08 20:41:34 +000044
Nils Diewalde15b7a22015-01-09 21:50:21 +000045 // Utility for analysing boolean values
Nils Diewald966abf12014-12-20 02:27:45 +000046 function _bool (bool) {
Nils Diewalde15b7a22015-01-09 21:50:21 +000047 return (bool === undefined || bool === null || bool === false) ? false : true;
Nils Diewald966abf12014-12-20 02:27:45 +000048 };
49
Nils Diewaldd599d542015-01-08 20:41:34 +000050
Nils Diewalde15b7a22015-01-09 21:50:21 +000051 // Utility for removing all children of a node
Nils Diewald966abf12014-12-20 02:27:45 +000052 function _removeChildren (node) {
53 // Remove everything underneath
Nils Diewald8f6b6102015-01-08 18:25:33 +000054 while (node.firstChild)
Nils Diewald966abf12014-12-20 02:27:45 +000055 node.removeChild(node.firstChild);
Nils Diewald966abf12014-12-20 02:27:45 +000056 };
57
Nils Diewald4019bd22015-01-08 19:57:50 +000058
Nils Diewald9fcc1712015-01-09 14:24:32 +000059 // Add doc
60 KorAP._add = function (obj, type) {
61 var ref = obj.parentNode.refTo;
62 if (ref.ldType() === 'docGroup') {
Nils Diewaldd599d542015-01-08 20:41:34 +000063 console.log('~~~~~~~~~');
64 }
Nils Diewald9fcc1712015-01-09 14:24:32 +000065 else if (ref.ldType() === 'doc') {
66 var parent = ref.parent();
67// Todo: Check if parent is a group
68 if (parent.operation() === type) {
69 parent.newAfter(ref);
70 }
71 else {
72 ref.wrap(type);
73 };
Nils Diewaldd599d542015-01-08 20:41:34 +000074 };
Nils Diewald4019bd22015-01-08 19:57:50 +000075 };
76
Nils Diewaldd599d542015-01-08 20:41:34 +000077
Nils Diewalde15b7a22015-01-09 21:50:21 +000078 // Add doc with 'and' relation
79 KorAP._and = function () {
80 return KorAP._add(this, 'and');
81 };
82
83
84 // Add doc with 'or' relation
85 KorAP._or = function () {
86 return KorAP._add(this, 'or');
87 };
88
Nils Diewald4019bd22015-01-08 19:57:50 +000089 // Remove doc or docGroup
Nils Diewalde15b7a22015-01-09 21:50:21 +000090 KorAP._delete = function () {
Nils Diewald9fcc1712015-01-09 14:24:32 +000091 var ref = this.parentNode.refTo;
92 if (ref.parent().ldType() !== null)
93 ref.parent().delOperand(ref).update();
Nils Diewald4019bd22015-01-08 19:57:50 +000094 else
Nils Diewald9fcc1712015-01-09 14:24:32 +000095 ref.parent().clean();
Nils Diewald4019bd22015-01-08 19:57:50 +000096 };
97
Nils Diewaldd599d542015-01-08 20:41:34 +000098
99 /**
100 * Virtual Collection
101 */
Nils Diewald3a2d8022014-12-16 02:45:41 +0000102 KorAP.VirtualCollection = {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000103 ldType : function () {
104 return null;
105 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000106
Nils Diewald3a2d8022014-12-16 02:45:41 +0000107 create : function () {
108 return Object.create(KorAP.VirtualCollection);
109 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000110
Nils Diewald4019bd22015-01-08 19:57:50 +0000111 clean : function () {
112 if (this._root.ldType() !== "non") {
113 this._root.destroy();
114 this.root(KorAP.UnspecifiedDoc.create(this));
115 };
116 return this;
117 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000118
Nils Diewaldd0770492014-12-19 03:55:00 +0000119 render : function (json) {
120 var obj = Object.create(KorAP.VirtualCollection);
121
122 if (json !== undefined) {
123 // Root object
124 if (json['@type'] == 'korap:doc') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000125 obj._root = KorAP.Doc.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000126 }
127 else if (json['@type'] == 'korap:docGroup') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000128 obj._root = KorAP.DocGroup.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000129 }
130 else {
131 KorAP.log(813, "Collection type is not supported");
132 return;
133 };
134 }
135
136 else {
137 // Add unspecified object
Nils Diewaldf219eb82015-01-07 20:15:42 +0000138 obj._root = KorAP.UnspecifiedDoc.create(obj);
Nils Diewaldd0770492014-12-19 03:55:00 +0000139 };
140
Nils Diewald8e7182e2015-01-08 15:02:07 +0000141 // Init element and update
142 obj.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000143
144 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000145 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000146
Nils Diewaldf219eb82015-01-07 20:15:42 +0000147 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000148 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000149 var e = this.element();
150 if (e.firstChild !== null) {
151 if (e.firstChild !== obj.element())
152 e.replaceChild(obj.element(), e.firstChild);
153 }
154
155 // Append root element
156 else {
157 e.appendChild(obj.element());
158 };
159
160 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000161 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000162 obj.parent(this);
163
Nils Diewald8e7182e2015-01-08 15:02:07 +0000164 this.update();
165 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000166 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000167 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000168
Nils Diewaldd0770492014-12-19 03:55:00 +0000169 element : function () {
170 if (this._element !== undefined)
171 return this._element;
172
173 this._element = document.createElement('div');
174 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000175
Nils Diewald8f6b6102015-01-08 18:25:33 +0000176 // Initialize root
177 this._element.appendChild(this._root.element());
178
Nils Diewaldd0770492014-12-19 03:55:00 +0000179 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000180 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000181
182 update : function () {
183 this._root.update();
184 return this;
185 },
186
Nils Diewaldf219eb82015-01-07 20:15:42 +0000187 toJson : function () {
188 return this._root.toJson();
189 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000190
191 toQuery : function () {
192 return this._root.toQuery();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000193 }
194 };
195
Nils Diewaldd599d542015-01-08 20:41:34 +0000196
Nils Diewald8f4e2542014-12-19 04:42:09 +0000197 /**
198 * Operators for criteria
199 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000200 KorAP.Operators = {
201 create : function (and, or, del) {
202 var op = Object.create(KorAP.Operators);
203 op.and(and);
204 op.or(or);
205 op.del(del);
206 return op;
207 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000208
Nils Diewaldd0770492014-12-19 03:55:00 +0000209 update : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000210 // Init the element
211 if (this._element === undefined)
212 return this.element();
213
214 var op = this._element;
215
Nils Diewald0297ba12015-01-05 21:56:12 +0000216 op.refTo = this.parent();
217
Nils Diewaldd0770492014-12-19 03:55:00 +0000218 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000219 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000220
221 // Add and button
222 if (this._and === true) {
223 var andE = document.createElement('span');
224 andE.setAttribute('class', 'and');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000225 andE.addEventListener('click', KorAP._and, false);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000226 andE.appendChild(
227 document.createTextNode(KorAP.Locale.AND)
228 );
Nils Diewaldd0770492014-12-19 03:55:00 +0000229 op.appendChild(andE);
230 };
231
232 // Add or button
233 if (this._or === true) {
234 var orE = document.createElement('span');
235 orE.setAttribute('class', 'or');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000236 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000237 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
238 op.appendChild(orE);
239 };
240
241 // Add delete button
242 if (this._del === true) {
243 var delE = document.createElement('span');
244 delE.setAttribute('class', 'delete');
245 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000246 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000247 op.appendChild(delE);
248 };
Nils Diewald966abf12014-12-20 02:27:45 +0000249
250 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000251 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000252
253 // Be aware! This may be cyclic
254 parent : function (obj) {
255 if (arguments.length === 1)
256 this._parent = obj;
257 return this._parent;
258 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000259
Nils Diewaldd0770492014-12-19 03:55:00 +0000260 element : function () {
261
262 // Return existing element
263 if (this._element !== undefined)
264 return this._element;
265
266 this._element = document.createElement('div');
267 this._element.setAttribute('class', 'operators');
268
269 // Init elements
270 this.update();
271 return this._element;
272 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000273
Nils Diewaldd0770492014-12-19 03:55:00 +0000274 and : function (bool) {
275 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000276 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000277 return this._and;
278 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000279
Nils Diewaldd0770492014-12-19 03:55:00 +0000280 or : function (bool) {
281 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000282 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000283 return this._or;
284 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000285
Nils Diewaldd0770492014-12-19 03:55:00 +0000286 del : function (bool) {
287 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000288 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000289 return this._del;
290 }
291 };
292
293
294 /**
295 * Unspecified criterion
296 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000297 KorAP.UnspecifiedDoc = {
Nils Diewald4019bd22015-01-08 19:57:50 +0000298 _ldType : "non",
Nils Diewaldd0770492014-12-19 03:55:00 +0000299 create : function (parent) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000300 var obj = Object.create(KorAP.JsonLD).
301 upgradeTo(KorAP.UnspecifiedDoc);
302
Nils Diewaldd0770492014-12-19 03:55:00 +0000303 if (parent !== undefined)
304 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000305
Nils Diewaldd0770492014-12-19 03:55:00 +0000306 return obj;
307 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000308
Nils Diewald966abf12014-12-20 02:27:45 +0000309 update : function () {
Nils Diewald4019bd22015-01-08 19:57:50 +0000310
Nils Diewald966abf12014-12-20 02:27:45 +0000311 if (this._element === undefined)
312 return this.element();
313
Nils Diewald8f6b6102015-01-08 18:25:33 +0000314 // Remove element content
Nils Diewald966abf12014-12-20 02:27:45 +0000315 _removeChildren(this._element);
316
317 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000318 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000319 this._element.appendChild(ellipsis);
320
321 // Set operators
Nils Diewalde15b7a22015-01-09 21:50:21 +0000322 if (this._parent !== undefined && this.parent().ldType() !== null) {
323 var op = this.operators(
324 false,
325 false,
326 true
327 );
Nils Diewald966abf12014-12-20 02:27:45 +0000328
Nils Diewalde15b7a22015-01-09 21:50:21 +0000329 this._element.appendChild(
330 op.element()
331 );
332 };
Nils Diewald966abf12014-12-20 02:27:45 +0000333
Nils Diewald966abf12014-12-20 02:27:45 +0000334 return this.element();
335 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000336
Nils Diewaldd0770492014-12-19 03:55:00 +0000337 element : function () {
338 if (this._element !== undefined)
339 return this._element;
340 this._element = document.createElement('div');
Nils Diewaldd599d542015-01-08 20:41:34 +0000341 this._element.setAttribute('class', 'doc unspecified');
Nils Diewald966abf12014-12-20 02:27:45 +0000342 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000343 return this._element;
344 }
345 };
346
347
Nils Diewald8f4e2542014-12-19 04:42:09 +0000348 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000349 * Document criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000350 */
351 KorAP.Doc = {
352 _ldType : "doc",
353 _obj : function () { return KorAP.Doc; },
Nils Diewaldd0770492014-12-19 03:55:00 +0000354
355 create : function (parent, json) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000356 var obj = Object(KorAP.JsonLD).
357 create().
358 upgradeTo(KorAP.Doc).
359 fromJson(json);
360
Nils Diewaldd0770492014-12-19 03:55:00 +0000361 if (parent !== undefined)
362 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000363
364 obj._changed = true;
Nils Diewaldd0770492014-12-19 03:55:00 +0000365 return obj;
366 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000367
Nils Diewald966abf12014-12-20 02:27:45 +0000368 update : function () {
369 if (this._element === undefined)
370 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000371
Nils Diewald8f6b6102015-01-08 18:25:33 +0000372 // Get element
Nils Diewald966abf12014-12-20 02:27:45 +0000373 var e = this._element;
374
Nils Diewald8f6b6102015-01-08 18:25:33 +0000375 // Check if there is a change
376 if (this._changed) {
Nils Diewald966abf12014-12-20 02:27:45 +0000377
Nils Diewald8f6b6102015-01-08 18:25:33 +0000378 // Added key
379 var key = document.createElement('span');
380 key.setAttribute('class', 'key');
381 if (this.key())
382 key.appendChild(document.createTextNode(this.key()));
Nils Diewald966abf12014-12-20 02:27:45 +0000383
Nils Diewald8f6b6102015-01-08 18:25:33 +0000384 // Added match operator
385 var matchop = document.createElement('span');
386 matchop.setAttribute('data-type', this.type());
387 matchop.setAttribute('class', 'match');
388 matchop.appendChild(
389 document.createTextNode(this.matchop())
390 );
391
392 // Added match operator
393 var value = document.createElement('span');
394 value.setAttribute('data-type', this.type());
395 value.setAttribute('class', 'value');
396 if (this.value())
397 value.appendChild(
398 document.createTextNode(this.value())
399 );
400
401 // Remove all element children
402 _removeChildren(e);
403
404 // Add spans
405 e.appendChild(key);
406 e.appendChild(matchop);
407 e.appendChild(value);
408
409 this._changed = false;
410 };
411
412 if (this._parent !== undefined) {
413 // Set operators
414 var op = this.operators(
415 true,
416 true,
Nils Diewald4019bd22015-01-08 19:57:50 +0000417 true
Nils Diewald8f6b6102015-01-08 18:25:33 +0000418 );
419
420 // Append new operators
421 e.appendChild(op.element());
422 };
Nils Diewald966abf12014-12-20 02:27:45 +0000423
Nils Diewaldd0770492014-12-19 03:55:00 +0000424 return e;
425 },
426
Nils Diewald966abf12014-12-20 02:27:45 +0000427 element : function () {
428 if (this._element !== undefined)
429 return this._element;
430
431 this._element = document.createElement('div');
432 this._element.setAttribute('class', 'doc');
433
434 this.update();
435 return this._element;
436 },
437
Nils Diewaldd0770492014-12-19 03:55:00 +0000438 // Wrap a new operation around the doc element
439 wrap : function (op) {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000440 var parent = this.parent();
441 var group = KorAP.DocGroup.create(parent);
442 group.operation(op);
Nils Diewald966abf12014-12-20 02:27:45 +0000443 group.append(this);
Nils Diewald9fcc1712015-01-09 14:24:32 +0000444 group.append();
445 return parent.replaceOperand(this, group).update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000446 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000447
Nils Diewald3a2d8022014-12-16 02:45:41 +0000448 // Deserialize from json
449 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000450 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000451 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000452
Nils Diewald3a2d8022014-12-16 02:45:41 +0000453 if (json["@type"] !== "korap:doc") {
454 KorAP.log(701, "JSON-LD group has no @type attribute");
455 return;
456 };
457
Nils Diewald3a2d8022014-12-16 02:45:41 +0000458 if (json["value"] === undefined ||
459 typeof json["value"] != 'string') {
460 KorAP.log(805, "Value is invalid");
461 return;
462 };
463
464 // There is a defined key
465 if (json["key"] !== undefined &&
466 typeof json["key"] === 'string') {
467
468 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000469 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000470
471 // Set match operation
472 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000473 if (typeof json["match"] === 'string') {
474 this.matchop(json["match"]);
475 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000476 else {
477 KorAP.log(802, "Match type is not supported by value type");
478 return;
479 };
480 };
481
482 // Key is a string
483 if (json["type"] === undefined ||
484 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000485 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000486
487 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000488 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000489 KorAP.log(802, "Match type is not supported by value type");
490 return;
491 };
492
493 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000494 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000495 }
496
497 // Key is a date
498 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000499 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000500
501 if (json["value"] !== undefined &&
502 KorAP._validDateRE.test(json["value"])) {
503
Nils Diewaldd0770492014-12-19 03:55:00 +0000504 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000505 KorAP.log(802, "Match type is not supported by value type");
506 return;
507 };
508
509 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000510 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000511 }
512 else {
513 KorAP.log(806, "Value is not a valid date string");
514 return;
515 };
516 }
517
518 // Key is a regular expression
519 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000520 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000521
522 try {
523
524 // Try to create a regular expression
525 var check = new RegExp(json["value"]);
526
Nils Diewaldd0770492014-12-19 03:55:00 +0000527 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000528 KorAP.log(802, "Match type is not supported by value type");
529 return;
530 };
531
Nils Diewaldd0770492014-12-19 03:55:00 +0000532 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000533 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000534
Nils Diewald3a2d8022014-12-16 02:45:41 +0000535 catch (e) {
536 KorAP.log(807, "Value is not a valid regular expression");
537 return;
538 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000539 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000540 }
541
542 else {
543 KorAP.log(804, "Unknown value type");
544 return;
545 };
546 };
547
548 return this;
549 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000550
Nils Diewaldd0770492014-12-19 03:55:00 +0000551 key : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000552 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000553 this._key = value;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000554 this._changed = true;
555 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000556 return this._key;
557 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000558
Nils Diewaldd0770492014-12-19 03:55:00 +0000559 matchop : function (match) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000560 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000561 this._matchop = match.replace(/^match:/, '');
Nils Diewald8f6b6102015-01-08 18:25:33 +0000562 this._changed = true;
563 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000564 return this._matchop || "eq";
565 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000566
Nils Diewaldd0770492014-12-19 03:55:00 +0000567 type : function (type) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000568 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000569 this._type = type;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000570 this._changed = true;
571 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000572 return this._type || "string";
573 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000574
Nils Diewaldd0770492014-12-19 03:55:00 +0000575 value : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000576 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000577 this._value = value;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000578 this._changed = true;
579 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000580 return this._value;
581 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000582
Nils Diewald3a2d8022014-12-16 02:45:41 +0000583 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000584 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000585 return {};
586
587 return {
Nils Diewaldd0770492014-12-19 03:55:00 +0000588 "@type" : "korap:" + this.ldType(),
589 "key" : this.key(),
590 "match" : "match:" + this.matchop(),
591 "value" : this.value() || '',
592 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000593 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000594 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000595
596 toQuery : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000597 if (!this.matchop() || !this.key())
598 return "";
599
600 // Build doc string based on key
601 var string = this.key() + ' ';
602
603 // Add match operator
604 switch (this.matchop()) {
605 case "ne":
606 string += '!=';
607 break;
608 case "contains":
609 string += '~';
610 break;
611 case "geq":
612 string += 'since';
613 break;
614 case "leq":
615 string += 'until';
616 break;
617 default:
618 string += (this.type() == 'date') ? 'in' : '=';
619 break;
620 };
621
622 string += ' ';
623
624 // Add value
625 switch (this.type()) {
626 case "date":
627 return string + this.value();
628 break;
629 case "regex":
630 return string + '/' + this.value() + '/';
631 break;
632 case "string":
633 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
634 break;
635 };
636
Nils Diewaldd599d542015-01-08 20:41:34 +0000637 return "";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000638 }
639 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000640
Nils Diewaldd599d542015-01-08 20:41:34 +0000641
Nils Diewald8f4e2542014-12-19 04:42:09 +0000642 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000643 * Document group criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000644 */
645 KorAP.DocGroup = {
646 _ldType : "docGroup",
647
648 create : function (parent, json) {
649 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
650 obj._operands = [];
651 obj.fromJson(json);
652 if (parent !== undefined)
653 obj._parent = parent;
654 return obj;
655 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000656
657 newAfter : function (obj) {
658 for (var i in this._operands) {
659 if (this._operands[i] === obj) {
660 var operand = KorAP.UnspecifiedDoc.create(this);
661 this._operands.splice(i + 1, 0, operand);
662 return this.update();
663 };
664 };
665 },
666
Nils Diewald966abf12014-12-20 02:27:45 +0000667 append : function (operand) {
668
669 // Append unspecified object
670 if (operand === undefined) {
671
672 // Be aware of cyclic structures!
673 operand = KorAP.UnspecifiedDoc.create(this);
674 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000675 return operand;
676 };
677
Nils Diewald8f4e2542014-12-19 04:42:09 +0000678 switch (operand["@type"]) {
679 case undefined:
680 if (operand["ldType"] !== undefined) {
681 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000682 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000683 KorAP.log(812, "Operand not supported in document group");
684 return;
685 };
Nils Diewald966abf12014-12-20 02:27:45 +0000686 // Be aware of cyclic structures!
687 operand.parent(this);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000688 this._operands.push(operand);
689 return operand;
690 };
691
692 KorAP.log(701, "JSON-LD group has no @type attribute");
693 return;
694
695 case "korap:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000696 // Be aware of cyclic structures!
697 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000698 if (doc === undefined)
699 return;
700 this._operands.push(doc);
701 return doc;
702
703 case "korap:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000704 // Be aware of cyclic structures!
705 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000706 if (docGroup === undefined)
707 return;
708 this._operands.push(docGroup);
709 return docGroup;
710
711 default:
712 KorAP.log(812, "Operand not supported in document group");
713 return;
714 };
715 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000716
Nils Diewald966abf12014-12-20 02:27:45 +0000717 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000718 // There is only one operand in group
719 if (this._operands.length === 1) {
720 var parent = this.parent();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000721 var op = this.getOperand(0);
722
Nils Diewald8f6b6102015-01-08 18:25:33 +0000723 // This will prevent destruction of
724 // the operand
725 this._operands = [];
Nils Diewaldf219eb82015-01-07 20:15:42 +0000726
727 // Parent is a group
728 if (parent.ldType() !== null) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000729 return parent.replaceOperand(this, op).update();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000730 }
731
Nils Diewald8f6b6102015-01-08 18:25:33 +0000732 // Parent is vc
Nils Diewaldf219eb82015-01-07 20:15:42 +0000733 else {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000734 this.destroy();
Nils Diewald8f6b6102015-01-08 18:25:33 +0000735 // Cyclic madness
736 parent.root(op);
737 op.parent(parent);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000738 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000739 };
740 };
741
Nils Diewald966abf12014-12-20 02:27:45 +0000742 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000743 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000744
Nils Diewald5c817a42015-01-06 01:08:56 +0000745 var group = this._element;
746 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000747
Nils Diewald5c817a42015-01-06 01:08:56 +0000748 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000749
750 // Append operands
Nils Diewald5c817a42015-01-06 01:08:56 +0000751 for (var i in this._operands) {
752 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000753 this.getOperand(i).element()
754 );
755 };
756
757 // Set operators
758 var op = this.operators(
759 this.operation() == 'and' ? false : true,
760 this.operation() == 'or' ? false : true,
761 true
762 );
763
Nils Diewald5c817a42015-01-06 01:08:56 +0000764 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000765 op.element()
766 );
767
Nils Diewald5c817a42015-01-06 01:08:56 +0000768 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000769 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000770
Nils Diewald8f4e2542014-12-19 04:42:09 +0000771 element : function () {
772 if (this._element !== undefined)
773 return this._element;
774
775 this._element = document.createElement('div');
776 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000777
Nils Diewaldf219eb82015-01-07 20:15:42 +0000778 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000779 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000780
781 return this._element;
782 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000783
Nils Diewald8f4e2542014-12-19 04:42:09 +0000784 operation : function (op) {
785 if (arguments.length === 1) {
786 if (KorAP._validGroupOpRE.test(op)) {
787 this._op = op;
788 }
789 else {
790 KorAP.log(810, "Unknown operation type");
791 return;
792 };
793 };
794 return this._op || 'and';
795 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000796
Nils Diewald8f4e2542014-12-19 04:42:09 +0000797 operands : function () {
798 return this._operands;
799 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000800
Nils Diewald8f4e2542014-12-19 04:42:09 +0000801 getOperand : function (index) {
802 return this._operands[index];
803 },
804
Nils Diewald5c817a42015-01-06 01:08:56 +0000805 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000806 replaceOperand : function (oldOp, newOp) {
Nils Diewald5c817a42015-01-06 01:08:56 +0000807 for (var i in this._operands) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000808 if (this._operands[i] === oldOp) {
809
Nils Diewalde15b7a22015-01-09 21:50:21 +0000810 // Just insert a doc or ...
811 if (newOp.ldType() === "doc" ||
812 // ... insert a group of a different operation
813 // (i.e. "and" in "or"/"or" in "and")
814 newOp.operation() != this.operation()) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000815 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000816 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000817 }
818
819 // Flatten the group
820 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000821 // Remove old group
822 this._operands.splice(i, 1);
823
824 // Inject new operands
Nils Diewald8f6b6102015-01-08 18:25:33 +0000825 for (var op in newOp.operands().reverse()) {
826 this._operands.splice(i, 0, newOp.getOperand(op));
827 newOp.getOperand(0).parent(this);
828 };
829 // Prevent destruction of operands
830 newOp._operands = [];
831 newOp.destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000832 };
833 oldOp.destroy();
834 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000835 }
836 };
837 return false;
838 },
839
Nils Diewald0297ba12015-01-05 21:56:12 +0000840 // Delete operand from group
841 delOperand : function (obj) {
842 for (var i in this._operands) {
843 if (this._operands[i] === obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000844
Nils Diewald8f6b6102015-01-08 18:25:33 +0000845 // Delete identified operand
Nils Diewald0297ba12015-01-05 21:56:12 +0000846 this._operands.splice(i,1);
847
Nils Diewald5c817a42015-01-06 01:08:56 +0000848 // Destroy object for cyclic references
849 obj.destroy();
850
Nils Diewaldf219eb82015-01-07 20:15:42 +0000851 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +0000852 };
853 };
Nils Diewald5c817a42015-01-06 01:08:56 +0000854
855 // Operand not found
856 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +0000857 },
858
Nils Diewald8f4e2542014-12-19 04:42:09 +0000859 // Deserialize from json
860 fromJson : function (json) {
861 if (json === undefined)
862 return this;
863
864 if (json["@type"] !== "korap:docGroup") {
865 KorAP.log(701, "JSON-LD group has no @type attribute");
866 return;
867 };
868
869 if (json["operation"] === undefined ||
870 typeof json["operation"] !== 'string') {
871 KorAP.log(811, "Document group expects operation");
872 return;
873 };
874
875 var operation = json["operation"];
876
877 this.operation(operation.replace(/^operation:/,''));
878
879 if (json["operands"] === undefined ||
880 !(json["operands"] instanceof Array)) {
881 KorAP.log(704, "Operation needs operand list")
882 return;
883 };
884
885 // Add all documents
886 for (var i in json["operands"]) {
887 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +0000888 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000889 };
890
891 return this;
892 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000893
Nils Diewald8f4e2542014-12-19 04:42:09 +0000894 toJson : function () {
895 var opArray = new Array();
896 for (var i in this._operands) {
Nils Diewalde15b7a22015-01-09 21:50:21 +0000897 if (this._operands[i].ldType() !== 'non')
898 opArray.push(this._operands[i].toJson());
Nils Diewald8f4e2542014-12-19 04:42:09 +0000899 };
900 return {
901 "@type" : "korap:" + this.ldType(),
902 "operation" : "operation:" + this.operation(),
903 "operands" : opArray
904 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000905 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000906
Nils Diewalde15b7a22015-01-09 21:50:21 +0000907 toQuery : function (brackets) {
908 var list = this._operands
909 .filter(function (op) {
910 return op.ldType() !== 'non';
911 })
912 .map(function (op) {
Nils Diewaldd599d542015-01-08 20:41:34 +0000913 return (op.ldType() === 'docGroup') ?
Nils Diewalde15b7a22015-01-09 21:50:21 +0000914 op.toQuery(true) :
Nils Diewaldd599d542015-01-08 20:41:34 +0000915 op.toQuery();
Nils Diewalde15b7a22015-01-09 21:50:21 +0000916 });
917
918 if (list.length === 1)
919 return list.join('');
920 else {
921 var str = list.join(this.operation() === 'or' ? ' | ' : ' & ');
922 return brackets ? '(' + str + ')' : str;
923 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000924 }
925 };
926
927
Nils Diewaldd599d542015-01-08 20:41:34 +0000928 /**
929 * Abstract JsonLD criterion object
930 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000931 KorAP.JsonLD = {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000932 _changed : false,
933
Nils Diewald8f4e2542014-12-19 04:42:09 +0000934 create : function () {
935 return Object.create(KorAP.JsonLD);
936 },
937
938 /**
939 * Upgrade this object to another object
940 * while private data stays intact
941 */
942 upgradeTo : function (props) {
943 for (var prop in props) {
944 this[prop] = props[prop];
945 };
946 return this;
947 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000948
Nils Diewald8f4e2542014-12-19 04:42:09 +0000949 ldType : function (type) {
950 if (arguments.length === 1)
951 this._ldType = type;
952 return this._ldType;
953 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000954
Nils Diewald8f4e2542014-12-19 04:42:09 +0000955 parent : function (obj) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000956 if (arguments.length === 1) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000957 this._parent = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000958 this._changed = true;
959 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000960 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +0000961 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000962
Nils Diewald5c817a42015-01-06 01:08:56 +0000963 // Destroy object - especially for
964 // acyclic structures!
965 // I'm a paranoid chicken!
966 destroy : function () {
967 if (this._ops != undefined) {
968 this._ops._parent = undefined;
969 if (this._ops._element !== undefined)
970 this._ops._element.refTo = undefined;
971 this._ops = undefined;
972 };
973 if (this._element !== undefined)
974 this._element = undefined;
975
976 // In case of a group, destroy all operands
977 if (this._operands !== undefined) {
978 for (var i in this._operands)
979 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000980 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +0000981 };
982 },
983
Nils Diewald0297ba12015-01-05 21:56:12 +0000984 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +0000985 operators : function (and, or, del) {
986 if (arguments === 0)
987 return this._ops;
988 this._ops = KorAP.Operators.create(
989 and, or, del
990 );
Nils Diewald0297ba12015-01-05 21:56:12 +0000991 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +0000992 return this._ops;
993 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000994
Nils Diewald966abf12014-12-20 02:27:45 +0000995 toJson : function () {
996 return {
997 // Unspecified object
998 "@type" : "korap:" + this.ldType()
999 };
Nils Diewald8f6b6102015-01-08 18:25:33 +00001000 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001001
1002 toQuery : function () {
Nils Diewald8f6b6102015-01-08 18:25:33 +00001003 return loc.EMPTY;
Nils Diewald8f4e2542014-12-19 04:42:09 +00001004 }
1005 };
1006
Nils Diewald3a2d8022014-12-16 02:45:41 +00001007}(this.KorAP));