blob: d226fc46d43f481eee2b95c8fb814e68751bc8fc [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 */
6
Nils Diewald3a2d8022014-12-16 02:45:41 +00007var KorAP = KorAP || {};
Nils Diewald3a2d8022014-12-16 02:45:41 +00008
Nils Diewaldd0770492014-12-19 03:55:00 +00009/*
Nils Diewald86dad5b2015-01-28 15:09:07 +000010 TODO: Implement a working localization solution!
11 TODO: Disable "and" or "or" in case it's followed
12 by an unspecified document
13
Nils Diewaldd599d542015-01-08 20:41:34 +000014 Error codes:
Nils Diewaldd0770492014-12-19 03:55:00 +000015 701: "JSON-LD group has no @type attribute"
16 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000017 802: "Match type is not supported by value type"
18 804: "Unknown value type"
19 805: "Value is invalid"
20 806: "Value is not a valid date string"
21 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000022 810: "Unknown document group operation" (like 711)
23 811: "Document group expects operation" (like 703)
24 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000025 813: "Collection type is not supported" (like 713)
Nils Diewald86dad5b2015-01-28 15:09:07 +000026 814: "Unknown rewrite operation"
27 815: "Rewrite expects source"
Nils Diewaldd0770492014-12-19 03:55:00 +000028*/
29
Nils Diewald3a2d8022014-12-16 02:45:41 +000030(function (KorAP) {
31 "use strict";
32
33 // Default log message
34 KorAP.log = KorAP.log || function (type, msg) {
35 console.log(type + ": " + msg);
36 };
37
Nils Diewald86dad5b2015-01-28 15:09:07 +000038 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains|excludes)$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000039 KorAP._validRegexMatchRE = new RegExp("^(?:eq|ne)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000040 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000041 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
42 KorAP._validGroupOpRE = new RegExp("^(?:and|or)$");
Nils Diewald86dad5b2015-01-28 15:09:07 +000043 KorAP._validRewriteOpRE = new RegExp("^(?:injec|modifica)tion$");
Nils Diewaldf219eb82015-01-07 20:15:42 +000044 KorAP._quote = new RegExp("([\"\\\\])", 'g');
Nils Diewald3a2d8022014-12-16 02:45:41 +000045
Nils Diewalde15b7a22015-01-09 21:50:21 +000046 // Localization values
Nils Diewaldf219eb82015-01-07 20:15:42 +000047 var loc = (KorAP.Locale = KorAP.Locale || {} );
48 loc.AND = loc.AND || 'and';
49 loc.OR = loc.OR || 'or';
50 loc.DEL = loc.DEL || '×';
51 loc.EMPTY = loc.EMPTY || '⋯'
Nils Diewaldd0770492014-12-19 03:55:00 +000052
Nils Diewaldd599d542015-01-08 20:41:34 +000053
Nils Diewalde15b7a22015-01-09 21:50:21 +000054 // Utility for analysing boolean values
Nils Diewald966abf12014-12-20 02:27:45 +000055 function _bool (bool) {
Nils Diewalde15b7a22015-01-09 21:50:21 +000056 return (bool === undefined || bool === null || bool === false) ? false : true;
Nils Diewald966abf12014-12-20 02:27:45 +000057 };
58
Nils Diewaldd599d542015-01-08 20:41:34 +000059
Nils Diewalde15b7a22015-01-09 21:50:21 +000060 // Utility for removing all children of a node
Nils Diewald966abf12014-12-20 02:27:45 +000061 function _removeChildren (node) {
62 // Remove everything underneath
Nils Diewald8f6b6102015-01-08 18:25:33 +000063 while (node.firstChild)
Nils Diewald966abf12014-12-20 02:27:45 +000064 node.removeChild(node.firstChild);
Nils Diewald966abf12014-12-20 02:27:45 +000065 };
66
Nils Diewald4019bd22015-01-08 19:57:50 +000067
Nils Diewald52f7eb12015-01-12 17:30:04 +000068 // Add new unspecified document
Nils Diewald9fcc1712015-01-09 14:24:32 +000069 KorAP._add = function (obj, type) {
70 var ref = obj.parentNode.refTo;
Nils Diewaldd5070b02015-01-11 01:44:47 +000071 var parent = ref.parent();
Nils Diewald52f7eb12015-01-12 17:30:04 +000072
Nils Diewald9fcc1712015-01-09 14:24:32 +000073 if (ref.ldType() === 'docGroup') {
Nils Diewaldd5070b02015-01-11 01:44:47 +000074
75 // Check that the action differs from the type
76 if (ref.operation() === type)
77 return;
78
79 if (parent.ldType() !== null) {
80 return parent.newAfter(ref);
Nils Diewald9fcc1712015-01-09 14:24:32 +000081 }
82 else {
Nils Diewaldd5070b02015-01-11 01:44:47 +000083 // The group is on root - wrap
84 return ref.wrapOnRoot();
85 };
86 }
87 else if (ref.ldType() === 'doc') {
Nils Diewald52f7eb12015-01-12 17:30:04 +000088
89 if (parent.ldType() === null) {
90 return ref.wrapOnRoot(type);
91 }
92 else if (parent.operation() === type) {
Nils Diewaldd5070b02015-01-11 01:44:47 +000093 return parent.newAfter(ref);
94 }
95 else {
96 return ref.wrap(type);
Nils Diewald9fcc1712015-01-09 14:24:32 +000097 };
Nils Diewaldd599d542015-01-08 20:41:34 +000098 };
Nils Diewald4019bd22015-01-08 19:57:50 +000099 };
100
Nils Diewaldd599d542015-01-08 20:41:34 +0000101
Nils Diewalde15b7a22015-01-09 21:50:21 +0000102 // Add doc with 'and' relation
103 KorAP._and = function () {
104 return KorAP._add(this, 'and');
105 };
106
107
108 // Add doc with 'or' relation
109 KorAP._or = function () {
110 return KorAP._add(this, 'or');
111 };
112
Nils Diewald52f7eb12015-01-12 17:30:04 +0000113
Nils Diewald4019bd22015-01-08 19:57:50 +0000114 // Remove doc or docGroup
Nils Diewalde15b7a22015-01-09 21:50:21 +0000115 KorAP._delete = function () {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000116 var ref = this.parentNode.refTo;
Nils Diewald52f7eb12015-01-12 17:30:04 +0000117 if (ref.parent().ldType() !== null) {
118 return ref.parent().delOperand(ref).update();
119 }
120 else {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000121 ref.parent().clean();
Nils Diewald52f7eb12015-01-12 17:30:04 +0000122 };
Nils Diewald4019bd22015-01-08 19:57:50 +0000123 };
124
Nils Diewaldd599d542015-01-08 20:41:34 +0000125
126 /**
127 * Virtual Collection
128 */
Nils Diewald3a2d8022014-12-16 02:45:41 +0000129 KorAP.VirtualCollection = {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000130 ldType : function () {
131 return null;
132 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000133
Nils Diewald3a2d8022014-12-16 02:45:41 +0000134 create : function () {
135 return Object.create(KorAP.VirtualCollection);
136 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000137
Nils Diewald4019bd22015-01-08 19:57:50 +0000138 clean : function () {
139 if (this._root.ldType() !== "non") {
140 this._root.destroy();
141 this.root(KorAP.UnspecifiedDoc.create(this));
142 };
143 return this;
144 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000145
Nils Diewaldd0770492014-12-19 03:55:00 +0000146 render : function (json) {
147 var obj = Object.create(KorAP.VirtualCollection);
148
149 if (json !== undefined) {
150 // Root object
151 if (json['@type'] == 'korap:doc') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000152 obj._root = KorAP.Doc.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000153 }
154 else if (json['@type'] == 'korap:docGroup') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000155 obj._root = KorAP.DocGroup.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000156 }
157 else {
158 KorAP.log(813, "Collection type is not supported");
159 return;
160 };
161 }
162
163 else {
164 // Add unspecified object
Nils Diewaldf219eb82015-01-07 20:15:42 +0000165 obj._root = KorAP.UnspecifiedDoc.create(obj);
Nils Diewaldd0770492014-12-19 03:55:00 +0000166 };
167
Nils Diewald8e7182e2015-01-08 15:02:07 +0000168 // Init element and update
169 obj.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000170
171 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000172 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000173
Nils Diewaldf219eb82015-01-07 20:15:42 +0000174 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000175 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000176 var e = this.element();
177 if (e.firstChild !== null) {
Nils Diewaldd5070b02015-01-11 01:44:47 +0000178 if (e.firstChild !== obj.element()) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000179 e.replaceChild(obj.element(), e.firstChild);
Nils Diewaldd5070b02015-01-11 01:44:47 +0000180 };
Nils Diewald8f6b6102015-01-08 18:25:33 +0000181 }
182
183 // Append root element
184 else {
185 e.appendChild(obj.element());
186 };
187
188 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000189 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000190 obj.parent(this);
191
Nils Diewald8e7182e2015-01-08 15:02:07 +0000192 this.update();
193 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000194 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000195 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000196
Nils Diewaldd0770492014-12-19 03:55:00 +0000197 element : function () {
198 if (this._element !== undefined)
199 return this._element;
200
201 this._element = document.createElement('div');
202 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000203
Nils Diewald8f6b6102015-01-08 18:25:33 +0000204 // Initialize root
205 this._element.appendChild(this._root.element());
206
Nils Diewaldd0770492014-12-19 03:55:00 +0000207 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000208 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000209
210 update : function () {
211 this._root.update();
212 return this;
213 },
214
Nils Diewaldf219eb82015-01-07 20:15:42 +0000215 toJson : function () {
216 return this._root.toJson();
217 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000218
219 toQuery : function () {
220 return this._root.toQuery();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000221 }
222 };
223
Nils Diewaldd599d542015-01-08 20:41:34 +0000224
Nils Diewald8f4e2542014-12-19 04:42:09 +0000225 /**
226 * Operators for criteria
227 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000228 KorAP.Operators = {
229 create : function (and, or, del) {
230 var op = Object.create(KorAP.Operators);
231 op.and(and);
232 op.or(or);
233 op.del(del);
234 return op;
235 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000236
Nils Diewaldd0770492014-12-19 03:55:00 +0000237 update : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000238 // Init the element
239 if (this._element === undefined)
240 return this.element();
241
242 var op = this._element;
243
Nils Diewald0297ba12015-01-05 21:56:12 +0000244 op.refTo = this.parent();
245
Nils Diewaldd0770492014-12-19 03:55:00 +0000246 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000247 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000248
249 // Add and button
250 if (this._and === true) {
251 var andE = document.createElement('span');
252 andE.setAttribute('class', 'and');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000253 andE.addEventListener('click', KorAP._and, false);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000254 andE.appendChild(
255 document.createTextNode(KorAP.Locale.AND)
256 );
Nils Diewaldd0770492014-12-19 03:55:00 +0000257 op.appendChild(andE);
258 };
259
260 // Add or button
261 if (this._or === true) {
262 var orE = document.createElement('span');
263 orE.setAttribute('class', 'or');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000264 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000265 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
266 op.appendChild(orE);
267 };
268
269 // Add delete button
270 if (this._del === true) {
271 var delE = document.createElement('span');
272 delE.setAttribute('class', 'delete');
273 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000274 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000275 op.appendChild(delE);
276 };
Nils Diewald966abf12014-12-20 02:27:45 +0000277
278 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000279 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000280
281 // Be aware! This may be cyclic
282 parent : function (obj) {
283 if (arguments.length === 1)
284 this._parent = obj;
285 return this._parent;
286 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000287
Nils Diewaldd0770492014-12-19 03:55:00 +0000288 element : function () {
289
290 // Return existing element
291 if (this._element !== undefined)
292 return this._element;
293
294 this._element = document.createElement('div');
295 this._element.setAttribute('class', 'operators');
296
297 // Init elements
298 this.update();
299 return this._element;
300 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000301
Nils Diewaldd0770492014-12-19 03:55:00 +0000302 and : function (bool) {
303 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000304 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000305 return this._and;
306 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000307
Nils Diewaldd0770492014-12-19 03:55:00 +0000308 or : function (bool) {
309 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000310 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000311 return this._or;
312 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000313
Nils Diewaldd0770492014-12-19 03:55:00 +0000314 del : function (bool) {
315 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000316 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000317 return this._del;
318 }
319 };
320
321
322 /**
323 * Unspecified criterion
324 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000325 KorAP.UnspecifiedDoc = {
Nils Diewald4019bd22015-01-08 19:57:50 +0000326 _ldType : "non",
Nils Diewaldd0770492014-12-19 03:55:00 +0000327 create : function (parent) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000328 var obj = Object.create(KorAP.JsonLD).
329 upgradeTo(KorAP.UnspecifiedDoc);
330
Nils Diewaldd0770492014-12-19 03:55:00 +0000331 if (parent !== undefined)
332 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000333
Nils Diewaldd0770492014-12-19 03:55:00 +0000334 return obj;
335 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000336
Nils Diewaldfda29d92015-01-22 17:28:01 +0000337 // Set key - replace
338 key : function (v) {
339
340 // Not replaceable
341 if (this._parent === undefined)
342 return null;
343
344 // Set JSON-LD type
345 var newDoc = KorAP.Doc.create(this._parent, {
346 "@type" : "korap:doc",
347 "value" : "",
348 "key" : v
349 });
350
351 // Unspecified document on root
352 if (this._parent.ldType() === null) {
353 this._parent.root(newDoc);
354 this.destroy();
355 }
356
357 // Unspecified document in group
358 else {
359 this._parent.replaceOperand(this, newDoc);
360 };
361 this._parent.update();
362 return newDoc;
363 },
364
Nils Diewald966abf12014-12-20 02:27:45 +0000365 update : function () {
Nils Diewald4019bd22015-01-08 19:57:50 +0000366
Nils Diewald966abf12014-12-20 02:27:45 +0000367 if (this._element === undefined)
368 return this.element();
369
Nils Diewald8f6b6102015-01-08 18:25:33 +0000370 // Remove element content
Nils Diewald966abf12014-12-20 02:27:45 +0000371 _removeChildren(this._element);
372
373 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000374 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000375 this._element.appendChild(ellipsis);
376
377 // Set operators
Nils Diewalde15b7a22015-01-09 21:50:21 +0000378 if (this._parent !== undefined && this.parent().ldType() !== null) {
379 var op = this.operators(
380 false,
381 false,
382 true
383 );
Nils Diewald966abf12014-12-20 02:27:45 +0000384
Nils Diewalde15b7a22015-01-09 21:50:21 +0000385 this._element.appendChild(
386 op.element()
387 );
388 };
Nils Diewald966abf12014-12-20 02:27:45 +0000389
Nils Diewald966abf12014-12-20 02:27:45 +0000390 return this.element();
391 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000392
Nils Diewaldd0770492014-12-19 03:55:00 +0000393 element : function () {
394 if (this._element !== undefined)
395 return this._element;
396 this._element = document.createElement('div');
Nils Diewaldd599d542015-01-08 20:41:34 +0000397 this._element.setAttribute('class', 'doc unspecified');
Nils Diewald966abf12014-12-20 02:27:45 +0000398 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000399 return this._element;
Nils Diewaldfda29d92015-01-22 17:28:01 +0000400 },
401
402
Nils Diewaldd0770492014-12-19 03:55:00 +0000403 };
404
405
Nils Diewald8f4e2542014-12-19 04:42:09 +0000406 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000407 * Document criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000408 */
409 KorAP.Doc = {
410 _ldType : "doc",
Nils Diewaldfda29d92015-01-22 17:28:01 +0000411 _obj : function () { return KorAP.Doc },
Nils Diewaldd0770492014-12-19 03:55:00 +0000412
413 create : function (parent, json) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000414 var obj = Object(KorAP.JsonLD).
415 create().
416 upgradeTo(KorAP.Doc).
417 fromJson(json);
418
Nils Diewaldd0770492014-12-19 03:55:00 +0000419 if (parent !== undefined)
420 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000421
Nils Diewald86dad5b2015-01-28 15:09:07 +0000422 obj.__changed = true;
Nils Diewaldd0770492014-12-19 03:55:00 +0000423 return obj;
424 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000425
Nils Diewald966abf12014-12-20 02:27:45 +0000426 update : function () {
427 if (this._element === undefined)
428 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000429
Nils Diewald8f6b6102015-01-08 18:25:33 +0000430 // Get element
Nils Diewald966abf12014-12-20 02:27:45 +0000431 var e = this._element;
432
Nils Diewald8f6b6102015-01-08 18:25:33 +0000433 // Check if there is a change
Nils Diewald86dad5b2015-01-28 15:09:07 +0000434 if (this.__changed) {
435
436 // Was rewritten
437 if (this.rewrites() !== undefined) {
438 e.classList.add("rewritten");
439 };
Nils Diewald966abf12014-12-20 02:27:45 +0000440
Nils Diewald8f6b6102015-01-08 18:25:33 +0000441 // Added key
442 var key = document.createElement('span');
443 key.setAttribute('class', 'key');
444 if (this.key())
445 key.appendChild(document.createTextNode(this.key()));
Nils Diewald966abf12014-12-20 02:27:45 +0000446
Nils Diewald8f6b6102015-01-08 18:25:33 +0000447 // Added match operator
448 var matchop = document.createElement('span');
449 matchop.setAttribute('data-type', this.type());
450 matchop.setAttribute('class', 'match');
451 matchop.appendChild(
452 document.createTextNode(this.matchop())
453 );
454
455 // Added match operator
456 var value = document.createElement('span');
457 value.setAttribute('data-type', this.type());
458 value.setAttribute('class', 'value');
459 if (this.value())
460 value.appendChild(
461 document.createTextNode(this.value())
462 );
463
464 // Remove all element children
465 _removeChildren(e);
466
467 // Add spans
468 e.appendChild(key);
469 e.appendChild(matchop);
470 e.appendChild(value);
471
Nils Diewald86dad5b2015-01-28 15:09:07 +0000472 this.__changed = false;
473 };
474
475 if (this._rewrites !== undefined) {
476 e.appendChild(this._rewrites.element());
Nils Diewald8f6b6102015-01-08 18:25:33 +0000477 };
478
479 if (this._parent !== undefined) {
480 // Set operators
481 var op = this.operators(
482 true,
483 true,
Nils Diewald4019bd22015-01-08 19:57:50 +0000484 true
Nils Diewald8f6b6102015-01-08 18:25:33 +0000485 );
486
487 // Append new operators
488 e.appendChild(op.element());
489 };
Nils Diewald966abf12014-12-20 02:27:45 +0000490
Nils Diewaldd0770492014-12-19 03:55:00 +0000491 return e;
492 },
493
Nils Diewald966abf12014-12-20 02:27:45 +0000494 element : function () {
495 if (this._element !== undefined)
496 return this._element;
497
498 this._element = document.createElement('div');
499 this._element.setAttribute('class', 'doc');
500
501 this.update();
502 return this._element;
503 },
504
Nils Diewaldd0770492014-12-19 03:55:00 +0000505 // Wrap a new operation around the doc element
506 wrap : function (op) {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000507 var parent = this.parent();
508 var group = KorAP.DocGroup.create(parent);
509 group.operation(op);
Nils Diewald966abf12014-12-20 02:27:45 +0000510 group.append(this);
Nils Diewald9fcc1712015-01-09 14:24:32 +0000511 group.append();
512 return parent.replaceOperand(this, group).update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000513 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000514
Nils Diewald3a2d8022014-12-16 02:45:41 +0000515 // Deserialize from json
516 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000517 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000518 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000519
Nils Diewald86dad5b2015-01-28 15:09:07 +0000520 if (json["@type"] === undefined) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000521 KorAP.log(701, "JSON-LD group has no @type attribute");
522 return;
523 };
524
Nils Diewald3a2d8022014-12-16 02:45:41 +0000525 if (json["value"] === undefined ||
526 typeof json["value"] != 'string') {
527 KorAP.log(805, "Value is invalid");
528 return;
529 };
530
531 // There is a defined key
532 if (json["key"] !== undefined &&
533 typeof json["key"] === 'string') {
534
535 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000536 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000537
538 // Set match operation
539 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000540 if (typeof json["match"] === 'string') {
541 this.matchop(json["match"]);
542 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000543 else {
544 KorAP.log(802, "Match type is not supported by value type");
545 return;
546 };
547 };
548
549 // Key is a string
550 if (json["type"] === undefined ||
551 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000552 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000553
554 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000555 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000556 KorAP.log(802, "Match type is not supported by value type");
557 return;
558 };
559
560 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000561 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000562 }
563
564 // Key is a date
565 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000566 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000567
568 if (json["value"] !== undefined &&
569 KorAP._validDateRE.test(json["value"])) {
570
Nils Diewaldd0770492014-12-19 03:55:00 +0000571 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000572 KorAP.log(802, "Match type is not supported by value type");
573 return;
574 };
575
576 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000577 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000578 }
579 else {
580 KorAP.log(806, "Value is not a valid date string");
581 return;
582 };
583 }
584
585 // Key is a regular expression
586 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000587 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000588
589 try {
590
591 // Try to create a regular expression
592 var check = new RegExp(json["value"]);
593
Nils Diewaldd0770492014-12-19 03:55:00 +0000594 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000595 KorAP.log(802, "Match type is not supported by value type");
596 return;
597 };
598
Nils Diewaldd0770492014-12-19 03:55:00 +0000599 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000600 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000601
Nils Diewald3a2d8022014-12-16 02:45:41 +0000602 catch (e) {
603 KorAP.log(807, "Value is not a valid regular expression");
604 return;
605 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000606 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000607 }
608
609 else {
610 KorAP.log(804, "Unknown value type");
611 return;
612 };
Nils Diewald86dad5b2015-01-28 15:09:07 +0000613
Nils Diewald3a2d8022014-12-16 02:45:41 +0000614 };
615
Nils Diewald86dad5b2015-01-28 15:09:07 +0000616 if (json["rewrites"] !== undefined) {
617 this._rewrites = KorAP.RewriteList.create(json["rewrites"]);
618 };
619
Nils Diewald3a2d8022014-12-16 02:45:41 +0000620 return this;
621 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000622
Nils Diewaldd0770492014-12-19 03:55:00 +0000623 key : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000624 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000625 this._key = value;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000626 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000627 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000628 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000629 return this._key;
630 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000631
Nils Diewaldd0770492014-12-19 03:55:00 +0000632 matchop : function (match) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000633 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000634 this._matchop = match.replace(/^match:/, '');
Nils Diewald86dad5b2015-01-28 15:09:07 +0000635 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000636 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000637 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000638 return this._matchop || "eq";
639 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000640
Nils Diewaldd0770492014-12-19 03:55:00 +0000641 type : function (type) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000642 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000643 this._type = type;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000644 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000645 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000646 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000647 return this._type || "string";
648 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000649
Nils Diewaldd0770492014-12-19 03:55:00 +0000650 value : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000651 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000652 this._value = value;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000653 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000654 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000655 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000656 return this._value;
657 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000658
Nils Diewald86dad5b2015-01-28 15:09:07 +0000659 rewrites : function () {
660 return this._rewrites;
661 },
662
663 _changed : function () {
664 this.__changed = true;
665
666 if (this._rewrites === undefined)
667 return;
668 delete this["_rewrites"];
669 if (this._element === undefined)
670 return;
671 this._element.classList.remove("rewritten");
672 },
673
Nils Diewald3a2d8022014-12-16 02:45:41 +0000674 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000675 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000676 return {};
677
678 return {
Nils Diewaldd0770492014-12-19 03:55:00 +0000679 "@type" : "korap:" + this.ldType(),
680 "key" : this.key(),
681 "match" : "match:" + this.matchop(),
682 "value" : this.value() || '',
683 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000684 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000685 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000686
687 toQuery : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000688 if (!this.matchop() || !this.key())
689 return "";
690
691 // Build doc string based on key
692 var string = this.key() + ' ';
693
694 // Add match operator
695 switch (this.matchop()) {
696 case "ne":
697 string += '!=';
698 break;
699 case "contains":
700 string += '~';
701 break;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000702 case "excludes":
703 string += '!~';
704 break;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000705 case "geq":
706 string += 'since';
707 break;
708 case "leq":
709 string += 'until';
710 break;
711 default:
712 string += (this.type() == 'date') ? 'in' : '=';
713 break;
714 };
715
716 string += ' ';
717
718 // Add value
719 switch (this.type()) {
720 case "date":
721 return string + this.value();
722 break;
723 case "regex":
724 return string + '/' + this.value() + '/';
725 break;
726 case "string":
727 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
728 break;
729 };
730
Nils Diewaldd599d542015-01-08 20:41:34 +0000731 return "";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000732 }
733 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000734
Nils Diewaldd599d542015-01-08 20:41:34 +0000735
Nils Diewald8f4e2542014-12-19 04:42:09 +0000736 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000737 * Document group criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000738 */
739 KorAP.DocGroup = {
740 _ldType : "docGroup",
741
742 create : function (parent, json) {
743 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
744 obj._operands = [];
745 obj.fromJson(json);
746 if (parent !== undefined)
747 obj._parent = parent;
748 return obj;
749 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000750
751 newAfter : function (obj) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000752 for (var i = 0; i < this._operands.length; i++) {
Nils Diewaldd599d542015-01-08 20:41:34 +0000753 if (this._operands[i] === obj) {
754 var operand = KorAP.UnspecifiedDoc.create(this);
755 this._operands.splice(i + 1, 0, operand);
756 return this.update();
757 };
758 };
759 },
760
Nils Diewald86dad5b2015-01-28 15:09:07 +0000761 // The doc is already set in the group
762 _duplicate : function (operand) {
763 if (operand.ldType() !== 'doc')
764 return null;
765
766 for (var i = 0; i < this._operands.length; i++) {
767 var op = this.getOperand(i);
768 if (op.ldType() === 'doc'
769 && operand.key() === op.key()
770 && operand.matchop() === op.matchop()
771 && operand.value() === op.value()) {
772 return op;
773 };
774 };
775 return null;
776 },
777
Nils Diewald966abf12014-12-20 02:27:45 +0000778 append : function (operand) {
779
780 // Append unspecified object
781 if (operand === undefined) {
782
783 // Be aware of cyclic structures!
784 operand = KorAP.UnspecifiedDoc.create(this);
785 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000786 return operand;
787 };
788
Nils Diewald8f4e2542014-12-19 04:42:09 +0000789 switch (operand["@type"]) {
Nils Diewald86dad5b2015-01-28 15:09:07 +0000790
Nils Diewald8f4e2542014-12-19 04:42:09 +0000791 case undefined:
Nils Diewald86dad5b2015-01-28 15:09:07 +0000792 // No @type defined
Nils Diewald8f4e2542014-12-19 04:42:09 +0000793 if (operand["ldType"] !== undefined) {
794 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000795 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000796 KorAP.log(812, "Operand not supported in document group");
797 return;
798 };
Nils Diewald966abf12014-12-20 02:27:45 +0000799 // Be aware of cyclic structures!
800 operand.parent(this);
Nils Diewald86dad5b2015-01-28 15:09:07 +0000801
802 var dupl = this._duplicate(operand);
803 if (dupl === null) {
804 this._operands.push(operand);
805 return operand;
806 };
807 return dupl;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000808 };
809
810 KorAP.log(701, "JSON-LD group has no @type attribute");
811 return;
812
813 case "korap:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000814 // Be aware of cyclic structures!
815 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000816 if (doc === undefined)
817 return;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000818 var dupl = this._duplicate(doc);
819 if (dupl === null) {
820 this._operands.push(doc);
821 return doc;
822 };
823 return dupl;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000824
825 case "korap:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000826 // Be aware of cyclic structures!
827 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000828 if (docGroup === undefined)
829 return;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000830
831 // Flatten group
832 if (docGroup.operation() === this.operation()) {
833 for (var op in docGroup.operands()) {
834 op = docGroup.getOperand(op);
835 var dupl = this._duplicate(op);
836 if (dupl === null) {
837 this._operands.push(op);
838 op.parent(this);
839 };
840 };
841 docGroup._operands = [];
842 docGroup.destroy();
843 return this;
844 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000845 this._operands.push(docGroup);
846 return docGroup;
847
848 default:
849 KorAP.log(812, "Operand not supported in document group");
850 return;
851 };
852 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000853
Nils Diewald966abf12014-12-20 02:27:45 +0000854 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000855 // There is only one operand in group
Nils Diewald52f7eb12015-01-12 17:30:04 +0000856
Nils Diewaldf219eb82015-01-07 20:15:42 +0000857 if (this._operands.length === 1) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000858
Nils Diewaldf219eb82015-01-07 20:15:42 +0000859 var parent = this.parent();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000860 var op = this.getOperand(0);
861
Nils Diewald8f6b6102015-01-08 18:25:33 +0000862 // This will prevent destruction of
863 // the operand
864 this._operands = [];
Nils Diewaldf219eb82015-01-07 20:15:42 +0000865
866 // Parent is a group
Nils Diewald52f7eb12015-01-12 17:30:04 +0000867 if (parent.ldType() !== null)
Nils Diewald8e7182e2015-01-08 15:02:07 +0000868 return parent.replaceOperand(this, op).update();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000869
Nils Diewald8f6b6102015-01-08 18:25:33 +0000870 // Parent is vc
Nils Diewaldf219eb82015-01-07 20:15:42 +0000871 else {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000872 this.destroy();
Nils Diewald8f6b6102015-01-08 18:25:33 +0000873 // Cyclic madness
874 parent.root(op);
875 op.parent(parent);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000876 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000877 };
878 };
879
Nils Diewald966abf12014-12-20 02:27:45 +0000880 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000881 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000882
Nils Diewald5c817a42015-01-06 01:08:56 +0000883 var group = this._element;
884 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000885
Nils Diewald5c817a42015-01-06 01:08:56 +0000886 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000887
888 // Append operands
Nils Diewald52f7eb12015-01-12 17:30:04 +0000889 for (var i = 0; i < this._operands.length; i++) {
Nils Diewald5c817a42015-01-06 01:08:56 +0000890 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000891 this.getOperand(i).element()
892 );
893 };
894
895 // Set operators
896 var op = this.operators(
897 this.operation() == 'and' ? false : true,
898 this.operation() == 'or' ? false : true,
899 true
900 );
901
Nils Diewald5c817a42015-01-06 01:08:56 +0000902 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000903 op.element()
904 );
905
Nils Diewald5c817a42015-01-06 01:08:56 +0000906 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000907 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000908
Nils Diewald8f4e2542014-12-19 04:42:09 +0000909 element : function () {
910 if (this._element !== undefined)
911 return this._element;
912
913 this._element = document.createElement('div');
914 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000915
Nils Diewaldf219eb82015-01-07 20:15:42 +0000916 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000917 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000918
919 return this._element;
920 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000921
Nils Diewald8f4e2542014-12-19 04:42:09 +0000922 operation : function (op) {
923 if (arguments.length === 1) {
924 if (KorAP._validGroupOpRE.test(op)) {
925 this._op = op;
926 }
927 else {
928 KorAP.log(810, "Unknown operation type");
929 return;
930 };
931 };
932 return this._op || 'and';
933 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000934
Nils Diewald8f4e2542014-12-19 04:42:09 +0000935 operands : function () {
936 return this._operands;
937 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000938
Nils Diewald8f4e2542014-12-19 04:42:09 +0000939 getOperand : function (index) {
940 return this._operands[index];
941 },
942
Nils Diewald5c817a42015-01-06 01:08:56 +0000943 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000944 replaceOperand : function (oldOp, newOp) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000945
946 for (var i = 0; i < this._operands.length; i++) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000947 if (this._operands[i] === oldOp) {
948
Nils Diewalde15b7a22015-01-09 21:50:21 +0000949 // Just insert a doc or ...
950 if (newOp.ldType() === "doc" ||
Nils Diewald52f7eb12015-01-12 17:30:04 +0000951 newOp.ldType() === "non" ||
Nils Diewalde15b7a22015-01-09 21:50:21 +0000952 // ... insert a group of a different operation
953 // (i.e. "and" in "or"/"or" in "and")
954 newOp.operation() != this.operation()) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000955 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000956 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000957 }
958
Nils Diewald86dad5b2015-01-28 15:09:07 +0000959 // Flatten group
Nils Diewaldf219eb82015-01-07 20:15:42 +0000960 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000961 // Remove old group
962 this._operands.splice(i, 1);
963
964 // Inject new operands
Nils Diewald8f6b6102015-01-08 18:25:33 +0000965 for (var op in newOp.operands().reverse()) {
Nils Diewald86dad5b2015-01-28 15:09:07 +0000966 op = newOp.getOperand(op);
967 this._operands.splice(i, 0, op);
968 op.parent(this);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000969 };
970 // Prevent destruction of operands
971 newOp._operands = [];
972 newOp.destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000973 };
974 oldOp.destroy();
975 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000976 }
977 };
978 return false;
979 },
980
Nils Diewald0297ba12015-01-05 21:56:12 +0000981 // Delete operand from group
982 delOperand : function (obj) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000983 for (var i = 0; i < this._operands.length; i++) {
Nils Diewald0297ba12015-01-05 21:56:12 +0000984 if (this._operands[i] === obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000985
Nils Diewald8f6b6102015-01-08 18:25:33 +0000986 // Delete identified operand
Nils Diewald0297ba12015-01-05 21:56:12 +0000987 this._operands.splice(i,1);
988
Nils Diewald5c817a42015-01-06 01:08:56 +0000989 // Destroy object for cyclic references
990 obj.destroy();
991
Nils Diewaldf219eb82015-01-07 20:15:42 +0000992 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +0000993 };
994 };
Nils Diewald5c817a42015-01-06 01:08:56 +0000995
996 // Operand not found
997 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +0000998 },
999
Nils Diewald8f4e2542014-12-19 04:42:09 +00001000 // Deserialize from json
1001 fromJson : function (json) {
1002 if (json === undefined)
1003 return this;
1004
Nils Diewald86dad5b2015-01-28 15:09:07 +00001005 if (json["@type"] === undefined) {
Nils Diewald8f4e2542014-12-19 04:42:09 +00001006 KorAP.log(701, "JSON-LD group has no @type attribute");
1007 return;
1008 };
1009
1010 if (json["operation"] === undefined ||
1011 typeof json["operation"] !== 'string') {
1012 KorAP.log(811, "Document group expects operation");
1013 return;
1014 };
1015
1016 var operation = json["operation"];
1017
1018 this.operation(operation.replace(/^operation:/,''));
1019
1020 if (json["operands"] === undefined ||
1021 !(json["operands"] instanceof Array)) {
1022 KorAP.log(704, "Operation needs operand list")
1023 return;
1024 };
1025
1026 // Add all documents
1027 for (var i in json["operands"]) {
1028 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +00001029 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +00001030 };
1031
1032 return this;
1033 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001034
Nils Diewald8f4e2542014-12-19 04:42:09 +00001035 toJson : function () {
1036 var opArray = new Array();
Nils Diewald52f7eb12015-01-12 17:30:04 +00001037 for (var i = 0; i < this._operands.length; i++) {
Nils Diewalde15b7a22015-01-09 21:50:21 +00001038 if (this._operands[i].ldType() !== 'non')
1039 opArray.push(this._operands[i].toJson());
Nils Diewald8f4e2542014-12-19 04:42:09 +00001040 };
1041 return {
1042 "@type" : "korap:" + this.ldType(),
1043 "operation" : "operation:" + this.operation(),
1044 "operands" : opArray
1045 };
Nils Diewaldf219eb82015-01-07 20:15:42 +00001046 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001047
Nils Diewalde15b7a22015-01-09 21:50:21 +00001048 toQuery : function (brackets) {
1049 var list = this._operands
1050 .filter(function (op) {
1051 return op.ldType() !== 'non';
1052 })
1053 .map(function (op) {
Nils Diewaldd599d542015-01-08 20:41:34 +00001054 return (op.ldType() === 'docGroup') ?
Nils Diewalde15b7a22015-01-09 21:50:21 +00001055 op.toQuery(true) :
Nils Diewaldd599d542015-01-08 20:41:34 +00001056 op.toQuery();
Nils Diewalde15b7a22015-01-09 21:50:21 +00001057 });
1058
1059 if (list.length === 1)
1060 return list.join('');
1061 else {
1062 var str = list.join(this.operation() === 'or' ? ' | ' : ' & ');
1063 return brackets ? '(' + str + ')' : str;
1064 };
Nils Diewald8f4e2542014-12-19 04:42:09 +00001065 }
1066 };
1067
1068
Nils Diewald86dad5b2015-01-28 15:09:07 +00001069 KorAP.RewriteList = {
1070 // Construction method
1071 create : function (json) {
1072 var obj = Object(KorAP.JsonLD).
1073 create().
1074 upgradeTo(KorAP.RewriteList).
1075 fromJson(json);
1076 return obj;
1077 },
1078 fromJson : function (json) {
1079 this._list = new Array();
1080 for (var i = 0; i < json.length; i++) {
1081 this._list.push(
1082 KorAP.Rewrite.create(json[i])
1083 );
1084 };
1085 return this;
1086 },
1087 element : function () {
1088 if (this._element !== undefined)
1089 return this._element;
1090
1091 this._element = document.createElement('div');
1092 this._element.setAttribute('class', 'rewrite');
1093 for (var x in this._list) {
1094 var rewrite = this._list[x];
1095 var span = document.createElement('span');
1096
1097 // Set class attribute
1098 span.setAttribute('class', rewrite.operation());
1099
1100 // Append source information
1101 span.appendChild(document.createTextNode(rewrite.src()));
1102
1103 // Append scope information
1104 if (rewrite.scope() !== undefined) {
1105 span.appendChild(
1106 document.createTextNode(
1107 ': ' + rewrite.scope()
1108 )
1109 );
1110 };
1111 this._element.appendChild(span);
1112 };
1113 return this._element;
1114 }
1115 };
1116
1117
1118 /**
1119 * Implementation of rewrite objects.
1120 */
1121 KorAP.Rewrite = {
1122
1123 // Construction method
1124 create : function (json) {
1125 var obj = Object(KorAP.JsonLD).
1126 create().
1127 upgradeTo(KorAP.Rewrite).
1128 fromJson(json);
1129 return obj;
1130 },
1131
1132 // Get or set source
1133 src : function (string) {
1134 if (arguments.length === 1)
1135 this._src = string;
1136 return this._src;
1137 },
1138
1139 // Get or set operation
1140 operation : function (op) {
1141 if (arguments.length === 1) {
1142 if (KorAP._validRewriteOpRE.test(op)) {
1143 this._op = op;
1144 }
1145 else {
1146 KorAP.log(814, "Unknown rewrite operation");
1147 return;
1148 };
1149 };
1150 return this._op || 'injection';
1151 },
1152
1153 // Get or set scope
1154 scope : function (attr) {
1155 if (arguments.length === 1)
1156 this._scope = attr;
1157 return this._scope;
1158 },
1159
1160 // Serialize from Json
1161 fromJson : function (json) {
1162 if (json === undefined)
1163 return this;
1164
1165 // Missing @type
1166 if (json["@type"] === undefined) {
1167 KorAP.log(701, "JSON-LD group has no @type attribute");
1168 return;
1169 };
1170
1171 // Missing source
1172 if (json["src"] === undefined ||
1173 typeof json["src"] !== 'string') {
1174 KorAP.log(815, "Rewrite expects source");
1175 return;
1176 };
1177
1178 // Set source
1179 this.src(json["src"]);
1180
1181 // Set operation
1182 if (json["operation"] !== undefined) {
1183 var operation = json["operation"];
1184 this.operation(operation.replace(/^operation:/,''));
1185 };
1186
1187 // Set scope
1188 if (json["scope"] !== undefined &&
1189 typeof json["scope"] === 'string')
1190 this.scope(json["scope"]);
1191
1192 return this;
1193 },
1194
1195 toString : function () {
1196 var str = '';
1197 var op = this.operation();
1198 str += op.charAt(0).toUpperCase() + op.slice(1);
1199 str += ' of ' + (
1200 this._scope === null ?
1201 'object' :
1202 '"' +
1203 this.scope().replace(KorAP._quote, '\\$1') +
1204 '"'
1205 );
1206 str += ' by ' +
1207 '"' +
1208 this.src().replace(KorAP._quote, '\\$1') +
1209 '"';
1210 return str;
1211 }
1212 };
1213
1214
Nils Diewaldd599d542015-01-08 20:41:34 +00001215 /**
1216 * Abstract JsonLD criterion object
1217 */
Nils Diewald8f4e2542014-12-19 04:42:09 +00001218 KorAP.JsonLD = {
Nils Diewald86dad5b2015-01-28 15:09:07 +00001219 __changed : false,
Nils Diewald8f6b6102015-01-08 18:25:33 +00001220
Nils Diewald8f4e2542014-12-19 04:42:09 +00001221 create : function () {
1222 return Object.create(KorAP.JsonLD);
1223 },
1224
1225 /**
1226 * Upgrade this object to another object
1227 * while private data stays intact
1228 */
1229 upgradeTo : function (props) {
1230 for (var prop in props) {
1231 this[prop] = props[prop];
1232 };
1233 return this;
1234 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001235
Nils Diewald8f4e2542014-12-19 04:42:09 +00001236 ldType : function (type) {
1237 if (arguments.length === 1)
1238 this._ldType = type;
1239 return this._ldType;
1240 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001241
Nils Diewald8f4e2542014-12-19 04:42:09 +00001242 parent : function (obj) {
Nils Diewald8f6b6102015-01-08 18:25:33 +00001243 if (arguments.length === 1) {
Nils Diewald8f4e2542014-12-19 04:42:09 +00001244 this._parent = obj;
Nils Diewald86dad5b2015-01-28 15:09:07 +00001245 this.__changed = true;
Nils Diewald8f6b6102015-01-08 18:25:33 +00001246 };
Nils Diewald8f4e2542014-12-19 04:42:09 +00001247 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +00001248 },
Nils Diewald0297ba12015-01-05 21:56:12 +00001249
Nils Diewald5c817a42015-01-06 01:08:56 +00001250 // Destroy object - especially for
1251 // acyclic structures!
Nils Diewald86dad5b2015-01-28 15:09:07 +00001252 // I'm paranoid!
Nils Diewald5c817a42015-01-06 01:08:56 +00001253 destroy : function () {
1254 if (this._ops != undefined) {
1255 this._ops._parent = undefined;
1256 if (this._ops._element !== undefined)
1257 this._ops._element.refTo = undefined;
1258 this._ops = undefined;
1259 };
1260 if (this._element !== undefined)
1261 this._element = undefined;
1262
1263 // In case of a group, destroy all operands
1264 if (this._operands !== undefined) {
Nils Diewald52f7eb12015-01-12 17:30:04 +00001265 for (var i = 0; i < this._operands.length; i++)
Nils Diewald5c817a42015-01-06 01:08:56 +00001266 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +00001267 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +00001268 };
1269 },
1270
Nils Diewald52f7eb12015-01-12 17:30:04 +00001271 // Wrap a new operation around the root group element
1272 wrapOnRoot : function (op) {
1273 var parent = this.parent();
1274
1275 var group = KorAP.DocGroup.create(parent);
1276 if (arguments.length === 1)
1277 group.operation(op);
1278 else
1279 group.operation(
1280 this.operation() === 'and' ? 'or' : 'and'
1281 );
1282 group.append(this);
1283 this.parent(group);
1284 group.append();
1285 group.element(); // Init (seems to be necessary)
1286 parent.root(group);
1287 return this.parent();
1288 },
1289
Nils Diewald0297ba12015-01-05 21:56:12 +00001290 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +00001291 operators : function (and, or, del) {
1292 if (arguments === 0)
1293 return this._ops;
1294 this._ops = KorAP.Operators.create(
1295 and, or, del
1296 );
Nils Diewald0297ba12015-01-05 21:56:12 +00001297 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +00001298 return this._ops;
1299 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001300
Nils Diewald966abf12014-12-20 02:27:45 +00001301 toJson : function () {
1302 return {
1303 // Unspecified object
1304 "@type" : "korap:" + this.ldType()
1305 };
Nils Diewald8f6b6102015-01-08 18:25:33 +00001306 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001307
1308 toQuery : function () {
Nils Diewaldfda29d92015-01-22 17:28:01 +00001309 return '';
Nils Diewald8f4e2542014-12-19 04:42:09 +00001310 }
1311 };
1312
Nils Diewald3a2d8022014-12-16 02:45:41 +00001313}(this.KorAP));