blob: fa6345760c56d896fdfe2119dc55c6e35a9bc218 [file] [log] [blame]
Nils Diewald86dad5b2015-01-28 15:09:07 +00001/**
2 * Create virtual collections with a visual user interface.
3 *
4 * @author Nils Diewald
5 */
Nils Diewald2fe12e12015-03-06 16:47:06 +00006/*
7 * Replaces a previous version written by Mengfei Zhou
8 */
Nils Diewald3a2d8022014-12-16 02:45:41 +00009var KorAP = KorAP || {};
Nils Diewald3a2d8022014-12-16 02:45:41 +000010
Nils Diewald2fe12e12015-03-06 16:47:06 +000011// Requires menu.js
12
Nils Diewaldd0770492014-12-19 03:55:00 +000013/*
Nils Diewald86dad5b2015-01-28 15:09:07 +000014 TODO: Implement a working localization solution!
15 TODO: Disable "and" or "or" in case it's followed
16 by an unspecified document
17
Nils Diewaldd599d542015-01-08 20:41:34 +000018 Error codes:
Nils Diewaldd0770492014-12-19 03:55:00 +000019 701: "JSON-LD group has no @type attribute"
20 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000021 802: "Match type is not supported by value type"
22 804: "Unknown value type"
23 805: "Value is invalid"
24 806: "Value is not a valid date string"
25 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000026 810: "Unknown document group operation" (like 711)
27 811: "Document group expects operation" (like 703)
28 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000029 813: "Collection type is not supported" (like 713)
Nils Diewald86dad5b2015-01-28 15:09:07 +000030 814: "Unknown rewrite operation"
31 815: "Rewrite expects source"
Nils Diewaldd0770492014-12-19 03:55:00 +000032*/
33
Nils Diewald3a2d8022014-12-16 02:45:41 +000034(function (KorAP) {
35 "use strict";
36
37 // Default log message
38 KorAP.log = KorAP.log || function (type, msg) {
39 console.log(type + ": " + msg);
40 };
41
Nils Diewald86dad5b2015-01-28 15:09:07 +000042 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains|excludes)$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000043 KorAP._validRegexMatchRE = new RegExp("^(?:eq|ne)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000044 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000045 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
46 KorAP._validGroupOpRE = new RegExp("^(?:and|or)$");
Nils Diewald86dad5b2015-01-28 15:09:07 +000047 KorAP._validRewriteOpRE = new RegExp("^(?:injec|modifica)tion$");
Nils Diewaldf219eb82015-01-07 20:15:42 +000048 KorAP._quote = new RegExp("([\"\\\\])", 'g');
Nils Diewald3a2d8022014-12-16 02:45:41 +000049
Nils Diewalde15b7a22015-01-09 21:50:21 +000050 // Localization values
Nils Diewaldf219eb82015-01-07 20:15:42 +000051 var loc = (KorAP.Locale = KorAP.Locale || {} );
52 loc.AND = loc.AND || 'and';
53 loc.OR = loc.OR || 'or';
54 loc.DEL = loc.DEL || '×';
55 loc.EMPTY = loc.EMPTY || '⋯'
Nils Diewaldd0770492014-12-19 03:55:00 +000056
Nils Diewalde15b7a22015-01-09 21:50:21 +000057 // Utility for analysing boolean values
Nils Diewald966abf12014-12-20 02:27:45 +000058 function _bool (bool) {
Nils Diewalde15b7a22015-01-09 21:50:21 +000059 return (bool === undefined || bool === null || bool === false) ? false : true;
Nils Diewald966abf12014-12-20 02:27:45 +000060 };
61
Nils Diewaldd599d542015-01-08 20:41:34 +000062
Nils Diewalde15b7a22015-01-09 21:50:21 +000063 // Utility for removing all children of a node
Nils Diewald966abf12014-12-20 02:27:45 +000064 function _removeChildren (node) {
65 // Remove everything underneath
Nils Diewald8f6b6102015-01-08 18:25:33 +000066 while (node.firstChild)
Nils Diewald966abf12014-12-20 02:27:45 +000067 node.removeChild(node.firstChild);
Nils Diewald966abf12014-12-20 02:27:45 +000068 };
69
Nils Diewald4019bd22015-01-08 19:57:50 +000070
Nils Diewald52f7eb12015-01-12 17:30:04 +000071 // Add new unspecified document
Nils Diewald9fcc1712015-01-09 14:24:32 +000072 KorAP._add = function (obj, type) {
73 var ref = obj.parentNode.refTo;
Nils Diewaldd5070b02015-01-11 01:44:47 +000074 var parent = ref.parent();
Nils Diewald52f7eb12015-01-12 17:30:04 +000075
Nils Diewald9fcc1712015-01-09 14:24:32 +000076 if (ref.ldType() === 'docGroup') {
Nils Diewaldd5070b02015-01-11 01:44:47 +000077
78 // Check that the action differs from the type
79 if (ref.operation() === type)
80 return;
81
82 if (parent.ldType() !== null) {
83 return parent.newAfter(ref);
Nils Diewald9fcc1712015-01-09 14:24:32 +000084 }
85 else {
Nils Diewaldd5070b02015-01-11 01:44:47 +000086 // The group is on root - wrap
87 return ref.wrapOnRoot();
88 };
89 }
90 else if (ref.ldType() === 'doc') {
Nils Diewald52f7eb12015-01-12 17:30:04 +000091
92 if (parent.ldType() === null) {
93 return ref.wrapOnRoot(type);
94 }
95 else if (parent.operation() === type) {
Nils Diewaldd5070b02015-01-11 01:44:47 +000096 return parent.newAfter(ref);
97 }
98 else {
99 return ref.wrap(type);
Nils Diewald9fcc1712015-01-09 14:24:32 +0000100 };
Nils Diewaldd599d542015-01-08 20:41:34 +0000101 };
Nils Diewald4019bd22015-01-08 19:57:50 +0000102 };
103
Nils Diewaldd599d542015-01-08 20:41:34 +0000104
Nils Diewalde15b7a22015-01-09 21:50:21 +0000105 // Add doc with 'and' relation
106 KorAP._and = function () {
107 return KorAP._add(this, 'and');
108 };
109
110
111 // Add doc with 'or' relation
112 KorAP._or = function () {
113 return KorAP._add(this, 'or');
114 };
115
Nils Diewald52f7eb12015-01-12 17:30:04 +0000116
Nils Diewald4019bd22015-01-08 19:57:50 +0000117 // Remove doc or docGroup
Nils Diewalde15b7a22015-01-09 21:50:21 +0000118 KorAP._delete = function () {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000119 var ref = this.parentNode.refTo;
Nils Diewald52f7eb12015-01-12 17:30:04 +0000120 if (ref.parent().ldType() !== null) {
121 return ref.parent().delOperand(ref).update();
122 }
123 else {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000124 ref.parent().clean();
Nils Diewald52f7eb12015-01-12 17:30:04 +0000125 };
Nils Diewald4019bd22015-01-08 19:57:50 +0000126 };
127
Nils Diewaldd599d542015-01-08 20:41:34 +0000128
129 /**
130 * Virtual Collection
131 */
Nils Diewald3a2d8022014-12-16 02:45:41 +0000132 KorAP.VirtualCollection = {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000133 ldType : function () {
134 return null;
135 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000136
Nils Diewald3a2d8022014-12-16 02:45:41 +0000137 create : function () {
138 return Object.create(KorAP.VirtualCollection);
139 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000140
Nils Diewald4019bd22015-01-08 19:57:50 +0000141 clean : function () {
142 if (this._root.ldType() !== "non") {
143 this._root.destroy();
144 this.root(KorAP.UnspecifiedDoc.create(this));
145 };
146 return this;
147 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000148
Nils Diewaldd0770492014-12-19 03:55:00 +0000149 render : function (json) {
150 var obj = Object.create(KorAP.VirtualCollection);
151
152 if (json !== undefined) {
153 // Root object
Nils Diewald2fe12e12015-03-06 16:47:06 +0000154 if (json['@type'] == 'koral:doc') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000155 obj._root = KorAP.Doc.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000156 }
Nils Diewald2fe12e12015-03-06 16:47:06 +0000157 else if (json['@type'] == 'koral:docGroup') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000158 obj._root = KorAP.DocGroup.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000159 }
160 else {
161 KorAP.log(813, "Collection type is not supported");
162 return;
163 };
164 }
165
166 else {
167 // Add unspecified object
Nils Diewaldf219eb82015-01-07 20:15:42 +0000168 obj._root = KorAP.UnspecifiedDoc.create(obj);
Nils Diewaldd0770492014-12-19 03:55:00 +0000169 };
170
Nils Diewald8e7182e2015-01-08 15:02:07 +0000171 // Init element and update
172 obj.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000173
174 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000175 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000176
Nils Diewaldf219eb82015-01-07 20:15:42 +0000177 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000178 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000179 var e = this.element();
180 if (e.firstChild !== null) {
Nils Diewaldd5070b02015-01-11 01:44:47 +0000181 if (e.firstChild !== obj.element()) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000182 e.replaceChild(obj.element(), e.firstChild);
Nils Diewaldd5070b02015-01-11 01:44:47 +0000183 };
Nils Diewald8f6b6102015-01-08 18:25:33 +0000184 }
185
186 // Append root element
187 else {
188 e.appendChild(obj.element());
189 };
190
191 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000192 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000193 obj.parent(this);
194
Nils Diewald8e7182e2015-01-08 15:02:07 +0000195 this.update();
196 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000197 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000198 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000199
Nils Diewaldd0770492014-12-19 03:55:00 +0000200 element : function () {
201 if (this._element !== undefined)
202 return this._element;
203
204 this._element = document.createElement('div');
205 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000206
Nils Diewald8f6b6102015-01-08 18:25:33 +0000207 // Initialize root
208 this._element.appendChild(this._root.element());
209
Nils Diewaldd0770492014-12-19 03:55:00 +0000210 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000211 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000212
213 update : function () {
214 this._root.update();
215 return this;
216 },
217
Nils Diewaldf219eb82015-01-07 20:15:42 +0000218 toJson : function () {
219 return this._root.toJson();
220 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000221
222 toQuery : function () {
223 return this._root.toQuery();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000224 }
225 };
226
Nils Diewaldd599d542015-01-08 20:41:34 +0000227
Nils Diewald8f4e2542014-12-19 04:42:09 +0000228 /**
229 * Operators for criteria
230 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000231 KorAP.Operators = {
232 create : function (and, or, del) {
233 var op = Object.create(KorAP.Operators);
234 op.and(and);
235 op.or(or);
236 op.del(del);
237 return op;
238 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000239
Nils Diewaldd0770492014-12-19 03:55:00 +0000240 update : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000241 // Init the element
242 if (this._element === undefined)
243 return this.element();
244
245 var op = this._element;
246
Nils Diewald0297ba12015-01-05 21:56:12 +0000247 op.refTo = this.parent();
248
Nils Diewaldd0770492014-12-19 03:55:00 +0000249 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000250 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000251
252 // Add and button
253 if (this._and === true) {
254 var andE = document.createElement('span');
255 andE.setAttribute('class', 'and');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000256 andE.addEventListener('click', KorAP._and, false);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000257 andE.appendChild(
258 document.createTextNode(KorAP.Locale.AND)
259 );
Nils Diewaldd0770492014-12-19 03:55:00 +0000260 op.appendChild(andE);
261 };
262
263 // Add or button
264 if (this._or === true) {
265 var orE = document.createElement('span');
266 orE.setAttribute('class', 'or');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000267 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000268 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
269 op.appendChild(orE);
270 };
271
272 // Add delete button
273 if (this._del === true) {
274 var delE = document.createElement('span');
275 delE.setAttribute('class', 'delete');
276 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000277 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000278 op.appendChild(delE);
279 };
Nils Diewald966abf12014-12-20 02:27:45 +0000280
281 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000282 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000283
284 // Be aware! This may be cyclic
285 parent : function (obj) {
286 if (arguments.length === 1)
287 this._parent = obj;
288 return this._parent;
289 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000290
Nils Diewaldd0770492014-12-19 03:55:00 +0000291 element : function () {
292
293 // Return existing element
294 if (this._element !== undefined)
295 return this._element;
296
297 this._element = document.createElement('div');
298 this._element.setAttribute('class', 'operators');
299
300 // Init elements
301 this.update();
302 return this._element;
303 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000304
Nils Diewaldd0770492014-12-19 03:55:00 +0000305 and : function (bool) {
306 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000307 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000308 return this._and;
309 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000310
Nils Diewaldd0770492014-12-19 03:55:00 +0000311 or : function (bool) {
312 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000313 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000314 return this._or;
315 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000316
Nils Diewaldd0770492014-12-19 03:55:00 +0000317 del : function (bool) {
318 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000319 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000320 return this._del;
321 }
322 };
323
324
325 /**
326 * Unspecified criterion
327 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000328 KorAP.UnspecifiedDoc = {
Nils Diewald4019bd22015-01-08 19:57:50 +0000329 _ldType : "non",
Nils Diewaldd0770492014-12-19 03:55:00 +0000330 create : function (parent) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000331 var obj = Object.create(KorAP.JsonLD).
332 upgradeTo(KorAP.UnspecifiedDoc);
333
Nils Diewaldd0770492014-12-19 03:55:00 +0000334 if (parent !== undefined)
335 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000336
Nils Diewaldd0770492014-12-19 03:55:00 +0000337 return obj;
338 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000339
Nils Diewaldfda29d92015-01-22 17:28:01 +0000340 // Set key - replace
341 key : function (v) {
342
343 // Not replaceable
344 if (this._parent === undefined)
345 return null;
346
347 // Set JSON-LD type
348 var newDoc = KorAP.Doc.create(this._parent, {
Nils Diewald2fe12e12015-03-06 16:47:06 +0000349 "@type" : "koral:doc",
Nils Diewaldfda29d92015-01-22 17:28:01 +0000350 "value" : "",
351 "key" : v
352 });
353
354 // Unspecified document on root
355 if (this._parent.ldType() === null) {
356 this._parent.root(newDoc);
357 this.destroy();
358 }
359
360 // Unspecified document in group
361 else {
362 this._parent.replaceOperand(this, newDoc);
363 };
364 this._parent.update();
365 return newDoc;
366 },
367
Nils Diewald966abf12014-12-20 02:27:45 +0000368 update : function () {
Nils Diewald4019bd22015-01-08 19:57:50 +0000369
Nils Diewald966abf12014-12-20 02:27:45 +0000370 if (this._element === undefined)
371 return this.element();
372
Nils Diewald8f6b6102015-01-08 18:25:33 +0000373 // Remove element content
Nils Diewald966abf12014-12-20 02:27:45 +0000374 _removeChildren(this._element);
375
376 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000377 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000378 this._element.appendChild(ellipsis);
379
Nils Diewald2fe12e12015-03-06 16:47:06 +0000380 // Set ref - TODO: Cleanup!
381 this._element.refTo = this;
382
Nils Diewald966abf12014-12-20 02:27:45 +0000383 // Set operators
Nils Diewalde15b7a22015-01-09 21:50:21 +0000384 if (this._parent !== undefined && this.parent().ldType() !== null) {
385 var op = this.operators(
386 false,
387 false,
388 true
389 );
Nils Diewald966abf12014-12-20 02:27:45 +0000390
Nils Diewalde15b7a22015-01-09 21:50:21 +0000391 this._element.appendChild(
392 op.element()
393 );
394 };
Nils Diewald966abf12014-12-20 02:27:45 +0000395
Nils Diewald966abf12014-12-20 02:27:45 +0000396 return this.element();
397 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000398
Nils Diewaldd0770492014-12-19 03:55:00 +0000399 element : function () {
400 if (this._element !== undefined)
401 return this._element;
402 this._element = document.createElement('div');
Nils Diewaldd599d542015-01-08 20:41:34 +0000403 this._element.setAttribute('class', 'doc unspecified');
Nils Diewald966abf12014-12-20 02:27:45 +0000404 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000405 return this._element;
Nils Diewaldfda29d92015-01-22 17:28:01 +0000406 },
407
408
Nils Diewaldd0770492014-12-19 03:55:00 +0000409 };
410
411
Nils Diewald8f4e2542014-12-19 04:42:09 +0000412 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000413 * Document criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000414 */
415 KorAP.Doc = {
416 _ldType : "doc",
Nils Diewaldfda29d92015-01-22 17:28:01 +0000417 _obj : function () { return KorAP.Doc },
Nils Diewaldd0770492014-12-19 03:55:00 +0000418
419 create : function (parent, json) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000420 var obj = Object(KorAP.JsonLD).
421 create().
422 upgradeTo(KorAP.Doc).
423 fromJson(json);
424
Nils Diewaldd0770492014-12-19 03:55:00 +0000425 if (parent !== undefined)
426 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000427
Nils Diewald86dad5b2015-01-28 15:09:07 +0000428 obj.__changed = true;
Nils Diewaldd0770492014-12-19 03:55:00 +0000429 return obj;
430 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000431
Nils Diewald966abf12014-12-20 02:27:45 +0000432 update : function () {
433 if (this._element === undefined)
434 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000435
Nils Diewald8f6b6102015-01-08 18:25:33 +0000436 // Get element
Nils Diewald966abf12014-12-20 02:27:45 +0000437 var e = this._element;
438
Nils Diewald2fe12e12015-03-06 16:47:06 +0000439 // Set ref - TODO: Cleanup!
440 e.refTo = this;
441
Nils Diewald8f6b6102015-01-08 18:25:33 +0000442 // Check if there is a change
Nils Diewald86dad5b2015-01-28 15:09:07 +0000443 if (this.__changed) {
444
445 // Was rewritten
446 if (this.rewrites() !== undefined) {
447 e.classList.add("rewritten");
448 };
Nils Diewald966abf12014-12-20 02:27:45 +0000449
Nils Diewald8f6b6102015-01-08 18:25:33 +0000450 // Added key
451 var key = document.createElement('span');
452 key.setAttribute('class', 'key');
Nils Diewald2fe12e12015-03-06 16:47:06 +0000453
454 // Change key
455 key.addEventListener('click', KorAP._changeKey, false);
456
Nils Diewald8f6b6102015-01-08 18:25:33 +0000457 if (this.key())
458 key.appendChild(document.createTextNode(this.key()));
Nils Diewald966abf12014-12-20 02:27:45 +0000459
Nils Diewald8f6b6102015-01-08 18:25:33 +0000460 // Added match operator
461 var matchop = document.createElement('span');
462 matchop.setAttribute('data-type', this.type());
463 matchop.setAttribute('class', 'match');
464 matchop.appendChild(
465 document.createTextNode(this.matchop())
466 );
467
468 // Added match operator
469 var value = document.createElement('span');
470 value.setAttribute('data-type', this.type());
471 value.setAttribute('class', 'value');
472 if (this.value())
473 value.appendChild(
474 document.createTextNode(this.value())
475 );
476
477 // Remove all element children
478 _removeChildren(e);
479
480 // Add spans
481 e.appendChild(key);
482 e.appendChild(matchop);
483 e.appendChild(value);
484
Nils Diewald86dad5b2015-01-28 15:09:07 +0000485 this.__changed = false;
486 };
487
488 if (this._rewrites !== undefined) {
489 e.appendChild(this._rewrites.element());
Nils Diewald8f6b6102015-01-08 18:25:33 +0000490 };
491
492 if (this._parent !== undefined) {
493 // Set operators
494 var op = this.operators(
495 true,
496 true,
Nils Diewald4019bd22015-01-08 19:57:50 +0000497 true
Nils Diewald8f6b6102015-01-08 18:25:33 +0000498 );
499
500 // Append new operators
501 e.appendChild(op.element());
502 };
Nils Diewald966abf12014-12-20 02:27:45 +0000503
Nils Diewaldd0770492014-12-19 03:55:00 +0000504 return e;
505 },
506
Nils Diewald966abf12014-12-20 02:27:45 +0000507 element : function () {
508 if (this._element !== undefined)
509 return this._element;
510
511 this._element = document.createElement('div');
512 this._element.setAttribute('class', 'doc');
513
514 this.update();
515 return this._element;
516 },
517
Nils Diewaldd0770492014-12-19 03:55:00 +0000518 // Wrap a new operation around the doc element
519 wrap : function (op) {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000520 var parent = this.parent();
521 var group = KorAP.DocGroup.create(parent);
522 group.operation(op);
Nils Diewald966abf12014-12-20 02:27:45 +0000523 group.append(this);
Nils Diewald9fcc1712015-01-09 14:24:32 +0000524 group.append();
525 return parent.replaceOperand(this, group).update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000526 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000527
Nils Diewald3a2d8022014-12-16 02:45:41 +0000528 // Deserialize from json
529 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000530 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000531 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000532
Nils Diewald86dad5b2015-01-28 15:09:07 +0000533 if (json["@type"] === undefined) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000534 KorAP.log(701, "JSON-LD group has no @type attribute");
535 return;
536 };
537
Nils Diewald3a2d8022014-12-16 02:45:41 +0000538 if (json["value"] === undefined ||
539 typeof json["value"] != 'string') {
540 KorAP.log(805, "Value is invalid");
541 return;
542 };
543
544 // There is a defined key
545 if (json["key"] !== undefined &&
546 typeof json["key"] === 'string') {
547
548 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000549 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000550
551 // Set match operation
552 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000553 if (typeof json["match"] === 'string') {
554 this.matchop(json["match"]);
555 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000556 else {
557 KorAP.log(802, "Match type is not supported by value type");
558 return;
559 };
560 };
561
562 // Key is a string
563 if (json["type"] === undefined ||
564 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000565 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000566
567 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000568 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000569 KorAP.log(802, "Match type is not supported by value type");
570 return;
571 };
572
573 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000574 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000575 }
576
577 // Key is a date
578 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000579 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000580
581 if (json["value"] !== undefined &&
582 KorAP._validDateRE.test(json["value"])) {
583
Nils Diewaldd0770492014-12-19 03:55:00 +0000584 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000585 KorAP.log(802, "Match type is not supported by value type");
586 return;
587 };
588
589 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000590 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000591 }
592 else {
593 KorAP.log(806, "Value is not a valid date string");
594 return;
595 };
596 }
597
598 // Key is a regular expression
599 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000600 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000601
602 try {
603
604 // Try to create a regular expression
605 var check = new RegExp(json["value"]);
606
Nils Diewaldd0770492014-12-19 03:55:00 +0000607 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000608 KorAP.log(802, "Match type is not supported by value type");
609 return;
610 };
611
Nils Diewaldd0770492014-12-19 03:55:00 +0000612 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000613 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000614
Nils Diewald3a2d8022014-12-16 02:45:41 +0000615 catch (e) {
616 KorAP.log(807, "Value is not a valid regular expression");
617 return;
618 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000619 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000620 }
621
622 else {
623 KorAP.log(804, "Unknown value type");
624 return;
625 };
Nils Diewald86dad5b2015-01-28 15:09:07 +0000626
Nils Diewald3a2d8022014-12-16 02:45:41 +0000627 };
628
Nils Diewald86dad5b2015-01-28 15:09:07 +0000629 if (json["rewrites"] !== undefined) {
630 this._rewrites = KorAP.RewriteList.create(json["rewrites"]);
631 };
632
Nils Diewald3a2d8022014-12-16 02:45:41 +0000633 return this;
634 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000635
Nils Diewaldd0770492014-12-19 03:55:00 +0000636 key : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000637 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000638 this._key = value;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000639 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000640 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000641 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000642 return this._key;
643 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000644
Nils Diewaldd0770492014-12-19 03:55:00 +0000645 matchop : function (match) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000646 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000647 this._matchop = match.replace(/^match:/, '');
Nils Diewald86dad5b2015-01-28 15:09:07 +0000648 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000649 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000650 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000651 return this._matchop || "eq";
652 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000653
Nils Diewaldd0770492014-12-19 03:55:00 +0000654 type : function (type) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000655 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000656 this._type = type;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000657 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000658 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000659 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000660 return this._type || "string";
661 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000662
Nils Diewaldd0770492014-12-19 03:55:00 +0000663 value : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000664 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000665 this._value = value;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000666 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000667 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000668 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000669 return this._value;
670 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000671
Nils Diewald86dad5b2015-01-28 15:09:07 +0000672 rewrites : function () {
673 return this._rewrites;
674 },
675
676 _changed : function () {
677 this.__changed = true;
678
679 if (this._rewrites === undefined)
680 return;
681 delete this["_rewrites"];
682 if (this._element === undefined)
683 return;
684 this._element.classList.remove("rewritten");
685 },
686
Nils Diewald3a2d8022014-12-16 02:45:41 +0000687 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000688 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000689 return {};
690
691 return {
Nils Diewald2fe12e12015-03-06 16:47:06 +0000692 "@type" : "koral:" + this.ldType(),
Nils Diewaldd0770492014-12-19 03:55:00 +0000693 "key" : this.key(),
694 "match" : "match:" + this.matchop(),
695 "value" : this.value() || '',
696 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000697 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000698 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000699
700 toQuery : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000701 if (!this.matchop() || !this.key())
702 return "";
703
704 // Build doc string based on key
705 var string = this.key() + ' ';
706
707 // Add match operator
708 switch (this.matchop()) {
709 case "ne":
710 string += '!=';
711 break;
712 case "contains":
713 string += '~';
714 break;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000715 case "excludes":
716 string += '!~';
717 break;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000718 case "geq":
719 string += 'since';
720 break;
721 case "leq":
722 string += 'until';
723 break;
724 default:
725 string += (this.type() == 'date') ? 'in' : '=';
726 break;
727 };
728
729 string += ' ';
730
731 // Add value
732 switch (this.type()) {
733 case "date":
734 return string + this.value();
735 break;
736 case "regex":
737 return string + '/' + this.value() + '/';
738 break;
739 case "string":
740 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
741 break;
742 };
743
Nils Diewaldd599d542015-01-08 20:41:34 +0000744 return "";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000745 }
746 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000747
Nils Diewaldd599d542015-01-08 20:41:34 +0000748
Nils Diewald8f4e2542014-12-19 04:42:09 +0000749 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000750 * Document group criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000751 */
752 KorAP.DocGroup = {
753 _ldType : "docGroup",
754
755 create : function (parent, json) {
756 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
757 obj._operands = [];
758 obj.fromJson(json);
759 if (parent !== undefined)
760 obj._parent = parent;
761 return obj;
762 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000763
764 newAfter : function (obj) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000765 for (var i = 0; i < this._operands.length; i++) {
Nils Diewaldd599d542015-01-08 20:41:34 +0000766 if (this._operands[i] === obj) {
767 var operand = KorAP.UnspecifiedDoc.create(this);
768 this._operands.splice(i + 1, 0, operand);
769 return this.update();
770 };
771 };
772 },
773
Nils Diewald86dad5b2015-01-28 15:09:07 +0000774 // The doc is already set in the group
775 _duplicate : function (operand) {
776 if (operand.ldType() !== 'doc')
777 return null;
778
779 for (var i = 0; i < this._operands.length; i++) {
780 var op = this.getOperand(i);
781 if (op.ldType() === 'doc'
782 && operand.key() === op.key()
783 && operand.matchop() === op.matchop()
784 && operand.value() === op.value()) {
785 return op;
786 };
787 };
788 return null;
789 },
790
Nils Diewald966abf12014-12-20 02:27:45 +0000791 append : function (operand) {
792
793 // Append unspecified object
794 if (operand === undefined) {
795
796 // Be aware of cyclic structures!
797 operand = KorAP.UnspecifiedDoc.create(this);
798 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000799 return operand;
800 };
801
Nils Diewald8f4e2542014-12-19 04:42:09 +0000802 switch (operand["@type"]) {
Nils Diewald86dad5b2015-01-28 15:09:07 +0000803
Nils Diewald8f4e2542014-12-19 04:42:09 +0000804 case undefined:
Nils Diewald86dad5b2015-01-28 15:09:07 +0000805 // No @type defined
Nils Diewald8f4e2542014-12-19 04:42:09 +0000806 if (operand["ldType"] !== undefined) {
807 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000808 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000809 KorAP.log(812, "Operand not supported in document group");
810 return;
811 };
Nils Diewald966abf12014-12-20 02:27:45 +0000812 // Be aware of cyclic structures!
813 operand.parent(this);
Nils Diewald86dad5b2015-01-28 15:09:07 +0000814
815 var dupl = this._duplicate(operand);
816 if (dupl === null) {
817 this._operands.push(operand);
818 return operand;
819 };
820 return dupl;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000821 };
822
823 KorAP.log(701, "JSON-LD group has no @type attribute");
824 return;
825
Nils Diewald2fe12e12015-03-06 16:47:06 +0000826 case "koral:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000827 // Be aware of cyclic structures!
828 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000829 if (doc === undefined)
830 return;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000831 var dupl = this._duplicate(doc);
832 if (dupl === null) {
833 this._operands.push(doc);
834 return doc;
835 };
836 return dupl;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000837
Nils Diewald2fe12e12015-03-06 16:47:06 +0000838 case "koral:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000839 // Be aware of cyclic structures!
840 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000841 if (docGroup === undefined)
842 return;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000843
844 // Flatten group
845 if (docGroup.operation() === this.operation()) {
846 for (var op in docGroup.operands()) {
847 op = docGroup.getOperand(op);
848 var dupl = this._duplicate(op);
849 if (dupl === null) {
850 this._operands.push(op);
851 op.parent(this);
852 };
853 };
854 docGroup._operands = [];
855 docGroup.destroy();
856 return this;
857 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000858 this._operands.push(docGroup);
859 return docGroup;
860
861 default:
862 KorAP.log(812, "Operand not supported in document group");
863 return;
864 };
865 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000866
Nils Diewald966abf12014-12-20 02:27:45 +0000867 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000868 // There is only one operand in group
Nils Diewald52f7eb12015-01-12 17:30:04 +0000869
Nils Diewaldf219eb82015-01-07 20:15:42 +0000870 if (this._operands.length === 1) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000871
Nils Diewaldf219eb82015-01-07 20:15:42 +0000872 var parent = this.parent();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000873 var op = this.getOperand(0);
874
Nils Diewald8f6b6102015-01-08 18:25:33 +0000875 // This will prevent destruction of
876 // the operand
877 this._operands = [];
Nils Diewaldf219eb82015-01-07 20:15:42 +0000878
879 // Parent is a group
Nils Diewald52f7eb12015-01-12 17:30:04 +0000880 if (parent.ldType() !== null)
Nils Diewald8e7182e2015-01-08 15:02:07 +0000881 return parent.replaceOperand(this, op).update();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000882
Nils Diewald8f6b6102015-01-08 18:25:33 +0000883 // Parent is vc
Nils Diewaldf219eb82015-01-07 20:15:42 +0000884 else {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000885 this.destroy();
Nils Diewald8f6b6102015-01-08 18:25:33 +0000886 // Cyclic madness
887 parent.root(op);
888 op.parent(parent);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000889 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000890 };
891 };
892
Nils Diewald966abf12014-12-20 02:27:45 +0000893 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000894 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000895
Nils Diewald5c817a42015-01-06 01:08:56 +0000896 var group = this._element;
897 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000898
Nils Diewald5c817a42015-01-06 01:08:56 +0000899 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000900
901 // Append operands
Nils Diewald52f7eb12015-01-12 17:30:04 +0000902 for (var i = 0; i < this._operands.length; i++) {
Nils Diewald5c817a42015-01-06 01:08:56 +0000903 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000904 this.getOperand(i).element()
905 );
906 };
907
908 // Set operators
909 var op = this.operators(
910 this.operation() == 'and' ? false : true,
911 this.operation() == 'or' ? false : true,
912 true
913 );
914
Nils Diewald5c817a42015-01-06 01:08:56 +0000915 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000916 op.element()
917 );
918
Nils Diewald5c817a42015-01-06 01:08:56 +0000919 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000920 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000921
Nils Diewald8f4e2542014-12-19 04:42:09 +0000922 element : function () {
923 if (this._element !== undefined)
924 return this._element;
925
926 this._element = document.createElement('div');
927 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000928
Nils Diewaldf219eb82015-01-07 20:15:42 +0000929 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000930 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000931
932 return this._element;
933 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000934
Nils Diewald8f4e2542014-12-19 04:42:09 +0000935 operation : function (op) {
936 if (arguments.length === 1) {
937 if (KorAP._validGroupOpRE.test(op)) {
938 this._op = op;
939 }
940 else {
941 KorAP.log(810, "Unknown operation type");
942 return;
943 };
944 };
945 return this._op || 'and';
946 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000947
Nils Diewald8f4e2542014-12-19 04:42:09 +0000948 operands : function () {
949 return this._operands;
950 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000951
Nils Diewald8f4e2542014-12-19 04:42:09 +0000952 getOperand : function (index) {
953 return this._operands[index];
954 },
955
Nils Diewald5c817a42015-01-06 01:08:56 +0000956 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000957 replaceOperand : function (oldOp, newOp) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000958
959 for (var i = 0; i < this._operands.length; i++) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000960 if (this._operands[i] === oldOp) {
961
Nils Diewalde15b7a22015-01-09 21:50:21 +0000962 // Just insert a doc or ...
963 if (newOp.ldType() === "doc" ||
Nils Diewald52f7eb12015-01-12 17:30:04 +0000964 newOp.ldType() === "non" ||
Nils Diewalde15b7a22015-01-09 21:50:21 +0000965 // ... insert a group of a different operation
966 // (i.e. "and" in "or"/"or" in "and")
967 newOp.operation() != this.operation()) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000968 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000969 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000970 }
971
Nils Diewald86dad5b2015-01-28 15:09:07 +0000972 // Flatten group
Nils Diewaldf219eb82015-01-07 20:15:42 +0000973 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000974 // Remove old group
975 this._operands.splice(i, 1);
976
977 // Inject new operands
Nils Diewald8f6b6102015-01-08 18:25:33 +0000978 for (var op in newOp.operands().reverse()) {
Nils Diewald86dad5b2015-01-28 15:09:07 +0000979 op = newOp.getOperand(op);
980 this._operands.splice(i, 0, op);
981 op.parent(this);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000982 };
983 // Prevent destruction of operands
984 newOp._operands = [];
985 newOp.destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000986 };
987 oldOp.destroy();
988 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000989 }
990 };
991 return false;
992 },
993
Nils Diewald0297ba12015-01-05 21:56:12 +0000994 // Delete operand from group
995 delOperand : function (obj) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000996 for (var i = 0; i < this._operands.length; i++) {
Nils Diewald0297ba12015-01-05 21:56:12 +0000997 if (this._operands[i] === obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000998
Nils Diewald8f6b6102015-01-08 18:25:33 +0000999 // Delete identified operand
Nils Diewald0297ba12015-01-05 21:56:12 +00001000 this._operands.splice(i,1);
1001
Nils Diewald5c817a42015-01-06 01:08:56 +00001002 // Destroy object for cyclic references
1003 obj.destroy();
1004
Nils Diewaldf219eb82015-01-07 20:15:42 +00001005 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +00001006 };
1007 };
Nils Diewald5c817a42015-01-06 01:08:56 +00001008
1009 // Operand not found
1010 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +00001011 },
1012
Nils Diewald8f4e2542014-12-19 04:42:09 +00001013 // Deserialize from json
1014 fromJson : function (json) {
1015 if (json === undefined)
1016 return this;
1017
Nils Diewald86dad5b2015-01-28 15:09:07 +00001018 if (json["@type"] === undefined) {
Nils Diewald8f4e2542014-12-19 04:42:09 +00001019 KorAP.log(701, "JSON-LD group has no @type attribute");
1020 return;
1021 };
1022
1023 if (json["operation"] === undefined ||
1024 typeof json["operation"] !== 'string') {
1025 KorAP.log(811, "Document group expects operation");
1026 return;
1027 };
1028
1029 var operation = json["operation"];
1030
1031 this.operation(operation.replace(/^operation:/,''));
1032
1033 if (json["operands"] === undefined ||
1034 !(json["operands"] instanceof Array)) {
1035 KorAP.log(704, "Operation needs operand list")
1036 return;
1037 };
1038
1039 // Add all documents
1040 for (var i in json["operands"]) {
1041 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +00001042 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +00001043 };
1044
1045 return this;
1046 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001047
Nils Diewald8f4e2542014-12-19 04:42:09 +00001048 toJson : function () {
1049 var opArray = new Array();
Nils Diewald52f7eb12015-01-12 17:30:04 +00001050 for (var i = 0; i < this._operands.length; i++) {
Nils Diewalde15b7a22015-01-09 21:50:21 +00001051 if (this._operands[i].ldType() !== 'non')
1052 opArray.push(this._operands[i].toJson());
Nils Diewald8f4e2542014-12-19 04:42:09 +00001053 };
1054 return {
Nils Diewald2fe12e12015-03-06 16:47:06 +00001055 "@type" : "koral:" + this.ldType(),
Nils Diewald8f4e2542014-12-19 04:42:09 +00001056 "operation" : "operation:" + this.operation(),
1057 "operands" : opArray
1058 };
Nils Diewaldf219eb82015-01-07 20:15:42 +00001059 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001060
Nils Diewalde15b7a22015-01-09 21:50:21 +00001061 toQuery : function (brackets) {
1062 var list = this._operands
1063 .filter(function (op) {
1064 return op.ldType() !== 'non';
1065 })
1066 .map(function (op) {
Nils Diewaldd599d542015-01-08 20:41:34 +00001067 return (op.ldType() === 'docGroup') ?
Nils Diewalde15b7a22015-01-09 21:50:21 +00001068 op.toQuery(true) :
Nils Diewaldd599d542015-01-08 20:41:34 +00001069 op.toQuery();
Nils Diewalde15b7a22015-01-09 21:50:21 +00001070 });
1071
1072 if (list.length === 1)
1073 return list.join('');
1074 else {
1075 var str = list.join(this.operation() === 'or' ? ' | ' : ' & ');
1076 return brackets ? '(' + str + ')' : str;
1077 };
Nils Diewald8f4e2542014-12-19 04:42:09 +00001078 }
1079 };
1080
1081
Nils Diewald86dad5b2015-01-28 15:09:07 +00001082 KorAP.RewriteList = {
1083 // Construction method
1084 create : function (json) {
1085 var obj = Object(KorAP.JsonLD).
1086 create().
1087 upgradeTo(KorAP.RewriteList).
1088 fromJson(json);
1089 return obj;
1090 },
1091 fromJson : function (json) {
1092 this._list = new Array();
1093 for (var i = 0; i < json.length; i++) {
1094 this._list.push(
1095 KorAP.Rewrite.create(json[i])
1096 );
1097 };
1098 return this;
1099 },
1100 element : function () {
1101 if (this._element !== undefined)
1102 return this._element;
1103
1104 this._element = document.createElement('div');
1105 this._element.setAttribute('class', 'rewrite');
1106 for (var x in this._list) {
1107 var rewrite = this._list[x];
1108 var span = document.createElement('span');
1109
1110 // Set class attribute
1111 span.setAttribute('class', rewrite.operation());
1112
1113 // Append source information
1114 span.appendChild(document.createTextNode(rewrite.src()));
1115
1116 // Append scope information
1117 if (rewrite.scope() !== undefined) {
1118 span.appendChild(
1119 document.createTextNode(
1120 ': ' + rewrite.scope()
1121 )
1122 );
1123 };
1124 this._element.appendChild(span);
1125 };
1126 return this._element;
1127 }
1128 };
1129
1130
1131 /**
1132 * Implementation of rewrite objects.
1133 */
1134 KorAP.Rewrite = {
1135
1136 // Construction method
1137 create : function (json) {
1138 var obj = Object(KorAP.JsonLD).
1139 create().
1140 upgradeTo(KorAP.Rewrite).
1141 fromJson(json);
1142 return obj;
1143 },
1144
1145 // Get or set source
1146 src : function (string) {
1147 if (arguments.length === 1)
1148 this._src = string;
1149 return this._src;
1150 },
1151
1152 // Get or set operation
1153 operation : function (op) {
1154 if (arguments.length === 1) {
1155 if (KorAP._validRewriteOpRE.test(op)) {
1156 this._op = op;
1157 }
1158 else {
1159 KorAP.log(814, "Unknown rewrite operation");
1160 return;
1161 };
1162 };
1163 return this._op || 'injection';
1164 },
1165
1166 // Get or set scope
1167 scope : function (attr) {
1168 if (arguments.length === 1)
1169 this._scope = attr;
1170 return this._scope;
1171 },
1172
1173 // Serialize from Json
1174 fromJson : function (json) {
1175 if (json === undefined)
1176 return this;
1177
1178 // Missing @type
1179 if (json["@type"] === undefined) {
1180 KorAP.log(701, "JSON-LD group has no @type attribute");
1181 return;
1182 };
1183
1184 // Missing source
1185 if (json["src"] === undefined ||
1186 typeof json["src"] !== 'string') {
1187 KorAP.log(815, "Rewrite expects source");
1188 return;
1189 };
1190
1191 // Set source
1192 this.src(json["src"]);
1193
1194 // Set operation
1195 if (json["operation"] !== undefined) {
1196 var operation = json["operation"];
1197 this.operation(operation.replace(/^operation:/,''));
1198 };
1199
1200 // Set scope
1201 if (json["scope"] !== undefined &&
1202 typeof json["scope"] === 'string')
1203 this.scope(json["scope"]);
1204
1205 return this;
1206 },
1207
1208 toString : function () {
1209 var str = '';
1210 var op = this.operation();
1211 str += op.charAt(0).toUpperCase() + op.slice(1);
1212 str += ' of ' + (
1213 this._scope === null ?
1214 'object' :
1215 '"' +
1216 this.scope().replace(KorAP._quote, '\\$1') +
1217 '"'
1218 );
1219 str += ' by ' +
1220 '"' +
1221 this.src().replace(KorAP._quote, '\\$1') +
1222 '"';
1223 return str;
1224 }
1225 };
1226
1227
Nils Diewaldd599d542015-01-08 20:41:34 +00001228 /**
1229 * Abstract JsonLD criterion object
1230 */
Nils Diewald8f4e2542014-12-19 04:42:09 +00001231 KorAP.JsonLD = {
Nils Diewald86dad5b2015-01-28 15:09:07 +00001232 __changed : false,
Nils Diewald8f6b6102015-01-08 18:25:33 +00001233
Nils Diewald8f4e2542014-12-19 04:42:09 +00001234 create : function () {
1235 return Object.create(KorAP.JsonLD);
1236 },
1237
1238 /**
1239 * Upgrade this object to another object
1240 * while private data stays intact
1241 */
1242 upgradeTo : function (props) {
1243 for (var prop in props) {
1244 this[prop] = props[prop];
1245 };
1246 return this;
1247 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001248
Nils Diewald8f4e2542014-12-19 04:42:09 +00001249 ldType : function (type) {
1250 if (arguments.length === 1)
1251 this._ldType = type;
1252 return this._ldType;
1253 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001254
Nils Diewald8f4e2542014-12-19 04:42:09 +00001255 parent : function (obj) {
Nils Diewald8f6b6102015-01-08 18:25:33 +00001256 if (arguments.length === 1) {
Nils Diewald8f4e2542014-12-19 04:42:09 +00001257 this._parent = obj;
Nils Diewald86dad5b2015-01-28 15:09:07 +00001258 this.__changed = true;
Nils Diewald8f6b6102015-01-08 18:25:33 +00001259 };
Nils Diewald8f4e2542014-12-19 04:42:09 +00001260 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +00001261 },
Nils Diewald0297ba12015-01-05 21:56:12 +00001262
Nils Diewald5c817a42015-01-06 01:08:56 +00001263 // Destroy object - especially for
1264 // acyclic structures!
Nils Diewald86dad5b2015-01-28 15:09:07 +00001265 // I'm paranoid!
Nils Diewald5c817a42015-01-06 01:08:56 +00001266 destroy : function () {
1267 if (this._ops != undefined) {
1268 this._ops._parent = undefined;
1269 if (this._ops._element !== undefined)
1270 this._ops._element.refTo = undefined;
1271 this._ops = undefined;
1272 };
1273 if (this._element !== undefined)
1274 this._element = undefined;
1275
1276 // In case of a group, destroy all operands
1277 if (this._operands !== undefined) {
Nils Diewald52f7eb12015-01-12 17:30:04 +00001278 for (var i = 0; i < this._operands.length; i++)
Nils Diewald5c817a42015-01-06 01:08:56 +00001279 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +00001280 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +00001281 };
1282 },
1283
Nils Diewald52f7eb12015-01-12 17:30:04 +00001284 // Wrap a new operation around the root group element
1285 wrapOnRoot : function (op) {
1286 var parent = this.parent();
1287
1288 var group = KorAP.DocGroup.create(parent);
1289 if (arguments.length === 1)
1290 group.operation(op);
1291 else
1292 group.operation(
1293 this.operation() === 'and' ? 'or' : 'and'
1294 );
1295 group.append(this);
1296 this.parent(group);
1297 group.append();
1298 group.element(); // Init (seems to be necessary)
1299 parent.root(group);
1300 return this.parent();
1301 },
1302
Nils Diewald0297ba12015-01-05 21:56:12 +00001303 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +00001304 operators : function (and, or, del) {
1305 if (arguments === 0)
1306 return this._ops;
1307 this._ops = KorAP.Operators.create(
1308 and, or, del
1309 );
Nils Diewald0297ba12015-01-05 21:56:12 +00001310 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +00001311 return this._ops;
1312 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001313
Nils Diewald966abf12014-12-20 02:27:45 +00001314 toJson : function () {
1315 return {
1316 // Unspecified object
Nils Diewald2fe12e12015-03-06 16:47:06 +00001317 "@type" : "koral:" + this.ldType()
Nils Diewald966abf12014-12-20 02:27:45 +00001318 };
Nils Diewald8f6b6102015-01-08 18:25:33 +00001319 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001320
1321 toQuery : function () {
Nils Diewaldfda29d92015-01-22 17:28:01 +00001322 return '';
Nils Diewald8f4e2542014-12-19 04:42:09 +00001323 }
1324 };
Nils Diewald2fe12e12015-03-06 16:47:06 +00001325
1326
1327 /**
1328 * Criterion in a KorAP.Doc
1329 */
1330 KorAP._changeKey = function () {
1331 var doc = this.parentNode.refTo;
Nils Diewaldd2b57372015-03-10 20:09:48 +00001332 var key = doc.element().firstChild;
1333 key.appendChild(KorAP.FieldChooser.element());
1334 KorAP.FieldChooser.show();
1335 KorAP.FieldChooser.focus();
Nils Diewald2fe12e12015-03-06 16:47:06 +00001336 // key, matchop, type, value
1337 };
1338
Nils Diewald2fe12e12015-03-06 16:47:06 +00001339 // Field menu
1340 KorAP.FieldMenu = {
1341 create : function (params) {
1342 return Object.create(KorAP.Menu)
1343 .upgradeTo(KorAP.FieldMenu)
Nils Diewaldd2b57372015-03-10 20:09:48 +00001344 ._init(KorAP.FieldMenuItem, undefined, params)
Nils Diewald2fe12e12015-03-06 16:47:06 +00001345 }
1346 };
1347
1348
1349 // Field menu item
1350 KorAP.FieldMenuItem = {
1351 create : function (params) {
1352 return Object.create(KorAP.MenuItem)
1353 .upgradeTo(KorAP.FieldMenuItem)
1354 ._init(params);
1355 },
1356 _init : function (params) {
1357 if (params[0] === undefined)
1358 throw new Error("Missing parameters");
1359
1360 this._name = params[0];
1361 this._value = params[1];
1362 this._type = params[2];
1363
1364 this._lcField = ' ' + this._name.toLowerCase();
1365
1366 return this;
1367 },
1368 name : function () {
1369 return this._name;
1370 },
1371 type : function () {
1372 return this._type;
1373 },
1374 element : function () {
1375 // already defined
1376 if (this._element !== undefined)
1377 return this._element;
1378
1379 // Create list item
1380 var li = document.createElement("li");
1381 li.setAttribute("data-type", this._type);
1382 li.setAttribute("data-value", this._value);
1383 li.appendChild(document.createTextNode(this._name));
1384 return this._element = li;
1385 }
1386 };
Nils Diewaldd2b57372015-03-10 20:09:48 +00001387
1388 KorAP.FieldChooser = KorAP.FieldMenu.create([
1389 ['Titel', 'title', 'string'],
1390 ['Untertitel', 'subTitle', 'string'],
1391 ['Veröffentlichungsdatum', 'pubDate', 'date'],
1392 ['Autor', 'author', 'string']
1393 ]);
1394 KorAP.FieldChooser.limit(5);
Nils Diewald8f4e2542014-12-19 04:42:09 +00001395
Nils Diewald3a2d8022014-12-16 02:45:41 +00001396}(this.KorAP));