4902ca9585f31305253120fc603b58d70137fbc9
[dlux.git] / modules / common-yangutils-resources / src / main / resources / yangutils / services / path-utils.services.js
1 define([], function () {
2     'use strict';
3
4     function PathUtilsService(ArrayUtilsService){
5
6         var service = {
7                 clearPath: clearPath,
8                 checkEmptyIdentifiers: checkEmptyIdentifiers,
9                 createPathElement: createPathElement,
10                 getModuleNameFromPath: getModuleNameFromPath,
11                 getStorageAndNormalizedPath: getStorageAndNormalizedPath,
12                 fillIdentifiers: fillIdentifiers,
13                 findIndexOfStrInPathStr: findIndexOfStrInPathStr,
14                 fillListNode: fillListNode,
15                 fillListRequestData: fillListRequestData,
16                 fillPath: fillPath,
17                 search: search,
18                 searchNodeByPath: searchNodeByPath,
19                 translate: translate,
20                 translatePathArray: translatePathArray,
21                 __test: {
22                     PathElem: PathElem,
23                     getModuleNodePair: getModuleNodePair,
24                     isIdentifier: isIdentifier,
25                 },
26             },
27             parentPath = '..';
28
29         return service;
30
31         // TODO: add service's description
32         function createPathElement(name, module, identifierStrings, moduleChanged, revision) {
33             return new PathElem(name, module, identifierStrings, moduleChanged, revision);
34         }
35
36         // TODO: add service's description
37         function search(node, path) {
38             var pathElem = path.shift(),
39                 selNode = pathElem.name === parentPath ?
40                     node.parent :
41                     ArrayUtilsService.getFirstElementByCondition(node.children, function (child) {
42                         return pathElem.checkNode(child);
43                     });
44
45             if (selNode !== null) {
46                 if (path.length) {
47                     return search(selNode, path);
48                 } else {
49                     return selNode;
50                 }
51             } else {
52                 console.warn('search: cannot find element ', pathElem.name);
53                 return null;
54             }
55         }
56
57         /**
58          * Translate path url into path elements array
59          * @param path
60          * @param prefixConverter
61          * @param importNodes
62          * @param getDefaultModuleCallback
63          * @param notIdentifiers
64          * @returns {Array}
65          */
66         function translate(path, prefixConverter, importNodes, getDefaultModuleCallback, notIdentifiers) {
67             var pathStrElements = path.split('/').filter(function (e) {
68                     return e !== '';
69                 }),
70                 pathArrayElements = [],
71                 index,
72                 maxIndex = pathStrElements.length,
73                 getLastElement = function (a) {
74                     return pathArrayElements.length > 0 ? pathArrayElements[pathArrayElements.length - 1] : null;
75                 },
76                 getElementModule = function (e) {
77                     return e ? e.module : '';
78                 },
79                 getModuleChange = function (actModule, lastElemModule) {
80                     return (lastElemModule !== null) ? actModule !== lastElemModule : false;
81                 };
82
83             for (index = 0; index < maxIndex; index += 1) {
84                 var actElem = pathStrElements[index],
85                     lastElem = getLastElement(pathArrayElements),
86                     checkIdentifier = notIdentifiers ? false : isIdentifier(actElem);
87
88                 if (checkIdentifier && lastElem) {
89                     lastElem.addIdentifier(actElem.slice(1, -1));
90                 } else {
91
92                     var lastElemModule = getElementModule(lastElem),
93                         defaultModule = getDefaultModuleCallback ? getDefaultModuleCallback() : lastElemModule,
94                         pair = getModuleNodePair(actElem, defaultModule),
95                         processedModule = (prefixConverter && pair[0] !== lastElemModule) ?
96                                                                                 prefixConverter(pair[0]) : pair[0],
97                         revision = importNodes ? searchForRevisionInImportNodes(processedModule, importNodes) : null,
98                         pathElem = createPathElement(pair[1], processedModule, null, getModuleChange(processedModule, lastElemModule), revision);
99
100                     pathArrayElements.push(pathElem);
101                 }
102             }
103
104             return pathArrayElements;
105         }
106
107         // TODO: add service's description
108         function translatePathArray(pathArray) {
109             var getIdentifiersValues = function (identifiers) {
110                     return identifiers.map(function (i) {
111                         return i.value.length ? i.value.replace(/\//g, '%2F') : '{' + i.label + '}';
112                     }).join('/');
113                 },
114                 getLastElem = function (i) {
115                     var result = null;
116                     if ((i - 1) >= 0) {
117                         result = pathArray[i - 1];
118                     }
119                     return result;
120                 },
121                 getModuleStr = function (actElem, lastElem) {
122                     return ((lastElem && actElem.module && lastElem.module !== actElem.module) ?
123                                                                                         (actElem.module + ':') : '');
124                 },
125                 getIdentifiersStr = function (actElem) {
126                     return (actElem.hasIdentifier() ? '/' + getIdentifiersValues(actElem.identifiers) : '');
127                 },
128                 getElemStr = function (actElem, lastElem) {
129                     return getModuleStr(actElem, lastElem) + actElem.name + getIdentifiersStr(actElem);
130                 };
131
132             return pathArray.map(function (pe, i) {
133                 return getElemStr(pe, getLastElem(i));
134             });
135         }
136
137         /**
138          * Check if in path elements array is empty identifier
139          * @param pathArray
140          * @returns {*}
141          */
142         function checkEmptyIdentifiers(pathArray){
143             return pathArray.some(function (item) {
144                 return item.hasEmptyIdentifier();
145             });
146         }
147
148         /**
149          * Service for filling API url object from url string data
150          * @param pathArrayIn
151          * @param pathString
152          */
153         function fillPath(pathArrayIn, pathString) {
154             var pathArray = trimPath(pathString).split('/'),
155                 pathPosition = 0;
156
157             pathArrayIn.forEach(function (pathItem){
158                 if ( pathItem.hasIdentifier() ){
159                     pathItem.identifiers.forEach(function (identifier){
160                         pathPosition++;
161                         identifier.value = isIdentifier(pathArray[pathPosition]) ? '' : pathArray[pathPosition];
162                     });
163                 }
164                 pathPosition++;
165             });
166
167         }
168
169         /**
170          * Service for clearing api path object
171          * @param pathArrayIn
172          */
173         function clearPath(pathArrayIn){
174             pathArrayIn.forEach(function (pathItem){
175                 if ( pathItem.hasIdentifier() ){
176                     pathItem.identifiers.forEach(function (identifier){
177                         identifier.value = '';
178                     });
179                 }
180             });
181         }
182
183         // TODO: add service's description
184         function getModuleNameFromPath(path){
185             var pathArray = translate(trimPath(path));
186
187             return pathArray.length > 1 ? pathArray[1].module : null;
188         }
189
190         // TODO: add service's description
191         function searchNodeByPath(pathString, treeApis, treeData, disabledExpand, notIdentifiers) {
192             var pathArray = translate(trimPath(pathString), null, null, null, notIdentifiers),
193                 module = pathArray.length > 1 ? pathArray[1].module : null,
194                 selectedTreeApi = module ? treeApis.filter(function (treeApi) {
195                     return treeApi.module === module;
196                 })[0] : null,
197                 retObj = null;
198
199             if (selectedTreeApi && pathArray.length) {
200                 var actElem = selectedTreeApi,
201                     continueCondition = true;
202
203                 if ( !disabledExpand ) {
204                     changeTreeDataByProp(treeData, ['expanded', 'selected'], [false, false]);
205                 }
206
207                 for (var i = 0; i < pathArray.length && continueCondition; ) {
208                     if ( !disabledExpand ) {
209                         changeTreeDataNode(actElem, treeData, 'expanded', true);
210                     }
211
212                     var nextElem = getActElementChild(actElem, pathArray[i].name);
213                     if (nextElem !== null) {
214                         actElem = nextElem;
215                         i = i + ( actElem && actElem.identifiersLength > 0 ? actElem.identifiersLength + 1 : 1);
216                     } else {
217                         continueCondition = false;
218                     }
219                 }
220
221                 if ( !disabledExpand ) {
222                     changeTreeDataNode(actElem, treeData, 'selected', true);
223                 }
224
225                 if (actElem) {
226                     retObj = { indexApi: actElem.indexApi, indexSubApi: actElem.indexSubApi };
227                 }
228             }
229             return retObj;
230         }
231
232         /**
233          * Fill path element's identifiers
234          * @param identifiers
235          * @param label
236          * @param value
237          */
238         function fillIdentifiers(identifiers, label, value) {
239             identifiers.some(function (i) {
240                 var identifierMatch = i.label === label;
241                 if (identifierMatch) {
242                     i.value = value || '';
243                 }
244
245                 return identifierMatch;
246             });
247         }
248
249         // TODO: add service's description
250         function fillListNode(node, label, value) {
251             if (node.type === 'list' && node.actElemStructure !== null) {
252                 var nodeToFill = node.actElemStructure.getChildren('leaf', label)[0];
253
254                 if (nodeToFill) {
255                     nodeToFill.fill(nodeToFill.label, value);
256                 }
257             }
258         }
259
260         // TODO: add service's description
261         function fillListRequestData(data, listLabel, label, value){
262             if ( data.hasOwnProperty(listLabel) && data[listLabel].length ) {
263                 data[listLabel][0][label] = value;
264             }
265         }
266
267         // TODO: add service's description
268         function findIndexOfStrInPathStr(pathParts, targetStr) { // pathParts is path string split by '/'
269             var targetIndex = -1;
270
271             pathParts.some(function (p, i) {
272                 var condition = p === targetStr;
273                 if (condition) {
274                     targetIndex = i;
275                 }
276                 return condition;
277             });
278
279             return targetIndex;
280         }
281
282         // TODO: add service's description
283         function getStorageAndNormalizedPath(pathStr) {
284             var pathParts = pathStr.split('/'),
285                 restconfIndex = findIndexOfStrInPathStr(pathParts, 'restconf'),
286                 storage = pathParts[restconfIndex + 1],
287                 normalizedPath = pathParts.slice(restconfIndex + 1).join('/');
288
289             return { storage: storage, normalizedPath: normalizedPath };
290         }
291
292         /**
293          * Base identifier object
294          * @param label
295          * @param value
296          * @constructor
297          */
298         function Identifier(label, value) {
299             this.label = label;
300             this.value = value || '';
301         }
302
303         /**
304          * Base path element object
305          * @param name
306          * @param module
307          * @param identifierNames
308          * @param moduleChanged
309          * @param revision
310          * @constructor
311          */
312         function PathElem(name, module, identifierNames, moduleChanged, revision) {
313             this.name = name;
314             this.module = module;
315             this.identifiers = identifierNames ? identifierNames.map(function (name) {
316                 return new Identifier(name);
317             }) : [];
318             this.moduleChanged = moduleChanged || false;
319             this.revision = revision;
320
321             this.equals = function (comparedElem, compareIdentifierValues) {
322                 var result = this.name === comparedElem.name &&
323                                 this.module === comparedElem.module &&
324                                 this.identifiers.length === comparedElem.identifiers.length;
325
326                 if (result) {
327                     var identifiersCnt = this.identifiers.length,
328                         i;
329
330                     for (i = 0; i < identifiersCnt && result; i++) {
331                         result = this.identifiers[i].label === comparedElem.identifiers[i].label;
332                         if (compareIdentifierValues) {
333                             result = this.identifiers[i].value === comparedElem.identifiers[i].value;
334                         }
335                     }
336                 }
337
338                 return result;
339             };
340
341             this.hasIdentifier = function () {
342                 return this.identifiers.length > 0;
343             };
344
345             this.addIdentifier = function (name) {
346                 this.identifiers.push(new Identifier(name));
347             };
348
349             this.getIdentifierValues = function () {
350                 return this.identifiers.map(function (i) {
351                     return i.value;
352                 });
353             };
354
355             this.hasEmptyIdentifier = function () {
356                 return this.identifiers.some(function (item) {
357                     return item.value.length === 0;
358                 });
359             };
360
361             this.toString = function () {
362                 return (this.module ? this.module + ':' : '') + this.name + '/' + (this.hasIdentifier() ?
363                                                                     this.getIdentifierValues().join('/') + '/' : '');
364             };
365
366             this.checkNode = function (node) {
367                 return (this.module ? this.module === node.module : true) &&
368                         (this.name ? this.name === node.label : true) &&
369                         (this.revision ? this.revision === node.moduleRevision : true);
370             };
371
372             this.clone = function () {
373                 var copy = new PathElem(this.name, this.module, null, this.moduleChanged, this.revision);
374
375                 copy.identifiers = this.identifiers.map(function (i) {
376                     return new Identifier(i.label, i.value);
377                 });
378
379                 return copy;
380             };
381         }
382
383         // TODO: add function's description
384         function trimPath(pathString) {
385             var searchStr = 'restconf',
386                 output = pathString;
387
388             if (pathString.indexOf(searchStr) > -1) {
389                 output = pathString.slice(pathString.indexOf(searchStr) + searchStr.length + 1);
390             }
391
392             return output;
393         }
394
395         // TODO: add function's description
396         function changeTreeDataNode(treeApiNode, treeData, prop, val) {
397             var sel = treeApiNode ? treeData.filter(function (d) {
398                 return d.branch.uid === treeApiNode.uid;
399             }) : [];
400
401             if (sel.length === 1) {
402                 sel[0].branch[prop] = val;
403             }
404         }
405
406         // TODO: add function's description
407         function changeTreeDataByProp(treeData, props, vals) {
408             treeData.forEach(function (d, index) {
409                 props.forEach(function (v, i){
410                     d.branch[v] = vals[i];
411                 });
412             });
413         }
414
415         // TODO: add function's description
416         function getActElementChild(actElem, childLabel) {
417             var sel = actElem.children.filter(function (child) {
418                     return child.label === childLabel;
419                 }),
420                 ret = sel.length === 1 ? sel[0] : null;
421
422             return ret;
423         }
424
425         // TODO: add function's description
426         function getModuleNodePair(pathString, defaultModule) {
427             return pathString.indexOf(':') > -1 ? pathString.split(':') : [defaultModule, pathString];
428         }
429
430         /**
431          * Tool for check if item is identifier
432          * @param item
433          * @returns {boolean}
434          */
435         function isIdentifier(item) {
436             return (item.indexOf('{') === item.indexOf('}')) === false;
437         }
438
439         // TODO: add function's description
440         function searchForRevisionInImportNodes(module, importNodes) {
441             var revision = null,
442                 node = importNodes.filter(function (i) {
443                     return i.label === module;
444                 })[0];
445
446             if (node) {
447                 revision = node._revisionDate;
448             }
449
450             return revision;
451         }
452     }
453
454     PathUtilsService.$inject = ['ArrayUtilsService'];
455
456     return PathUtilsService;
457
458 });