blob: 6cb3925732ab86fe5a49279f71d0233c359bf07e [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
Nils Diewald8e7182e2015-01-08 15:02:07 +000083 // Init element and update
84 obj.update();
Nils Diewaldd0770492014-12-19 03:55:00 +000085
86 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +000087 },
Nils Diewaldf219eb82015-01-07 20:15:42 +000088 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +000089 if (arguments.length === 1) {
90console.log("Set vc root to " + obj.toString());
Nils Diewaldf219eb82015-01-07 20:15:42 +000091 this._root = obj;
Nils Diewald8e7182e2015-01-08 15:02:07 +000092 this.update();
93 };
Nils Diewaldd0770492014-12-19 03:55:00 +000094 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +000095 },
Nils Diewaldd0770492014-12-19 03:55:00 +000096 element : function () {
97 if (this._element !== undefined)
98 return this._element;
99
100 this._element = document.createElement('div');
101 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000102
Nils Diewaldd0770492014-12-19 03:55:00 +0000103 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000104 },
105 toJson : function () {
106 return this._root.toJson();
107 },
108 toString : function () {
109 return this._root.toString();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000110 },
111 update : function () {
112 var e = this.element();
113 if (e.firstChild !== null)
114 e.replaceChild(this._root.element(), e.firstChild);
115 else
116 e.appendChild(this._root.element());
Nils Diewald3a2d8022014-12-16 02:45:41 +0000117 }
118 };
119
Nils Diewald0297ba12015-01-05 21:56:12 +0000120 KorAP._or = function (e) {
121 var obj = this.parentNode.refTo;
122 };
123
124 KorAP._and = function (e) {
125 var obj = this.parentNode.refTo;
126 };
127
128 KorAP._delete = function (e) {
129 var obj = this.parentNode.refTo;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000130 obj.parent().delOperand(obj).update();
Nils Diewald0297ba12015-01-05 21:56:12 +0000131 // Todo: CLEAR ALL THE THINGS!
132 };
133
Nils Diewald8f4e2542014-12-19 04:42:09 +0000134 /**
135 * Operators for criteria
136 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000137 KorAP.Operators = {
138 create : function (and, or, del) {
139 var op = Object.create(KorAP.Operators);
140 op.and(and);
141 op.or(or);
142 op.del(del);
143 return op;
144 },
145 update : function () {
146
147 // Init the element
148 if (this._element === undefined)
149 return this.element();
150
151 var op = this._element;
152
Nils Diewald0297ba12015-01-05 21:56:12 +0000153 op.refTo = this.parent();
154
Nils Diewaldd0770492014-12-19 03:55:00 +0000155 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000156 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000157
158 // Add and button
159 if (this._and === true) {
160 var andE = document.createElement('span');
161 andE.setAttribute('class', 'and');
Nils Diewald0297ba12015-01-05 21:56:12 +0000162 andE.addEventListener('click', KorAP._and, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000163 andE.appendChild(document.createTextNode(KorAP.Locale.AND));
164 op.appendChild(andE);
165 };
166
167 // Add or button
168 if (this._or === true) {
169 var orE = document.createElement('span');
170 orE.setAttribute('class', 'or');
Nils Diewald0297ba12015-01-05 21:56:12 +0000171 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000172 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
173 op.appendChild(orE);
174 };
175
176 // Add delete button
177 if (this._del === true) {
178 var delE = document.createElement('span');
179 delE.setAttribute('class', 'delete');
180 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000181 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000182 op.appendChild(delE);
183 };
Nils Diewald966abf12014-12-20 02:27:45 +0000184
185 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000186 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000187
188 // Be aware! This may be cyclic
189 parent : function (obj) {
190 if (arguments.length === 1)
191 this._parent = obj;
192 return this._parent;
193 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000194
Nils Diewaldd0770492014-12-19 03:55:00 +0000195 element : function () {
196
197 // Return existing element
198 if (this._element !== undefined)
199 return this._element;
200
201 this._element = document.createElement('div');
202 this._element.setAttribute('class', 'operators');
203
204 // Init elements
205 this.update();
206 return this._element;
207 },
208 and : function (bool) {
209 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000210 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000211 return this._and;
212 },
213 or : function (bool) {
214 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000215 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000216 return this._or;
217 },
218 del : function (bool) {
219 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000220 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000221 return this._del;
222 }
223 };
224
225
226 /**
227 * Unspecified criterion
228 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000229 KorAP.UnspecifiedDoc = {
Nils Diewald966abf12014-12-20 02:27:45 +0000230 _ldType : "doc",
Nils Diewaldd0770492014-12-19 03:55:00 +0000231 create : function (parent) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000232 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.UnspecifiedDoc);
Nils Diewaldd0770492014-12-19 03:55:00 +0000233 if (parent !== undefined)
234 obj._parent = parent;
235 return obj;
236 },
Nils Diewald966abf12014-12-20 02:27:45 +0000237 update : function () {
238 if (this._element === undefined)
239 return this.element();
240
241 _removeChildren(this._element);
242
243 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000244 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000245 this._element.appendChild(ellipsis);
246
247 // Set operators
248 var op = this.operators(
249 false,
250 false,
251 // No delete object, if this is the root
Nils Diewaldf219eb82015-01-07 20:15:42 +0000252 (this._parent !== undefined && this.parent().ldType() !== null) ? true : false
Nils Diewald966abf12014-12-20 02:27:45 +0000253 );
254
255 this._element.appendChild(
256 op.element()
257 );
258
Nils Diewald966abf12014-12-20 02:27:45 +0000259 return this.element();
260 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000261 element : function () {
262 if (this._element !== undefined)
263 return this._element;
Nils Diewald966abf12014-12-20 02:27:45 +0000264
Nils Diewaldd0770492014-12-19 03:55:00 +0000265 this._element = document.createElement('div');
Nils Diewald966abf12014-12-20 02:27:45 +0000266 this._element.setAttribute('class', 'unspecified');
267
268 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000269 return this._element;
270 }
271 };
272
273
Nils Diewald8f4e2542014-12-19 04:42:09 +0000274 /**
275 * Virtual collection doc criterion.
276 */
277 KorAP.Doc = {
278 _ldType : "doc",
279 _obj : function () { return KorAP.Doc; },
Nils Diewaldd0770492014-12-19 03:55:00 +0000280
281 create : function (parent, json) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000282 var obj = Object(KorAP.JsonLD).create().upgradeTo(KorAP.Doc).fromJson(json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000283 if (parent !== undefined)
284 obj._parent = parent;
285 return obj;
286 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000287
Nils Diewald966abf12014-12-20 02:27:45 +0000288 update : function () {
289 if (this._element === undefined)
290 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000291
292 // Added key
293 var key = document.createElement('span');
294 key.setAttribute('class', 'key');
295 if (this.key())
296 key.appendChild(document.createTextNode(this.key()));
297
298 // Added match operator
299 var matchop = document.createElement('span');
300 matchop.setAttribute('data-type', this.type());
301 matchop.setAttribute('class', 'match');
302 matchop.appendChild(document.createTextNode(this.matchop()));
303
304 // Added match operator
305 var value = document.createElement('span');
306 value.setAttribute('data-type', this.type());
307 value.setAttribute('class', 'value');
308 if (this.value())
309 value.appendChild(document.createTextNode(this.value()));
310
Nils Diewald966abf12014-12-20 02:27:45 +0000311 var e = this._element;
312
Nils Diewaldd0770492014-12-19 03:55:00 +0000313 // Add spans
314 e.appendChild(key);
315 e.appendChild(matchop);
316 e.appendChild(value);
Nils Diewald966abf12014-12-20 02:27:45 +0000317
318 // Set operators
319 var op = this.operators(true, true, true);
320
321 e.appendChild(op.element());
322
Nils Diewaldd0770492014-12-19 03:55:00 +0000323 return e;
324 },
325
Nils Diewald966abf12014-12-20 02:27:45 +0000326 element : function () {
327 if (this._element !== undefined)
328 return this._element;
329
330 this._element = document.createElement('div');
331 this._element.setAttribute('class', 'doc');
332
333 this.update();
334 return this._element;
335 },
336
Nils Diewaldd0770492014-12-19 03:55:00 +0000337 // Wrap a new operation around the doc element
338 wrap : function (op) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000339/*
Nils Diewald8f4e2542014-12-19 04:42:09 +0000340 var group = KorAP.DocGroup.create(undefined);
Nils Diewald966abf12014-12-20 02:27:45 +0000341 group.append(this);
342 group.append(null);
Nils Diewaldd0770492014-12-19 03:55:00 +0000343 this.parent(group);
Nils Diewaldd0770492014-12-19 03:55:00 +0000344 var div = document.createElement('div');
345 div.setAttribute('data-operation', op);
346 var parent = this.element.parent;
347 parent.removeChild(this.element);
348 parent.appendChild(div);
349 div.appendChild(this.element);
350 return div;
351*/
Nils Diewaldd0770492014-12-19 03:55:00 +0000352 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000353 // Deserialize from json
354 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000355 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000356 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000357
Nils Diewald3a2d8022014-12-16 02:45:41 +0000358 if (json["@type"] !== "korap:doc") {
359 KorAP.log(701, "JSON-LD group has no @type attribute");
360 return;
361 };
362
Nils Diewald3a2d8022014-12-16 02:45:41 +0000363 if (json["value"] === undefined ||
364 typeof json["value"] != 'string') {
365 KorAP.log(805, "Value is invalid");
366 return;
367 };
368
369 // There is a defined key
370 if (json["key"] !== undefined &&
371 typeof json["key"] === 'string') {
372
373 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000374 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000375
376 // Set match operation
377 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000378 if (typeof json["match"] === 'string') {
379 this.matchop(json["match"]);
380 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000381 else {
382 KorAP.log(802, "Match type is not supported by value type");
383 return;
384 };
385 };
386
387 // Key is a string
388 if (json["type"] === undefined ||
389 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000390 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000391
392 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000393 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000394 KorAP.log(802, "Match type is not supported by value type");
395 return;
396 };
397
398 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000399 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000400 }
401
402 // Key is a date
403 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000404 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000405
406 if (json["value"] !== undefined &&
407 KorAP._validDateRE.test(json["value"])) {
408
Nils Diewaldd0770492014-12-19 03:55:00 +0000409 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000410 KorAP.log(802, "Match type is not supported by value type");
411 return;
412 };
413
414 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000415 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000416 }
417 else {
418 KorAP.log(806, "Value is not a valid date string");
419 return;
420 };
421 }
422
423 // Key is a regular expression
424 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000425 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000426
427 try {
428
429 // Try to create a regular expression
430 var check = new RegExp(json["value"]);
431
Nils Diewaldd0770492014-12-19 03:55:00 +0000432 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000433 KorAP.log(802, "Match type is not supported by value type");
434 return;
435 };
436
Nils Diewaldd0770492014-12-19 03:55:00 +0000437 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000438 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000439
Nils Diewald3a2d8022014-12-16 02:45:41 +0000440 catch (e) {
441 KorAP.log(807, "Value is not a valid regular expression");
442 return;
443 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000444 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000445 }
446
447 else {
448 KorAP.log(804, "Unknown value type");
449 return;
450 };
451 };
452
453 return this;
454 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000455 key : function (value) {
456 if (arguments.length === 1)
457 this._key = value;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000458 return this._key;
459 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000460 matchop : function (match) {
461 if (arguments.length === 1)
462 this._matchop = match.replace(/^match:/, '');
Nils Diewald3a2d8022014-12-16 02:45:41 +0000463 return this._matchop || "eq";
464 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000465 type : function (type) {
466 if (arguments.length === 1)
467 this._type = type;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000468 return this._type || "string";
469 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000470 value : function (value) {
471 if (arguments.length === 1)
472 this._value = value;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000473 return this._value;
474 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000475 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000476 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000477 return {};
478
479 return {
Nils Diewaldd0770492014-12-19 03:55:00 +0000480 "@type" : "korap:" + this.ldType(),
481 "key" : this.key(),
482 "match" : "match:" + this.matchop(),
483 "value" : this.value() || '',
484 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000485 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000486 },
487 toString : function () {
488 if (!this.matchop() || !this.key())
489 return "";
490
491 // Build doc string based on key
492 var string = this.key() + ' ';
493
494 // Add match operator
495 switch (this.matchop()) {
496 case "ne":
497 string += '!=';
498 break;
499 case "contains":
500 string += '~';
501 break;
502 case "geq":
503 string += 'since';
504 break;
505 case "leq":
506 string += 'until';
507 break;
508 default:
509 string += (this.type() == 'date') ? 'in' : '=';
510 break;
511 };
512
513 string += ' ';
514
515 // Add value
516 switch (this.type()) {
517 case "date":
518 return string + this.value();
519 break;
520 case "regex":
521 return string + '/' + this.value() + '/';
522 break;
523 case "string":
524 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
525 break;
526 };
527
528 return "...";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000529 }
530 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000531
532 /**
533 * Virtual collection group criterion.
534 */
535 KorAP.DocGroup = {
536 _ldType : "docGroup",
537
538 create : function (parent, json) {
539 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
540 obj._operands = [];
541 obj.fromJson(json);
542 if (parent !== undefined)
543 obj._parent = parent;
544 return obj;
545 },
Nils Diewald966abf12014-12-20 02:27:45 +0000546 append : function (operand) {
547
548 // Append unspecified object
549 if (operand === undefined) {
550
551 // Be aware of cyclic structures!
552 operand = KorAP.UnspecifiedDoc.create(this);
553 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000554 return operand;
555 };
556
Nils Diewald8f4e2542014-12-19 04:42:09 +0000557 switch (operand["@type"]) {
558 case undefined:
559 if (operand["ldType"] !== undefined) {
560 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000561 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000562 KorAP.log(812, "Operand not supported in document group");
563 return;
564 };
Nils Diewald966abf12014-12-20 02:27:45 +0000565 // Be aware of cyclic structures!
566 operand.parent(this);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000567 this._operands.push(operand);
568 return operand;
569 };
570
571 KorAP.log(701, "JSON-LD group has no @type attribute");
572 return;
573
574 case "korap:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000575 // Be aware of cyclic structures!
576 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000577 if (doc === undefined)
578 return;
579 this._operands.push(doc);
580 return doc;
581
582 case "korap:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000583 // Be aware of cyclic structures!
584 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000585 if (docGroup === undefined)
586 return;
587 this._operands.push(docGroup);
588 return docGroup;
589
590 default:
591 KorAP.log(812, "Operand not supported in document group");
592 return;
593 };
594 },
Nils Diewald966abf12014-12-20 02:27:45 +0000595 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000596
Nils Diewald8e7182e2015-01-08 15:02:07 +0000597 console.log("Update");
598
Nils Diewaldf219eb82015-01-07 20:15:42 +0000599 // There is only one operand in group
600 if (this._operands.length === 1) {
601 var parent = this.parent();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000602 var op = this.getOperand(0);
603
604 console.log("There is only one operand left in the group");
Nils Diewaldf219eb82015-01-07 20:15:42 +0000605
606 // Parent is a group
607 if (parent.ldType() !== null) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000608 console.log("The group is not directly below root");
609 return parent.replaceOperand(this, op).update();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000610 }
611
612 // Parent is vc root
613 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000614 console.log("The group is directly below root");
615 parent.root(op);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000616 this.destroy();
617 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000618 };
619 };
620
Nils Diewald966abf12014-12-20 02:27:45 +0000621 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000622 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000623
Nils Diewald5c817a42015-01-06 01:08:56 +0000624 var group = this._element;
625 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000626
Nils Diewald5c817a42015-01-06 01:08:56 +0000627 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000628
629 // Append operands
Nils Diewald5c817a42015-01-06 01:08:56 +0000630 for (var i in this._operands) {
631 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000632 this.getOperand(i).element()
633 );
634 };
635
636 // Set operators
637 var op = this.operators(
638 this.operation() == 'and' ? false : true,
639 this.operation() == 'or' ? false : true,
640 true
641 );
642
Nils Diewald5c817a42015-01-06 01:08:56 +0000643 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000644 op.element()
645 );
646
Nils Diewald5c817a42015-01-06 01:08:56 +0000647 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000648 },
Nils Diewald8f4e2542014-12-19 04:42:09 +0000649 element : function () {
650 if (this._element !== undefined)
651 return this._element;
652
653 this._element = document.createElement('div');
654 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000655
Nils Diewaldf219eb82015-01-07 20:15:42 +0000656 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000657 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000658
659 return this._element;
660 },
661 operation : function (op) {
662 if (arguments.length === 1) {
663 if (KorAP._validGroupOpRE.test(op)) {
664 this._op = op;
665 }
666 else {
667 KorAP.log(810, "Unknown operation type");
668 return;
669 };
670 };
671 return this._op || 'and';
672 },
673 operands : function () {
674 return this._operands;
675 },
676 getOperand : function (index) {
677 return this._operands[index];
678 },
679
Nils Diewald5c817a42015-01-06 01:08:56 +0000680 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000681 replaceOperand : function (oldOp, newOp) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000682
Nils Diewald5c817a42015-01-06 01:08:56 +0000683 for (var i in this._operands) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000684 if (this._operands[i] === oldOp) {
685
686 // Just insert a doc
687 if (newOp.ldType() === "doc") {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000688 this._operands[i] = newOp;
689 }
690 // Insert a group of a different operation
691 // (i.e. "and" in "or"/"or" in "and")
Nils Diewald8e7182e2015-01-08 15:02:07 +0000692 else if (newOp.operation() != this.operation()) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000693 this._operands[i] = newOp;
694 }
695
696 // Flatten the group
697 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000698 // Remove old group
699 this._operands.splice(i, 1);
700
701 // Inject new operands
Nils Diewaldf219eb82015-01-07 20:15:42 +0000702 for (var op in newOp.operands().reverse())
Nils Diewald8e7182e2015-01-08 15:02:07 +0000703 this._operands.splice(i, 0, newOp.getOperand(op))
Nils Diewaldf219eb82015-01-07 20:15:42 +0000704 };
705 oldOp.destroy();
706 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000707 }
708 };
709 return false;
710 },
711
Nils Diewald0297ba12015-01-05 21:56:12 +0000712 // Delete operand from group
713 delOperand : function (obj) {
714 for (var i in this._operands) {
715 if (this._operands[i] === obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000716
717 console.log("Deleted operand " + i);
718
Nils Diewald0297ba12015-01-05 21:56:12 +0000719 this._operands.splice(i,1);
720
Nils Diewald5c817a42015-01-06 01:08:56 +0000721 // Destroy object for cyclic references
722 obj.destroy();
723
Nils Diewald0297ba12015-01-05 21:56:12 +0000724 // Todo: Update has to check
725 // that this may mean the group is empty etc.
Nils Diewaldf219eb82015-01-07 20:15:42 +0000726 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +0000727 };
728 };
Nils Diewald5c817a42015-01-06 01:08:56 +0000729
730 // Operand not found
731 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +0000732 },
733
Nils Diewald8f4e2542014-12-19 04:42:09 +0000734 // Deserialize from json
735 fromJson : function (json) {
736 if (json === undefined)
737 return this;
738
739 if (json["@type"] !== "korap:docGroup") {
740 KorAP.log(701, "JSON-LD group has no @type attribute");
741 return;
742 };
743
744 if (json["operation"] === undefined ||
745 typeof json["operation"] !== 'string') {
746 KorAP.log(811, "Document group expects operation");
747 return;
748 };
749
750 var operation = json["operation"];
751
752 this.operation(operation.replace(/^operation:/,''));
753
754 if (json["operands"] === undefined ||
755 !(json["operands"] instanceof Array)) {
756 KorAP.log(704, "Operation needs operand list")
757 return;
758 };
759
760 // Add all documents
761 for (var i in json["operands"]) {
762 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +0000763 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000764 };
765
766 return this;
767 },
768 toJson : function () {
769 var opArray = new Array();
770 for (var i in this._operands) {
771 opArray.push(this._operands[i].toJson());
772 };
773 return {
774 "@type" : "korap:" + this.ldType(),
775 "operation" : "operation:" + this.operation(),
776 "operands" : opArray
777 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000778 },
779 toString : function () {
780 return this._operands.
781 map(function (op) {
782 return op.ldType() === 'docGroup' ? '(' + op.toString() + ')' : op.toString()
783 }).
784 join(this.operation() === 'or' ? ' | ' : ' & ')
Nils Diewald8f4e2542014-12-19 04:42:09 +0000785 }
786 };
787
788
789 // Abstract JsonLD object
790 KorAP.JsonLD = {
791 create : function () {
792 return Object.create(KorAP.JsonLD);
793 },
794
795 /**
796 * Upgrade this object to another object
797 * while private data stays intact
798 */
799 upgradeTo : function (props) {
800 for (var prop in props) {
801 this[prop] = props[prop];
802 };
803 return this;
804 },
805 ldType : function (type) {
806 if (arguments.length === 1)
807 this._ldType = type;
808 return this._ldType;
809 },
810 parent : function (obj) {
811 if (arguments.length === 1)
812 this._parent = obj;
813 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +0000814 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000815
Nils Diewald5c817a42015-01-06 01:08:56 +0000816 // Destroy object - especially for
817 // acyclic structures!
818 // I'm a paranoid chicken!
819 destroy : function () {
820 if (this._ops != undefined) {
821 this._ops._parent = undefined;
822 if (this._ops._element !== undefined)
823 this._ops._element.refTo = undefined;
824 this._ops = undefined;
825 };
826 if (this._element !== undefined)
827 this._element = undefined;
828
829 // In case of a group, destroy all operands
830 if (this._operands !== undefined) {
831 for (var i in this._operands)
832 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000833 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +0000834 };
835 },
836
Nils Diewald0297ba12015-01-05 21:56:12 +0000837 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +0000838 operators : function (and, or, del) {
839 if (arguments === 0)
840 return this._ops;
841 this._ops = KorAP.Operators.create(
842 and, or, del
843 );
Nils Diewald0297ba12015-01-05 21:56:12 +0000844 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +0000845 return this._ops;
846 },
847 toJson : function () {
848 return {
849 // Unspecified object
850 "@type" : "korap:" + this.ldType()
851 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000852 }
853 };
854
Nils Diewald3a2d8022014-12-16 02:45:41 +0000855}(this.KorAP));