blob: 290531ac510ce86550d40e4da903237abbf1101a [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/*
8 * Error codes:
9 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 Diewaldf219eb82015-01-07 20:15:42 +000037 var loc = (KorAP.Locale = KorAP.Locale || {} );
38 loc.AND = loc.AND || 'and';
39 loc.OR = loc.OR || 'or';
40 loc.DEL = loc.DEL || '×';
41 loc.EMPTY = loc.EMPTY || '⋯'
Nils Diewaldd0770492014-12-19 03:55:00 +000042
Nils Diewald966abf12014-12-20 02:27:45 +000043 function _bool (bool) {
44 return (bool === undefined || bool === false) ? false : true;
45 };
46
47 function _removeChildren (node) {
48 // Remove everything underneath
Nils Diewald8f6b6102015-01-08 18:25:33 +000049 while (node.firstChild)
Nils Diewald966abf12014-12-20 02:27:45 +000050 node.removeChild(node.firstChild);
Nils Diewald966abf12014-12-20 02:27:45 +000051 };
52
Nils Diewald4019bd22015-01-08 19:57:50 +000053
54 // Add 'or'-criterion
55 KorAP._or = function (e) {
56 var obj = this.parentNode.refTo;
57 };
58
59
60 // Add 'and'-criterion
61 KorAP._and = function (e) {
62 var obj = this.parentNode.refTo;
63 };
64
65 // Remove doc or docGroup
66 KorAP._delete = function (e) {
67 var obj = this.parentNode.refTo;
68 if (obj.parent().ldType() !== null)
69 obj.parent().delOperand(obj).update();
70 else
71 obj.parent().clean();
72 };
73
Nils Diewald3a2d8022014-12-16 02:45:41 +000074 KorAP.VirtualCollection = {
Nils Diewaldf219eb82015-01-07 20:15:42 +000075 ldType : function () {
76 return null;
77 },
Nils Diewald3a2d8022014-12-16 02:45:41 +000078 create : function () {
79 return Object.create(KorAP.VirtualCollection);
80 },
Nils Diewald4019bd22015-01-08 19:57:50 +000081 clean : function () {
82 if (this._root.ldType() !== "non") {
83 this._root.destroy();
84 this.root(KorAP.UnspecifiedDoc.create(this));
85 };
86 return this;
87 },
Nils Diewaldd0770492014-12-19 03:55:00 +000088 render : function (json) {
89 var obj = Object.create(KorAP.VirtualCollection);
90
91 if (json !== undefined) {
92 // Root object
93 if (json['@type'] == 'korap:doc') {
Nils Diewaldf219eb82015-01-07 20:15:42 +000094 obj._root = KorAP.Doc.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000095 }
96 else if (json['@type'] == 'korap:docGroup') {
Nils Diewaldf219eb82015-01-07 20:15:42 +000097 obj._root = KorAP.DocGroup.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000098 }
99 else {
100 KorAP.log(813, "Collection type is not supported");
101 return;
102 };
103 }
104
105 else {
106 // Add unspecified object
Nils Diewaldf219eb82015-01-07 20:15:42 +0000107 obj._root = KorAP.UnspecifiedDoc.create(obj);
Nils Diewaldd0770492014-12-19 03:55:00 +0000108 };
109
Nils Diewald8e7182e2015-01-08 15:02:07 +0000110 // Init element and update
111 obj.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000112
113 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000114 },
Nils Diewaldf219eb82015-01-07 20:15:42 +0000115 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000116 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000117 var e = this.element();
118 if (e.firstChild !== null) {
119 if (e.firstChild !== obj.element())
120 e.replaceChild(obj.element(), e.firstChild);
121 }
122
123 // Append root element
124 else {
125 e.appendChild(obj.element());
126 };
127
128 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000129 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000130 obj.parent(this);
131
Nils Diewald8e7182e2015-01-08 15:02:07 +0000132 this.update();
133 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000134 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000135 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000136
Nils Diewaldd0770492014-12-19 03:55:00 +0000137 element : function () {
138 if (this._element !== undefined)
139 return this._element;
140
141 this._element = document.createElement('div');
142 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000143
Nils Diewald8f6b6102015-01-08 18:25:33 +0000144 // Initialize root
145 this._element.appendChild(this._root.element());
146
Nils Diewaldd0770492014-12-19 03:55:00 +0000147 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000148 },
149 toJson : function () {
150 return this._root.toJson();
151 },
152 toString : function () {
153 return this._root.toString();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000154 },
155 update : function () {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000156 this._root.update();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000157 }
158 };
159
Nils Diewald8f4e2542014-12-19 04:42:09 +0000160 /**
161 * Operators for criteria
162 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000163 KorAP.Operators = {
164 create : function (and, or, del) {
165 var op = Object.create(KorAP.Operators);
166 op.and(and);
167 op.or(or);
168 op.del(del);
169 return op;
170 },
171 update : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000172 // Init the element
173 if (this._element === undefined)
174 return this.element();
175
176 var op = this._element;
177
Nils Diewald0297ba12015-01-05 21:56:12 +0000178 op.refTo = this.parent();
179
Nils Diewaldd0770492014-12-19 03:55:00 +0000180 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000181 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000182
183 // Add and button
184 if (this._and === true) {
185 var andE = document.createElement('span');
186 andE.setAttribute('class', 'and');
Nils Diewald0297ba12015-01-05 21:56:12 +0000187 andE.addEventListener('click', KorAP._and, false);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000188 andE.appendChild(
189 document.createTextNode(KorAP.Locale.AND)
190 );
Nils Diewaldd0770492014-12-19 03:55:00 +0000191 op.appendChild(andE);
192 };
193
194 // Add or button
195 if (this._or === true) {
196 var orE = document.createElement('span');
197 orE.setAttribute('class', 'or');
Nils Diewald0297ba12015-01-05 21:56:12 +0000198 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000199 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
200 op.appendChild(orE);
201 };
202
203 // Add delete button
204 if (this._del === true) {
205 var delE = document.createElement('span');
206 delE.setAttribute('class', 'delete');
207 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000208 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000209 op.appendChild(delE);
210 };
Nils Diewald966abf12014-12-20 02:27:45 +0000211
212 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000213 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000214
215 // Be aware! This may be cyclic
216 parent : function (obj) {
217 if (arguments.length === 1)
218 this._parent = obj;
219 return this._parent;
220 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000221
Nils Diewaldd0770492014-12-19 03:55:00 +0000222 element : function () {
223
224 // Return existing element
225 if (this._element !== undefined)
226 return this._element;
227
228 this._element = document.createElement('div');
229 this._element.setAttribute('class', 'operators');
230
231 // Init elements
232 this.update();
233 return this._element;
234 },
235 and : function (bool) {
236 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000237 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000238 return this._and;
239 },
240 or : function (bool) {
241 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000242 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000243 return this._or;
244 },
245 del : function (bool) {
246 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000247 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000248 return this._del;
249 }
250 };
251
252
253 /**
254 * Unspecified criterion
255 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000256 KorAP.UnspecifiedDoc = {
Nils Diewald4019bd22015-01-08 19:57:50 +0000257 _ldType : "non",
Nils Diewaldd0770492014-12-19 03:55:00 +0000258 create : function (parent) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000259 var obj = Object.create(KorAP.JsonLD).
260 upgradeTo(KorAP.UnspecifiedDoc);
261
Nils Diewaldd0770492014-12-19 03:55:00 +0000262 if (parent !== undefined)
263 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000264
Nils Diewaldd0770492014-12-19 03:55:00 +0000265 return obj;
266 },
Nils Diewald966abf12014-12-20 02:27:45 +0000267 update : function () {
Nils Diewald4019bd22015-01-08 19:57:50 +0000268
Nils Diewald966abf12014-12-20 02:27:45 +0000269 if (this._element === undefined)
270 return this.element();
271
Nils Diewald8f6b6102015-01-08 18:25:33 +0000272 // Remove element content
Nils Diewald966abf12014-12-20 02:27:45 +0000273 _removeChildren(this._element);
274
275 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000276 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000277 this._element.appendChild(ellipsis);
278
279 // Set operators
280 var op = this.operators(
281 false,
282 false,
283 // No delete object, if this is the root
Nils Diewald8f6b6102015-01-08 18:25:33 +0000284 (this._parent !== undefined &&
285 this.parent().ldType() !== null) ? true : false
Nils Diewald966abf12014-12-20 02:27:45 +0000286 );
287
288 this._element.appendChild(
289 op.element()
290 );
291
Nils Diewald966abf12014-12-20 02:27:45 +0000292 return this.element();
293 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000294 element : function () {
295 if (this._element !== undefined)
296 return this._element;
Nils Diewald966abf12014-12-20 02:27:45 +0000297
Nils Diewaldd0770492014-12-19 03:55:00 +0000298 this._element = document.createElement('div');
Nils Diewald966abf12014-12-20 02:27:45 +0000299 this._element.setAttribute('class', 'unspecified');
300
301 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000302 return this._element;
303 }
304 };
305
306
Nils Diewald8f4e2542014-12-19 04:42:09 +0000307 /**
308 * Virtual collection doc criterion.
309 */
310 KorAP.Doc = {
311 _ldType : "doc",
312 _obj : function () { return KorAP.Doc; },
Nils Diewaldd0770492014-12-19 03:55:00 +0000313
314 create : function (parent, json) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000315 var obj = Object(KorAP.JsonLD).
316 create().
317 upgradeTo(KorAP.Doc).
318 fromJson(json);
319
Nils Diewaldd0770492014-12-19 03:55:00 +0000320 if (parent !== undefined)
321 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000322
323 obj._changed = true;
Nils Diewaldd0770492014-12-19 03:55:00 +0000324 return obj;
325 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000326
Nils Diewald966abf12014-12-20 02:27:45 +0000327 update : function () {
328 if (this._element === undefined)
329 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000330
Nils Diewald8f6b6102015-01-08 18:25:33 +0000331 // Get element
Nils Diewald966abf12014-12-20 02:27:45 +0000332 var e = this._element;
333
Nils Diewald8f6b6102015-01-08 18:25:33 +0000334 // Check if there is a change
335 if (this._changed) {
Nils Diewald966abf12014-12-20 02:27:45 +0000336
Nils Diewald8f6b6102015-01-08 18:25:33 +0000337 // Added key
338 var key = document.createElement('span');
339 key.setAttribute('class', 'key');
340 if (this.key())
341 key.appendChild(document.createTextNode(this.key()));
Nils Diewald966abf12014-12-20 02:27:45 +0000342
Nils Diewald8f6b6102015-01-08 18:25:33 +0000343 // Added match operator
344 var matchop = document.createElement('span');
345 matchop.setAttribute('data-type', this.type());
346 matchop.setAttribute('class', 'match');
347 matchop.appendChild(
348 document.createTextNode(this.matchop())
349 );
350
351 // Added match operator
352 var value = document.createElement('span');
353 value.setAttribute('data-type', this.type());
354 value.setAttribute('class', 'value');
355 if (this.value())
356 value.appendChild(
357 document.createTextNode(this.value())
358 );
359
360 // Remove all element children
361 _removeChildren(e);
362
363 // Add spans
364 e.appendChild(key);
365 e.appendChild(matchop);
366 e.appendChild(value);
367
368 this._changed = false;
369 };
370
371 if (this._parent !== undefined) {
372 // Set operators
373 var op = this.operators(
374 true,
375 true,
Nils Diewald4019bd22015-01-08 19:57:50 +0000376 true
Nils Diewald8f6b6102015-01-08 18:25:33 +0000377 );
378
379 // Append new operators
380 e.appendChild(op.element());
381 };
Nils Diewald966abf12014-12-20 02:27:45 +0000382
Nils Diewaldd0770492014-12-19 03:55:00 +0000383 return e;
384 },
385
Nils Diewald966abf12014-12-20 02:27:45 +0000386 element : function () {
387 if (this._element !== undefined)
388 return this._element;
389
390 this._element = document.createElement('div');
391 this._element.setAttribute('class', 'doc');
392
393 this.update();
394 return this._element;
395 },
396
Nils Diewaldd0770492014-12-19 03:55:00 +0000397 // Wrap a new operation around the doc element
398 wrap : function (op) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000399/*
Nils Diewald8f4e2542014-12-19 04:42:09 +0000400 var group = KorAP.DocGroup.create(undefined);
Nils Diewald966abf12014-12-20 02:27:45 +0000401 group.append(this);
402 group.append(null);
Nils Diewaldd0770492014-12-19 03:55:00 +0000403 this.parent(group);
Nils Diewaldd0770492014-12-19 03:55:00 +0000404 var div = document.createElement('div');
405 div.setAttribute('data-operation', op);
406 var parent = this.element.parent;
407 parent.removeChild(this.element);
408 parent.appendChild(div);
409 div.appendChild(this.element);
410 return div;
411*/
Nils Diewaldd0770492014-12-19 03:55:00 +0000412 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000413 // Deserialize from json
414 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000415 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000416 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000417
Nils Diewald3a2d8022014-12-16 02:45:41 +0000418 if (json["@type"] !== "korap:doc") {
419 KorAP.log(701, "JSON-LD group has no @type attribute");
420 return;
421 };
422
Nils Diewald3a2d8022014-12-16 02:45:41 +0000423 if (json["value"] === undefined ||
424 typeof json["value"] != 'string') {
425 KorAP.log(805, "Value is invalid");
426 return;
427 };
428
429 // There is a defined key
430 if (json["key"] !== undefined &&
431 typeof json["key"] === 'string') {
432
433 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000434 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000435
436 // Set match operation
437 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000438 if (typeof json["match"] === 'string') {
439 this.matchop(json["match"]);
440 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000441 else {
442 KorAP.log(802, "Match type is not supported by value type");
443 return;
444 };
445 };
446
447 // Key is a string
448 if (json["type"] === undefined ||
449 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000450 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000451
452 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000453 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000454 KorAP.log(802, "Match type is not supported by value type");
455 return;
456 };
457
458 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000459 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000460 }
461
462 // Key is a date
463 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000464 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000465
466 if (json["value"] !== undefined &&
467 KorAP._validDateRE.test(json["value"])) {
468
Nils Diewaldd0770492014-12-19 03:55:00 +0000469 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000470 KorAP.log(802, "Match type is not supported by value type");
471 return;
472 };
473
474 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000475 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000476 }
477 else {
478 KorAP.log(806, "Value is not a valid date string");
479 return;
480 };
481 }
482
483 // Key is a regular expression
484 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000485 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000486
487 try {
488
489 // Try to create a regular expression
490 var check = new RegExp(json["value"]);
491
Nils Diewaldd0770492014-12-19 03:55:00 +0000492 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000493 KorAP.log(802, "Match type is not supported by value type");
494 return;
495 };
496
Nils Diewaldd0770492014-12-19 03:55:00 +0000497 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000498 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000499
Nils Diewald3a2d8022014-12-16 02:45:41 +0000500 catch (e) {
501 KorAP.log(807, "Value is not a valid regular expression");
502 return;
503 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000504 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000505 }
506
507 else {
508 KorAP.log(804, "Unknown value type");
509 return;
510 };
511 };
512
513 return this;
514 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000515 key : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000516 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000517 this._key = value;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000518 this._changed = true;
519 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000520 return this._key;
521 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000522 matchop : function (match) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000523 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000524 this._matchop = match.replace(/^match:/, '');
Nils Diewald8f6b6102015-01-08 18:25:33 +0000525 this._changed = true;
526 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000527 return this._matchop || "eq";
528 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000529 type : function (type) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000530 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000531 this._type = type;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000532 this._changed = true;
533 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000534 return this._type || "string";
535 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000536 value : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000537 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000538 this._value = value;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000539 this._changed = true;
540 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000541 return this._value;
542 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000543 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000544 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000545 return {};
546
547 return {
Nils Diewaldd0770492014-12-19 03:55:00 +0000548 "@type" : "korap:" + this.ldType(),
549 "key" : this.key(),
550 "match" : "match:" + this.matchop(),
551 "value" : this.value() || '',
552 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000553 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000554 },
555 toString : function () {
556 if (!this.matchop() || !this.key())
557 return "";
558
559 // Build doc string based on key
560 var string = this.key() + ' ';
561
562 // Add match operator
563 switch (this.matchop()) {
564 case "ne":
565 string += '!=';
566 break;
567 case "contains":
568 string += '~';
569 break;
570 case "geq":
571 string += 'since';
572 break;
573 case "leq":
574 string += 'until';
575 break;
576 default:
577 string += (this.type() == 'date') ? 'in' : '=';
578 break;
579 };
580
581 string += ' ';
582
583 // Add value
584 switch (this.type()) {
585 case "date":
586 return string + this.value();
587 break;
588 case "regex":
589 return string + '/' + this.value() + '/';
590 break;
591 case "string":
592 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
593 break;
594 };
595
596 return "...";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000597 }
598 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000599
600 /**
601 * Virtual collection group criterion.
602 */
603 KorAP.DocGroup = {
604 _ldType : "docGroup",
605
606 create : function (parent, json) {
607 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
608 obj._operands = [];
609 obj.fromJson(json);
610 if (parent !== undefined)
611 obj._parent = parent;
612 return obj;
613 },
Nils Diewald966abf12014-12-20 02:27:45 +0000614 append : function (operand) {
615
616 // Append unspecified object
617 if (operand === undefined) {
618
619 // Be aware of cyclic structures!
620 operand = KorAP.UnspecifiedDoc.create(this);
621 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000622 return operand;
623 };
624
Nils Diewald8f4e2542014-12-19 04:42:09 +0000625 switch (operand["@type"]) {
626 case undefined:
627 if (operand["ldType"] !== undefined) {
628 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000629 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000630 KorAP.log(812, "Operand not supported in document group");
631 return;
632 };
Nils Diewald966abf12014-12-20 02:27:45 +0000633 // Be aware of cyclic structures!
634 operand.parent(this);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000635 this._operands.push(operand);
636 return operand;
637 };
638
639 KorAP.log(701, "JSON-LD group has no @type attribute");
640 return;
641
642 case "korap:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000643 // Be aware of cyclic structures!
644 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000645 if (doc === undefined)
646 return;
647 this._operands.push(doc);
648 return doc;
649
650 case "korap:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000651 // Be aware of cyclic structures!
652 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000653 if (docGroup === undefined)
654 return;
655 this._operands.push(docGroup);
656 return docGroup;
657
658 default:
659 KorAP.log(812, "Operand not supported in document group");
660 return;
661 };
662 },
Nils Diewald966abf12014-12-20 02:27:45 +0000663 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000664 // There is only one operand in group
665 if (this._operands.length === 1) {
666 var parent = this.parent();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000667 var op = this.getOperand(0);
668
Nils Diewald8f6b6102015-01-08 18:25:33 +0000669 // This will prevent destruction of
670 // the operand
671 this._operands = [];
Nils Diewaldf219eb82015-01-07 20:15:42 +0000672
673 // Parent is a group
674 if (parent.ldType() !== null) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000675 return parent.replaceOperand(this, op).update();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000676 }
677
Nils Diewald8f6b6102015-01-08 18:25:33 +0000678 // Parent is vc
Nils Diewaldf219eb82015-01-07 20:15:42 +0000679 else {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000680 this.destroy();
Nils Diewald8f6b6102015-01-08 18:25:33 +0000681 // Cyclic madness
682 parent.root(op);
683 op.parent(parent);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000684 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000685 };
686 };
687
Nils Diewald966abf12014-12-20 02:27:45 +0000688 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000689 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000690
Nils Diewald5c817a42015-01-06 01:08:56 +0000691 var group = this._element;
692 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000693
Nils Diewald5c817a42015-01-06 01:08:56 +0000694 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000695
696 // Append operands
Nils Diewald5c817a42015-01-06 01:08:56 +0000697 for (var i in this._operands) {
698 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000699 this.getOperand(i).element()
700 );
701 };
702
703 // Set operators
704 var op = this.operators(
705 this.operation() == 'and' ? false : true,
706 this.operation() == 'or' ? false : true,
707 true
708 );
709
Nils Diewald5c817a42015-01-06 01:08:56 +0000710 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000711 op.element()
712 );
713
Nils Diewald5c817a42015-01-06 01:08:56 +0000714 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000715 },
Nils Diewald8f4e2542014-12-19 04:42:09 +0000716 element : function () {
717 if (this._element !== undefined)
718 return this._element;
719
720 this._element = document.createElement('div');
721 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000722
Nils Diewaldf219eb82015-01-07 20:15:42 +0000723 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000724 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000725
726 return this._element;
727 },
728 operation : function (op) {
729 if (arguments.length === 1) {
730 if (KorAP._validGroupOpRE.test(op)) {
731 this._op = op;
732 }
733 else {
734 KorAP.log(810, "Unknown operation type");
735 return;
736 };
737 };
738 return this._op || 'and';
739 },
740 operands : function () {
741 return this._operands;
742 },
743 getOperand : function (index) {
744 return this._operands[index];
745 },
746
Nils Diewald5c817a42015-01-06 01:08:56 +0000747 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000748 replaceOperand : function (oldOp, newOp) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000749
Nils Diewald5c817a42015-01-06 01:08:56 +0000750 for (var i in this._operands) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000751 if (this._operands[i] === oldOp) {
752
753 // Just insert a doc
754 if (newOp.ldType() === "doc") {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000755 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000756 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000757 }
758 // Insert a group of a different operation
759 // (i.e. "and" in "or"/"or" in "and")
Nils Diewald8e7182e2015-01-08 15:02:07 +0000760 else if (newOp.operation() != this.operation()) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000761 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000762 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000763 }
764
765 // Flatten the group
766 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000767 // Remove old group
768 this._operands.splice(i, 1);
769
770 // Inject new operands
Nils Diewald8f6b6102015-01-08 18:25:33 +0000771 for (var op in newOp.operands().reverse()) {
772 this._operands.splice(i, 0, newOp.getOperand(op));
773 newOp.getOperand(0).parent(this);
774 };
775 // Prevent destruction of operands
776 newOp._operands = [];
777 newOp.destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000778 };
779 oldOp.destroy();
780 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000781 }
782 };
783 return false;
784 },
785
Nils Diewald0297ba12015-01-05 21:56:12 +0000786 // Delete operand from group
787 delOperand : function (obj) {
788 for (var i in this._operands) {
789 if (this._operands[i] === obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000790
Nils Diewald8f6b6102015-01-08 18:25:33 +0000791 // Delete identified operand
Nils Diewald0297ba12015-01-05 21:56:12 +0000792 this._operands.splice(i,1);
793
Nils Diewald5c817a42015-01-06 01:08:56 +0000794 // Destroy object for cyclic references
795 obj.destroy();
796
Nils Diewaldf219eb82015-01-07 20:15:42 +0000797 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +0000798 };
799 };
Nils Diewald5c817a42015-01-06 01:08:56 +0000800
801 // Operand not found
802 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +0000803 },
804
Nils Diewald8f4e2542014-12-19 04:42:09 +0000805 // Deserialize from json
806 fromJson : function (json) {
807 if (json === undefined)
808 return this;
809
810 if (json["@type"] !== "korap:docGroup") {
811 KorAP.log(701, "JSON-LD group has no @type attribute");
812 return;
813 };
814
815 if (json["operation"] === undefined ||
816 typeof json["operation"] !== 'string') {
817 KorAP.log(811, "Document group expects operation");
818 return;
819 };
820
821 var operation = json["operation"];
822
823 this.operation(operation.replace(/^operation:/,''));
824
825 if (json["operands"] === undefined ||
826 !(json["operands"] instanceof Array)) {
827 KorAP.log(704, "Operation needs operand list")
828 return;
829 };
830
831 // Add all documents
832 for (var i in json["operands"]) {
833 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +0000834 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000835 };
836
837 return this;
838 },
839 toJson : function () {
840 var opArray = new Array();
841 for (var i in this._operands) {
842 opArray.push(this._operands[i].toJson());
843 };
844 return {
845 "@type" : "korap:" + this.ldType(),
846 "operation" : "operation:" + this.operation(),
847 "operands" : opArray
848 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000849 },
850 toString : function () {
851 return this._operands.
852 map(function (op) {
853 return op.ldType() === 'docGroup' ? '(' + op.toString() + ')' : op.toString()
854 }).
855 join(this.operation() === 'or' ? ' | ' : ' & ')
Nils Diewald8f4e2542014-12-19 04:42:09 +0000856 }
857 };
858
859
860 // Abstract JsonLD object
861 KorAP.JsonLD = {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000862 _changed : false,
863
Nils Diewald8f4e2542014-12-19 04:42:09 +0000864 create : function () {
865 return Object.create(KorAP.JsonLD);
866 },
867
868 /**
869 * Upgrade this object to another object
870 * while private data stays intact
871 */
872 upgradeTo : function (props) {
873 for (var prop in props) {
874 this[prop] = props[prop];
875 };
876 return this;
877 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000878
Nils Diewald8f4e2542014-12-19 04:42:09 +0000879 ldType : function (type) {
880 if (arguments.length === 1)
881 this._ldType = type;
882 return this._ldType;
883 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000884
Nils Diewald8f4e2542014-12-19 04:42:09 +0000885 parent : function (obj) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000886 if (arguments.length === 1) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000887 this._parent = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000888 this._changed = true;
889 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000890 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +0000891 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000892
Nils Diewald5c817a42015-01-06 01:08:56 +0000893 // Destroy object - especially for
894 // acyclic structures!
895 // I'm a paranoid chicken!
896 destroy : function () {
897 if (this._ops != undefined) {
898 this._ops._parent = undefined;
899 if (this._ops._element !== undefined)
900 this._ops._element.refTo = undefined;
901 this._ops = undefined;
902 };
903 if (this._element !== undefined)
904 this._element = undefined;
905
906 // In case of a group, destroy all operands
907 if (this._operands !== undefined) {
908 for (var i in this._operands)
909 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000910 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +0000911 };
912 },
913
Nils Diewald0297ba12015-01-05 21:56:12 +0000914 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +0000915 operators : function (and, or, del) {
916 if (arguments === 0)
917 return this._ops;
918 this._ops = KorAP.Operators.create(
919 and, or, del
920 );
Nils Diewald0297ba12015-01-05 21:56:12 +0000921 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +0000922 return this._ops;
923 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000924
Nils Diewald966abf12014-12-20 02:27:45 +0000925 toJson : function () {
926 return {
927 // Unspecified object
928 "@type" : "korap:" + this.ldType()
929 };
Nils Diewald8f6b6102015-01-08 18:25:33 +0000930 },
931 toString : function () {
932 return loc.EMPTY;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000933 }
934 };
935
Nils Diewald3a2d8022014-12-16 02:45:41 +0000936}(this.KorAP));