Yangman - Rpc output list is appending elements instead of replacing
[dlux.git] / modules / common-yangutils-resources / src / main / resources / yangutils / services / node-wrapper.services.js
1 define([], function () {
2     'use strict';
3
4     function NodeWrapperService(constants, RequestBuilderService, RestrictionsService, TypeWrapperService,
5                                 ListFilteringService, EventDispatcherService, FilterNodeWrapperService){
6
7         var service = {
8             case: caseYang,
9             config: config,
10             container: container,
11             checkKeyDuplicity: checkKeyDuplicity,
12             choice: choice,
13             input: input,
14             key: key,
15             leaf: leaf,
16             'leaf-list': leafList,
17             length: length,
18             list: list,
19             _listElem: _listElem,
20             output: output,
21             pattern: pattern,
22             range: range,
23             rpc: rpc,
24             type: type,
25             wrap: wrap,
26             wrapAll: wrapAll,
27             __test: {
28                 comparePropToElemByName: comparePropToElemByName,
29                 equalArrays: equalArrays,
30                 equalListElems: equalListElems,
31                 parseRestrictText: parseRestrictText,
32                 getTypes: getTypes,
33                 checkListElemKeys: checkListElemKeys,
34             },
35         };
36
37         return service;
38
39         /**
40          * Service for wrapping list element
41          * @param node
42          * @private
43          */
44         function _listElem(node) {
45             node.refKey = [];
46
47             node.listElemBuildRequest = function (builder, req) {
48                 var added = false,
49                     objToAdd = builder.createObj();
50
51                 node.getChildren(null, null, constants.NODE_UI_DISPLAY).forEach(function (child) {
52                     var childAdded = child.buildRequest(builder, objToAdd, node.module);
53                     added = added || childAdded;
54                 });
55
56                 if (added) {
57                     builder.insertObjToList(req, objToAdd);
58                 }
59
60                 return added;
61             };
62
63             node.fillListElement = function (name, data) {
64                 var filled = false;
65
66                 node.getChildren(null, null, constants.NODE_UI_DISPLAY).forEach(function (child) {
67                     var childFilled = child.fill(name, data);
68                     filled = filled || childFilled;
69                 });
70
71                 return filled;
72             };
73
74             node.isFilled = function () {
75                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
76                     return child.isFilled();
77                 });
78             };
79
80             node.clear = function () {
81                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
82
83                 if (nodesToClear.length) {
84                     nodesToClear.forEach(function (child) {
85                         child.clear();
86                     });
87                 }
88             };
89
90             node.children.forEach(function (child) {
91                 wrapAll(child);
92             });
93         }
94
95         /**
96          * Service for wrapping list yang element
97          * @param node
98          */
99         function list(node) {
100             node.refKey = [];
101             node.doubleKeyIndexes = [];
102             node.actElemStructure = null;
103             node.actElemIndex = -1;
104             node.listData = [];
105             node.expanded = true;
106             node.filters = [];
107             node.filterNodes = [];
108             node.searchedPath = [];
109             node.referenceNode = null;
110             node.filteredListData = [];
111             node.currentFilter = 0;
112
113             node.toggleExpand = function () {
114                 node.expanded = !node.expanded;
115             };
116
117             node.createStructure = function () {
118                 if (node.actElemStructure === null) {
119                     var copy = node.deepCopy(['augmentionGroups', 'augmentationId']);
120                     _listElem(copy);
121                     node.actElemStructure = copy;
122                     node.actElemStructure.getActElemIndex = node.getActElemIndex;
123                 }
124             };
125
126             node.getActElemIndex = function () {
127                 return node.actElemIndex;
128             };
129
130             node.addListElem = function () {
131                 node.createStructure();
132                 var newElemData = {};
133                 node.listData.push(newElemData);
134                 node.changeActElementData(node.listData.length - 1, true);
135             };
136
137             node.buildActElemData = function () {
138                 var list = [],
139                     result;
140
141                 if (node.actElemStructure) {
142                     node.actElemStructure.listElemBuildRequest(RequestBuilderService, list, node.module);
143                     result = list[0] ? list[0] : {};
144                 }
145                 return result;
146             };
147
148             node.changeActElementData = function (index, fromAdd) {
149                 var storeData = node.buildActElemData();
150                 node.expanded = true;
151
152                 if (node.actElemIndex > -1) { // we are changing already existing data
153                     if (node.filteredListData && node.filteredListData.length){
154                         node.listData[node.listData.indexOf(node.filteredListData[node.actElemIndex])] = storeData;
155                         node.filteredListData[node.actElemIndex] = storeData;
156                         if (fromAdd){
157                             ListFilteringService.clearFilterData(node, true, false);
158                         }
159                     } else {
160                         node.listData[node.actElemIndex] = storeData;
161                     }
162                 }
163                 node.actElemIndex = index;
164
165                 var actData = null;
166                 if (!(node.filteredListData && node.filteredListData.length)){
167                     actData = node.listData[node.actElemIndex];
168                 } else {
169                     actData = node.listData[node.listData.indexOf(node.filteredListData[node.actElemIndex])];
170                 }
171
172                 node.actElemStructure.clear();
173                 Object.keys(actData).forEach(function(prop) {
174                     node.actElemStructure.fillListElement(prop, actData[prop]);
175                 });
176
177                 EventDispatcherService.dispatch(constants.EV_LIST_CHANGED, node.actElemStructure);
178             };
179
180             node.removeListElem = function (elemIndex, fromFilter) {
181
182                 if (fromFilter){
183                     elemIndex = node.listData.indexOf(node.filteredListData[elemIndex]);
184                 }
185
186                 node.listData.splice(elemIndex, 1);
187                 node.actElemIndex = node.listData.length - 1;
188
189                 if (fromFilter){
190                     ListFilteringService.clearFilterData(node, true, false);
191                 }
192
193                 if (node.actElemIndex === -1) {
194                     node.actElemStructure = null;
195                 } else {
196                     var actData = node.listData[node.actElemIndex];
197
198                     node.actElemStructure.clear();
199                     Object.keys(actData).forEach(function(prop) {
200                         node.actElemStructure.fillListElement(prop, actData[prop]);
201                     });
202                 }
203
204                 EventDispatcherService.dispatch(constants.EV_LIST_CHANGED, node.actElemStructure);
205             };
206
207             node.buildRequest = function (builder, req, module) {
208                 var added = false;
209                 // store entered data
210                 var storeData = node.buildActElemData(),
211                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
212
213                 if (node.actElemIndex > -1) {
214                     if (node.filteredListData && node.filteredListData.length){
215                         node.listData[node.listData.indexOf(node.filteredListData[node.actElemIndex])] = storeData;
216                         node.filteredListData[node.actElemIndex] = storeData;
217                     } else {
218                         node.listData[node.actElemIndex] = storeData;
219                     }
220                 }
221
222                 added = node.listData.filter(function (data) {
223                     return $.isEmptyObject(data) === false;
224                 }).length > 0;
225
226                 var buildedDataCopy = node.listData.slice().map(function (item) {
227                     var newItem = {};
228                     Object.keys(item).forEach(function(prop) {
229                         if (prop !== '$$hashKey'){
230                             newItem[prop] = item[prop];
231                         }
232                     });
233                     return newItem;
234                 }).filter(function (item){
235                     return Object.keys(item).length !== 0;
236                 });
237
238                 // check of listElems keyValues duplicity
239                 if (node.filteredListData && node.filteredListData.length){
240                     node.doubleKeyIndexes = checkKeyDuplicity(node.filteredListData, node.refKey);
241                 } else {
242                     node.doubleKeyIndexes = checkKeyDuplicity(node.listData, node.refKey);
243                 }
244
245                 if (added) {
246                     builder.insertPropertyToObj(req, labelWithModule, buildedDataCopy);
247                 }
248
249                 return added;
250             };
251
252             node.fill = function (name, array) { // data is array
253
254                 var match = comparePropToElemByName(name, node.label);
255
256                 if (match && array.length) {
257                     node.createStructure();
258                     node.listData = array.slice();
259                     node.actElemIndex = node.listData.length - 1;
260
261                     Object.keys(node.listData[node.actElemIndex]).forEach(function(prop) {
262                         node.actElemStructure.fillListElement(prop, node.listData[node.actElemIndex][prop]);
263                     });
264                 }
265
266                 return (match && array.length > 0);
267             };
268
269             node.clear = function () {
270                 while (node.listData.length > 0) {
271                     node.listData.pop();
272                 }
273                 while (node.filteredListData.length > 0) {
274                     node.filteredListData.pop();
275                 }
276
277                 node.actElemIndex = -1;
278                 node.actElemStructure = null;
279                 node.nodeType = constants.NODE_UI_DISPLAY;
280             };
281
282             node.isFilled = function () {
283                 return node.listData.length > 0;
284             };
285
286             node.createListName = function (index) {
287                 var name = '',
288                     val = '',
289                     currentList = null;
290
291                 if (node.filteredListData && node.filteredListData.length){
292                     currentList = node.filteredListData;
293                 } else {
294                     currentList = node.listData;
295                 }
296
297                 if (index > -1) {
298                     node.actElemStructure.refKey.forEach(function (key) {
299                         if (index === node.getActElemIndex()) {
300                             val = key.value !== '' ? key.label + ':' + key.value : '';
301                         } else {
302                             var prop = '';
303                             if (!($.isEmptyObject(currentList[index]))) {
304                                 if (currentList[index][key.label]) {
305                                     prop = key.label;
306                                 } else if (currentList[index][key.module + ':' + key.label]) {
307                                     prop = key.module + ':' + key.label;
308                                 }
309                                 val = prop ? key.label + ':' + currentList[index][prop] : prop;
310                             }
311                         }
312
313                         name = name ? (name + (val ? (' ' + val) : '')) : (name + (val ? (' <' + val) : ''));
314                     });
315                 }
316
317                 if (name) {
318                     name = name + '>';
319                 }
320
321                 return name;
322             };
323
324             node.getNewFilterElement = function (){
325                 return node.getChildrenForFilter().map(function (element){
326                     FilterNodeWrapperService.init(element);
327                     var copy = element.deepCopyForFilter();
328                     wrapAll(copy);
329                     FilterNodeWrapperService.wrapForFilter(copy);
330                     return copy;
331                 });
332             };
333         }
334
335         // TODO: add service's description
336         function config(node) {
337             node.parent.isConfigStm = (node.label === 'true');
338         }
339
340         // TODO: add service's description
341         function key(node) {
342             // do this only on list, not on listElem because deepCopy on list doesn't copy property keys to
343             // listElem => don't do this when button for add new list is clicked
344             if (node.parent.hasOwnProperty('refKey')) {
345                 var keyLabels = node.label.split(' '),
346                     keyNodes = node.parent.getChildren(null, null, constants.NODE_UI_DISPLAY).filter(function (child) {
347                         return keyLabels.indexOf(child.label) > -1;
348                     }),
349                     getRefKeyArray = function (keys){
350                         var refKeyArray = [];
351                         keyLabels.forEach(function (keyLabel){
352                             var nk = keys.filter(function (k){
353                                 return keyLabel === k.label;
354                             });
355
356                             if ( nk.length ) {
357                                 refKeyArray.push(nk[0]);
358                             }
359                         });
360                         return refKeyArray;
361                     };
362
363                 node.parent.refKey = getRefKeyArray(keyNodes);
364             }
365         }
366
367         /**
368          * Service for wrapping leaf list yang element
369          * @param node
370          */
371         function leafList(node) {
372             node.value = [];
373             node.expanded = true;
374
375             node.toggleExpand = function () {
376                 node.expanded = !node.expanded;
377             };
378
379             node.addListElem = function () {
380                 var newElement = {
381                     value: '',
382                 };
383                 node.value.push(newElement);
384             };
385
386             node.removeListElem = function (elem) {
387                 node.value.splice(node.value.indexOf(elem), 1);
388             };
389
390             node.buildRequest = function (builder, req, module) {
391                 var valueArray = [],
392                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
393
394                 for (var i = 0; i < node.value.length; i++) {
395                     valueArray.push(node.value[i].value);
396                 }
397
398                 if (valueArray.length > 0) {
399                     builder.insertPropertyToObj(req, labelWithModule, valueArray);
400                     return true;
401                 }
402
403                 return false;
404
405             };
406
407
408             node.fill = function (name, array) {
409                 var match = comparePropToElemByName(name, node.label),
410                     newLeafListItem;
411
412                 if (match) {
413                     node.value = [];
414                     for (var i = 0; i < array.length; i++) {
415                         newLeafListItem = {
416                             value: array[i],
417                         };
418                         node.value.push(newLeafListItem);
419                     }
420
421                 }
422                 return match;
423             };
424
425             node.clear = function () {
426                 node.nodeType = constants.NODE_UI_DISPLAY;
427                 node.value = [];
428             };
429
430             node.isFilled = function () {
431                 return node.value.length > 0;
432             };
433         }
434
435         /**
436          * Service for wrapping choice yang element
437          * @param node
438          */
439         function choice(node) {
440             node.choice = null;
441             node.expanded = true;
442
443             node.buildRequest = function (builder, req, module) {
444                 var added = false;
445
446                 if (node.choice) {
447                     added = node.choice.buildRequest(builder, req, module);
448                 }
449
450                 return added;
451             };
452
453             node.fill = function (name, data) {
454                 var filled = false,
455                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
456
457                 nodesToFill.forEach(function (child) {
458                     var childFilled = child.fill(name, data);
459
460                     if (childFilled) {
461                         node.choice = child;
462                     }
463
464                     filled = filled || childFilled;
465                     if (filled) {
466                         return false;
467                     }
468                 });
469
470                 return filled;
471             };
472
473             node.clear = function () {
474                 node.nodeType = constants.NODE_UI_DISPLAY;
475
476                 if (node.choice) {
477                     node.choice.clear();
478                     node.choice = null;
479                 }
480             };
481
482             node.isFilled = function () {
483                 return node.choice !== null;
484             };
485         }
486
487         /**
488          * Service for wrapping case yang element
489          * @param node
490          */
491         function caseYang(node) {
492
493             node.buildRequest = function (builder, req, module) {
494                 var added = false;
495
496                 node.getChildren(null, null, constants.NODE_UI_DISPLAY).forEach(function (child) {
497                     var childAdded = child.buildRequest(builder, req, module);
498                     added = added || childAdded;
499                 });
500
501                 return added;
502             };
503
504             node.fill = function (name, data) {
505                 var filled = false,
506                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
507
508                 nodesToFill.forEach(function (child) {
509                     var childFilled = child.fill(name, data);
510                     filled = filled || childFilled;
511                 });
512
513                 return filled;
514             };
515
516             node.clear = function () {
517                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
518
519                 nodesToClear.forEach(function (child) {
520                     child.clear();
521                 });
522             };
523
524             node.isFilled = function () {
525                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
526                     return child.isFilled();
527                 });
528             };
529         }
530
531         /**
532          * Service for wrapping output yang element
533          * @param node
534          */
535         function output(node) {
536             node.expanded = true;
537
538             node.buildRequest = function (builder, req) {
539
540             };
541
542             node.fill = function (name, data) {
543                 var match = comparePropToElemByName(name, node.label),
544                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
545
546                 if (match && nodesToFill.length) {
547                     nodesToFill.forEach(function (child) {
548                         Object.keys(data).forEach(function(prop) {
549                             child.fill(prop, data[prop]);
550                         });
551                     });
552                     node.expanded = match;
553                 }
554
555                 return match;
556             };
557
558             node.clear = function () {
559                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
560
561                 if (nodesToClear.length) {
562                     nodesToClear.forEach(function (child) {
563                         child.clear();
564                     });
565                 }
566             };
567
568             node.isFilled = function () {
569                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
570                     return child.isFilled();
571                 });
572             };
573
574         }
575
576         // TODO: add service's description
577         function input(node) {
578             node.expanded = true;
579
580             node.buildRequest = function (builder, req, module) {
581                 var added = false,
582                     objToAdd = builder.createObj(),
583                     builderNodes = node.getChildren(null, null, constants.NODE_UI_DISPLAY),
584                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
585
586                 if (builderNodes.length) {
587
588                     builderNodes.forEach(function (child) {
589                         var childAdded = child.buildRequest(builder, objToAdd, node.module);
590                         added = added || childAdded;
591                     });
592                 } else {
593                     added = true;
594                 }
595
596                 if (added) {
597                     builder.insertPropertyToObj(req, labelWithModule, objToAdd);
598                 }
599
600                 return added;
601             };
602
603             node.fill = function (name, data) {
604                 var match = comparePropToElemByName(name, node.label),
605                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
606
607                 if (match && nodesToFill.length) {
608                     nodesToFill.forEach(function (child) {
609                         Object.keys(data).forEach(function(prop) {
610                             child.fill(prop, data[prop]);
611                         });
612                     });
613                     node.expanded = match;
614                 }
615
616                 return match;
617             };
618
619             node.clear = function () {
620                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
621
622                 if (nodesToClear.length) {
623                     nodesToClear.forEach(function (child) {
624                         child.clear();
625                     });
626                 }
627             };
628
629             node.isFilled = function () {
630                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
631                     return child.isFilled();
632                 });
633             };
634
635         }
636
637         /**
638          * Service for wrapping rpc yang element
639          * @param node
640          */
641         function rpc(node) {
642             node.expanded = true;
643             node.buildRequest = function (builder, req, module) {
644                 var added = false,
645                     objToAdd = builder.createObj(),
646                     builderNodes = node.getChildren(null, null, constants.NODE_UI_DISPLAY),
647                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
648
649                 if (builderNodes.length) {
650                     builderNodes.forEach(function (child) {
651                         var childAdded = child.buildRequest(builder, objToAdd, node.module);
652                         added = added || childAdded;
653                     });
654                 } else {
655                     added = true;
656                     objToAdd = constants.NULL_DATA;
657                 }
658
659                 if (added) {
660                     builder.insertPropertyToObj(req, labelWithModule, objToAdd);
661                 }
662
663                 return added;
664             };
665
666             node.fill = function (name, data) {
667                 var match = comparePropToElemByName(name, node.label),
668                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
669
670                 if (match && nodesToFill.length) {
671                     nodesToFill.forEach(function (child) {
672                         Object.keys(data).forEach(function(prop) {
673                             child.fill(prop, data[prop]);
674                         });
675                     });
676                 }
677
678                 node.expanded = match;
679
680                 return match;
681             };
682
683             node.clear = function () {
684                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
685
686                 if (nodesToClear.length) {
687                     nodesToClear.forEach(function (child) {
688                         child.clear();
689                     });
690                 }
691             };
692
693             node.isFilled = function () {
694                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
695                     return child.isFilled();
696                 });
697             };
698
699         }
700
701         /**
702          * Service for wrapping container yang element
703          * @param node
704          */
705         function container(node) {
706             node.expanded = false;
707
708             node.toggleExpand = function () {
709                 node.expanded = !node.expanded;
710             };
711
712             node.buildRequest = function (builder, req, module) {
713                 var added = false,
714                     objToAdd = builder.createObj(),
715                     builderNodes = node.getChildren(null, null, constants.NODE_UI_DISPLAY),
716                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
717
718                 if (builderNodes.length) {
719                     builderNodes.forEach(function (child) {
720                         var childAdded = child.buildRequest(builder, objToAdd, node.module);
721                         added = added || childAdded;
722                     });
723                 } else  {
724                     added = true;
725                 }
726
727                 if (added && (checkEmptyContainer(node.parent ? node.parent.type : 'blanktype', objToAdd) ||
728                     checkPresence(node))) {
729                     builder.insertPropertyToObj(req, labelWithModule, objToAdd);
730                 }
731
732                 return added;
733
734                 // TODO: add function's description
735                 function checkPresence(containerNode) {
736                     return containerNode.children.some(function (ch) {
737                         return ch.type === 'presence';
738                     });
739                 }
740
741                 // TODO: add function's description
742                 function checkEmptyContainer(type, obj) { // TODO: absolete after when statement is implemented
743                     return !!(type === 'case' || !$.isEmptyObject(objToAdd));
744                 }
745             };
746
747             node.fill = function (name, data) {
748                 var match = comparePropToElemByName(name, node.label),
749                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
750
751                 if (match && nodesToFill.length) {
752                     nodesToFill.forEach(function (child) {
753                         Object.keys(data).forEach(function(prop) {
754                             child.fill(prop, data[prop]);
755                         });
756                     });
757
758                     node.expanded = match;
759                 }
760
761                 return match;
762             };
763
764             node.clear = function () {
765                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
766                 node.nodeType = constants.NODE_UI_DISPLAY;
767
768                 if (nodesToClear.length) {
769                     nodesToClear.forEach(function (child) {
770                         child.clear();
771                     });
772                 }
773             };
774
775             node.isFilled = function () {
776                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
777                     return child.isFilled();
778                 });
779             };
780         }
781
782         /**
783          * Service for set patern restriction from yang element
784          * @param node
785          */
786         function pattern(node) {
787             node.restrictions = [RestrictionsService.getReqexpValidationFnc(node.label)];
788         }
789
790         /**
791          * Service for set range restriction from yang element
792          * @param node
793          */
794         function range(node) {
795             node.restrictions = parseRestrictText(node.label);
796         }
797
798         /**
799          * Service for set length restriction from yang element
800          * @param node
801          */
802         function length(node) {
803             node.restrictions = parseRestrictText(node.label);
804         }
805
806         /**
807          * Service for wrapping type yang element
808          * @param node
809          */
810         function type(node) {
811             TypeWrapperService.wrapAll(node);
812         }
813
814         /**
815          * Service for wrapping leaf yang element
816          * @param node
817          */
818         function leaf(node) {
819             node.value = '';
820             node.valueIsValid = true;
821             node.typeChild = node.getChildren('type')[0];
822
823             node.buildRequest = function (builder, req, module) {
824                 var value = node.typeChild.getValue(),
825                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
826
827                 if (node.isKey()) {
828                     EventDispatcherService.dispatch(constants.EV_FILL_PATH, node, value);
829                 }
830
831                 if (value) {
832                     builder.insertPropertyToObj(req, labelWithModule, value);
833                     return true;
834                 }
835
836                 return false;
837             };
838
839             node.fill = function (name, data) {
840                 var match = '';
841
842                 match = comparePropToElemByName(name, node.label);
843                 if (match) {
844                     node.value = data.toString();
845                     if (node.typeChild) {
846                         node.typeChild.fill(node.value);
847                     }
848                 }
849                 return match;
850             };
851
852             node.clear = function () {
853                 node.value = '';
854
855                 if (node.typeChild) {
856                     node.typeChild.clear();
857                 }
858             };
859
860             node.isFilled = function () {
861                 var filled = node.typeChild.getValue() ? true : false;
862                 return filled;
863             };
864
865             node.checkValueType = function () {
866                 node.valueIsValid = node.typeChild ? node.typeChild.check(node.value) : true;
867             };
868
869             node.isKey = function () {
870                 return node.parent &&
871                     node.parent.type === 'list' &&
872                     node.parent.refKey && node.parent.refKey.indexOf(node) !== -1;
873             };
874         }
875
876         /**
877          * Service for wrapping single node
878          * @param node
879          */
880         function wrap(node) {
881             if (service.hasOwnProperty(node.type)) {
882                 service[node.type](node);
883             }
884         }
885
886         /**
887          * Main service for wrapping nodes
888          * @param node
889          */
890         function wrapAll(node) {
891             service.wrap(node);
892             node.children.forEach(function (child) {
893                 service.wrapAll(child);
894             });
895         }
896
897         // TODO: add service's description
898         function checkKeyDuplicity(listData, refKey) {
899             return checkListElemKeys(listData, refKey);
900         }
901
902         // TODO: add function's description
903         function comparePropToElemByName(propName, elemName) {
904             // AUGMENT FIX
905             // return propName === elemName; // TODO also check by namespace - redundancy?
906
907             // TODO also check by namespace - redundancy?
908             return (propName.indexOf(':') > -1 ? propName.split(':')[1] : propName) === elemName;
909         }
910
911         // TODO: add function's description
912         function equalArrays(arrA, arrB) {
913             var match = (arrA.length === arrB.length) && arrA.length > 0;
914
915             if (match) {
916                 var i = 0;
917                 while (i < arrA.length && match) {
918                     var valMatch = arrA[i] === arrB[i];
919                     match = match && valMatch;
920                     i++;
921                 }
922             }
923             return match;
924         }
925
926         // TODO: add function's description
927         function equalListElems(listElemA, listElemB, refKey) {
928             var keyValuesA = getKeyArrayValues(listElemA, refKey),
929                 keyValuesB = getKeyArrayValues(listElemB, refKey);
930
931             return equalArrays(keyValuesA, keyValuesB);
932
933             // TODO: add function's description
934             function getKeyValue(data, label, module) {
935                 if (data && data.hasOwnProperty(label)) {
936                     return data[label];
937                 } else if (data && data.hasOwnProperty(module + ':' + label)) {
938                     return data[module + ':' + label];
939                 } else {
940                     return null;
941                 }
942             }
943
944             // TODO: add function's description
945             function getKeyArrayValues(data, refKey) {
946                 return refKey.map(function (key) {
947                     return getKeyValue(data, key.label, key.module);
948                 }).filter(function (item) {
949                     return item !== null;
950                 });
951             }
952         }
953
954         // TODO: add function's description
955         function checkListElemKeys(listData, refKey) {
956             var doubleKeyIndexes = [],
957                 checkedElems = [];
958
959             listData.forEach(function (item, index) {
960                 var duplitactes = checkedElems.filter(function (checked) {
961                     var isDuplicate = equalListElems(item, checked.item, refKey);
962                     if (isDuplicate && doubleKeyIndexes.indexOf(checked.index) === -1) {
963                         doubleKeyIndexes.push(checked.index);
964                     }
965                     return isDuplicate;
966                 });
967
968                 if (duplitactes.length) {
969                     // item is already in checkedElems so we don't need to push it again
970                     doubleKeyIndexes.push(index);
971                 } else {
972                     checkedElems.push({ index: index, item: item });
973                 }
974             });
975
976             return doubleKeyIndexes;
977         }
978
979         // TODO: add function's description
980         function parseRestrictText(text) {
981             return text.split('|').map(function (elem) {
982                 var subElems = elem.split('..');
983                 return subElems.length === 1 ? RestrictionsService.getEqualsFnc(subElems[0]) :
984                     RestrictionsService.getMinMaxFnc(subElems[0], subElems[1]);
985             });
986         }
987
988         // TODO: add function's description
989         function getTypes(node) {
990             var types = [];
991
992             var getTypesRecursive = function (node, types) {
993                 types.push(node);
994
995                 node.getChildren('type').forEach(function (child) {
996                     getTypesRecursive(child, types);
997                 });
998             };
999
1000             node.getChildren('type').forEach(function (child) {
1001                 getTypesRecursive(child, types);
1002             });
1003
1004             return types;
1005         }
1006     }
1007
1008     NodeWrapperService.$inject = ['constants', 'RequestBuilderService', 'RestrictionsService', 'TypeWrapperService',
1009         'ListFilteringService', 'EventDispatcherService', 'FilterNodeWrapperService'];
1010
1011     return NodeWrapperService;
1012
1013 });