blob: 2c8ad0116c9c4d5512dd3aa2ecee8c4dcb56d41b [file] [log] [blame]
Nils Diewald86dad5b2015-01-28 15:09:07 +00001/**
2 * Create virtual collections with a visual user interface.
3 *
4 * @author Nils Diewald
5 */
Nils Diewald2fe12e12015-03-06 16:47:06 +00006/*
7 * Replaces a previous version written by Mengfei Zhou
8 */
Nils Diewald3a2d8022014-12-16 02:45:41 +00009var KorAP = KorAP || {};
Nils Diewald3a2d8022014-12-16 02:45:41 +000010
Nils Diewald2fe12e12015-03-06 16:47:06 +000011// Requires menu.js
12
Nils Diewaldd0770492014-12-19 03:55:00 +000013/*
Nils Diewald86dad5b2015-01-28 15:09:07 +000014 TODO: Implement a working localization solution!
15 TODO: Disable "and" or "or" in case it's followed
16 by an unspecified document
Nils Diewald6e43ffd2015-03-25 18:55:39 +000017 TODO: Implement "persistance"-Option,
18 injecting the current creation date stamp
Nils Diewald86dad5b2015-01-28 15:09:07 +000019
Nils Diewaldd599d542015-01-08 20:41:34 +000020 Error codes:
Nils Diewaldd0770492014-12-19 03:55:00 +000021 701: "JSON-LD group has no @type attribute"
22 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000023 802: "Match type is not supported by value type"
24 804: "Unknown value type"
25 805: "Value is invalid"
26 806: "Value is not a valid date string"
27 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000028 810: "Unknown document group operation" (like 711)
29 811: "Document group expects operation" (like 703)
30 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000031 813: "Collection type is not supported" (like 713)
Nils Diewald86dad5b2015-01-28 15:09:07 +000032 814: "Unknown rewrite operation"
33 815: "Rewrite expects source"
Nils Diewaldd0770492014-12-19 03:55:00 +000034*/
35
Nils Diewald3a2d8022014-12-16 02:45:41 +000036(function (KorAP) {
37 "use strict";
38
39 // Default log message
40 KorAP.log = KorAP.log || function (type, msg) {
41 console.log(type + ": " + msg);
42 };
43
Nils Diewald86dad5b2015-01-28 15:09:07 +000044 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains|excludes)$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000045 KorAP._validRegexMatchRE = new RegExp("^(?:eq|ne)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000046 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000047 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
48 KorAP._validGroupOpRE = new RegExp("^(?:and|or)$");
Nils Diewald86dad5b2015-01-28 15:09:07 +000049 KorAP._validRewriteOpRE = new RegExp("^(?:injec|modifica)tion$");
Nils Diewaldf219eb82015-01-07 20:15:42 +000050 KorAP._quote = new RegExp("([\"\\\\])", 'g');
Nils Diewald3a2d8022014-12-16 02:45:41 +000051
Nils Diewalde15b7a22015-01-09 21:50:21 +000052 // Localization values
Nils Diewaldf219eb82015-01-07 20:15:42 +000053 var loc = (KorAP.Locale = KorAP.Locale || {} );
54 loc.AND = loc.AND || 'and';
55 loc.OR = loc.OR || 'or';
56 loc.DEL = loc.DEL || '×';
57 loc.EMPTY = loc.EMPTY || '⋯'
Nils Diewaldd0770492014-12-19 03:55:00 +000058
Nils Diewalde15b7a22015-01-09 21:50:21 +000059 // Utility for analysing boolean values
Nils Diewald966abf12014-12-20 02:27:45 +000060 function _bool (bool) {
Nils Diewalde15b7a22015-01-09 21:50:21 +000061 return (bool === undefined || bool === null || bool === false) ? false : true;
Nils Diewald966abf12014-12-20 02:27:45 +000062 };
63
Nils Diewaldd599d542015-01-08 20:41:34 +000064
Nils Diewalde15b7a22015-01-09 21:50:21 +000065 // Utility for removing all children of a node
Nils Diewald966abf12014-12-20 02:27:45 +000066 function _removeChildren (node) {
67 // Remove everything underneath
Nils Diewald8f6b6102015-01-08 18:25:33 +000068 while (node.firstChild)
Nils Diewald966abf12014-12-20 02:27:45 +000069 node.removeChild(node.firstChild);
Nils Diewald966abf12014-12-20 02:27:45 +000070 };
71
Nils Diewald4019bd22015-01-08 19:57:50 +000072
Nils Diewald52f7eb12015-01-12 17:30:04 +000073 // Add new unspecified document
Nils Diewald9fcc1712015-01-09 14:24:32 +000074 KorAP._add = function (obj, type) {
75 var ref = obj.parentNode.refTo;
Nils Diewaldd5070b02015-01-11 01:44:47 +000076 var parent = ref.parent();
Nils Diewald52f7eb12015-01-12 17:30:04 +000077
Nils Diewald9fcc1712015-01-09 14:24:32 +000078 if (ref.ldType() === 'docGroup') {
Nils Diewaldd5070b02015-01-11 01:44:47 +000079
80 // Check that the action differs from the type
81 if (ref.operation() === type)
82 return;
83
84 if (parent.ldType() !== null) {
85 return parent.newAfter(ref);
Nils Diewald9fcc1712015-01-09 14:24:32 +000086 }
87 else {
Nils Diewaldd5070b02015-01-11 01:44:47 +000088 // The group is on root - wrap
89 return ref.wrapOnRoot();
90 };
91 }
92 else if (ref.ldType() === 'doc') {
Nils Diewald52f7eb12015-01-12 17:30:04 +000093
94 if (parent.ldType() === null) {
95 return ref.wrapOnRoot(type);
96 }
97 else if (parent.operation() === type) {
Nils Diewaldd5070b02015-01-11 01:44:47 +000098 return parent.newAfter(ref);
99 }
100 else {
101 return ref.wrap(type);
Nils Diewald9fcc1712015-01-09 14:24:32 +0000102 };
Nils Diewaldd599d542015-01-08 20:41:34 +0000103 };
Nils Diewald4019bd22015-01-08 19:57:50 +0000104 };
105
Nils Diewaldd599d542015-01-08 20:41:34 +0000106
Nils Diewalde15b7a22015-01-09 21:50:21 +0000107 // Add doc with 'and' relation
108 KorAP._and = function () {
109 return KorAP._add(this, 'and');
110 };
111
112
113 // Add doc with 'or' relation
114 KorAP._or = function () {
115 return KorAP._add(this, 'or');
116 };
117
Nils Diewald52f7eb12015-01-12 17:30:04 +0000118
Nils Diewald4019bd22015-01-08 19:57:50 +0000119 // Remove doc or docGroup
Nils Diewalde15b7a22015-01-09 21:50:21 +0000120 KorAP._delete = function () {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000121 var ref = this.parentNode.refTo;
Nils Diewald52f7eb12015-01-12 17:30:04 +0000122 if (ref.parent().ldType() !== null) {
123 return ref.parent().delOperand(ref).update();
124 }
125 else {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000126 ref.parent().clean();
Nils Diewald52f7eb12015-01-12 17:30:04 +0000127 };
Nils Diewald4019bd22015-01-08 19:57:50 +0000128 };
129
Nils Diewaldd599d542015-01-08 20:41:34 +0000130
131 /**
132 * Virtual Collection
133 */
Nils Diewald3a2d8022014-12-16 02:45:41 +0000134 KorAP.VirtualCollection = {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000135 ldType : function () {
136 return null;
137 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000138
Nils Diewald3a2d8022014-12-16 02:45:41 +0000139 create : function () {
140 return Object.create(KorAP.VirtualCollection);
141 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000142
Nils Diewald4019bd22015-01-08 19:57:50 +0000143 clean : function () {
144 if (this._root.ldType() !== "non") {
145 this._root.destroy();
146 this.root(KorAP.UnspecifiedDoc.create(this));
147 };
148 return this;
149 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000150
Nils Diewaldd0770492014-12-19 03:55:00 +0000151 render : function (json) {
152 var obj = Object.create(KorAP.VirtualCollection);
153
154 if (json !== undefined) {
155 // Root object
Nils Diewald2fe12e12015-03-06 16:47:06 +0000156 if (json['@type'] == 'koral:doc') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000157 obj._root = KorAP.Doc.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000158 }
Nils Diewald2fe12e12015-03-06 16:47:06 +0000159 else if (json['@type'] == 'koral:docGroup') {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000160 obj._root = KorAP.DocGroup.create(obj, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000161 }
162 else {
163 KorAP.log(813, "Collection type is not supported");
164 return;
165 };
166 }
167
168 else {
169 // Add unspecified object
Nils Diewaldf219eb82015-01-07 20:15:42 +0000170 obj._root = KorAP.UnspecifiedDoc.create(obj);
Nils Diewaldd0770492014-12-19 03:55:00 +0000171 };
172
Nils Diewald8e7182e2015-01-08 15:02:07 +0000173 // Init element and update
174 obj.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000175
176 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000177 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000178
Nils Diewaldf219eb82015-01-07 20:15:42 +0000179 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000180 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000181 var e = this.element();
182 if (e.firstChild !== null) {
Nils Diewaldd5070b02015-01-11 01:44:47 +0000183 if (e.firstChild !== obj.element()) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000184 e.replaceChild(obj.element(), e.firstChild);
Nils Diewaldd5070b02015-01-11 01:44:47 +0000185 };
Nils Diewald8f6b6102015-01-08 18:25:33 +0000186 }
187
188 // Append root element
189 else {
190 e.appendChild(obj.element());
191 };
192
193 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000194 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000195 obj.parent(this);
196
Nils Diewald8e7182e2015-01-08 15:02:07 +0000197 this.update();
198 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000199 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000200 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000201
Nils Diewaldd0770492014-12-19 03:55:00 +0000202 element : function () {
203 if (this._element !== undefined)
204 return this._element;
205
206 this._element = document.createElement('div');
207 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000208
Nils Diewald8f6b6102015-01-08 18:25:33 +0000209 // Initialize root
210 this._element.appendChild(this._root.element());
211
Nils Diewaldd0770492014-12-19 03:55:00 +0000212 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000213 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000214
215 update : function () {
216 this._root.update();
217 return this;
218 },
219
Nils Diewaldf219eb82015-01-07 20:15:42 +0000220 toJson : function () {
221 return this._root.toJson();
222 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000223
224 toQuery : function () {
225 return this._root.toQuery();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000226 }
227 };
228
Nils Diewaldd599d542015-01-08 20:41:34 +0000229
Nils Diewald8f4e2542014-12-19 04:42:09 +0000230 /**
231 * Operators for criteria
232 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000233 KorAP.Operators = {
234 create : function (and, or, del) {
235 var op = Object.create(KorAP.Operators);
236 op.and(and);
237 op.or(or);
238 op.del(del);
239 return op;
240 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000241
Nils Diewaldd0770492014-12-19 03:55:00 +0000242 update : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000243 // Init the element
244 if (this._element === undefined)
245 return this.element();
246
247 var op = this._element;
248
Nils Diewald0297ba12015-01-05 21:56:12 +0000249 op.refTo = this.parent();
250
Nils Diewaldd0770492014-12-19 03:55:00 +0000251 // Remove everything underneath
Nils Diewald966abf12014-12-20 02:27:45 +0000252 _removeChildren(op);
Nils Diewaldd0770492014-12-19 03:55:00 +0000253
254 // Add and button
255 if (this._and === true) {
256 var andE = document.createElement('span');
257 andE.setAttribute('class', 'and');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000258 andE.addEventListener('click', KorAP._and, false);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000259 andE.appendChild(
260 document.createTextNode(KorAP.Locale.AND)
261 );
Nils Diewaldd0770492014-12-19 03:55:00 +0000262 op.appendChild(andE);
263 };
264
265 // Add or button
266 if (this._or === true) {
267 var orE = document.createElement('span');
268 orE.setAttribute('class', 'or');
Nils Diewalde15b7a22015-01-09 21:50:21 +0000269 orE.addEventListener('click', KorAP._or, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000270 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
271 op.appendChild(orE);
272 };
273
274 // Add delete button
275 if (this._del === true) {
276 var delE = document.createElement('span');
277 delE.setAttribute('class', 'delete');
278 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
Nils Diewald0297ba12015-01-05 21:56:12 +0000279 delE.addEventListener('click', KorAP._delete, false);
Nils Diewaldd0770492014-12-19 03:55:00 +0000280 op.appendChild(delE);
281 };
Nils Diewald966abf12014-12-20 02:27:45 +0000282
283 return op;
Nils Diewaldd0770492014-12-19 03:55:00 +0000284 },
Nils Diewald0297ba12015-01-05 21:56:12 +0000285
286 // Be aware! This may be cyclic
287 parent : function (obj) {
288 if (arguments.length === 1)
289 this._parent = obj;
290 return this._parent;
291 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000292
Nils Diewaldd0770492014-12-19 03:55:00 +0000293 element : function () {
294
295 // Return existing element
296 if (this._element !== undefined)
297 return this._element;
298
299 this._element = document.createElement('div');
300 this._element.setAttribute('class', 'operators');
301
302 // Init elements
303 this.update();
304 return this._element;
305 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000306
Nils Diewaldd0770492014-12-19 03:55:00 +0000307 and : function (bool) {
308 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000309 this._and = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000310 return this._and;
311 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000312
Nils Diewaldd0770492014-12-19 03:55:00 +0000313 or : function (bool) {
314 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000315 this._or = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000316 return this._or;
317 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000318
Nils Diewaldd0770492014-12-19 03:55:00 +0000319 del : function (bool) {
320 if (arguments.length === 1)
Nils Diewald966abf12014-12-20 02:27:45 +0000321 this._del = _bool(bool);
Nils Diewaldd0770492014-12-19 03:55:00 +0000322 return this._del;
323 }
324 };
325
326
327 /**
328 * Unspecified criterion
329 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000330 KorAP.UnspecifiedDoc = {
Nils Diewald4019bd22015-01-08 19:57:50 +0000331 _ldType : "non",
Nils Diewaldd0770492014-12-19 03:55:00 +0000332 create : function (parent) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000333 var obj = Object.create(KorAP.JsonLD).
334 upgradeTo(KorAP.UnspecifiedDoc);
335
Nils Diewaldd0770492014-12-19 03:55:00 +0000336 if (parent !== undefined)
337 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000338
Nils Diewaldd0770492014-12-19 03:55:00 +0000339 return obj;
340 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000341
Nils Diewaldfda29d92015-01-22 17:28:01 +0000342 // Set key - replace
343 key : function (v) {
344
345 // Not replaceable
346 if (this._parent === undefined)
347 return null;
348
349 // Set JSON-LD type
350 var newDoc = KorAP.Doc.create(this._parent, {
Nils Diewald2fe12e12015-03-06 16:47:06 +0000351 "@type" : "koral:doc",
Nils Diewaldfda29d92015-01-22 17:28:01 +0000352 "value" : "",
353 "key" : v
354 });
355
356 // Unspecified document on root
357 if (this._parent.ldType() === null) {
358 this._parent.root(newDoc);
359 this.destroy();
360 }
361
362 // Unspecified document in group
363 else {
364 this._parent.replaceOperand(this, newDoc);
365 };
366 this._parent.update();
367 return newDoc;
368 },
369
Nils Diewald966abf12014-12-20 02:27:45 +0000370 update : function () {
Nils Diewald4019bd22015-01-08 19:57:50 +0000371
Nils Diewald966abf12014-12-20 02:27:45 +0000372 if (this._element === undefined)
373 return this.element();
374
Nils Diewald8f6b6102015-01-08 18:25:33 +0000375 // Remove element content
Nils Diewald966abf12014-12-20 02:27:45 +0000376 _removeChildren(this._element);
377
378 var ellipsis = document.createElement('span');
Nils Diewaldf219eb82015-01-07 20:15:42 +0000379 ellipsis.appendChild(document.createTextNode(loc.EMPTY));
Nils Diewald966abf12014-12-20 02:27:45 +0000380 this._element.appendChild(ellipsis);
381
Nils Diewald2fe12e12015-03-06 16:47:06 +0000382 // Set ref - TODO: Cleanup!
383 this._element.refTo = this;
384
Nils Diewald966abf12014-12-20 02:27:45 +0000385 // Set operators
Nils Diewalde15b7a22015-01-09 21:50:21 +0000386 if (this._parent !== undefined && this.parent().ldType() !== null) {
387 var op = this.operators(
388 false,
389 false,
390 true
391 );
Nils Diewald966abf12014-12-20 02:27:45 +0000392
Nils Diewalde15b7a22015-01-09 21:50:21 +0000393 this._element.appendChild(
394 op.element()
395 );
396 };
Nils Diewald966abf12014-12-20 02:27:45 +0000397
Nils Diewald966abf12014-12-20 02:27:45 +0000398 return this.element();
399 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000400
Nils Diewaldd0770492014-12-19 03:55:00 +0000401 element : function () {
402 if (this._element !== undefined)
403 return this._element;
404 this._element = document.createElement('div');
Nils Diewaldd599d542015-01-08 20:41:34 +0000405 this._element.setAttribute('class', 'doc unspecified');
Nils Diewald966abf12014-12-20 02:27:45 +0000406 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000407 return this._element;
Nils Diewaldfda29d92015-01-22 17:28:01 +0000408 },
409
410
Nils Diewaldd0770492014-12-19 03:55:00 +0000411 };
412
413
Nils Diewald8f4e2542014-12-19 04:42:09 +0000414 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000415 * Document criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000416 */
417 KorAP.Doc = {
418 _ldType : "doc",
Nils Diewaldfda29d92015-01-22 17:28:01 +0000419 _obj : function () { return KorAP.Doc },
Nils Diewaldd0770492014-12-19 03:55:00 +0000420
421 create : function (parent, json) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000422 var obj = Object(KorAP.JsonLD).
423 create().
424 upgradeTo(KorAP.Doc).
425 fromJson(json);
426
Nils Diewaldd0770492014-12-19 03:55:00 +0000427 if (parent !== undefined)
428 obj._parent = parent;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000429
Nils Diewald86dad5b2015-01-28 15:09:07 +0000430 obj.__changed = true;
Nils Diewaldd0770492014-12-19 03:55:00 +0000431 return obj;
432 },
Nils Diewald5c817a42015-01-06 01:08:56 +0000433
Nils Diewald966abf12014-12-20 02:27:45 +0000434 update : function () {
435 if (this._element === undefined)
436 return this.element();
Nils Diewaldd0770492014-12-19 03:55:00 +0000437
Nils Diewald8f6b6102015-01-08 18:25:33 +0000438 // Get element
Nils Diewald966abf12014-12-20 02:27:45 +0000439 var e = this._element;
440
Nils Diewald2fe12e12015-03-06 16:47:06 +0000441 // Set ref - TODO: Cleanup!
442 e.refTo = this;
443
Nils Diewald8f6b6102015-01-08 18:25:33 +0000444 // Check if there is a change
Nils Diewald86dad5b2015-01-28 15:09:07 +0000445 if (this.__changed) {
446
447 // Was rewritten
448 if (this.rewrites() !== undefined) {
449 e.classList.add("rewritten");
450 };
Nils Diewald966abf12014-12-20 02:27:45 +0000451
Nils Diewald8f6b6102015-01-08 18:25:33 +0000452 // Added key
453 var key = document.createElement('span');
454 key.setAttribute('class', 'key');
Nils Diewald2fe12e12015-03-06 16:47:06 +0000455
456 // Change key
457 key.addEventListener('click', KorAP._changeKey, false);
458
Nils Diewald8f6b6102015-01-08 18:25:33 +0000459 if (this.key())
460 key.appendChild(document.createTextNode(this.key()));
Nils Diewald966abf12014-12-20 02:27:45 +0000461
Nils Diewald8f6b6102015-01-08 18:25:33 +0000462 // Added match operator
463 var matchop = document.createElement('span');
464 matchop.setAttribute('data-type', this.type());
465 matchop.setAttribute('class', 'match');
466 matchop.appendChild(
467 document.createTextNode(this.matchop())
468 );
469
470 // Added match operator
471 var value = document.createElement('span');
472 value.setAttribute('data-type', this.type());
473 value.setAttribute('class', 'value');
474 if (this.value())
475 value.appendChild(
476 document.createTextNode(this.value())
477 );
478
479 // Remove all element children
480 _removeChildren(e);
481
482 // Add spans
483 e.appendChild(key);
484 e.appendChild(matchop);
485 e.appendChild(value);
486
Nils Diewald86dad5b2015-01-28 15:09:07 +0000487 this.__changed = false;
488 };
489
490 if (this._rewrites !== undefined) {
491 e.appendChild(this._rewrites.element());
Nils Diewald8f6b6102015-01-08 18:25:33 +0000492 };
493
494 if (this._parent !== undefined) {
495 // Set operators
496 var op = this.operators(
497 true,
498 true,
Nils Diewald4019bd22015-01-08 19:57:50 +0000499 true
Nils Diewald8f6b6102015-01-08 18:25:33 +0000500 );
501
502 // Append new operators
503 e.appendChild(op.element());
504 };
Nils Diewald966abf12014-12-20 02:27:45 +0000505
Nils Diewaldd0770492014-12-19 03:55:00 +0000506 return e;
507 },
508
Nils Diewald966abf12014-12-20 02:27:45 +0000509 element : function () {
510 if (this._element !== undefined)
511 return this._element;
512
513 this._element = document.createElement('div');
514 this._element.setAttribute('class', 'doc');
515
516 this.update();
517 return this._element;
518 },
519
Nils Diewaldd0770492014-12-19 03:55:00 +0000520 // Wrap a new operation around the doc element
521 wrap : function (op) {
Nils Diewald9fcc1712015-01-09 14:24:32 +0000522 var parent = this.parent();
523 var group = KorAP.DocGroup.create(parent);
524 group.operation(op);
Nils Diewald966abf12014-12-20 02:27:45 +0000525 group.append(this);
Nils Diewald9fcc1712015-01-09 14:24:32 +0000526 group.append();
527 return parent.replaceOperand(this, group).update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000528 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000529
Nils Diewald3a2d8022014-12-16 02:45:41 +0000530 // Deserialize from json
531 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000532 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000533 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000534
Nils Diewald86dad5b2015-01-28 15:09:07 +0000535 if (json["@type"] === undefined) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000536 KorAP.log(701, "JSON-LD group has no @type attribute");
537 return;
538 };
539
Nils Diewald3a2d8022014-12-16 02:45:41 +0000540 if (json["value"] === undefined ||
541 typeof json["value"] != 'string') {
542 KorAP.log(805, "Value is invalid");
543 return;
544 };
545
546 // There is a defined key
547 if (json["key"] !== undefined &&
548 typeof json["key"] === 'string') {
549
550 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000551 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000552
553 // Set match operation
554 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000555 if (typeof json["match"] === 'string') {
556 this.matchop(json["match"]);
557 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000558 else {
559 KorAP.log(802, "Match type is not supported by value type");
560 return;
561 };
562 };
563
564 // Key is a string
565 if (json["type"] === undefined ||
566 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000567 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000568
569 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000570 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000571 KorAP.log(802, "Match type is not supported by value type");
572 return;
573 };
574
575 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000576 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000577 }
578
579 // Key is a date
580 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000581 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000582
583 if (json["value"] !== undefined &&
584 KorAP._validDateRE.test(json["value"])) {
585
Nils Diewaldd0770492014-12-19 03:55:00 +0000586 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000587 KorAP.log(802, "Match type is not supported by value type");
588 return;
589 };
590
591 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000592 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000593 }
594 else {
595 KorAP.log(806, "Value is not a valid date string");
596 return;
597 };
598 }
599
600 // Key is a regular expression
601 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000602 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000603
604 try {
605
606 // Try to create a regular expression
607 var check = new RegExp(json["value"]);
608
Nils Diewaldd0770492014-12-19 03:55:00 +0000609 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000610 KorAP.log(802, "Match type is not supported by value type");
611 return;
612 };
613
Nils Diewaldd0770492014-12-19 03:55:00 +0000614 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000615 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000616
Nils Diewald3a2d8022014-12-16 02:45:41 +0000617 catch (e) {
618 KorAP.log(807, "Value is not a valid regular expression");
619 return;
620 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000621 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000622 }
623
624 else {
625 KorAP.log(804, "Unknown value type");
626 return;
627 };
Nils Diewald86dad5b2015-01-28 15:09:07 +0000628
Nils Diewald3a2d8022014-12-16 02:45:41 +0000629 };
630
Nils Diewald86dad5b2015-01-28 15:09:07 +0000631 if (json["rewrites"] !== undefined) {
632 this._rewrites = KorAP.RewriteList.create(json["rewrites"]);
633 };
634
Nils Diewald3a2d8022014-12-16 02:45:41 +0000635 return this;
636 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000637
Nils Diewaldd0770492014-12-19 03:55:00 +0000638 key : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000639 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000640 this._key = value;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000641 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000642 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000643 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000644 return this._key;
645 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000646
Nils Diewaldd0770492014-12-19 03:55:00 +0000647 matchop : function (match) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000648 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000649 this._matchop = match.replace(/^match:/, '');
Nils Diewald86dad5b2015-01-28 15:09:07 +0000650 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000651 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000652 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000653 return this._matchop || "eq";
654 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000655
Nils Diewaldd0770492014-12-19 03:55:00 +0000656 type : function (type) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000657 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000658 this._type = type;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000659 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000660 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000661 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000662 return this._type || "string";
663 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000664
Nils Diewaldd0770492014-12-19 03:55:00 +0000665 value : function (value) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000666 if (arguments.length === 1) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000667 this._value = value;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000668 this._changed();
Nils Diewaldfda29d92015-01-22 17:28:01 +0000669 return this;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000670 };
Nils Diewald3a2d8022014-12-16 02:45:41 +0000671 return this._value;
672 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000673
Nils Diewald86dad5b2015-01-28 15:09:07 +0000674 rewrites : function () {
675 return this._rewrites;
676 },
677
678 _changed : function () {
679 this.__changed = true;
680
681 if (this._rewrites === undefined)
682 return;
683 delete this["_rewrites"];
684 if (this._element === undefined)
685 return;
686 this._element.classList.remove("rewritten");
687 },
688
Nils Diewald3a2d8022014-12-16 02:45:41 +0000689 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000690 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000691 return {};
692
693 return {
Nils Diewald2fe12e12015-03-06 16:47:06 +0000694 "@type" : "koral:" + this.ldType(),
Nils Diewaldd0770492014-12-19 03:55:00 +0000695 "key" : this.key(),
696 "match" : "match:" + this.matchop(),
697 "value" : this.value() || '',
698 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000699 };
Nils Diewaldf219eb82015-01-07 20:15:42 +0000700 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000701
702 toQuery : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000703 if (!this.matchop() || !this.key())
704 return "";
705
706 // Build doc string based on key
707 var string = this.key() + ' ';
708
709 // Add match operator
710 switch (this.matchop()) {
711 case "ne":
712 string += '!=';
713 break;
714 case "contains":
715 string += '~';
716 break;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000717 case "excludes":
718 string += '!~';
719 break;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000720 case "geq":
721 string += 'since';
722 break;
723 case "leq":
724 string += 'until';
725 break;
726 default:
727 string += (this.type() == 'date') ? 'in' : '=';
728 break;
729 };
730
731 string += ' ';
732
733 // Add value
734 switch (this.type()) {
735 case "date":
736 return string + this.value();
737 break;
738 case "regex":
739 return string + '/' + this.value() + '/';
740 break;
741 case "string":
742 return string + '"' + this.value().replace(KorAP._quote, '\\$1') + '"';
743 break;
744 };
745
Nils Diewaldd599d542015-01-08 20:41:34 +0000746 return "";
Nils Diewald3a2d8022014-12-16 02:45:41 +0000747 }
748 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000749
Nils Diewaldd599d542015-01-08 20:41:34 +0000750
Nils Diewald8f4e2542014-12-19 04:42:09 +0000751 /**
Nils Diewaldd599d542015-01-08 20:41:34 +0000752 * Document group criterion
Nils Diewald8f4e2542014-12-19 04:42:09 +0000753 */
754 KorAP.DocGroup = {
755 _ldType : "docGroup",
756
757 create : function (parent, json) {
758 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
759 obj._operands = [];
760 obj.fromJson(json);
761 if (parent !== undefined)
762 obj._parent = parent;
763 return obj;
764 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000765
766 newAfter : function (obj) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000767 for (var i = 0; i < this._operands.length; i++) {
Nils Diewaldd599d542015-01-08 20:41:34 +0000768 if (this._operands[i] === obj) {
769 var operand = KorAP.UnspecifiedDoc.create(this);
770 this._operands.splice(i + 1, 0, operand);
771 return this.update();
772 };
773 };
774 },
775
Nils Diewald86dad5b2015-01-28 15:09:07 +0000776 // The doc is already set in the group
777 _duplicate : function (operand) {
778 if (operand.ldType() !== 'doc')
779 return null;
780
781 for (var i = 0; i < this._operands.length; i++) {
782 var op = this.getOperand(i);
783 if (op.ldType() === 'doc'
784 && operand.key() === op.key()
785 && operand.matchop() === op.matchop()
786 && operand.value() === op.value()) {
787 return op;
788 };
789 };
790 return null;
791 },
792
Nils Diewald966abf12014-12-20 02:27:45 +0000793 append : function (operand) {
794
795 // Append unspecified object
796 if (operand === undefined) {
797
798 // Be aware of cyclic structures!
799 operand = KorAP.UnspecifiedDoc.create(this);
800 this._operands.push(operand);
Nils Diewald966abf12014-12-20 02:27:45 +0000801 return operand;
802 };
803
Nils Diewald8f4e2542014-12-19 04:42:09 +0000804 switch (operand["@type"]) {
Nils Diewald86dad5b2015-01-28 15:09:07 +0000805
Nils Diewald8f4e2542014-12-19 04:42:09 +0000806 case undefined:
Nils Diewald86dad5b2015-01-28 15:09:07 +0000807 // No @type defined
Nils Diewald8f4e2542014-12-19 04:42:09 +0000808 if (operand["ldType"] !== undefined) {
809 if (operand.ldType() !== 'doc' &&
Nils Diewald966abf12014-12-20 02:27:45 +0000810 operand.ldType() !== 'docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000811 KorAP.log(812, "Operand not supported in document group");
812 return;
813 };
Nils Diewald966abf12014-12-20 02:27:45 +0000814 // Be aware of cyclic structures!
815 operand.parent(this);
Nils Diewald86dad5b2015-01-28 15:09:07 +0000816
817 var dupl = this._duplicate(operand);
818 if (dupl === null) {
819 this._operands.push(operand);
820 return operand;
821 };
822 return dupl;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000823 };
824
825 KorAP.log(701, "JSON-LD group has no @type attribute");
826 return;
827
Nils Diewald2fe12e12015-03-06 16:47:06 +0000828 case "koral:doc":
Nils Diewald966abf12014-12-20 02:27:45 +0000829 // Be aware of cyclic structures!
830 var doc = KorAP.Doc.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000831 if (doc === undefined)
832 return;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000833 var dupl = this._duplicate(doc);
834 if (dupl === null) {
835 this._operands.push(doc);
836 return doc;
837 };
838 return dupl;
Nils Diewald8f4e2542014-12-19 04:42:09 +0000839
Nils Diewald2fe12e12015-03-06 16:47:06 +0000840 case "koral:docGroup":
Nils Diewald966abf12014-12-20 02:27:45 +0000841 // Be aware of cyclic structures!
842 var docGroup = KorAP.DocGroup.create(this, operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +0000843 if (docGroup === undefined)
844 return;
Nils Diewald86dad5b2015-01-28 15:09:07 +0000845
846 // Flatten group
847 if (docGroup.operation() === this.operation()) {
848 for (var op in docGroup.operands()) {
849 op = docGroup.getOperand(op);
850 var dupl = this._duplicate(op);
851 if (dupl === null) {
852 this._operands.push(op);
853 op.parent(this);
854 };
855 };
856 docGroup._operands = [];
857 docGroup.destroy();
858 return this;
859 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000860 this._operands.push(docGroup);
861 return docGroup;
862
863 default:
864 KorAP.log(812, "Operand not supported in document group");
865 return;
866 };
867 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000868
Nils Diewald966abf12014-12-20 02:27:45 +0000869 update : function () {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000870 // There is only one operand in group
Nils Diewald52f7eb12015-01-12 17:30:04 +0000871
Nils Diewaldf219eb82015-01-07 20:15:42 +0000872 if (this._operands.length === 1) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000873
Nils Diewaldf219eb82015-01-07 20:15:42 +0000874 var parent = this.parent();
Nils Diewald8e7182e2015-01-08 15:02:07 +0000875 var op = this.getOperand(0);
876
Nils Diewald8f6b6102015-01-08 18:25:33 +0000877 // This will prevent destruction of
878 // the operand
879 this._operands = [];
Nils Diewaldf219eb82015-01-07 20:15:42 +0000880
881 // Parent is a group
Nils Diewald52f7eb12015-01-12 17:30:04 +0000882 if (parent.ldType() !== null)
Nils Diewald8e7182e2015-01-08 15:02:07 +0000883 return parent.replaceOperand(this, op).update();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000884
Nils Diewald8f6b6102015-01-08 18:25:33 +0000885 // Parent is vc
Nils Diewaldf219eb82015-01-07 20:15:42 +0000886 else {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000887 this.destroy();
Nils Diewald8f6b6102015-01-08 18:25:33 +0000888 // Cyclic madness
889 parent.root(op);
890 op.parent(parent);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000891 return parent.root();
Nils Diewald5c817a42015-01-06 01:08:56 +0000892 };
893 };
894
Nils Diewald966abf12014-12-20 02:27:45 +0000895 if (this._element === undefined)
Nils Diewald5c817a42015-01-06 01:08:56 +0000896 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000897
Nils Diewald5c817a42015-01-06 01:08:56 +0000898 var group = this._element;
899 group.setAttribute('data-operation', this.operation());
Nils Diewald966abf12014-12-20 02:27:45 +0000900
Nils Diewald5c817a42015-01-06 01:08:56 +0000901 _removeChildren(group);
Nils Diewald966abf12014-12-20 02:27:45 +0000902
903 // Append operands
Nils Diewald52f7eb12015-01-12 17:30:04 +0000904 for (var i = 0; i < this._operands.length; i++) {
Nils Diewald5c817a42015-01-06 01:08:56 +0000905 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000906 this.getOperand(i).element()
907 );
908 };
909
910 // Set operators
911 var op = this.operators(
912 this.operation() == 'and' ? false : true,
913 this.operation() == 'or' ? false : true,
914 true
915 );
916
Nils Diewald5c817a42015-01-06 01:08:56 +0000917 group.appendChild(
Nils Diewald966abf12014-12-20 02:27:45 +0000918 op.element()
919 );
920
Nils Diewald5c817a42015-01-06 01:08:56 +0000921 return this;
Nils Diewald966abf12014-12-20 02:27:45 +0000922 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000923
Nils Diewald8f4e2542014-12-19 04:42:09 +0000924 element : function () {
925 if (this._element !== undefined)
926 return this._element;
927
928 this._element = document.createElement('div');
929 this._element.setAttribute('class', 'docGroup');
Nils Diewald8f4e2542014-12-19 04:42:09 +0000930
Nils Diewaldf219eb82015-01-07 20:15:42 +0000931 // Update the object - including optimization
Nils Diewald966abf12014-12-20 02:27:45 +0000932 this.update();
Nils Diewald8f4e2542014-12-19 04:42:09 +0000933
934 return this._element;
935 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000936
Nils Diewald8f4e2542014-12-19 04:42:09 +0000937 operation : function (op) {
938 if (arguments.length === 1) {
939 if (KorAP._validGroupOpRE.test(op)) {
940 this._op = op;
941 }
942 else {
943 KorAP.log(810, "Unknown operation type");
944 return;
945 };
946 };
947 return this._op || 'and';
948 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000949
Nils Diewald8f4e2542014-12-19 04:42:09 +0000950 operands : function () {
951 return this._operands;
952 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000953
Nils Diewald8f4e2542014-12-19 04:42:09 +0000954 getOperand : function (index) {
955 return this._operands[index];
956 },
957
Nils Diewald5c817a42015-01-06 01:08:56 +0000958 // Replace operand
Nils Diewaldf219eb82015-01-07 20:15:42 +0000959 replaceOperand : function (oldOp, newOp) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000960
961 for (var i = 0; i < this._operands.length; i++) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000962 if (this._operands[i] === oldOp) {
963
Nils Diewalde15b7a22015-01-09 21:50:21 +0000964 // Just insert a doc or ...
965 if (newOp.ldType() === "doc" ||
Nils Diewald52f7eb12015-01-12 17:30:04 +0000966 newOp.ldType() === "non" ||
Nils Diewalde15b7a22015-01-09 21:50:21 +0000967 // ... insert a group of a different operation
968 // (i.e. "and" in "or"/"or" in "and")
969 newOp.operation() != this.operation()) {
Nils Diewaldf219eb82015-01-07 20:15:42 +0000970 this._operands[i] = newOp;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000971 newOp.parent(this);
Nils Diewaldf219eb82015-01-07 20:15:42 +0000972 }
973
Nils Diewald86dad5b2015-01-28 15:09:07 +0000974 // Flatten group
Nils Diewaldf219eb82015-01-07 20:15:42 +0000975 else {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000976 // Remove old group
977 this._operands.splice(i, 1);
978
979 // Inject new operands
Nils Diewald8f6b6102015-01-08 18:25:33 +0000980 for (var op in newOp.operands().reverse()) {
Nils Diewald86dad5b2015-01-28 15:09:07 +0000981 op = newOp.getOperand(op);
982 this._operands.splice(i, 0, op);
983 op.parent(this);
Nils Diewald8f6b6102015-01-08 18:25:33 +0000984 };
985 // Prevent destruction of operands
986 newOp._operands = [];
987 newOp.destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +0000988 };
989 oldOp.destroy();
990 return this;
Nils Diewald5c817a42015-01-06 01:08:56 +0000991 }
992 };
993 return false;
994 },
995
Nils Diewald0297ba12015-01-05 21:56:12 +0000996 // Delete operand from group
997 delOperand : function (obj) {
Nils Diewald52f7eb12015-01-12 17:30:04 +0000998 for (var i = 0; i < this._operands.length; i++) {
Nils Diewald0297ba12015-01-05 21:56:12 +0000999 if (this._operands[i] === obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +00001000
Nils Diewald8f6b6102015-01-08 18:25:33 +00001001 // Delete identified operand
Nils Diewald0297ba12015-01-05 21:56:12 +00001002 this._operands.splice(i,1);
1003
Nils Diewald5c817a42015-01-06 01:08:56 +00001004 // Destroy object for cyclic references
1005 obj.destroy();
1006
Nils Diewaldf219eb82015-01-07 20:15:42 +00001007 return this;
Nils Diewald0297ba12015-01-05 21:56:12 +00001008 };
1009 };
Nils Diewald5c817a42015-01-06 01:08:56 +00001010
1011 // Operand not found
1012 return undefined;
Nils Diewald0297ba12015-01-05 21:56:12 +00001013 },
1014
Nils Diewald8f4e2542014-12-19 04:42:09 +00001015 // Deserialize from json
1016 fromJson : function (json) {
1017 if (json === undefined)
1018 return this;
1019
Nils Diewald86dad5b2015-01-28 15:09:07 +00001020 if (json["@type"] === undefined) {
Nils Diewald8f4e2542014-12-19 04:42:09 +00001021 KorAP.log(701, "JSON-LD group has no @type attribute");
1022 return;
1023 };
1024
1025 if (json["operation"] === undefined ||
1026 typeof json["operation"] !== 'string') {
1027 KorAP.log(811, "Document group expects operation");
1028 return;
1029 };
1030
1031 var operation = json["operation"];
1032
1033 this.operation(operation.replace(/^operation:/,''));
1034
1035 if (json["operands"] === undefined ||
1036 !(json["operands"] instanceof Array)) {
1037 KorAP.log(704, "Operation needs operand list")
1038 return;
1039 };
1040
1041 // Add all documents
1042 for (var i in json["operands"]) {
1043 var operand = json["operands"][i];
Nils Diewald966abf12014-12-20 02:27:45 +00001044 this.append(operand);
Nils Diewald8f4e2542014-12-19 04:42:09 +00001045 };
1046
1047 return this;
1048 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001049
Nils Diewald8f4e2542014-12-19 04:42:09 +00001050 toJson : function () {
1051 var opArray = new Array();
Nils Diewald52f7eb12015-01-12 17:30:04 +00001052 for (var i = 0; i < this._operands.length; i++) {
Nils Diewalde15b7a22015-01-09 21:50:21 +00001053 if (this._operands[i].ldType() !== 'non')
1054 opArray.push(this._operands[i].toJson());
Nils Diewald8f4e2542014-12-19 04:42:09 +00001055 };
1056 return {
Nils Diewald2fe12e12015-03-06 16:47:06 +00001057 "@type" : "koral:" + this.ldType(),
Nils Diewald8f4e2542014-12-19 04:42:09 +00001058 "operation" : "operation:" + this.operation(),
1059 "operands" : opArray
1060 };
Nils Diewaldf219eb82015-01-07 20:15:42 +00001061 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001062
Nils Diewalde15b7a22015-01-09 21:50:21 +00001063 toQuery : function (brackets) {
1064 var list = this._operands
1065 .filter(function (op) {
1066 return op.ldType() !== 'non';
1067 })
1068 .map(function (op) {
Nils Diewaldd599d542015-01-08 20:41:34 +00001069 return (op.ldType() === 'docGroup') ?
Nils Diewalde15b7a22015-01-09 21:50:21 +00001070 op.toQuery(true) :
Nils Diewaldd599d542015-01-08 20:41:34 +00001071 op.toQuery();
Nils Diewalde15b7a22015-01-09 21:50:21 +00001072 });
1073
1074 if (list.length === 1)
1075 return list.join('');
1076 else {
1077 var str = list.join(this.operation() === 'or' ? ' | ' : ' & ');
1078 return brackets ? '(' + str + ')' : str;
1079 };
Nils Diewald8f4e2542014-12-19 04:42:09 +00001080 }
1081 };
1082
1083
Nils Diewald86dad5b2015-01-28 15:09:07 +00001084 KorAP.RewriteList = {
1085 // Construction method
1086 create : function (json) {
1087 var obj = Object(KorAP.JsonLD).
1088 create().
1089 upgradeTo(KorAP.RewriteList).
1090 fromJson(json);
1091 return obj;
1092 },
1093 fromJson : function (json) {
1094 this._list = new Array();
1095 for (var i = 0; i < json.length; i++) {
1096 this._list.push(
1097 KorAP.Rewrite.create(json[i])
1098 );
1099 };
1100 return this;
1101 },
1102 element : function () {
1103 if (this._element !== undefined)
1104 return this._element;
1105
1106 this._element = document.createElement('div');
1107 this._element.setAttribute('class', 'rewrite');
1108 for (var x in this._list) {
1109 var rewrite = this._list[x];
1110 var span = document.createElement('span');
1111
1112 // Set class attribute
1113 span.setAttribute('class', rewrite.operation());
1114
1115 // Append source information
1116 span.appendChild(document.createTextNode(rewrite.src()));
1117
1118 // Append scope information
1119 if (rewrite.scope() !== undefined) {
1120 span.appendChild(
1121 document.createTextNode(
1122 ': ' + rewrite.scope()
1123 )
1124 );
1125 };
1126 this._element.appendChild(span);
1127 };
1128 return this._element;
1129 }
1130 };
1131
1132
1133 /**
1134 * Implementation of rewrite objects.
1135 */
1136 KorAP.Rewrite = {
1137
1138 // Construction method
1139 create : function (json) {
1140 var obj = Object(KorAP.JsonLD).
1141 create().
1142 upgradeTo(KorAP.Rewrite).
1143 fromJson(json);
1144 return obj;
1145 },
1146
1147 // Get or set source
1148 src : function (string) {
1149 if (arguments.length === 1)
1150 this._src = string;
1151 return this._src;
1152 },
1153
1154 // Get or set operation
1155 operation : function (op) {
1156 if (arguments.length === 1) {
1157 if (KorAP._validRewriteOpRE.test(op)) {
1158 this._op = op;
1159 }
1160 else {
1161 KorAP.log(814, "Unknown rewrite operation");
1162 return;
1163 };
1164 };
1165 return this._op || 'injection';
1166 },
1167
1168 // Get or set scope
1169 scope : function (attr) {
1170 if (arguments.length === 1)
1171 this._scope = attr;
1172 return this._scope;
1173 },
1174
1175 // Serialize from Json
1176 fromJson : function (json) {
1177 if (json === undefined)
1178 return this;
1179
1180 // Missing @type
1181 if (json["@type"] === undefined) {
1182 KorAP.log(701, "JSON-LD group has no @type attribute");
1183 return;
1184 };
1185
1186 // Missing source
1187 if (json["src"] === undefined ||
1188 typeof json["src"] !== 'string') {
1189 KorAP.log(815, "Rewrite expects source");
1190 return;
1191 };
1192
1193 // Set source
1194 this.src(json["src"]);
1195
1196 // Set operation
1197 if (json["operation"] !== undefined) {
1198 var operation = json["operation"];
1199 this.operation(operation.replace(/^operation:/,''));
1200 };
1201
1202 // Set scope
1203 if (json["scope"] !== undefined &&
1204 typeof json["scope"] === 'string')
1205 this.scope(json["scope"]);
1206
1207 return this;
1208 },
1209
1210 toString : function () {
1211 var str = '';
1212 var op = this.operation();
1213 str += op.charAt(0).toUpperCase() + op.slice(1);
1214 str += ' of ' + (
1215 this._scope === null ?
1216 'object' :
1217 '"' +
1218 this.scope().replace(KorAP._quote, '\\$1') +
1219 '"'
1220 );
1221 str += ' by ' +
1222 '"' +
1223 this.src().replace(KorAP._quote, '\\$1') +
1224 '"';
1225 return str;
1226 }
1227 };
1228
1229
Nils Diewaldd599d542015-01-08 20:41:34 +00001230 /**
1231 * Abstract JsonLD criterion object
1232 */
Nils Diewald8f4e2542014-12-19 04:42:09 +00001233 KorAP.JsonLD = {
Nils Diewald86dad5b2015-01-28 15:09:07 +00001234 __changed : false,
Nils Diewald8f6b6102015-01-08 18:25:33 +00001235
Nils Diewald8f4e2542014-12-19 04:42:09 +00001236 create : function () {
1237 return Object.create(KorAP.JsonLD);
1238 },
1239
1240 /**
1241 * Upgrade this object to another object
1242 * while private data stays intact
1243 */
1244 upgradeTo : function (props) {
1245 for (var prop in props) {
1246 this[prop] = props[prop];
1247 };
1248 return this;
1249 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001250
Nils Diewald8f4e2542014-12-19 04:42:09 +00001251 ldType : function (type) {
1252 if (arguments.length === 1)
1253 this._ldType = type;
1254 return this._ldType;
1255 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001256
Nils Diewald8f4e2542014-12-19 04:42:09 +00001257 parent : function (obj) {
Nils Diewald8f6b6102015-01-08 18:25:33 +00001258 if (arguments.length === 1) {
Nils Diewald8f4e2542014-12-19 04:42:09 +00001259 this._parent = obj;
Nils Diewald86dad5b2015-01-28 15:09:07 +00001260 this.__changed = true;
Nils Diewald8f6b6102015-01-08 18:25:33 +00001261 };
Nils Diewald8f4e2542014-12-19 04:42:09 +00001262 return this._parent;
Nils Diewald966abf12014-12-20 02:27:45 +00001263 },
Nils Diewald0297ba12015-01-05 21:56:12 +00001264
Nils Diewald5c817a42015-01-06 01:08:56 +00001265 // Destroy object - especially for
1266 // acyclic structures!
Nils Diewald86dad5b2015-01-28 15:09:07 +00001267 // I'm paranoid!
Nils Diewald5c817a42015-01-06 01:08:56 +00001268 destroy : function () {
1269 if (this._ops != undefined) {
1270 this._ops._parent = undefined;
1271 if (this._ops._element !== undefined)
1272 this._ops._element.refTo = undefined;
1273 this._ops = undefined;
1274 };
1275 if (this._element !== undefined)
1276 this._element = undefined;
1277
1278 // In case of a group, destroy all operands
1279 if (this._operands !== undefined) {
Nils Diewald52f7eb12015-01-12 17:30:04 +00001280 for (var i = 0; i < this._operands.length; i++)
Nils Diewald5c817a42015-01-06 01:08:56 +00001281 this.getOperand(i).destroy();
Nils Diewaldf219eb82015-01-07 20:15:42 +00001282 this._operands = [];
Nils Diewald5c817a42015-01-06 01:08:56 +00001283 };
1284 },
1285
Nils Diewald52f7eb12015-01-12 17:30:04 +00001286 // Wrap a new operation around the root group element
1287 wrapOnRoot : function (op) {
1288 var parent = this.parent();
1289
1290 var group = KorAP.DocGroup.create(parent);
1291 if (arguments.length === 1)
1292 group.operation(op);
1293 else
1294 group.operation(
1295 this.operation() === 'and' ? 'or' : 'and'
1296 );
1297 group.append(this);
1298 this.parent(group);
1299 group.append();
1300 group.element(); // Init (seems to be necessary)
1301 parent.root(group);
1302 return this.parent();
1303 },
1304
Nils Diewald0297ba12015-01-05 21:56:12 +00001305 // Be aware! This may be cyclic
Nils Diewald966abf12014-12-20 02:27:45 +00001306 operators : function (and, or, del) {
1307 if (arguments === 0)
1308 return this._ops;
1309 this._ops = KorAP.Operators.create(
1310 and, or, del
1311 );
Nils Diewald0297ba12015-01-05 21:56:12 +00001312 this._ops.parent(this);
Nils Diewald966abf12014-12-20 02:27:45 +00001313 return this._ops;
1314 },
Nils Diewald8f6b6102015-01-08 18:25:33 +00001315
Nils Diewald966abf12014-12-20 02:27:45 +00001316 toJson : function () {
1317 return {
1318 // Unspecified object
Nils Diewald2fe12e12015-03-06 16:47:06 +00001319 "@type" : "koral:" + this.ldType()
Nils Diewald966abf12014-12-20 02:27:45 +00001320 };
Nils Diewald8f6b6102015-01-08 18:25:33 +00001321 },
Nils Diewaldd599d542015-01-08 20:41:34 +00001322
1323 toQuery : function () {
Nils Diewaldfda29d92015-01-22 17:28:01 +00001324 return '';
Nils Diewald8f4e2542014-12-19 04:42:09 +00001325 }
1326 };
Nils Diewald2fe12e12015-03-06 16:47:06 +00001327
1328
1329 /**
1330 * Criterion in a KorAP.Doc
1331 */
1332 KorAP._changeKey = function () {
1333 var doc = this.parentNode.refTo;
Nils Diewaldd2b57372015-03-10 20:09:48 +00001334 var key = doc.element().firstChild;
1335 key.appendChild(KorAP.FieldChooser.element());
1336 KorAP.FieldChooser.show();
1337 KorAP.FieldChooser.focus();
Nils Diewald2fe12e12015-03-06 16:47:06 +00001338 // key, matchop, type, value
1339 };
1340
Nils Diewald2fe12e12015-03-06 16:47:06 +00001341 // Field menu
1342 KorAP.FieldMenu = {
1343 create : function (params) {
1344 return Object.create(KorAP.Menu)
1345 .upgradeTo(KorAP.FieldMenu)
Nils Diewaldd2b57372015-03-10 20:09:48 +00001346 ._init(KorAP.FieldMenuItem, undefined, params)
Nils Diewald2fe12e12015-03-06 16:47:06 +00001347 }
1348 };
1349
1350
1351 // Field menu item
1352 KorAP.FieldMenuItem = {
1353 create : function (params) {
1354 return Object.create(KorAP.MenuItem)
1355 .upgradeTo(KorAP.FieldMenuItem)
1356 ._init(params);
1357 },
1358 _init : function (params) {
1359 if (params[0] === undefined)
1360 throw new Error("Missing parameters");
1361
1362 this._name = params[0];
1363 this._value = params[1];
1364 this._type = params[2];
1365
1366 this._lcField = ' ' + this._name.toLowerCase();
1367
1368 return this;
1369 },
1370 name : function () {
1371 return this._name;
1372 },
1373 type : function () {
1374 return this._type;
1375 },
1376 element : function () {
1377 // already defined
1378 if (this._element !== undefined)
1379 return this._element;
1380
1381 // Create list item
1382 var li = document.createElement("li");
1383 li.setAttribute("data-type", this._type);
1384 li.setAttribute("data-value", this._value);
1385 li.appendChild(document.createTextNode(this._name));
1386 return this._element = li;
1387 }
1388 };
Nils Diewaldd2b57372015-03-10 20:09:48 +00001389
1390 KorAP.FieldChooser = KorAP.FieldMenu.create([
1391 ['Titel', 'title', 'string'],
1392 ['Untertitel', 'subTitle', 'string'],
1393 ['Veröffentlichungsdatum', 'pubDate', 'date'],
1394 ['Autor', 'author', 'string']
1395 ]);
1396 KorAP.FieldChooser.limit(5);
Nils Diewald8f4e2542014-12-19 04:42:09 +00001397
Nils Diewald3a2d8022014-12-16 02:45:41 +00001398}(this.KorAP));