blob: fb8007691e58e6f5ebe896bd387e6d284c9aea41 [file] [log] [blame]
Bharat saraswald14cbe82016-07-14 13:26:18 +05301/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.yangutils.linker.impl;
18
Bharat saraswal039f59c2016-07-14 21:57:13 +053019import java.util.ArrayList;
20import java.util.Iterator;
21import java.util.List;
22import java.util.Set;
23import java.util.regex.Pattern;
24
VinodKumarS-Huawei423dc9a2016-08-17 22:08:42 +053025import org.onosproject.yangutils.datamodel.TraversalType;
Bharat saraswal8beac342016-08-04 02:00:03 +053026import org.onosproject.yangutils.datamodel.YangAtomicPath;
Bharat saraswald14cbe82016-07-14 13:26:18 +053027import org.onosproject.yangutils.datamodel.YangAugment;
28import org.onosproject.yangutils.datamodel.YangAugmentableNode;
29import org.onosproject.yangutils.datamodel.YangAugmentedInfo;
janani bebb143d2016-07-14 19:35:22 +053030import org.onosproject.yangutils.datamodel.YangCase;
Bharat saraswalaf413b82016-07-14 15:18:20 +053031import org.onosproject.yangutils.datamodel.YangChoice;
VinodKumarS-Huawei423dc9a2016-08-17 22:08:42 +053032import org.onosproject.yangutils.datamodel.YangGrouping;
33import org.onosproject.yangutils.datamodel.YangIdentityRef;
Bharat saraswal039f59c2016-07-14 21:57:13 +053034import org.onosproject.yangutils.datamodel.YangImport;
35import org.onosproject.yangutils.datamodel.YangInclude;
Bharat saraswald14cbe82016-07-14 13:26:18 +053036import org.onosproject.yangutils.datamodel.YangLeaf;
37import org.onosproject.yangutils.datamodel.YangLeafList;
janani bebb143d2016-07-14 19:35:22 +053038import org.onosproject.yangutils.datamodel.YangLeafRef;
Bharat saraswald14cbe82016-07-14 13:26:18 +053039import org.onosproject.yangutils.datamodel.YangLeavesHolder;
40import org.onosproject.yangutils.datamodel.YangNode;
janani bebb143d2016-07-14 19:35:22 +053041import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
Bharat saraswal039f59c2016-07-14 21:57:13 +053042import org.onosproject.yangutils.datamodel.YangReferenceResolver;
VinodKumarS-Huawei423dc9a2016-08-17 22:08:42 +053043import org.onosproject.yangutils.datamodel.YangType;
44import org.onosproject.yangutils.datamodel.YangTypeDef;
45import org.onosproject.yangutils.datamodel.YangUses;
46import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
47import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
janani bebb143d2016-07-14 19:35:22 +053048import org.onosproject.yangutils.datamodel.utils.YangConstructType;
Bharat saraswald14cbe82016-07-14 13:26:18 +053049import org.onosproject.yangutils.linker.exceptions.LinkerException;
50
VinodKumarS-Huawei423dc9a2016-08-17 22:08:42 +053051import static org.onosproject.yangutils.datamodel.TraversalType.CHILD;
52import static org.onosproject.yangutils.datamodel.TraversalType.PARENT;
53import static org.onosproject.yangutils.datamodel.TraversalType.ROOT;
54import static org.onosproject.yangutils.datamodel.TraversalType.SIBILING;
55import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.addResolutionInfo;
56import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.DERIVED;
57import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.IDENTITYREF;
janani bebb143d2016-07-14 19:35:22 +053058import static org.onosproject.yangutils.utils.UtilConstants.COLON;
59import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
janani bebb143d2016-07-14 19:35:22 +053060
Bharat saraswald14cbe82016-07-14 13:26:18 +053061/**
62 * Represent utilities for YANG linker.
63 */
64public final class YangLinkerUtils {
65
janani bebb143d2016-07-14 19:35:22 +053066 private static final int IDENTIFIER_LENGTH = 64;
67 private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
68 private static final String XML = "xml";
69
Bharat saraswal039f59c2016-07-14 21:57:13 +053070 private YangLinkerUtils() {
71 }
72
Bharat saraswald14cbe82016-07-14 13:26:18 +053073 /**
Bharat saraswalaf413b82016-07-14 15:18:20 +053074 * Detects collision between target nodes leaf/leaf-list or child node with augmented leaf/leaf-list or child node.
Bharat saraswald14cbe82016-07-14 13:26:18 +053075 *
76 * @param targetNode target node
77 * @param augment augment node
78 */
79 private static void detectCollision(YangNode targetNode, YangAugment augment) {
80 YangNode targetNodesChild = targetNode.getChild();
81 YangNode augmentsChild = augment.getChild();
Bharat saraswal039f59c2016-07-14 21:57:13 +053082 YangNode parent = targetNode;
83 if (targetNode instanceof YangAugment) {
84 parent = targetNode.getParent();
Bharat saraswalaf413b82016-07-14 15:18:20 +053085 } else {
Bharat saraswal039f59c2016-07-14 21:57:13 +053086 while (parent.getParent() != null) {
87 parent = parent.getParent();
88 }
89 }
90 if (targetNode instanceof YangChoice) {
Bharat saraswal8beac342016-08-04 02:00:03 +053091 //Do nothing
Bharat saraswal039f59c2016-07-14 21:57:13 +053092 } else {
93 detectCollisionInLeaveHolders(targetNode, augment);
94 while (augmentsChild != null) {
95 detectCollisionInChildNodes(targetNodesChild, augmentsChild, targetNode.getName(), parent.getName());
96 augmentsChild = augmentsChild.getNextSibling();
97 }
98 }
99 }
Bharat saraswald14cbe82016-07-14 13:26:18 +0530100
Bharat saraswal8beac342016-08-04 02:00:03 +0530101 /*Detects collision between leaves/leaf-lists*/
Bharat saraswal039f59c2016-07-14 21:57:13 +0530102 private static void detectCollisionInLeaveHolders(YangNode targetNode, YangAugment augment) {
103 YangLeavesHolder targetNodesLeavesHolder = (YangLeavesHolder) targetNode;
104 YangNode parent = targetNode;
105 if (targetNode instanceof YangAugment) {
106 parent = targetNode.getParent();
107 } else {
108 while (parent.getParent() != null) {
109 parent = parent.getParent();
110 }
111 }
112 if (augment.getListOfLeaf() != null && augment.getListOfLeaf().size() != 0
113 && targetNodesLeavesHolder.getListOfLeaf() != null) {
114 for (YangLeaf leaf : augment.getListOfLeaf()) {
115 for (YangLeaf targetLeaf : targetNodesLeavesHolder.getListOfLeaf()) {
116 if (targetLeaf.getName().equals(leaf.getName())) {
117 throw new LinkerException("target node " + targetNode.getName()
118 + " contains augmented leaf " + leaf.getName() + " in module "
119 + parent.getName());
120 }
Bharat saraswald14cbe82016-07-14 13:26:18 +0530121 }
122 }
Bharat saraswal039f59c2016-07-14 21:57:13 +0530123 } else if (augment.getListOfLeafList() != null
124 && augment.getListOfLeafList().size() != 0
125 && augment.getListOfLeafList() != null) {
126 for (YangLeafList leafList : augment.getListOfLeafList()) {
127 for (YangLeafList targetLeafList : targetNodesLeavesHolder.getListOfLeafList()) {
128 if (targetLeafList.getName().equals(leafList.getName())) {
129 throw new LinkerException("target node " + targetNode.getName()
130 + " contains augmented leaf-list" + leafList.getName() + " in module "
131 + parent.getName());
Bharat saraswald14cbe82016-07-14 13:26:18 +0530132 }
133 }
Bharat saraswald14cbe82016-07-14 13:26:18 +0530134 }
135 }
136 }
137
Bharat saraswal039f59c2016-07-14 21:57:13 +0530138 /*Detects collision for child nodes.*/
139 private static void detectCollisionInChildNodes(YangNode targetNodesChild, YangNode augmentsChild, String
140 targetName, String parentName) {
141 while (augmentsChild != null) {
142 while (targetNodesChild != null) {
143 if (targetNodesChild.getName().equals(augmentsChild.getName())) {
144 throw new LinkerException("target node " + targetName
145 + " contains augmented child node" + augmentsChild.getName() + " in module "
146 + parentName);
147 }
148 targetNodesChild = targetNodesChild.getNextSibling();
149 }
150 augmentsChild = augmentsChild.getNextSibling();
151 }
152 }
153
Bharat saraswald14cbe82016-07-14 13:26:18 +0530154 /**
Bharat saraswalaf413b82016-07-14 15:18:20 +0530155 * Detects collision between target nodes and its all leaf/leaf-list or child node with augmented leaf/leaf-list or
156 * child node.
Bharat saraswald14cbe82016-07-14 13:26:18 +0530157 *
158 * @param targetNode target node
159 * @param augment augment node
160 */
Bharat saraswal039f59c2016-07-14 21:57:13 +0530161 static void detectCollisionForAugmentedNode(YangNode targetNode, YangAugment augment) {
Bharat saraswald14cbe82016-07-14 13:26:18 +0530162 // Detect collision for target node and augment node.
163 detectCollision(targetNode, augment);
164 List<YangAugmentedInfo> yangAugmentedInfo = ((YangAugmentableNode) targetNode).getAugmentedInfoList();
165 // Detect collision for target augment node and current augment node.
166 for (YangAugmentedInfo info : yangAugmentedInfo) {
167 detectCollision((YangAugment) info, augment);
168 }
169 }
janani bebb143d2016-07-14 19:35:22 +0530170
171 /**
172 * Returns list of path names that are needed from augment.
173 *
174 * @param augment instance of YANG augment
175 * @param remainingAncestors ancestor count to move in augment path
176 * @return list of path names needed in leafref
177 */
Bharat saraswal8beac342016-08-04 02:00:03 +0530178 static List<String> getPathWithAugment(YangAugment augment, int remainingAncestors) {
janani bebb143d2016-07-14 19:35:22 +0530179 List<String> listOfPathName = new ArrayList<>();
Bharat saraswal8beac342016-08-04 02:00:03 +0530180 for (YangAtomicPath atomicPath : augment.getTargetNode()) {
181 if (atomicPath.getNodeIdentifier().getPrefix() != null && !atomicPath.getNodeIdentifier().getPrefix()
182 .equals(EMPTY_STRING)) {
183 listOfPathName.add(atomicPath.getNodeIdentifier().getPrefix() + ":" +
184 atomicPath.getNodeIdentifier().getName());
185 } else {
186 listOfPathName.add(atomicPath.getNodeIdentifier().getName());
janani bebb143d2016-07-14 19:35:22 +0530187 }
188 }
Bharat saraswal8beac342016-08-04 02:00:03 +0530189
190
janani bebb143d2016-07-14 19:35:22 +0530191 for (int countOfAncestor = 0; countOfAncestor < remainingAncestors; countOfAncestor++) {
192 listOfPathName.remove(listOfPathName.size() - 1);
193 }
194 return listOfPathName;
195 }
196
197 /**
198 * Skips the invalid nodes which cannot have data from YANG.
199 *
200 * @param currentParent current parent node reference
201 * @param leafref instance of YANG leafref
202 * @return parent node which can hold data
203 * @throws LinkerException a violation of linker rules
204 */
VinodKumarS-Huawei423dc9a2016-08-17 22:08:42 +0530205 static YangNode skipInvalidDataNodes(YangNode currentParent, YangLeafRef leafref)
206 throws LinkerException {
janani bebb143d2016-07-14 19:35:22 +0530207 while (currentParent instanceof YangChoice || currentParent instanceof YangCase) {
208 if (currentParent.getParent() == null) {
209 throw new LinkerException("YANG file error: The target node, in the leafref path " +
210 leafref.getPath() + ", is invalid.");
211 }
212 currentParent = currentParent.getParent();
213 }
214 return currentParent;
215 }
216
217 /**
218 * Checks and return valid node identifier.
219 *
220 * @param nodeIdentifierString string from yang file
221 * @param yangConstruct yang construct for creating error message
222 * @return valid node identifier
223 */
Bharat saraswal8beac342016-08-04 02:00:03 +0530224 static YangNodeIdentifier getValidNodeIdentifier(String nodeIdentifierString,
VinodKumarS-Huawei423dc9a2016-08-17 22:08:42 +0530225 YangConstructType yangConstruct) {
janani bebb143d2016-07-14 19:35:22 +0530226 String[] tmpData = nodeIdentifierString.split(Pattern.quote(COLON));
227 if (tmpData.length == 1) {
228 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
229 nodeIdentifier.setName(getValidIdentifier(tmpData[0], yangConstruct));
230 return nodeIdentifier;
231 } else if (tmpData.length == 2) {
232 YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
233 nodeIdentifier.setPrefix(getValidIdentifier(tmpData[0], yangConstruct));
234 nodeIdentifier.setName(getValidIdentifier(tmpData[1], yangConstruct));
235 return nodeIdentifier;
236 } else {
237 throw new LinkerException("YANG file error : " +
238 YangConstructType.getYangConstructType(yangConstruct) + " name " + nodeIdentifierString +
239 " is not valid.");
240 }
241 }
242
243 /**
244 * Validates identifier and returns concatenated string if string contains plus symbol.
245 *
246 * @param identifier string from yang file
247 * @param yangConstruct yang construct for creating error message=
248 * @return concatenated string after removing double quotes
249 */
250 public static String getValidIdentifier(String identifier, YangConstructType yangConstruct) {
251
252 if (identifier.length() > IDENTIFIER_LENGTH) {
253 throw new LinkerException("YANG file error : " +
254 YangConstructType.getYangConstructType(yangConstruct) + " name " + identifier + " is " +
255 "greater than 64 characters.");
256 } else if (!IDENTIFIER_PATTERN.matcher(identifier).matches()) {
257 throw new LinkerException("YANG file error : " +
258 YangConstructType.getYangConstructType(yangConstruct) + " name " + identifier + " is not " +
259 "valid.");
260 } else if (identifier.toLowerCase().startsWith(XML)) {
261 throw new LinkerException("YANG file error : " +
262 YangConstructType.getYangConstructType(yangConstruct) + " identifier " + identifier +
263 " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
264 } else {
265 return identifier;
266 }
267 }
Bharat saraswal039f59c2016-07-14 21:57:13 +0530268
269 /**
270 * Updates the priority for all the input files.
271 *
272 * @param yangNodeSet set of YANG files info
273 */
274 public static void updateFilePriority(Set<YangNode> yangNodeSet) {
275 for (YangNode yangNode : yangNodeSet) {
276 updateFilePriorityOfNode(yangNode);
277 }
278 }
279
280 /**
281 * Updates priority of the node.
282 *
283 * @param yangNode YANG node information
284 */
Bharat saraswal8beac342016-08-04 02:00:03 +0530285 private static void updateFilePriorityOfNode(YangNode yangNode) {
Bharat saraswal039f59c2016-07-14 21:57:13 +0530286 int curNodePriority = yangNode.getPriority();
287 if (yangNode instanceof YangReferenceResolver) {
288 List<YangImport> yangImportList = ((YangReferenceResolver) yangNode).getImportList();
289 Iterator<YangImport> importInfoIterator = yangImportList.iterator();
290 // Run through the imported list to update priority.
291 while (importInfoIterator.hasNext()) {
292 YangImport yangImport = importInfoIterator.next();
293 YangNode importedNode = yangImport.getImportedNode();
294 if (curNodePriority >= importedNode.getPriority()) {
295 importedNode.setPriority(curNodePriority + 1);
296 updateFilePriorityOfNode(importedNode);
297 }
298 }
299
300 List<YangInclude> yangIncludeList = ((YangReferenceResolver) yangNode).getIncludeList();
301 Iterator<YangInclude> includeInfoIterator = yangIncludeList.iterator();
302 // Run through the imported list to update priority.
303 while (includeInfoIterator.hasNext()) {
304 YangInclude yangInclude = includeInfoIterator.next();
305 YangNode includedNode = yangInclude.getIncludedNode();
306 if (curNodePriority >= includedNode.getPriority()) {
307 includedNode.setPriority(curNodePriority + 1);
308 updateFilePriorityOfNode(includedNode);
309 }
310 }
311 }
312 }
VinodKumarS-Huawei423dc9a2016-08-17 22:08:42 +0530313
314 /**
315 * Add the unresolved data under the root leve grouping to be resolved, since it will be used in interfile uses.
316 *
317 * @param referenceResolver module / sub-module
318 */
319 public static void resolveGroupingInDefinationScope(YangReferenceResolver referenceResolver) {
320 YangNode potentialInterFileGrouping = ((YangNode) referenceResolver).getChild();
321
322 while (potentialInterFileGrouping != null) {
323 if (potentialInterFileGrouping instanceof YangGrouping) {
324 addGroupingResolvableEntitiesToResolutionList((YangGrouping) potentialInterFileGrouping);
325 }
326
327 potentialInterFileGrouping = potentialInterFileGrouping.getNextSibling();
328 }
329 }
330
331 /**
332 * Add the interfile grouping resolvable entities to reesolution list.
333 *
334 * @param interFileGrouping interfile grouping
335 */
336 private static void addGroupingResolvableEntitiesToResolutionList(YangGrouping interFileGrouping) {
337 YangNode curNode = interFileGrouping;
338 TraversalType curTraversal = ROOT;
339 addResolvableLeavesToResolutionList((YangLeavesHolder) curNode);
340 curTraversal = CHILD;
341 curNode = interFileGrouping.getChild();
342 if (curNode == null) {
343 return;
344 }
345 while (curNode != interFileGrouping) {
346 if (curTraversal != PARENT) {
347 if (curNode instanceof YangGrouping || curNode instanceof YangUses) {
348 if (curNode.getNextSibling() != null) {
349 curTraversal = SIBILING;
350 curNode = curNode.getNextSibling();
351 } else {
352 curTraversal = PARENT;
353 curNode = curNode.getParent();
354 }
355 continue;
356 }
357
358 if (curNode instanceof YangLeavesHolder) {
359 addResolvableLeavesToResolutionList((YangLeavesHolder) curNode);
360 } else if (curNode instanceof YangTypeDef) {
361 List<YangType<?>> typeList = ((YangTypeDef) curNode).getTypeList();
362 if (!typeList.isEmpty()) {
363 YangType<?> type = typeList.get(0);
364 if (type.getDataType() == DERIVED) {
365 if (type.getResolvableStatus() != ResolvableStatus.RESOLVED) {
366
367 type.setTypeForInterFileGroupingResolution(true);
368
369 // Add resolution information to the list
370 YangResolutionInfoImpl resolutionInfo =
371 new YangResolutionInfoImpl<YangType>(type, curNode, type.getLineNumber(),
372 type.getCharPosition());
373 try {
374 addResolutionInfo(resolutionInfo);
375 } catch (DataModelException e) {
376 throw new LinkerException("Failed to add type info in grouping to resolution ");
377 }
378 }
379 }
380 }
381 }
382
383 }
384 if (curTraversal != PARENT && curNode.getChild() != null) {
385 curTraversal = CHILD;
386 curNode = curNode.getChild();
387 } else if (curNode.getNextSibling() != null) {
388
389 curTraversal = SIBILING;
390 curNode = curNode.getNextSibling();
391 } else {
392 curTraversal = PARENT;
393 curNode = curNode.getParent();
394 }
395 }
396 }
397
398 /**
399 * Add resolvable leaves type info to resolution list.
400 *
401 * @param leavesHolder leaves holder node
402 */
403 private static void addResolvableLeavesToResolutionList(YangLeavesHolder leavesHolder) {
404 if (leavesHolder.getListOfLeaf() != null && !leavesHolder.getListOfLeaf().isEmpty()) {
405 for (YangLeaf leaf : leavesHolder.getListOfLeaf()) {
406 YangType type = leaf.getDataType();
407 if (type.getDataType() == DERIVED) {
408
409 type.setTypeForInterFileGroupingResolution(true);
410
411 // Add resolution information to the list
412 YangResolutionInfoImpl resolutionInfo =
413 new YangResolutionInfoImpl<YangType>(type, (YangNode) leavesHolder,
414 type.getLineNumber(), type.getCharPosition());
415 try {
416 addResolutionInfo(resolutionInfo);
417 } catch (DataModelException e) {
418 throw new LinkerException("Failed to add leaf type info in grouping, to resolution ");
419 }
420 } else if (type.getDataType() == IDENTITYREF) {
421 YangIdentityRef identityRef = (YangIdentityRef) type.getDataTypeExtendedInfo();
422
423 identityRef.setIdentityForInterFileGroupingResolution(true);
424
425 // Add resolution information to the list
426 YangResolutionInfoImpl resolutionInfo =
427 new YangResolutionInfoImpl<YangIdentityRef>(identityRef, (YangNode) leavesHolder,
428 identityRef.getLineNumber(), identityRef.getCharPosition());
429 try {
430 addResolutionInfo(resolutionInfo);
431 } catch (DataModelException e) {
432 throw new LinkerException("Failed to add leaf identity ref info in grouping, to resolution ");
433 }
434 }
435 }
436 }
437
438 if (leavesHolder.getListOfLeafList() != null && !leavesHolder.getListOfLeafList().isEmpty()) {
439 for (YangLeafList leafList : leavesHolder.getListOfLeafList()) {
440 YangType type = leafList.getDataType();
441 if (type.getDataType() == DERIVED) {
442
443 type.setTypeForInterFileGroupingResolution(true);
444
445 // Add resolution information to the list
446 YangResolutionInfoImpl resolutionInfo =
447 new YangResolutionInfoImpl<YangType>(type, (YangNode) leavesHolder,
448 type.getLineNumber(), type.getCharPosition());
449 try {
450 addResolutionInfo(resolutionInfo);
451 } catch (DataModelException e) {
452 throw new LinkerException("Failed to add leaf type info in grouping, to resolution ");
453 }
454 } else if (type.getDataType() == IDENTITYREF) {
455 YangIdentityRef identityRef = (YangIdentityRef) type.getDataTypeExtendedInfo();
456
457 identityRef.setIdentityForInterFileGroupingResolution(true);
458 // Add resolution information to the list
459 YangResolutionInfoImpl resolutionInfo =
460 new YangResolutionInfoImpl<YangIdentityRef>(identityRef, (YangNode) leavesHolder,
461 identityRef.getLineNumber(), identityRef.getCharPosition());
462 try {
463 addResolutionInfo(resolutionInfo);
464 } catch (DataModelException e) {
465 throw new LinkerException("Failed to add leaf identity ref info in grouping, to resolution ");
466 }
467 }
468 }
469 }
470 }
471
Bharat saraswald14cbe82016-07-14 13:26:18 +0530472}