1 function isRelativePath(path
) {
2 if (path
.split('/')[0] == '..') {
8 function getResults(topLevelObject
, pathArray
) {
9 let objectCopy
= _cloneDeep(topLevelObject
);
10 let i
= pathArray
.length
;
13 while (pathArray
[pathArray
.length
- i
]) {
14 if (_isArray(objectCopy
[pathArray
[pathArray
.length
- i
]])) {
16 results
= _map(objectCopy
[pathArray
[pathArray
.length
- i
]], pathArray
[pathArray
.length
- 1]);
18 objectCopy
= objectCopy
[pathArray
[pathArray
.length
- i
]];
20 } else if (_isArray(objectCopy
)) {
21 objectCopy
.map((object
) => {
22 if (_isArray(object
[pathArray
[pathArray
.length
- i
]])) {
24 results
= results
.concat(_map(object
[pathArray
[pathArray
.length
- i
]], pathArray
[pathArray
.length
- 1]));
35 function getAbsoluteResults(topLevelObject
, pathArray
) {
36 let i
= pathArray
.length
;
37 let objectCopy
= _cloneDeep(topLevelObject
);
40 let fragment
= pathArray
[pathArray
.length
- i
]
45 if (_isArray(objectCopy
)) {
46 // results will be obtained from a map
47 results
= _map(objectCopy
, fragment
);
50 if (fragment
.match(/\[.*\]/g)) {
51 // contains a predicate
52 // shouldn't reach here
53 console
.log('Something went wrong while resolving a leafref. Reached a leaf with predicate.');
55 // contains no predicate
59 results
.push(objectCopy
[fragment
]);
63 if (_isArray(objectCopy
)) {
65 objectCopy
= _map(objectCopy
, fragment
);
67 // If any of the deeper object is an array, flatten the entire list.
68 // This would usually be a bad leafref going out of its scope.
70 for (let i
= 0; i
< objectCopy
.length
; i
++) {
71 if (_isArray(objectCopy
[i
])) {
72 objectCopy
= _flatten(objectCopy
);
73 console
.log('This might be a bad leafref. Verify with backend team.')
79 if (fragment
.match(/\[.*\]/g)) {
80 // contains a predicate
81 let predicateStr
= fragment
.match(/\[.*\]/g)[0];
82 // Clip leading [ and trailing ]
83 predicateStr
= predicateStr
.substr(1, predicateStr
.length
- 2);
84 const predicateKeyValue
= predicateStr
.split('=');
85 const predicateKey
= predicateKeyValue
[0];
86 const predicateValue
= predicateKeyValue
[1];
87 // get key for object to search into
88 let key
= fragment
.split('[')[0];
89 let searchObject
= {};
90 searchObject
[predicateKey
] = predicateValue
;
91 let found
= _find(objectCopy
[key
], searchObject
);
95 // check for numerical value
96 if (predicateValue
!= "" &&
97 predicateValue
!= null &&
98 predicateValue
!= NaN
&&
99 predicateValue
!= Infinity
&&
100 predicateValue
!= -Infinity
) {
101 let numericalPredicateValue
= _toNumber(predicateValue
);
102 if (_isNumber(numericalPredicateValue
)) {
103 searchObject
[predicateKey
] = numericalPredicateValue
;
104 found
= _find(objectCopy
[key
], searchObject
);
114 // contains no predicate
118 objectCopy
= objectCopy
[fragment
];
127 fragment
= pathArray
[pathArray
.length
- i
];
133 function resolveCurrentPredicate(leafRefPath
, container
, pathCopy
) {
134 if (leafRefPath
.indexOf('current()') != -1) {
137 // Get the relative path from current
138 let relativePath
= leafRefPath
.match("current\\(\\)\/(.*)\]");
139 let relativePathArray
= relativePath
[1].split('/');
141 while (relativePathArray
[0] == '..') {
143 relativePathArray
.shift();
146 // Supports only one relative path up
147 // To support deeper paths, will need to massage the string more
148 // i.e. change '/'' to '.'
149 const searchPath
= pathCopy
.join('.').concat('.', relativePathArray
[0]);
150 const searchValue
= resolvePath(container
.model
, searchPath
);
152 const predicateStr
= leafRefPath
.match("(current.*)\]")[1];
153 leafRefPath
= leafRefPath
.replace(predicateStr
, searchValue
);
158 function cleanupFieldKeyArray (fieldKeyArray
) {
159 fieldKeyArray
.map((fieldKey
, fieldKeyIndex
) => {
160 fieldKeyArray
[fieldKeyIndex
] = fieldKey
.replace(/.*\/(.*)/, '$1');
162 return fieldKeyArray
;
165 export default function resolveLeafRefPath(catalogs
, leafRefPath
, fieldKey
, path
, container
) {
166 let pathCopy
= _clone(path
);
167 // Strip any prefixes
168 let leafRefPathCopy
= leafRefPath
.replace(/[\w\d]*:/g, '');
170 leafRefPathCopy
= leafRefPathCopy
.replace(/\s/g, '');
172 // resolve any current paths
173 leafRefPathCopy
= resolveCurrentPredicate(leafRefPathCopy
, container
, pathCopy
);
175 // Split on delimiter (/)
176 const pathArray
= leafRefPathCopy
.split('/');
178 let fieldKeyArray
= fieldKey
.split(':');
180 // strip prepending qualifiers from fieldKeys
181 fieldKeyArray
= cleanupFieldKeyArray(fieldKeyArray
);
184 // Check if relative path or not
185 // TODO: Below works but
186 // better to convert the pathCopy to absolute/rooted path
187 // and use the absolute module instead
188 if (isRelativePath(leafRefPathCopy
)) {
189 let i
= pathArray
.length
;
190 while (pathArray
[pathArray
.length
- i
] == '..') {
191 fieldKeyArray
.splice(-1, 1);
192 if (!isNaN(Number(fieldKeyArray
[fieldKeyArray
.length
- 1]))) {
193 // found a number, so an index. strip it
194 fieldKeyArray
.splice(-1, 1);
199 // traversed all .. - now traverse down
200 if (fieldKeyArray
.length
== 1) {
201 for (let key
in catalogs
) {
202 for (let subKey
in catalogs
[key
]) {
203 let found
= _find(catalogs
[key
][subKey
], {
207 results
= getAbsoluteResults(found
, pathArray
.splice(-i
, i
));
212 } else if (fieldKeyArray
.length
== 2) {
213 for (let key
in catalogs
) {
214 for (let subKey
in catalogs
[key
]) {
215 console
.log(key
, subKey
);
216 var found
= _find(catalogs
[key
][subKey
], {
220 for (let foundKey
in found
) {
221 if (_isArray(found
[foundKey
])) {
222 let topLevel
= _find(found
[foundKey
], {
226 results
= getAbsoluteResults(topLevel
, pathArray
.splice(-i
, i
));
230 if (foundKey
== fieldKeyArray
[1]) {
231 results
= getAbsoluteResults(found
[foundKey
], pathArray
.splice(-i
, i
));
239 } else if (fieldKeyArray
.length
== 3) {
240 for (let key
in catalogs
) {
241 for (let subKey
in catalogs
[key
]) {
242 let found
= _find(catalogs
[key
][subKey
], {
246 for (let foundKey
in found
) {
247 if (_isArray(found
[foundKey
])) {
248 let topLevel
= _find(found
[foundKey
], {
252 results
= getAbsoluteResults(topLevel
, pathArray
.splice(-i
, i
));
256 if (foundKey
== fieldKeyArray
[1]) {
257 results
= getAbsoluteResults(found
[foundKey
], pathArray
.splice(-i
, i
));
266 // not supported - too many levels deep ... maybe some day
267 console
.log('The relative path is from a node too many levels deep from root. This is not supported at the time');
271 if (pathArray
[0] == "") {
272 pathArray
.splice(0, 1);
275 let catalogKey
= pathArray
[0];
276 let topLevelObject
= {};
278 topLevelObject
[catalogKey
] = catalogs
[catalogKey
];
280 results
= getAbsoluteResults(topLevelObject
, pathArray
);