blob: a713b095529a6581ded484b25ebf1244383246fb [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
49 while (node.firstChild) {
50 node.removeChild(node.firstChild);
51 };
52 };
53
Nils Diewald3a2d8022014-12-16 02:45:41 +000054 KorAP.VirtualCollection = {
Nils Diewaldf219eb82015-01-07 20:15:42 +000055 ldType : function () {
56 return null;
57 },
Nils Diewald3a2d8022014-12-16 02:45:41 +000058 create : function () {
59 return Object.create(KorAP.VirtualCollection);
60 },
Nils Diewaldd0770492014-12-19 03:55:00 +000061 render : function (json) {
62 var obj = Object.create(KorAP.VirtualCollection);
63
64 if (json !== undefined) {
65 // Root object
66 if (json['@type'] == 'korap:doc') {
Nils Diewaldf219eb82015-01-07 20:15:42 +000067 obj._root = KorAP.Doc.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000068 }
69 else if (json['@type'] == 'korap:docGroup') {
Nils Diewaldf219eb82015-01-07 20:15:42 +000070 obj._root = KorAP.DocGroup.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000071 }
72 else {
73 KorAP.log(813, "Collection type is not supported");
74 return;
75 };
76 }
77
78 else {
79 // Add unspecified object
Nils Diewaldf219eb82015-01-07 20:15:42 +000080 obj._root = KorAP.UnspecifiedDoc.create(obj);
Nils Diewaldd0770492014-12-19 03:55:00 +000081 };
82
83 // Add root element to root node
84 obj.element().appendChild(
85 obj._root.element()
86 );
87
88 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +000089 },
Nils Diewaldf219eb82015-01-07 20:15:42 +000090 root : function (obj) {
91 if (arguments.length === 1)
92 this._root = obj;
Nils Diewaldd0770492014-12-19 03:55:00 +000093 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +000094 },
Nils Diewaldd0770492014-12-19 03:55:00 +000095 element : function () {
96 if (this._element !== undefined)
97 return this._element;
98
99 this._element = document.createElement('div');
100 this._element.setAttribute('class', 'vc');
101 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000102 },
103 toJson : function () {
104 return this._root.toJson();
105 },
106 toString : function () {
107 return this._root.toString();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000108 }
109 };
110
Nils Diewald0297ba12015-01-05 21:56:12 +0000111 KorAP._or = function (e) {
112 var obj = this.parentNode.refTo;
113 };
114
115 KorAP._and = function (e) {
116 var obj = this.parentNode.refTo;
117 };
118
119 KorAP._delete = function (e) {
120 var obj = this.parentNode.refTo;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000121 obj.parent().delOperand(obj).update();
Nils Diewald0297ba12015-01-05 21:56:12 +0000122 // Todo: CLEAR ALL THE THINGS!
123 };
124
Nils Diewald8f4e2542014-12-19 04:42:09 +0000125 /**
126 * Operators for criteria
127 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000128 KorAP.Operators = {
129 create : function (and, or, del) {
130 var op = Object.create(KorAP.Operators);
131 op.and(and);
132 op.or(or);
133 op.del(del);
134 return op;
135 },
136 update : function () {
137
138 // Init the element
139 if (this._element === undefined)
140 return this.element();
141
142 var op = this._element;
143
Nils Diewald0297ba12015-01-05 21:56:12 +0000144 op.refTo = this.parent();
145
Nils Diewaldd0770492014-12-19 03:55:00 +0000146 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000147 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000148
149 // Add and button
150 if (this._and === true) {
151 var andE = document.createElement('span');
152 andE.setAttribute('class', 'and');
Nils Diewald0297ba12015-01-05 21:56:12 +0000153 andE.addEventListener('click', KorAP._and, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000154 andE.appendChild(document.createTextNode(KorAP.Locale.AND));
155 op.appendChild(andE);
156 };
157
158 // Add or button
159 if (this._or === true) {
160 var orE = document.createElement('span');
161 orE.setAttribute('class', 'or');
Nils Diewald0297ba12015-01-05 21:56:12 +0000162 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000163 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
164 op.appendChild(orE);
165 };
166
167 // Add delete button
168 if (this._del === true) {
169 var delE = document.createElement('span');
170 delE.setAttribute('class', 'delete');
171 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000172 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000173 op.appendChild(delE);
174 };
Nils Diewald966abf12014-12-20 02:27:45 +0000175
176 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000177 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000178
179 // Be aware! This may be cyclic
180 parent : function (obj) {
181 if (arguments.length === 1)
182 this._parent = obj;
183 return this._parent;
184 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000185
Nils Diewaldd0770492014-12-19 03:55:00 +0000186 element : function () {
187
188 // Return existing element
189 if (this._element !== undefined)
190 return this._element;
191
192 this._element = document.createElement('div');
193 this._element.setAttribute('class', 'operators');
194
195 // Init elements
196 this.update();
197 return this._element;
198 },
199 and : function (bool) {
200 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000201 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000202 return this._and;
203 },
204 or : function (bool) {
205 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000206 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000207 return this._or;
208 },
209 del : function (bool) {
210 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000211 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000212 return this._del;
213 }
214 };
215
216
217 /**
218 * Unspecified criterion
219 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000220 KorAP.UnspecifiedDoc = {
Nils Diewald966abf12014-12-20 02:27:45 +0000221 _ldType : "doc",
Nils Diewaldd0770492014-12-19 03:55:00 +0000222 create : function (parent) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000223 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.UnspecifiedDoc);
Nils Diewaldd0770492014-12-19 03:55:00 +0000224 if (parent !== undefined)
225 obj._parent = parent;
226 return obj;
227 },
Nils Diewald966abf12014-12-20 02:27:45 +0000228 update : function () {
229 if (this._element === undefined)
230 return this.element();
231
232 _removeChildren(this._element);
233
234 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000235 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000236 this._element.appendChild(ellipsis);
237
238 // Set operators
239 var op = this.operators(
240 false,
241 false,
242 // No delete object, if this is the root
Nils Diewaldf219eb82015-01-07 20:15:42 +0000243 (this._parent !== undefined && this.parent().ldType() !== null) ? true : false
Nils Diewald966abf12014-12-20 02:27:45 +0000244 );
245
246 this._element.appendChild(
247 op.element()
248 );
249
Nils Diewald966abf12014-12-20 02:27:45 +0000250 return this.element();
251 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000252 element : function () {
253 if (this._element !== undefined)
254 return this._element;
Nils Diewald966abf12014-12-20 02:27:45 +0000255
Nils Diewaldd0770492014-12-19 03:55:00 +0000256 this._element = document.createElement('div');
Nils Diewald966abf12014-12-20 02:27:45 +0000257 this._element.setAttribute('class', 'unspecified');
258
259 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000260 return this._element;
261 }
262 };
263
264
Nils Diewald8f4e2542014-12-19 04:42:09 +0000265 /**
266 * Virtual collection doc criterion.
267 */
268 KorAP.Doc = {
269 _ldType : "doc",
270 _obj : function () { return KorAP.Doc; },
Nils Diewaldd0770492014-12-19 03:55:00 +0000271
272 create : function (parent, json) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000273 var obj = Object(KorAP.JsonLD).create().upgradeTo(KorAP.Doc).fromJson(json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000274 if (parent !== undefined)
275 obj._parent = parent;
276 return obj;
277 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000278
Nils Diewald966abf12014-12-20 02:27:45 +0000279 update : function () {
280 if (this._element === undefined)
281 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000282
283 // Added key
284 var key = document.createElement('span');
285 key.setAttribute('class', 'key');
286 if (this.key())
287 key.appendChild(document.createTextNode(this.key()));
288
289 // Added match operator
290 var matchop = document.createElement('span');
291 matchop.setAttribute('data-type', this.type());
292 matchop.setAttribute('class', 'match');
293 matchop.appendChild(document.createTextNode(this.matchop()));
294
295 // Added match operator
296 var value = document.createElement('span');
297 value.setAttribute('data-type', this.type());
298 value.setAttribute('class', 'value');
299 if (this.value())
300 value.appendChild(document.createTextNode(this.value()));
301
Nils Diewald966abf12014-12-20 02:27:45 +0000302 var e = this._element;
303
Nils Diewaldd0770492014-12-19 03:55:00 +0000304 // Add spans
305 e.appendChild(key);
306 e.appendChild(matchop);
307 e.appendChild(value);
Nils Diewald966abf12014-12-20 02:27:45 +0000308
309 // Set operators
310 var op = this.operators(true, true, true);
311
312 e.appendChild(op.element());
313
Nils Diewaldd0770492014-12-19 03:55:00 +0000314 return e;
315 },
316
Nils Diewald966abf12014-12-20 02:27:45 +0000317 element : function () {
318 if (this._element !== undefined)
319 return this._element;
320
321 this._element = document.createElement('div');
322 this._element.setAttribute('class', 'doc');
323
324 this.update();
325 return this._element;
326 },
327
Nils Diewaldd0770492014-12-19 03:55:00 +0000328 // Wrap a new operation around the doc element
329 wrap : function (op) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000330/*
Nils Diewald8f4e2542014-12-19 04:42:09 +0000331 var group = KorAP.DocGroup.create(undefined);
Nils Diewald966abf12014-12-20 02:27:45 +0000332 group.append(this);
333 group.append(null);
Nils Diewaldd0770492014-12-19 03:55:00 +0000334 this.parent(group);
Nils Diewaldd0770492014-12-19 03:55:00 +0000335 var div = document.createElement('div');
336 div.setAttribute('data-operation', op);
337 var parent = this.element.parent;
338 parent.removeChild(this.element);
339 parent.appendChild(div);
340 div.appendChild(this.element);
341 return div;
342*/
Nils Diewaldd0770492014-12-19 03:55:00 +0000343 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000344 // Deserialize from json
345 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000346 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000347 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000348
Nils Diewald3a2d8022014-12-16 02:45:41 +0000349 if (json["@type"] !== "korap:doc") {
350 KorAP.log(701, "JSON-LD group has no @type attribute");
351 return;
352 };
353
Nils Diewald3a2d8022014-12-16 02:45:41 +0000354 if (json["value"] === undefined ||
355 typeof json["value"] != 'string') {
356 KorAP.log(805, "Value is invalid");
357 return;
358 };
359
360 // There is a defined key
361 if (json["key"] !== undefined &&
362 typeof json["key"] === 'string') {
363
364 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000365 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000366
367 // Set match operation
368 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000369 if (typeof json["match"] === 'string') {
370 this.matchop(json["match"]);
371 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000372 else {
373 KorAP.log(802, "Match type is not supported by value type");
374 return;
375 };
376 };
377
378 // Key is a string
379 if (json["type"] === undefined ||
380 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000381 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000382
383 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000384 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000385 KorAP.log(802, "Match type is not supported by value type");
386 return;
387 };
388
389 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000390 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000391 }
392
393 // Key is a date
394 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000395 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000396
397 if (json["value"] !== undefined &&
398 KorAP._validDateRE.test(json["value"])) {
399
Nils Diewaldd0770492014-12-19 03:55:00 +0000400 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000401 KorAP.log(802, "Match type is not supported by value type");
402 return;
403 };
404
405 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000406 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000407 }
408 else {
409 KorAP.log(806, "Value is not a valid date string");
410 return;
411 };
412 }
413
414 // Key is a regular expression
415 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000416 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000417
418 try {
419
420 // Try to create a regular expression
421 var check = new RegExp(json["value"]);
422
Nils Diewaldd0770492014-12-19 03:55:00 +0000423 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000424 KorAP.log(802, "Match type is not supported by value type");
425 return;
426 };
427
Nils Diewaldd0770492014-12-19 03:55:00 +0000428 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000429 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000430
Nils Diewald3a2d8022014-12-16 02:45:41 +0000431 catch (e) {
432 KorAP.log(807, "Value is not a valid regular expression");
433 return;
434 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000435 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000436 }
437
438 else {
439 KorAP.log(804, "Unknown value type");
440 return;
441 };
442 };
443
444 return this;
445 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000446 key : function (value) {
447 if (arguments.length === 1)
448 this._key = value;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000449 return this._key;
450 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000451 matchop : function (match) {
452 if (arguments.length === 1)
453 this._matchop = match.replace(/^match:/, '');
Nils Diewald3a2d8022014-12-16 02:45:41 +0000454 return this._matchop || "eq";
455 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000456 type : function (type) {
457 if (arguments.length === 1)
458 this._type = type;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000459 return this._type || "string";
460 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000461 value : function (value) {
462 if (arguments.length === 1)
463 this._value = value;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000464 return this._value;
465 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000466 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000467 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000468 return {};
469
470 return {
Nils Diewaldd0770492014-12-19 03:55:00 +0000471 "@type" : "korap:" + this.ldType(),
472 "key" : this.key(),
473 "match" : "match:" + this.matchop(),
474 "value" : this.value() || '',
475 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000476 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000477 },
478 toString : function () {
479 if (!this.matchop() || !this.key())
480 return "";
481
482 // Build doc string based on key
483 var string = this.key() + ' ';
484
485 // Add match operator
486 switch (this.matchop()) {
487 case "ne":
488 string += '!=';
489 break;
490 case "contains":
491 string += '~';
492 break;
493 case "geq":
494 string += 'since';
495 break;
496 case "leq":
497 string += 'until';
498 break;
499 default:
500 string += (this.type() == 'date') ? 'in' : '=';
501 break;
502 };
503
504 string += ' ';
505
506 // Add value
507 switch (this.type()) {
508 case "date":
509 return string + this.value();
510 break;
511 case "regex":
512 return string + '/' + this.value() + '/';
513 break;
514 case "string":
515 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
516 break;
517 };
518
519 return "...";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000520 }
521 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000522
523 /**
524 * Virtual collection group criterion.
525 */
526 KorAP.DocGroup = {
527 _ldType : "docGroup",
528
529 create : function (parent, json) {
530 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
531 obj._operands = [];
532 obj.fromJson(json);
533 if (parent !== undefined)
534 obj._parent = parent;
535 return obj;
536 },
Nils Diewald966abf12014-12-20 02:27:45 +0000537 append : function (operand) {
538
539 // Append unspecified object
540 if (operand === undefined) {
541
542 // Be aware of cyclic structures!
543 operand = KorAP.UnspecifiedDoc.create(this);
544 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000545 return operand;
546 };
547
Nils Diewald8f4e2542014-12-19 04:42:09 +0000548 switch (operand["@type"]) {
549 case undefined:
550 if (operand["ldType"] !== undefined) {
551 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000552 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000553 KorAP.log(812, "Operand not supported in document group");
554 return;
555 };
Nils Diewald966abf12014-12-20 02:27:45 +0000556 // Be aware of cyclic structures!
557 operand.parent(this);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000558 this._operands.push(operand);
559 return operand;
560 };
561
562 KorAP.log(701, "JSON-LD group has no @type attribute");
563 return;
564
565 case "korap:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000566 // Be aware of cyclic structures!
567 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000568 if (doc === undefined)
569 return;
570 this._operands.push(doc);
571 return doc;
572
573 case "korap:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000574 // Be aware of cyclic structures!
575 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000576 if (docGroup === undefined)
577 return;
578 this._operands.push(docGroup);
579 return docGroup;
580
581 default:
582 KorAP.log(812, "Operand not supported in document group");
583 return;
584 };
585 },
Nils Diewald966abf12014-12-20 02:27:45 +0000586 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000587
588 // There is only one operand in group
589 if (this._operands.length === 1) {
590 var parent = this.parent();
591
592 // Parent is a group
593 if (parent.ldType() !== null) {
594 return parent.replaceOperand(
Nils Diewald5c817a42015-01-06 01:08:56 +0000595 this,
596 this.getOperand(0)
Nils Diewaldf219eb82015-01-07 20:15:42 +0000597 ).update();
598 }
599
600 // Parent is vc root
601 else {
602console.log("parent is vc");
603 parent.root(this.getOperand(0));
604 this.destroy();
605 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000606 };
607 };
608
Nils Diewald966abf12014-12-20 02:27:45 +0000609 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000610 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000611
Nils Diewald5c817a42015-01-06 01:08:56 +0000612 var group = this._element;
613 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000614
Nils Diewald5c817a42015-01-06 01:08:56 +0000615 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000616
617 // Append operands
Nils Diewald5c817a42015-01-06 01:08:56 +0000618 for (var i in this._operands) {
619 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000620 this.getOperand(i).element()
621 );
622 };
623
624 // Set operators
625 var op = this.operators(
626 this.operation() == 'and' ? false : true,
627 this.operation() == 'or' ? false : true,
628 true
629 );
630
Nils Diewald5c817a42015-01-06 01:08:56 +0000631 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000632 op.element()
633 );
634
Nils Diewald5c817a42015-01-06 01:08:56 +0000635 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000636 },
Nils Diewald8f4e2542014-12-19 04:42:09 +0000637 element : function () {
638 if (this._element !== undefined)
639 return this._element;
640
641 this._element = document.createElement('div');
642 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000643
Nils Diewaldf219eb82015-01-07 20:15:42 +0000644 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000645 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000646
647 return this._element;
648 },
649 operation : function (op) {
650 if (arguments.length === 1) {
651 if (KorAP._validGroupOpRE.test(op)) {
652 this._op = op;
653 }
654 else {
655 KorAP.log(810, "Unknown operation type");
656 return;
657 };
658 };
659 return this._op || 'and';
660 },
661 operands : function () {
662 return this._operands;
663 },
664 getOperand : function (index) {
665 return this._operands[index];
666 },
667
Nils Diewald5c817a42015-01-06 01:08:56 +0000668 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000669 replaceOperand : function (oldOp, newOp) {
Nils Diewald5c817a42015-01-06 01:08:56 +0000670 for (var i in this._operands) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000671 if (this._operands[i] === oldOp) {
672
673 // Just insert a doc
674 if (newOp.ldType() === "doc") {
675 console.log("Insert doc in group");
676 this._operands[i] = newOp;
677 }
678 // Insert a group of a different operation
679 // (i.e. "and" in "or"/"or" in "and")
680 else if (newOp.operation() != oldOp.operation()) {
681 console.log("Insert group in group - no flatten");
682 this._operands[i] = newOp;
683 }
684
685 // Flatten the group
686 else {
687 console.log("Insert group in group - flatten");
688 for (var op in newOp.operands().reverse())
689 this._operands.splice(i, 1, newOp.getOperand(op))
690 };
691 oldOp.destroy();
692 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000693 }
694 };
695 return false;
696 },
697
Nils Diewald0297ba12015-01-05 21:56:12 +0000698 // Delete operand from group
699 delOperand : function (obj) {
700 for (var i in this._operands) {
701 if (this._operands[i] === obj) {
702 this._operands.splice(i,1);
703
Nils Diewald5c817a42015-01-06 01:08:56 +0000704 // Destroy object for cyclic references
705 obj.destroy();
706
Nils Diewald0297ba12015-01-05 21:56:12 +0000707 // Todo: Update has to check
708 // that this may mean the group is empty etc.
Nils Diewaldf219eb82015-01-07 20:15:42 +0000709 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +0000710 };
711 };
Nils Diewald5c817a42015-01-06 01:08:56 +0000712
713 // Operand not found
714 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +0000715 },
716
Nils Diewald8f4e2542014-12-19 04:42:09 +0000717 // Deserialize from json
718 fromJson : function (json) {
719 if (json === undefined)
720 return this;
721
722 if (json["@type"] !== "korap:docGroup") {
723 KorAP.log(701, "JSON-LD group has no @type attribute");
724 return;
725 };
726
727 if (json["operation"] === undefined ||
728 typeof json["operation"] !== 'string') {
729 KorAP.log(811, "Document group expects operation");
730 return;
731 };
732
733 var operation = json["operation"];
734
735 this.operation(operation.replace(/^operation:/,''));
736
737 if (json["operands"] === undefined ||
738 !(json["operands"] instanceof Array)) {
739 KorAP.log(704, "Operation needs operand list")
740 return;
741 };
742
743 // Add all documents
744 for (var i in json["operands"]) {
745 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +0000746 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000747 };
748
749 return this;
750 },
751 toJson : function () {
752 var opArray = new Array();
753 for (var i in this._operands) {
754 opArray.push(this._operands[i].toJson());
755 };
756 return {
757 "@type" : "korap:" + this.ldType(),
758 "operation" : "operation:" + this.operation(),
759 "operands" : opArray
760 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000761 },
762 toString : function () {
763 return this._operands.
764 map(function (op) {
765 return op.ldType() === 'docGroup' ? '(' + op.toString() + ')' : op.toString()
766 }).
767 join(this.operation() === 'or' ? ' | ' : ' & ')
Nils Diewald8f4e2542014-12-19 04:42:09 +0000768 }
769 };
770
771
772 // Abstract JsonLD object
773 KorAP.JsonLD = {
774 create : function () {
775 return Object.create(KorAP.JsonLD);
776 },
777
778 /**
779 * Upgrade this object to another object
780 * while private data stays intact
781 */
782 upgradeTo : function (props) {
783 for (var prop in props) {
784 this[prop] = props[prop];
785 };
786 return this;
787 },
788 ldType : function (type) {
789 if (arguments.length === 1)
790 this._ldType = type;
791 return this._ldType;
792 },
793 parent : function (obj) {
794 if (arguments.length === 1)
795 this._parent = obj;
796 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +0000797 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000798
Nils Diewald5c817a42015-01-06 01:08:56 +0000799 // Destroy object - especially for
800 // acyclic structures!
801 // I'm a paranoid chicken!
802 destroy : function () {
803 if (this._ops != undefined) {
804 this._ops._parent = undefined;
805 if (this._ops._element !== undefined)
806 this._ops._element.refTo = undefined;
807 this._ops = undefined;
808 };
809 if (this._element !== undefined)
810 this._element = undefined;
811
812 // In case of a group, destroy all operands
813 if (this._operands !== undefined) {
814 for (var i in this._operands)
815 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000816 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +0000817 };
818 },
819
Nils Diewald0297ba12015-01-05 21:56:12 +0000820 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +0000821 operators : function (and, or, del) {
822 if (arguments === 0)
823 return this._ops;
824 this._ops = KorAP.Operators.create(
825 and, or, del
826 );
Nils Diewald0297ba12015-01-05 21:56:12 +0000827 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +0000828 return this._ops;
829 },
830 toJson : function () {
831 return {
832 // Unspecified object
833 "@type" : "korap:" + this.ldType()
834 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000835 }
836 };
837
Nils Diewald3a2d8022014-12-16 02:45:41 +0000838}(this.KorAP));