blob: 03911ceb6a9b252a27bb0f6a1c2c9a478eb108ca [file] [log] [blame]
Nils Diewald3a2d8022014-12-16 02:45:41 +00001var KorAP = KorAP || {};
Nils Diewald3a2d8022014-12-16 02:45:41 +00002
Nils Diewald8f4e2542014-12-19 04:42:09 +00003// TODO: Implement a working localization solution!
4// TODO: Support 'update' method to update elements on change
Nils Diewald966abf12014-12-20 02:27:45 +00005// TODO: Implement "toQuery"
Nils Diewaldd0770492014-12-19 03:55:00 +00006
7/*
8 * Error codes:
9 701: "JSON-LD group has no @type attribute"
10 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000011 802: "Match type is not supported by value type"
12 804: "Unknown value type"
13 805: "Value is invalid"
14 806: "Value is not a valid date string"
15 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000016 810: "Unknown document group operation" (like 711)
17 811: "Document group expects operation" (like 703)
18 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000019 813: "Collection type is not supported" (like 713)
20*/
21
Nils Diewald3a2d8022014-12-16 02:45:41 +000022(function (KorAP) {
23 "use strict";
24
25 // Default log message
26 KorAP.log = KorAP.log || function (type, msg) {
27 console.log(type + ": " + msg);
28 };
29
30 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains)$");
31 KorAP._validRegexMatchRE = new RegExp("^(?:eq|ne)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000032 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000033 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
34 KorAP._validGroupOpRE = new RegExp("^(?:and|or)$");
Nils Diewaldf219eb82015-01-07 20:15:42 +000035 KorAP._quote = new RegExp("([\"\\\\])", 'g');
Nils Diewald3a2d8022014-12-16 02:45:41 +000036
Nils Diewaldf219eb82015-01-07 20:15:42 +000037 var loc = (KorAP.Locale = KorAP.Locale || {} );
38 loc.AND = loc.AND || 'and';
39 loc.OR = loc.OR || 'or';
40 loc.DEL = loc.DEL || '×';
41 loc.EMPTY = loc.EMPTY || '⋯'
Nils Diewaldd0770492014-12-19 03:55:00 +000042
Nils Diewald966abf12014-12-20 02:27:45 +000043 function _bool (bool) {
44 return (bool === undefined || bool === false) ? false : true;
45 };
46
47 function _removeChildren (node) {
48 // Remove everything underneath
Nils Diewald8f6b6102015-01-08 18:25:33 +000049 while (node.firstChild)
Nils Diewald966abf12014-12-20 02:27:45 +000050 node.removeChild(node.firstChild);
Nils Diewald966abf12014-12-20 02:27:45 +000051 };
52
Nils Diewald3a2d8022014-12-16 02:45:41 +000053 KorAP.VirtualCollection = {
Nils Diewaldf219eb82015-01-07 20:15:42 +000054 ldType : function () {
55 return null;
56 },
Nils Diewald3a2d8022014-12-16 02:45:41 +000057 create : function () {
58 return Object.create(KorAP.VirtualCollection);
59 },
Nils Diewaldd0770492014-12-19 03:55:00 +000060 render : function (json) {
61 var obj = Object.create(KorAP.VirtualCollection);
62
63 if (json !== undefined) {
64 // Root object
65 if (json['@type'] == 'korap:doc') {
Nils Diewaldf219eb82015-01-07 20:15:42 +000066 obj._root = KorAP.Doc.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000067 }
68 else if (json['@type'] == 'korap:docGroup') {
Nils Diewaldf219eb82015-01-07 20:15:42 +000069 obj._root = KorAP.DocGroup.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000070 }
71 else {
72 KorAP.log(813, "Collection type is not supported");
73 return;
74 };
75 }
76
77 else {
78 // Add unspecified object
Nils Diewaldf219eb82015-01-07 20:15:42 +000079 obj._root = KorAP.UnspecifiedDoc.create(obj);
Nils Diewaldd0770492014-12-19 03:55:00 +000080 };
81
Nils Diewald8e7182e2015-01-08 15:02:07 +000082 // Init element and update
83 obj.update();
Nils Diewaldd0770492014-12-19 03:55:00 +000084
85 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +000086 },
Nils Diewaldf219eb82015-01-07 20:15:42 +000087 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +000088 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +000089 var e = this.element();
90 if (e.firstChild !== null) {
91 if (e.firstChild !== obj.element())
92 e.replaceChild(obj.element(), e.firstChild);
93 }
94
95 // Append root element
96 else {
97 e.appendChild(obj.element());
98 };
99
100 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000101 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000102 obj.parent(this);
103
Nils Diewald8e7182e2015-01-08 15:02:07 +0000104 this.update();
105 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000106 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000107 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000108
Nils Diewaldd0770492014-12-19 03:55:00 +0000109 element : function () {
110 if (this._element !== undefined)
111 return this._element;
112
113 this._element = document.createElement('div');
114 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000115
Nils Diewald8f6b6102015-01-08 18:25:33 +0000116 // Initialize root
117 this._element.appendChild(this._root.element());
118
Nils Diewaldd0770492014-12-19 03:55:00 +0000119 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000120 },
121 toJson : function () {
122 return this._root.toJson();
123 },
124 toString : function () {
125 return this._root.toString();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000126 },
127 update : function () {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000128 this._root.update();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000129 }
130 };
131
Nils Diewald0297ba12015-01-05 21:56:12 +0000132 KorAP._or = function (e) {
133 var obj = this.parentNode.refTo;
134 };
135
136 KorAP._and = function (e) {
137 var obj = this.parentNode.refTo;
138 };
139
140 KorAP._delete = function (e) {
141 var obj = this.parentNode.refTo;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000142 obj.parent().delOperand(obj).update();
Nils Diewald0297ba12015-01-05 21:56:12 +0000143 };
144
Nils Diewald8f4e2542014-12-19 04:42:09 +0000145 /**
146 * Operators for criteria
147 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000148 KorAP.Operators = {
149 create : function (and, or, del) {
150 var op = Object.create(KorAP.Operators);
151 op.and(and);
152 op.or(or);
153 op.del(del);
154 return op;
155 },
156 update : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000157 // Init the element
158 if (this._element === undefined)
159 return this.element();
160
161 var op = this._element;
162
Nils Diewald0297ba12015-01-05 21:56:12 +0000163 op.refTo = this.parent();
164
Nils Diewaldd0770492014-12-19 03:55:00 +0000165 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000166 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000167
168 // Add and button
169 if (this._and === true) {
170 var andE = document.createElement('span');
171 andE.setAttribute('class', 'and');
Nils Diewald0297ba12015-01-05 21:56:12 +0000172 andE.addEventListener('click', KorAP._and, false);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000173 andE.appendChild(
174 document.createTextNode(KorAP.Locale.AND)
175 );
Nils Diewaldd0770492014-12-19 03:55:00 +0000176 op.appendChild(andE);
177 };
178
179 // Add or button
180 if (this._or === true) {
181 var orE = document.createElement('span');
182 orE.setAttribute('class', 'or');
Nils Diewald0297ba12015-01-05 21:56:12 +0000183 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000184 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
185 op.appendChild(orE);
186 };
187
188 // Add delete button
189 if (this._del === true) {
190 var delE = document.createElement('span');
191 delE.setAttribute('class', 'delete');
192 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000193 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000194 op.appendChild(delE);
195 };
Nils Diewald966abf12014-12-20 02:27:45 +0000196
197 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000198 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000199
200 // Be aware! This may be cyclic
201 parent : function (obj) {
202 if (arguments.length === 1)
203 this._parent = obj;
204 return this._parent;
205 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000206
Nils Diewaldd0770492014-12-19 03:55:00 +0000207 element : function () {
208
209 // Return existing element
210 if (this._element !== undefined)
211 return this._element;
212
213 this._element = document.createElement('div');
214 this._element.setAttribute('class', 'operators');
215
216 // Init elements
217 this.update();
218 return this._element;
219 },
220 and : function (bool) {
221 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000222 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000223 return this._and;
224 },
225 or : function (bool) {
226 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000227 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000228 return this._or;
229 },
230 del : function (bool) {
231 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000232 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000233 return this._del;
234 }
235 };
236
237
238 /**
239 * Unspecified criterion
240 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000241 KorAP.UnspecifiedDoc = {
Nils Diewald966abf12014-12-20 02:27:45 +0000242 _ldType : "doc",
Nils Diewaldd0770492014-12-19 03:55:00 +0000243 create : function (parent) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000244 var obj = Object.create(KorAP.JsonLD).
245 upgradeTo(KorAP.UnspecifiedDoc);
246
Nils Diewaldd0770492014-12-19 03:55:00 +0000247 if (parent !== undefined)
248 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000249
Nils Diewaldd0770492014-12-19 03:55:00 +0000250 return obj;
251 },
Nils Diewald966abf12014-12-20 02:27:45 +0000252 update : function () {
253 if (this._element === undefined)
254 return this.element();
255
Nils Diewald8f6b6102015-01-08 18:25:33 +0000256 // Remove element content
Nils Diewald966abf12014-12-20 02:27:45 +0000257 _removeChildren(this._element);
258
259 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000260 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000261 this._element.appendChild(ellipsis);
262
263 // Set operators
264 var op = this.operators(
265 false,
266 false,
267 // No delete object, if this is the root
Nils Diewald8f6b6102015-01-08 18:25:33 +0000268 (this._parent !== undefined &&
269 this.parent().ldType() !== null) ? true : false
Nils Diewald966abf12014-12-20 02:27:45 +0000270 );
271
272 this._element.appendChild(
273 op.element()
274 );
275
Nils Diewald966abf12014-12-20 02:27:45 +0000276 return this.element();
277 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000278 element : function () {
279 if (this._element !== undefined)
280 return this._element;
Nils Diewald966abf12014-12-20 02:27:45 +0000281
Nils Diewaldd0770492014-12-19 03:55:00 +0000282 this._element = document.createElement('div');
Nils Diewald966abf12014-12-20 02:27:45 +0000283 this._element.setAttribute('class', 'unspecified');
284
285 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000286 return this._element;
287 }
288 };
289
290
Nils Diewald8f4e2542014-12-19 04:42:09 +0000291 /**
292 * Virtual collection doc criterion.
293 */
294 KorAP.Doc = {
295 _ldType : "doc",
296 _obj : function () { return KorAP.Doc; },
Nils Diewaldd0770492014-12-19 03:55:00 +0000297
298 create : function (parent, json) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000299 var obj = Object(KorAP.JsonLD).
300 create().
301 upgradeTo(KorAP.Doc).
302 fromJson(json);
303
Nils Diewaldd0770492014-12-19 03:55:00 +0000304 if (parent !== undefined)
305 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000306
307 obj._changed = true;
Nils Diewaldd0770492014-12-19 03:55:00 +0000308 return obj;
309 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000310
Nils Diewald966abf12014-12-20 02:27:45 +0000311 update : function () {
312 if (this._element === undefined)
313 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000314
Nils Diewald8f6b6102015-01-08 18:25:33 +0000315 // Get element
Nils Diewald966abf12014-12-20 02:27:45 +0000316 var e = this._element;
317
Nils Diewald8f6b6102015-01-08 18:25:33 +0000318 // Check if there is a change
319 if (this._changed) {
Nils Diewald966abf12014-12-20 02:27:45 +0000320
Nils Diewald8f6b6102015-01-08 18:25:33 +0000321 // Added key
322 var key = document.createElement('span');
323 key.setAttribute('class', 'key');
324 if (this.key())
325 key.appendChild(document.createTextNode(this.key()));
Nils Diewald966abf12014-12-20 02:27:45 +0000326
Nils Diewald8f6b6102015-01-08 18:25:33 +0000327 // Added match operator
328 var matchop = document.createElement('span');
329 matchop.setAttribute('data-type', this.type());
330 matchop.setAttribute('class', 'match');
331 matchop.appendChild(
332 document.createTextNode(this.matchop())
333 );
334
335 // Added match operator
336 var value = document.createElement('span');
337 value.setAttribute('data-type', this.type());
338 value.setAttribute('class', 'value');
339 if (this.value())
340 value.appendChild(
341 document.createTextNode(this.value())
342 );
343
344 // Remove all element children
345 _removeChildren(e);
346
347 // Add spans
348 e.appendChild(key);
349 e.appendChild(matchop);
350 e.appendChild(value);
351
352 this._changed = false;
353 };
354
355 if (this._parent !== undefined) {
356 // Set operators
357 var op = this.operators(
358 true,
359 true,
360 // No delete object, if this is the root
361 (this._parent !== undefined &&
362 this.parent().ldType() !== null) ? true : false
363 );
364
365 // Append new operators
366 e.appendChild(op.element());
367 };
Nils Diewald966abf12014-12-20 02:27:45 +0000368
Nils Diewaldd0770492014-12-19 03:55:00 +0000369 return e;
370 },
371
Nils Diewald966abf12014-12-20 02:27:45 +0000372 element : function () {
373 if (this._element !== undefined)
374 return this._element;
375
376 this._element = document.createElement('div');
377 this._element.setAttribute('class', 'doc');
378
379 this.update();
380 return this._element;
381 },
382
Nils Diewaldd0770492014-12-19 03:55:00 +0000383 // Wrap a new operation around the doc element
384 wrap : function (op) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000385/*
Nils Diewald8f4e2542014-12-19 04:42:09 +0000386 var group = KorAP.DocGroup.create(undefined);
Nils Diewald966abf12014-12-20 02:27:45 +0000387 group.append(this);
388 group.append(null);
Nils Diewaldd0770492014-12-19 03:55:00 +0000389 this.parent(group);
Nils Diewaldd0770492014-12-19 03:55:00 +0000390 var div = document.createElement('div');
391 div.setAttribute('data-operation', op);
392 var parent = this.element.parent;
393 parent.removeChild(this.element);
394 parent.appendChild(div);
395 div.appendChild(this.element);
396 return div;
397*/
Nils Diewaldd0770492014-12-19 03:55:00 +0000398 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000399 // Deserialize from json
400 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000401 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000402 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000403
Nils Diewald3a2d8022014-12-16 02:45:41 +0000404 if (json["@type"] !== "korap:doc") {
405 KorAP.log(701, "JSON-LD group has no @type attribute");
406 return;
407 };
408
Nils Diewald3a2d8022014-12-16 02:45:41 +0000409 if (json["value"] === undefined ||
410 typeof json["value"] != 'string') {
411 KorAP.log(805, "Value is invalid");
412 return;
413 };
414
415 // There is a defined key
416 if (json["key"] !== undefined &&
417 typeof json["key"] === 'string') {
418
419 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000420 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000421
422 // Set match operation
423 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000424 if (typeof json["match"] === 'string') {
425 this.matchop(json["match"]);
426 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000427 else {
428 KorAP.log(802, "Match type is not supported by value type");
429 return;
430 };
431 };
432
433 // Key is a string
434 if (json["type"] === undefined ||
435 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000436 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000437
438 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000439 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000440 KorAP.log(802, "Match type is not supported by value type");
441 return;
442 };
443
444 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000445 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000446 }
447
448 // Key is a date
449 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000450 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000451
452 if (json["value"] !== undefined &&
453 KorAP._validDateRE.test(json["value"])) {
454
Nils Diewaldd0770492014-12-19 03:55:00 +0000455 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000456 KorAP.log(802, "Match type is not supported by value type");
457 return;
458 };
459
460 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000461 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000462 }
463 else {
464 KorAP.log(806, "Value is not a valid date string");
465 return;
466 };
467 }
468
469 // Key is a regular expression
470 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000471 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000472
473 try {
474
475 // Try to create a regular expression
476 var check = new RegExp(json["value"]);
477
Nils Diewaldd0770492014-12-19 03:55:00 +0000478 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000479 KorAP.log(802, "Match type is not supported by value type");
480 return;
481 };
482
Nils Diewaldd0770492014-12-19 03:55:00 +0000483 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000484 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000485
Nils Diewald3a2d8022014-12-16 02:45:41 +0000486 catch (e) {
487 KorAP.log(807, "Value is not a valid regular expression");
488 return;
489 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000490 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000491 }
492
493 else {
494 KorAP.log(804, "Unknown value type");
495 return;
496 };
497 };
498
499 return this;
500 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000501 key : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000502 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000503 this._key = value;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000504 this._changed = true;
505 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000506 return this._key;
507 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000508 matchop : function (match) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000509 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000510 this._matchop = match.replace(/^match:/, '');
Nils Diewald8f6b6102015-01-08 18:25:33 +0000511 this._changed = true;
512 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000513 return this._matchop || "eq";
514 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000515 type : function (type) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000516 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000517 this._type = type;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000518 this._changed = true;
519 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000520 return this._type || "string";
521 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000522 value : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000523 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000524 this._value = value;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000525 this._changed = true;
526 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000527 return this._value;
528 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000529 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000530 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000531 return {};
532
533 return {
Nils Diewaldd0770492014-12-19 03:55:00 +0000534 "@type" : "korap:" + this.ldType(),
535 "key" : this.key(),
536 "match" : "match:" + this.matchop(),
537 "value" : this.value() || '',
538 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000539 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000540 },
541 toString : function () {
542 if (!this.matchop() || !this.key())
543 return "";
544
545 // Build doc string based on key
546 var string = this.key() + ' ';
547
548 // Add match operator
549 switch (this.matchop()) {
550 case "ne":
551 string += '!=';
552 break;
553 case "contains":
554 string += '~';
555 break;
556 case "geq":
557 string += 'since';
558 break;
559 case "leq":
560 string += 'until';
561 break;
562 default:
563 string += (this.type() == 'date') ? 'in' : '=';
564 break;
565 };
566
567 string += ' ';
568
569 // Add value
570 switch (this.type()) {
571 case "date":
572 return string + this.value();
573 break;
574 case "regex":
575 return string + '/' + this.value() + '/';
576 break;
577 case "string":
578 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
579 break;
580 };
581
582 return "...";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000583 }
584 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000585
586 /**
587 * Virtual collection group criterion.
588 */
589 KorAP.DocGroup = {
590 _ldType : "docGroup",
591
592 create : function (parent, json) {
593 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
594 obj._operands = [];
595 obj.fromJson(json);
596 if (parent !== undefined)
597 obj._parent = parent;
598 return obj;
599 },
Nils Diewald966abf12014-12-20 02:27:45 +0000600 append : function (operand) {
601
602 // Append unspecified object
603 if (operand === undefined) {
604
605 // Be aware of cyclic structures!
606 operand = KorAP.UnspecifiedDoc.create(this);
607 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000608 return operand;
609 };
610
Nils Diewald8f4e2542014-12-19 04:42:09 +0000611 switch (operand["@type"]) {
612 case undefined:
613 if (operand["ldType"] !== undefined) {
614 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000615 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000616 KorAP.log(812, "Operand not supported in document group");
617 return;
618 };
Nils Diewald966abf12014-12-20 02:27:45 +0000619 // Be aware of cyclic structures!
620 operand.parent(this);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000621 this._operands.push(operand);
622 return operand;
623 };
624
625 KorAP.log(701, "JSON-LD group has no @type attribute");
626 return;
627
628 case "korap:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000629 // Be aware of cyclic structures!
630 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000631 if (doc === undefined)
632 return;
633 this._operands.push(doc);
634 return doc;
635
636 case "korap:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000637 // Be aware of cyclic structures!
638 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000639 if (docGroup === undefined)
640 return;
641 this._operands.push(docGroup);
642 return docGroup;
643
644 default:
645 KorAP.log(812, "Operand not supported in document group");
646 return;
647 };
648 },
Nils Diewald966abf12014-12-20 02:27:45 +0000649 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000650 // There is only one operand in group
651 if (this._operands.length === 1) {
652 var parent = this.parent();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000653 var op = this.getOperand(0);
654
Nils Diewald8f6b6102015-01-08 18:25:33 +0000655 // This will prevent destruction of
656 // the operand
657 this._operands = [];
Nils Diewaldf219eb82015-01-07 20:15:42 +0000658
659 // Parent is a group
660 if (parent.ldType() !== null) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000661 return parent.replaceOperand(this, op).update();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000662 }
663
Nils Diewald8f6b6102015-01-08 18:25:33 +0000664 // Parent is vc
Nils Diewaldf219eb82015-01-07 20:15:42 +0000665 else {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000666 this.destroy();
Nils Diewald8f6b6102015-01-08 18:25:33 +0000667 // Cyclic madness
668 parent.root(op);
669 op.parent(parent);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000670 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000671 };
672 };
673
Nils Diewald966abf12014-12-20 02:27:45 +0000674 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000675 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000676
Nils Diewald5c817a42015-01-06 01:08:56 +0000677 var group = this._element;
678 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000679
Nils Diewald5c817a42015-01-06 01:08:56 +0000680 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000681
682 // Append operands
Nils Diewald5c817a42015-01-06 01:08:56 +0000683 for (var i in this._operands) {
684 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000685 this.getOperand(i).element()
686 );
687 };
688
689 // Set operators
690 var op = this.operators(
691 this.operation() == 'and' ? false : true,
692 this.operation() == 'or' ? false : true,
693 true
694 );
695
Nils Diewald5c817a42015-01-06 01:08:56 +0000696 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000697 op.element()
698 );
699
Nils Diewald5c817a42015-01-06 01:08:56 +0000700 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000701 },
Nils Diewald8f4e2542014-12-19 04:42:09 +0000702 element : function () {
703 if (this._element !== undefined)
704 return this._element;
705
706 this._element = document.createElement('div');
707 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000708
Nils Diewaldf219eb82015-01-07 20:15:42 +0000709 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000710 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000711
712 return this._element;
713 },
714 operation : function (op) {
715 if (arguments.length === 1) {
716 if (KorAP._validGroupOpRE.test(op)) {
717 this._op = op;
718 }
719 else {
720 KorAP.log(810, "Unknown operation type");
721 return;
722 };
723 };
724 return this._op || 'and';
725 },
726 operands : function () {
727 return this._operands;
728 },
729 getOperand : function (index) {
730 return this._operands[index];
731 },
732
Nils Diewald5c817a42015-01-06 01:08:56 +0000733 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000734 replaceOperand : function (oldOp, newOp) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000735
Nils Diewald5c817a42015-01-06 01:08:56 +0000736 for (var i in this._operands) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000737 if (this._operands[i] === oldOp) {
738
739 // Just insert a doc
740 if (newOp.ldType() === "doc") {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000741 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000742 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000743 }
744 // Insert a group of a different operation
745 // (i.e. "and" in "or"/"or" in "and")
Nils Diewald8e7182e2015-01-08 15:02:07 +0000746 else if (newOp.operation() != this.operation()) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000747 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000748 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000749 }
750
751 // Flatten the group
752 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000753 // Remove old group
754 this._operands.splice(i, 1);
755
756 // Inject new operands
Nils Diewald8f6b6102015-01-08 18:25:33 +0000757 for (var op in newOp.operands().reverse()) {
758 this._operands.splice(i, 0, newOp.getOperand(op));
759 newOp.getOperand(0).parent(this);
760 };
761 // Prevent destruction of operands
762 newOp._operands = [];
763 newOp.destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000764 };
765 oldOp.destroy();
766 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000767 }
768 };
769 return false;
770 },
771
Nils Diewald0297ba12015-01-05 21:56:12 +0000772 // Delete operand from group
773 delOperand : function (obj) {
774 for (var i in this._operands) {
775 if (this._operands[i] === obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000776
Nils Diewald8f6b6102015-01-08 18:25:33 +0000777 // Delete identified operand
Nils Diewald0297ba12015-01-05 21:56:12 +0000778 this._operands.splice(i,1);
779
Nils Diewald5c817a42015-01-06 01:08:56 +0000780 // Destroy object for cyclic references
781 obj.destroy();
782
Nils Diewaldf219eb82015-01-07 20:15:42 +0000783 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +0000784 };
785 };
Nils Diewald5c817a42015-01-06 01:08:56 +0000786
787 // Operand not found
788 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +0000789 },
790
Nils Diewald8f4e2542014-12-19 04:42:09 +0000791 // Deserialize from json
792 fromJson : function (json) {
793 if (json === undefined)
794 return this;
795
796 if (json["@type"] !== "korap:docGroup") {
797 KorAP.log(701, "JSON-LD group has no @type attribute");
798 return;
799 };
800
801 if (json["operation"] === undefined ||
802 typeof json["operation"] !== 'string') {
803 KorAP.log(811, "Document group expects operation");
804 return;
805 };
806
807 var operation = json["operation"];
808
809 this.operation(operation.replace(/^operation:/,''));
810
811 if (json["operands"] === undefined ||
812 !(json["operands"] instanceof Array)) {
813 KorAP.log(704, "Operation needs operand list")
814 return;
815 };
816
817 // Add all documents
818 for (var i in json["operands"]) {
819 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +0000820 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000821 };
822
823 return this;
824 },
825 toJson : function () {
826 var opArray = new Array();
827 for (var i in this._operands) {
828 opArray.push(this._operands[i].toJson());
829 };
830 return {
831 "@type" : "korap:" + this.ldType(),
832 "operation" : "operation:" + this.operation(),
833 "operands" : opArray
834 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000835 },
836 toString : function () {
837 return this._operands.
838 map(function (op) {
839 return op.ldType() === 'docGroup' ? '(' + op.toString() + ')' : op.toString()
840 }).
841 join(this.operation() === 'or' ? ' | ' : ' & ')
Nils Diewald8f4e2542014-12-19 04:42:09 +0000842 }
843 };
844
845
846 // Abstract JsonLD object
847 KorAP.JsonLD = {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000848 _changed : false,
849
Nils Diewald8f4e2542014-12-19 04:42:09 +0000850 create : function () {
851 return Object.create(KorAP.JsonLD);
852 },
853
854 /**
855 * Upgrade this object to another object
856 * while private data stays intact
857 */
858 upgradeTo : function (props) {
859 for (var prop in props) {
860 this[prop] = props[prop];
861 };
862 return this;
863 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000864
Nils Diewald8f4e2542014-12-19 04:42:09 +0000865 ldType : function (type) {
866 if (arguments.length === 1)
867 this._ldType = type;
868 return this._ldType;
869 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000870
Nils Diewald8f4e2542014-12-19 04:42:09 +0000871 parent : function (obj) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000872 if (arguments.length === 1) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000873 this._parent = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000874 this._changed = true;
875 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000876 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +0000877 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000878
Nils Diewald5c817a42015-01-06 01:08:56 +0000879 // Destroy object - especially for
880 // acyclic structures!
881 // I'm a paranoid chicken!
882 destroy : function () {
883 if (this._ops != undefined) {
884 this._ops._parent = undefined;
885 if (this._ops._element !== undefined)
886 this._ops._element.refTo = undefined;
887 this._ops = undefined;
888 };
889 if (this._element !== undefined)
890 this._element = undefined;
891
892 // In case of a group, destroy all operands
893 if (this._operands !== undefined) {
894 for (var i in this._operands)
895 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000896 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +0000897 };
898 },
899
Nils Diewald0297ba12015-01-05 21:56:12 +0000900 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +0000901 operators : function (and, or, del) {
902 if (arguments === 0)
903 return this._ops;
904 this._ops = KorAP.Operators.create(
905 and, or, del
906 );
Nils Diewald0297ba12015-01-05 21:56:12 +0000907 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +0000908 return this._ops;
909 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000910
Nils Diewald966abf12014-12-20 02:27:45 +0000911 toJson : function () {
912 return {
913 // Unspecified object
914 "@type" : "korap:" + this.ldType()
915 };
Nils Diewald8f6b6102015-01-08 18:25:33 +0000916 },
917 toString : function () {
918 return loc.EMPTY;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000919 }
920 };
921
Nils Diewald3a2d8022014-12-16 02:45:41 +0000922}(this.KorAP));