Merge "Yangman - add yang form"
[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                 for (var prop in actData) {
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                     for (var prop in actData) {
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                     for (var prop in item){
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                     for (var prop in node.listData[node.actElemIndex]) {
261                         node.actElemStructure.fillListElement(prop, node.listData[node.actElemIndex][prop]);
262                     }
263                 }
264
265                 return (match && array.length > 0);
266             };
267
268             node.clear = function () {
269                 while (node.listData.length > 0) {
270                     node.listData.pop();
271                 }
272                 while (node.filteredListData.length > 0) {
273                     node.filteredListData.pop();
274                 }
275
276                 node.actElemIndex = -1;
277                 node.actElemStructure = null;
278                 node.nodeType = constants.NODE_UI_DISPLAY;
279             };
280
281             node.isFilled = function () {
282                 return node.listData.length > 0;
283             };
284
285             node.createListName = function (index) {
286                 var name = '',
287                     val = '',
288                     currentList = null;
289
290                 if (node.filteredListData && node.filteredListData.length){
291                     currentList = node.filteredListData;
292                 } else {
293                     currentList = node.listData;
294                 }
295
296                 if (index > -1) {
297                     node.actElemStructure.refKey.forEach(function (key) {
298                         if (index === node.getActElemIndex()) {
299                             val = key.value !== '' ? key.label + ':' + key.value : '';
300                         } else {
301                             var prop = '';
302                             if (!($.isEmptyObject(currentList[index]))) {
303                                 if (currentList[index][key.label]) {
304                                     prop = key.label;
305                                 } else if (currentList[index][key.module + ':' + key.label]) {
306                                     prop = key.module + ':' + key.label;
307                                 }
308                                 val = prop ? key.label + ':' + currentList[index][prop] : prop;
309                             }
310                         }
311
312                         name = name ? (name + (val ? (' ' + val) : '')) : (name + (val ? (' <' + val) : ''));
313                     });
314                 }
315
316                 if (name) {
317                     name = name + '>';
318                 }
319
320                 return name;
321             };
322
323             node.getNewFilterElement = function (){
324                 return node.getChildrenForFilter().map(function (element){
325                     FilterNodeWrapperService.init(element);
326                     var copy = element.deepCopyForFilter();
327                     wrapAll(copy);
328                     FilterNodeWrapperService.wrapForFilter(copy);
329                     return copy;
330                 });
331             };
332         }
333
334         // TODO: add service's description
335         function config(node) {
336             node.parent.isConfigStm = (node.label === 'true');
337         }
338
339         // TODO: add service's description
340         function key(node) {
341             // do this only on list, not on listElem because deepCopy on list doesn't copy property keys to
342             // listElem => don't do this when button for add new list is clicked
343             if (node.parent.hasOwnProperty('refKey')) {
344                 var keyLabels = node.label.split(' '),
345                     keyNodes = node.parent.getChildren(null, null, constants.NODE_UI_DISPLAY).filter(function (child) {
346                         return keyLabels.indexOf(child.label) > -1;
347                     }),
348                     getRefKeyArray = function (keys){
349                         var refKeyArray = [];
350                         keyLabels.forEach(function (keyLabel){
351                             var nk = keys.filter(function (k){
352                                 return keyLabel === k.label;
353                             });
354
355                             if ( nk.length ) {
356                                 refKeyArray.push(nk[0]);
357                             }
358                         });
359                         return refKeyArray;
360                     };
361
362                 node.parent.refKey = getRefKeyArray(keyNodes);
363             }
364         }
365
366         /**
367          * Service for wrapping leaf list yang element
368          * @param node
369          */
370         function leafList(node) {
371             node.value = [];
372             node.expanded = true;
373
374             node.toggleExpand = function () {
375                 node.expanded = !node.expanded;
376             };
377
378             node.addListElem = function () {
379                 var newElement = {
380                     value: '',
381                 };
382                 node.value.push(newElement);
383             };
384
385             node.removeListElem = function (elem) {
386                 node.value.splice(node.value.indexOf(elem), 1);
387             };
388
389             node.buildRequest = function (builder, req, module) {
390                 var valueArray = [],
391                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
392
393                 for (var i = 0; i < node.value.length; i++) {
394                     valueArray.push(node.value[i].value);
395                 }
396
397                 if (valueArray.length > 0) {
398                     builder.insertPropertyToObj(req, labelWithModule, valueArray);
399                     return true;
400                 }
401
402                 return false;
403
404             };
405
406
407             node.fill = function (name, array) {
408                 var match = comparePropToElemByName(name, node.label),
409                     newLeafListItem;
410
411                 if (match) {
412
413                     for (var i = 0; i < array.length; i++) {
414                         newLeafListItem = {
415                             value: array[i],
416                         };
417                         node.value.push(newLeafListItem);
418                     }
419
420                 }
421                 return match;
422             };
423
424             node.clear = function () {
425                 node.nodeType = constants.NODE_UI_DISPLAY;
426                 node.value = [];
427             };
428
429             node.isFilled = function () {
430                 return node.value.length > 0;
431             };
432         }
433
434         /**
435          * Service for wrapping choice yang element
436          * @param node
437          */
438         function choice(node) {
439             node.choice = null;
440             node.expanded = true;
441
442             node.buildRequest = function (builder, req, module) {
443                 var added = false;
444
445                 if (node.choice) {
446                     added = node.choice.buildRequest(builder, req, module);
447                 }
448
449                 return added;
450             };
451
452             node.fill = function (name, data) {
453                 var filled = false,
454                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
455
456                 nodesToFill.forEach(function (child) {
457                     var childFilled = child.fill(name, data);
458
459                     if (childFilled) {
460                         node.choice = child;
461                     }
462
463                     filled = filled || childFilled;
464                     if (filled) {
465                         return false;
466                     }
467                 });
468
469                 return filled;
470             };
471
472             node.clear = function () {
473                 node.nodeType = constants.NODE_UI_DISPLAY;
474
475                 if (node.choice) {
476                     node.choice.clear();
477                     node.choice = null;
478                 }
479             };
480
481             node.isFilled = function () {
482                 return node.choice !== null;
483             };
484         }
485
486         /**
487          * Service for wrapping case yang element
488          * @param node
489          */
490         function caseYang(node) {
491
492             node.buildRequest = function (builder, req, module) {
493                 var added = false;
494
495                 node.getChildren(null, null, constants.NODE_UI_DISPLAY).forEach(function (child) {
496                     var childAdded = child.buildRequest(builder, req, module);
497                     added = added || childAdded;
498                 });
499
500                 return added;
501             };
502
503             node.fill = function (name, data) {
504                 var filled = false,
505                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
506
507                 nodesToFill.forEach(function (child) {
508                     var childFilled = child.fill(name, data);
509                     filled = filled || childFilled;
510                 });
511
512                 return filled;
513             };
514
515             node.clear = function () {
516                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
517
518                 nodesToClear.forEach(function (child) {
519                     child.clear();
520                 });
521             };
522
523             node.isFilled = function () {
524                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
525                     return child.isFilled();
526                 });
527             };
528         }
529
530         /**
531          * Service for wrapping output yang element
532          * @param node
533          */
534         function output(node) {
535             node.expanded = true;
536
537             node.buildRequest = function (builder, req) {
538
539             };
540
541             node.fill = function (name, data) {
542                 var match = comparePropToElemByName(name, node.label),
543                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
544
545                 if (match && nodesToFill.length) {
546                     nodesToFill.forEach(function (child) {
547                         for (var prop in data) {
548                             child.fill(prop, data[prop]);
549                         }
550                     });
551                     node.expanded = match;
552                 }
553
554                 return match;
555             };
556
557             node.clear = function () {
558                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
559
560                 if (nodesToClear.length) {
561                     nodesToClear.forEach(function (child) {
562                         child.clear();
563                     });
564                 }
565             };
566
567             node.isFilled = function () {
568                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
569                     return child.isFilled();
570                 });
571             };
572
573         }
574
575         // TODO: add service's description
576         function input(node) {
577             node.expanded = true;
578
579             node.buildRequest = function (builder, req, module) {
580                 var added = false,
581                     objToAdd = builder.createObj(),
582                     builderNodes = node.getChildren(null, null, constants.NODE_UI_DISPLAY),
583                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
584
585                 if (builderNodes.length) {
586
587                     builderNodes.forEach(function (child) {
588                         var childAdded = child.buildRequest(builder, objToAdd, node.module);
589                         added = added || childAdded;
590                     });
591                 } else {
592                     added = true;
593                 }
594
595                 if (added) {
596                     builder.insertPropertyToObj(req, labelWithModule, objToAdd);
597                 }
598
599                 return added;
600             };
601
602             node.fill = function (name, data) {
603                 var match = comparePropToElemByName(name, node.label),
604                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
605
606                 if (match && nodesToFill.length) {
607                     nodesToFill.forEach(function (child) {
608                         for (var prop in data) {
609                             child.fill(prop, data[prop]);
610                         }
611                     });
612                     node.expanded = match;
613                 }
614
615                 return match;
616             };
617
618             node.clear = function () {
619                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
620
621                 if (nodesToClear.length) {
622                     nodesToClear.forEach(function (child) {
623                         child.clear();
624                     });
625                 }
626             };
627
628             node.isFilled = function () {
629                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
630                     return child.isFilled();
631                 });
632             };
633
634         }
635
636         /**
637          * Service for wrapping rpc yang element
638          * @param node
639          */
640         function rpc(node) {
641             node.expanded = true;
642             node.buildRequest = function (builder, req, module) {
643                 var added = false,
644                     objToAdd = builder.createObj(),
645                     builderNodes = node.getChildren(null, null, constants.NODE_UI_DISPLAY),
646                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
647
648                 if (builderNodes.length) {
649                     builderNodes.forEach(function (child) {
650                         var childAdded = child.buildRequest(builder, objToAdd, node.module);
651                         added = added || childAdded;
652                     });
653                 } else {
654                     added = true;
655                     objToAdd = constants.NULL_DATA;
656                 }
657
658                 if (added) {
659                     builder.insertPropertyToObj(req, labelWithModule, objToAdd);
660                 }
661
662                 return added;
663             };
664
665             node.fill = function (name, data) {
666                 var filled = false,
667                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
668
669                 nodesToFill.forEach(function (child) {
670                     var childFilled = child.fill(name, data);
671                     filled = filled || childFilled;
672                 });
673
674                 node.expanded = filled;
675
676                 return filled;
677             };
678
679             node.clear = function () {
680                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
681
682                 if (nodesToClear.length) {
683                     nodesToClear.forEach(function (child) {
684                         child.clear();
685                     });
686                 }
687             };
688
689             node.isFilled = function () {
690                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
691                     return child.isFilled();
692                 });
693             };
694
695         }
696
697         /**
698          * Service for wrapping container yang element
699          * @param node
700          */
701         function container(node) {
702             node.expanded = false;
703
704             node.toggleExpand = function () {
705                 node.expanded = !node.expanded;
706             };
707
708             node.buildRequest = function (builder, req, module) {
709                 var added = false,
710                     objToAdd = builder.createObj(),
711                     builderNodes = node.getChildren(null, null, constants.NODE_UI_DISPLAY),
712                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
713
714                 if (builderNodes.length) {
715                     builderNodes.forEach(function (child) {
716                         var childAdded = child.buildRequest(builder, objToAdd, node.module);
717                         added = added || childAdded;
718                     });
719                 } else  {
720                     added = true;
721                 }
722
723                 if (added && (checkEmptyContainer(node.parent ? node.parent.type : 'blanktype', objToAdd) ||
724                     checkPresence(node))) {
725                     builder.insertPropertyToObj(req, labelWithModule, objToAdd);
726                 }
727
728                 return added;
729
730                 // TODO: add function's description
731                 function checkPresence(containerNode) {
732                     return containerNode.children.some(function (ch) {
733                         return ch.type === 'presence';
734                     });
735                 }
736
737                 // TODO: add function's description
738                 function checkEmptyContainer(type, obj) { // TODO: absolete after when statement is implemented
739                     return !!(type === 'case' || !$.isEmptyObject(objToAdd));
740                 }
741             };
742
743             node.fill = function (name, data) {
744                 var match = comparePropToElemByName(name, node.label),
745                     nodesToFill = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
746
747                 if (match && nodesToFill.length) {
748                     nodesToFill.forEach(function (child) {
749                         for (var prop in data) {
750                             child.fill(prop, data[prop]);
751                         }
752                     });
753
754                     node.expanded = match;
755                 }
756
757                 return match;
758             };
759
760             node.clear = function () {
761                 var nodesToClear = node.getChildren(null, null, constants.NODE_UI_DISPLAY);
762                 node.nodeType = constants.NODE_UI_DISPLAY;
763
764                 if (nodesToClear.length) {
765                     nodesToClear.forEach(function (child) {
766                         child.clear();
767                     });
768                 }
769             };
770
771             node.isFilled = function () {
772                 return node.getChildren(null, null, constants.NODE_UI_DISPLAY).some(function (child) {
773                     return child.isFilled();
774                 });
775             };
776         }
777
778         /**
779          * Service for set patern restriction from yang element
780          * @param node
781          */
782         function pattern(node) {
783             node.restrictions = [RestrictionsService.getReqexpValidationFnc(node.label)];
784         }
785
786         /**
787          * Service for set range restriction from yang element
788          * @param node
789          */
790         function range(node) {
791             node.restrictions = parseRestrictText(node.label);
792         }
793
794         /**
795          * Service for set length restriction from yang element
796          * @param node
797          */
798         function length(node) {
799             node.restrictions = parseRestrictText(node.label);
800         }
801
802         /**
803          * Service for wrapping type yang element
804          * @param node
805          */
806         function type(node) {
807             TypeWrapperService.wrapAll(node);
808         }
809
810         /**
811          * Service for wrapping leaf yang element
812          * @param node
813          */
814         function leaf(node) {
815             node.value = '';
816             node.valueIsValid = true;
817             node.typeChild = node.getChildren('type')[0];
818
819             node.buildRequest = function (builder, req, module) {
820                 var value = node.typeChild.getValue(),
821                     labelWithModule = (module !== node.module ? node.module + ':' : '') + node.label;
822
823                 if (node.isKey()) {
824                     EventDispatcherService.dispatch(constants.EV_FILL_PATH, node, value);
825                 }
826
827                 if (value) {
828                     builder.insertPropertyToObj(req, labelWithModule, value);
829                     return true;
830                 }
831
832                 return false;
833             };
834
835             node.fill = function (name, data) {
836                 var match = '';
837
838                 match = comparePropToElemByName(name, node.label);
839                 if (match) {
840                     node.value = data.toString();
841                     if (node.typeChild) {
842                         node.typeChild.fill(node.value);
843                     }
844                 }
845                 return match;
846             };
847
848             node.clear = function () {
849                 node.value = '';
850
851                 if (node.typeChild) {
852                     node.typeChild.clear();
853                 }
854             };
855
856             node.isFilled = function () {
857                 var filled = node.typeChild.getValue() ? true : false;
858                 return filled;
859             };
860
861             node.checkValueType = function () {
862                 node.valueIsValid = node.typeChild ? node.typeChild.check(node.value) : true;
863             };
864
865             node.isKey = function () {
866                 return node.parent &&
867                     node.parent.type === 'list' &&
868                     node.parent.refKey && node.parent.refKey.indexOf(node) !== -1;
869             };
870         }
871
872         /**
873          * Service for wrapping single node
874          * @param node
875          */
876         function wrap(node) {
877             if (service.hasOwnProperty(node.type)) {
878                 service[node.type](node);
879             }
880         }
881
882         /**
883          * Main service for wrapping nodes
884          * @param node
885          */
886         function wrapAll(node) {
887             service.wrap(node);
888             node.children.forEach(function (child) {
889                 service.wrapAll(child);
890             });
891         }
892
893         // TODO: add service's description
894         function checkKeyDuplicity(listData, refKey) {
895             return checkListElemKeys(listData, refKey);
896         }
897
898         // TODO: add function's description
899         function comparePropToElemByName(propName, elemName) {
900             // AUGMENT FIX
901             // return propName === elemName; // TODO also check by namespace - redundancy?
902
903             // TODO also check by namespace - redundancy?
904             return (propName.indexOf(':') > -1 ? propName.split(':')[1] : propName) === elemName;
905         }
906
907         // TODO: add function's description
908         function equalArrays(arrA, arrB) {
909             var match = (arrA.length === arrB.length) && arrA.length > 0;
910
911             if (match) {
912                 var i = 0;
913                 while (i < arrA.length && match) {
914                     var valMatch = arrA[i] === arrB[i];
915                     match = match && valMatch;
916                     i++;
917                 }
918             }
919             return match;
920         }
921
922         // TODO: add function's description
923         function equalListElems(listElemA, listElemB, refKey) {
924             var keyValuesA = getKeyArrayValues(listElemA, refKey),
925                 keyValuesB = getKeyArrayValues(listElemB, refKey);
926
927             return equalArrays(keyValuesA, keyValuesB);
928
929             // TODO: add function's description
930             function getKeyValue(data, label, module) {
931                 if (data && data.hasOwnProperty(label)) {
932                     return data[label];
933                 } else if (data && data.hasOwnProperty(module + ':' + label)) {
934                     return data[module + ':' + label];
935                 } else {
936                     return null;
937                 }
938             }
939
940             // TODO: add function's description
941             function getKeyArrayValues(data, refKey) {
942                 return refKey.map(function (key) {
943                     return getKeyValue(data, key.label, key.module);
944                 }).filter(function (item) {
945                     return item !== null;
946                 });
947             }
948         }
949
950         // TODO: add function's description
951         function checkListElemKeys(listData, refKey) {
952             var doubleKeyIndexes = [],
953                 checkedElems = [];
954
955             listData.forEach(function (item, index) {
956                 var duplitactes = checkedElems.filter(function (checked) {
957                     var isDuplicate = equalListElems(item, checked.item, refKey);
958                     if (isDuplicate && doubleKeyIndexes.indexOf(checked.index) === -1) {
959                         doubleKeyIndexes.push(checked.index);
960                     }
961                     return isDuplicate;
962                 });
963
964                 if (duplitactes.length) {
965                     // item is already in checkedElems so we don't need to push it again
966                     doubleKeyIndexes.push(index);
967                 } else {
968                     checkedElems.push({ index: index, item: item });
969                 }
970             });
971
972             return doubleKeyIndexes;
973         }
974
975         // TODO: add function's description
976         function parseRestrictText(text) {
977             return text.split('|').map(function (elem) {
978                 var subElems = elem.split('..');
979                 return subElems.length === 1 ? RestrictionsService.getEqualsFnc(subElems[0]) :
980                     RestrictionsService.getMinMaxFnc(subElems[0], subElems[1]);
981             });
982         }
983
984         // TODO: add function's description
985         function getTypes(node) {
986             var types = [];
987
988             var getTypesRecursive = function (node, types) {
989                 types.push(node);
990
991                 node.getChildren('type').forEach(function (child) {
992                     getTypesRecursive(child, types);
993                 });
994             };
995
996             node.getChildren('type').forEach(function (child) {
997                 // console.info('child', child);
998                 getTypesRecursive(child, types);
999             });
1000
1001             return types;
1002         }
1003     }
1004
1005     NodeWrapperService.$inject = ['constants', 'RequestBuilderService', 'RestrictionsService', 'TypeWrapperService',
1006         'ListFilteringService', 'EventDispatcherService', 'FilterNodeWrapperService'];
1007
1008     return NodeWrapperService;
1009
1010 });