YangUI - quickfix operational list form
[dlux.git] / modules / common-yangutils-resources / src / main / resources / yangutils / services / yin-parser.services.js
1 define([], function () {
2     'use strict';
3
4     function YinParserService($http, SyncService, constants, PathUtilsService, YangUiApisService, NodeUtilsService){
5         var augmentType = 'augment',
6             path = './assets',
7             service = {
8                 parseYang: parseYang,
9                 parseYangMP: parseYangMP,
10                 Augmentations: Augmentations,
11                 Module: Module,
12                 yangParser: new YangParser(),
13                 __test: {
14                     path: path,
15                     parentTag: parentTag,
16                     yangParser: new YangParser(),
17                     Augmentation: Augmentation,
18                     Module: Module,
19                 },
20             };
21
22         return service;
23
24         // TODO: add service's description
25         function parseYangMP(baseApiPath, name, rev, callback, errorCbk) {
26             var path = baseApiPath + '/' + name + '/' + rev + '/schema';
27
28             YangUiApisService.getSingleModuleInfo(path)
29                 .then(function (data) {
30                     if ($.parseXML(data.data) !== null) {
31                         parseModule(data.data, callback);
32                     } else {
33                         loadStaticModule(name, callback, errorCbk);
34                     }
35                 }, function () {
36                     loadStaticModule(name, callback, errorCbk);
37                 });
38         }
39
40         // TODO: add service's description
41         function parseYang(name, rev, callback, errorCbk) {
42             YangUiApisService.getModuleSchema(name, rev).get()
43                 .then(function (data) {
44                     if ($.parseXML(data) !== null) {
45                         parseModule(data, callback);
46                     } else {
47                         loadStaticModule(name, callback, errorCbk);
48                     }
49                 }, function () {
50                     loadStaticModule(name, callback, errorCbk);
51                 });
52         }
53
54         // TODO: add service's description
55         function parentTag(xml) {
56             if (xml.get(0).tagName.toLowerCase() === 'module') {
57                 return xml.get(0);
58             } else {
59                 return parentTag(xml.parent());
60             }
61         }
62
63         // TODO: add function's description
64         function parseModule(data, callback) {
65             var yangParser = new YangParser();
66
67             var moduleName = $($.parseXML(data).documentElement).attr('name'),
68                 moduleNamespace = $($.parseXML(data)).find('namespace').attr('uri'),
69                 moduleoduleRevision = $($.parseXML(data)).find('revision').attr('date'),
70                 moduleObj = new Module(moduleName, moduleoduleRevision, moduleNamespace);
71
72             yangParser.setCurrentModuleObj(moduleObj);
73             yangParser.parse($.parseXML(data).documentElement, moduleObj);
74
75             yangParser.sync.waitFor(function () {
76                 callback(moduleObj);
77             });
78         }
79
80         // TODO: add function's description
81         function loadStaticModule(name, callback, errorCbk) {
82             var yinPath = '/yang2xml/' + name + '.yang.xml';
83             $http.get(path + yinPath).success(function (data) {
84                 parseModule(data, callback);
85             }).error(function () {
86                 errorCbk();
87                 return null;
88             });
89         }
90
91         /**
92          * Base Module object
93          * @param name
94          * @param revision
95          * @param namespace
96          * @constructor
97          */
98         function Module(name, revision, namespace) {
99             this._name = name;
100             this._revision = revision;
101             this._namespace = namespace;
102             this._statements = {};
103             this._roots = [];
104             this._augments = [];
105
106             this.getRoots = function () {
107                 return this._roots;
108             };
109
110             this.getImportByPrefix = function (prefix) {
111                 var importNode = null;
112
113                 if (this._statements.hasOwnProperty('import')) {
114                     importNode = this._statements.import.filter(function (importItem) {
115                         return importItem._prefix === prefix;
116                     })[0];
117                 }
118
119                 return importNode;
120             };
121
122             this.getRawAugments = function () {
123                 return this._augments;
124             };
125
126             this.getAugments = function () {
127                 var self = this;
128
129                 return this.getRawAugments().map(function (augNode) {
130                     augNode.path = PathUtilsService.translate(augNode.pathString, prefixConverter, self._statements.import, getDefaultModule);
131
132                     return new Augmentation(augNode);
133
134                     // TODO: add function's description
135                     function prefixConverter(prefix) {
136                         var importNode = self.getImportByPrefix(prefix);
137                         return importNode ? importNode.label : null;
138                     }
139
140                     // TODO: add function's description
141                     function getDefaultModule() {
142                         return null;
143                     }
144                 });
145             };
146
147             this.addChild = function (node) {
148                 if (!this._statements.hasOwnProperty(node.type)) {
149                     this._statements[node.type] = [];
150                 }
151
152                 var duplicates = this._statements[node.type].filter(function (item) {
153                     return node.label === item.label && node.nodeType === item.nodeType;
154                 });
155
156                 if (duplicates && duplicates.length > 0) {
157                 } else {
158                     this._statements[node.type].push(node);
159
160                     if (NodeUtilsService.isRootNode(node.type)) {
161                         this._roots.push(node);
162                     }
163
164                     if (node.type === 'augment') {
165                         this._augments.push(node);
166                     }
167                 }
168             };
169
170             this.searchNode = function (type, name) {
171                 var searchResults = null,
172                     searchedNode = null;
173
174                 if (this._statements[type]) {
175                     searchResults = this._statements[type].filter(function (node) {
176                         return name === node.label;
177                     });
178                 }
179
180                 if (searchResults && searchResults.length === 0) {
181                 } else if (searchResults && searchResults.length > 1) {
182                 } else if (searchResults && searchResults.length === 1) {
183                     searchedNode = searchResults[0];
184                 }
185
186                 return searchedNode;
187             };
188         }
189
190         /**
191          * Base Node element object
192          * @param id
193          * @param name
194          * @param type
195          * @param module
196          * @param namespace
197          * @param parent
198          * @param nodeType
199          * @param moduleRevision
200          * @constructor
201          */
202         function Node(id, name, type, module, namespace, parent, nodeType, moduleRevision) {
203             this.id = id;
204             this.label = name;
205             this.localeLabel = constants.LOCALE_PREFIX + name.toUpperCase();
206             this.type = type;
207             this.module = module;
208             this.children = [];
209             this.parent = parent;
210             this.nodeType = nodeType;
211             this.namespace = namespace;
212             this.moduleRevision = moduleRevision;
213
214             this.appendTo = function (parentNode) {
215                 parentNode.addChild(this);
216             };
217
218             this.addChild = function (node) {
219                 if (this.children.indexOf(node) === -1) {
220                     this.children.push(node);
221                     node.parent = this;
222                 }
223
224             };
225
226             this.deepCopy = function deepCopy(additionalProperties) {
227                 var copy = new Node(this.id, this.label, this.type, this.module, this.namespace, null,
228                                     this.nodeType, this.moduleRevision),
229                     self = this;
230
231                 additionalProperties = (additionalProperties || []).concat(['pathString']);
232
233                 additionalProperties.forEach(function (prop) {
234                     if (prop !== 'children' && self.hasOwnProperty(prop) && copy.hasOwnProperty(prop) === false) {
235                         copy[prop] = self[prop];
236                     }
237                 });
238
239                 this.children.forEach(function (child) {
240                     var childCopy = child.deepCopy(additionalProperties);
241                     childCopy.parent = copy;
242                     copy.children.push(childCopy);
243                 });
244                 return copy;
245             };
246
247             this.getCleanCopy = function (){
248                 return new Node(this.id, this.label, this.type, this.module, this.namespace, null,
249                                 this.nodeType, this.moduleRevision);
250             };
251
252             this.getChildren = function (type, name, nodeType, property) {
253                 var filteredChildren = this.children.filter(function (item) {
254                     return (name != null ? name === item.label : true) &&
255                                             (type != null ? type === item.type : true) &&
256                                             (nodeType != null ? nodeType === item.nodeType : true);
257                 });
258
259                 if (property) {
260                     return filteredChildren.filter(function (item) {
261                         return item.hasOwnProperty(property);
262                     }).map(function (item) {
263                         return item[property];
264                     });
265                 } else {
266                     return filteredChildren;
267                 }
268             };
269
270         }
271
272         /**
273          * Base Augment group object
274          * @constructor
275          */
276         function AugmentationsGroup(){
277             this.obj = {};
278
279             this.addAugumentation = function (augumentation){
280                 this.obj[augumentation.id] = augumentation;
281             };
282         }
283
284         /**
285          * Base augment's groups object
286          * @constructor
287          */
288         function Augmentations(){
289             this.groups = {};
290
291             this.addGroup  = function (groupId){
292                 this.groups[groupId] = !this.groups.hasOwnProperty(groupId) ?
293                                                                     new AugmentationsGroup() : this.groups[groupId];
294             };
295
296             this.getAugmentation = function (node, augId) {
297                 return this.groups[node.module + ':' + node.label] ?
298                                                         this.groups[node.module + ':' + node.label].obj[augId] : null;
299             };
300         }
301
302         /**
303          * Base Augment object
304          * @param node
305          * @constructor
306          */
307         function Augmentation(node) {
308             var self = this;
309             this.node = node;
310             this.path = (node.path ? node.path : []);
311             this.id = node.module + ':' + node.label;
312             this.expanded = true;
313             // AUGMENT FIX
314             // node.label = node.module + ':' + node.label;
315
316
317             this.toggleExpand = function () {
318                 this.expanded = !this.expanded;
319             };
320
321             this.setAugmentationGroup = function (targetNode, augumentations){
322                 var targetNodeId = targetNode.module + ':' + targetNode.label;
323                 targetNode.augmentionGroups = targetNode.augmentionGroups ? targetNode.augmentionGroups : [];
324                 targetNode.augmentionGroups.push(self.id);
325
326                 augumentations.addGroup(targetNodeId);
327                 augumentations.groups[targetNodeId].addAugumentation(self);
328             };
329
330             this.apply = function (nodeList, augumentations) {
331                 var targetNode = this.getTargetNodeToAugment(nodeList);
332
333                 if (targetNode) {
334                     this.setAugmentationGroup(targetNode, augumentations);
335
336                     this.node.children.forEach(function (child) {
337                         child.appendTo(targetNode);
338                         child.augmentationId = self.id;
339                         // AUGMENT FIX
340                         // child.children.forEach(function (moduleChild) {
341                         //     moduleChild.label = moduleChild.module + ':' + moduleChild.label;
342                         // });
343                     });
344                 } else {
345                 }
346             };
347
348             this.getTargetNodeToAugment = function (nodeList) {
349                 return PathUtilsService.search({ children: nodeList }, this.path.slice());
350             };
351
352             this.getPathString = function () {
353                 return this.path.map(function (elem) {
354                     return elem.module + ':' + elem.name;
355                 }).join('/');
356             };
357
358         }
359
360         /**
361          * Base yang xml parser
362          * @constructor
363          */
364         function YangParser() {
365             this.rootNodes = [];
366             this.nodeIndex = 0;
367             this.sync = SyncService.generateObj();
368             this.moduleObj = null;
369
370             this.setCurrentModuleObj = function (moduleObj) {
371                 this.moduleObj = moduleObj;
372             };
373
374             this.createNewNode = function (name, type, parentNode, nodeType) {
375                 var node = new Node(this.nodeIndex++, name, type, this.moduleObj._name, this.moduleObj._namespace, parentNode, nodeType, this.moduleObj._revision);
376
377                 if (parentNode) {
378                     parentNode.addChild(node);
379                 }
380
381                 return node;
382             };
383
384             this.parse = function (xml, parent) {
385                 var self = this;
386
387                 $(xml).children().each(function (_, item) {
388                     var prop = item.tagName.toLowerCase();
389                     if (self.hasOwnProperty(prop)) {
390                         self[prop](item, parent);
391                     } else {
392                         // self.parse(this, parent);
393                     }
394                 });
395             };
396
397             this.config = function (xml, parent) {
398                 var type = constants.DATA_STORE_CONFIG,
399                     name = $(xml).attr('value'),
400                     nodeType = constants.NODE_ALTER;
401
402                 this.createNewNode(name, type, parent, nodeType);
403             };
404
405             this.presence = function (xml, parent) {
406                 var type = 'presence',
407                     name = $(xml).attr('value'),
408                     nodeType = constants.NODE_ALTER;
409
410                 this.createNewNode(name, type, parent, nodeType);
411             };
412
413             this.leaf = function (xml, parent) {
414                 var type = 'leaf',
415                     name = $(xml).attr('name'),
416                     nodeType = constants.NODE_UI_DISPLAY,
417                     node = this.createNewNode(name, type, parent, nodeType);
418
419                 this.parse(xml, node);
420             };
421
422             this['leaf-list'] = function (xml, parent) {
423                 var type = 'leaf-list',
424                     name = $(xml).attr('name'),
425                     nodeType = constants.NODE_UI_DISPLAY,
426                     node = this.createNewNode(name, type, parent, nodeType);
427
428                 this.parse(xml, node);
429             };
430
431             this.container = function (xml, parent) {
432                 var type = 'container',
433                     name = $(xml).attr('name'),
434                     nodeType = constants.NODE_UI_DISPLAY,
435                     node = this.createNewNode(name, type, parent, nodeType);
436
437                 this.parse(xml, node);
438             };
439
440             this.choice = function (xml, parent) {
441                 var type = 'choice',
442                     name = $(xml).attr('name'),
443                     nodeType = constants.NODE_UI_DISPLAY,
444                     node = this.createNewNode(name, type, parent, nodeType);
445
446                 this.parse(xml, node);
447             };
448
449             this.case = function (xml, parent) {
450                 var type = 'case',
451                     name = $(xml).attr('name'),
452                     nodeType = constants.NODE_UI_DISPLAY,
453                     node = this.createNewNode(name, type, parent, nodeType);
454
455                 this.parse(xml, node);
456             };
457
458             this.list = function (xml, parent) {
459                 var type = 'list',
460                     name = $(xml).attr('name'),
461                     nodeType = constants.NODE_UI_DISPLAY,
462                     node = this.createNewNode(name, type, parent, nodeType);
463
464                 this.parse(xml, node);
465             };
466
467
468             this.key = function (xml, parent) {
469                 var type = 'key',
470                     name = $(xml).attr('value'),
471                     nodeType = constants.NODE_ALTER,
472                     node = this.createNewNode(name, type, parent, nodeType);
473
474                 this.parse(xml, node);
475             };
476
477             this.description = function (xml, parent) {
478                 var type = 'description',
479                     name = $(xml).attr('text') ? $(xml).attr('text') : $(xml).children('text:first').text(),
480                     nodeType = constants.NODE_ALTER,
481                     node = this.createNewNode(name, type, parent, nodeType);
482
483                 this.parse(xml, node);
484             };
485
486             this.typedef = function (xml, parent, typedefName) {
487                 var type = 'typedef',
488                     name = $(xml).attr('name'),
489                     nodeType = constants.NODE_LINK_TARGET,
490                     node = this.createNewNode(name, type, parent, nodeType);
491
492                 this.parse(xml, node);
493             };
494
495             this.grouping = function (xml, parent, groupingName) {
496                 var type = 'grouping',
497                     name = $(xml).attr('name'),
498                     nodeType = constants.NODE_LINK_TARGET,
499                     node = this.createNewNode(name, type, parent, nodeType);
500
501                 this.parse(xml, node);
502             };
503
504             this.uses = function (xml, parent) {
505                 var type = 'uses',
506                     name = $(xml).attr('name'),
507                     nodeType = constants.NODE_LINK,
508                     node = this.createNewNode(name, type, parent, nodeType);
509
510                 this.parse(xml, node);
511             };
512
513             this.import = function (xml, parent) {
514                 var type = 'import',
515                     name = $(xml).attr('module'),
516                     nodeType = constants.NODE_ALTER,
517                     node = this.createNewNode(name, type, parent, nodeType);
518
519                 node._prefix = $(xml).children('prefix:first').attr('value');
520                 node._revisionDate = $(xml).children('revision-date:first').attr('date');
521             };
522
523             this.augment = function (xml, parent) {
524                 var type = augmentType,
525                     nodeType = constants.NODE_ALTER,
526                     augmentIndentifier = $(xml).children('ext\\:augment-identifier:first').attr('ext:identifier'),
527                     name = augmentIndentifier ? augmentIndentifier : 'augment' + (this.nodeIndex + 1).toString(),
528                     pathString = $(xml).attr('target-node'),
529                     augmentRoot = this.createNewNode(name, type, parent, nodeType);
530
531                 augmentRoot.pathString = pathString;
532                 this.parse(xml, augmentRoot);
533             };
534
535
536             this.rpc = function (xml, parent) {
537                 var type = constants.NODE_RPC,
538                     name = $(xml).attr('name'),
539                     nodeType = constants.NODE_UI_DISPLAY,
540                     node = this.createNewNode(name, type, parent, nodeType);
541
542                 this.parse(xml, node);
543             };
544
545             this.input = function (xml, parent) {
546                 var type = 'input',
547                     name = 'input',
548                     nodeType = constants.NODE_UI_DISPLAY,
549                     node = this.createNewNode(name, type, parent, nodeType);
550
551                 this.parse(xml, node);
552             };
553
554             this.output = function (xml, parent) {
555                 var type = 'output',
556                     name = 'output',
557                     nodeType = constants.NODE_UI_DISPLAY,
558                     node = this.createNewNode(name, type, parent, nodeType);
559
560                 this.parse(xml, node);
561             };
562
563             this.pattern = function (xml, parent) {
564                 var type = 'pattern',
565                     name = $(xml).attr('value'),
566                     nodeType = constants.NODE_RESTRICTIONS;
567
568                 this.createNewNode(name, type, parent, nodeType);
569             };
570
571             this.range = function (xml, parent) {
572                 var type = 'range',
573                     name = $(xml).attr('value'),
574                     nodeType = constants.NODE_RESTRICTIONS;
575
576                 this.createNewNode(name, type, parent, nodeType);
577             };
578
579             this.length = function (xml, parent) {
580                 var type = 'length',
581                     name = $(xml).attr('value'),
582                     nodeType = constants.NODE_RESTRICTIONS;
583
584                 this.createNewNode(name, type, parent, nodeType);
585             };
586
587             this.enum = function (xml, parent) {
588                 var type = 'enum',
589                     name = $(xml).attr('name'),
590                     nodeType = constants.NODE_ALTER;
591
592                 this.createNewNode(name, type, parent, nodeType);
593             };
594
595             this.bit = function (xml, parent) {
596                 var type = 'bit',
597                     name = $(xml).attr('name'),
598                     nodeType = constants.NODE_ALTER,
599                     node = this.createNewNode(name, type, parent, nodeType);
600
601                 this.parse(xml, node);
602             };
603
604             this.position = function (xml, parent) {
605                 var type = 'position',
606                     name = $(xml).attr('value'),
607                     nodeType = constants.NODE_ALTER;
608
609                 this.createNewNode(name, type, parent, nodeType);
610             };
611
612             this.type = function (xml, parent) {
613                 var type = 'type',
614                     name = $(xml).attr('name'),
615                     nodeType = constants.NODE_ALTER,
616                     node = this.createNewNode(name, type, parent, nodeType);
617
618                 this.parse(xml, node);
619             };
620         }
621     }
622
623     YinParserService.$inject = ['$http', 'SyncService', 'constants', 'PathUtilsService', 'YangUiApisService',
624                                 'NodeUtilsService'];
625
626     return YinParserService;
627
628 });