blob: b70d44c3ba4365394400ac1cba1c94da4cafd08b [file] [log] [blame]
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +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 saraswal96dfef02016-06-16 00:29:12 +053019import java.io.Serializable;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053020import java.util.Iterator;
21import java.util.List;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053022import java.util.Stack;
Bharat saraswal96dfef02016-06-16 00:29:12 +053023
24import org.onosproject.yangutils.datamodel.Resolvable;
janani be18b5342016-07-13 21:06:41 +053025import org.onosproject.yangutils.datamodel.ResolvableType;
26import org.onosproject.yangutils.datamodel.YangAtomicPath;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053027import org.onosproject.yangutils.datamodel.YangDerivedInfo;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053028import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
29import org.onosproject.yangutils.datamodel.YangFeature;
30import org.onosproject.yangutils.datamodel.YangFeatureHolder;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053031import org.onosproject.yangutils.datamodel.YangGrouping;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053032import org.onosproject.yangutils.datamodel.YangIfFeature;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053033import org.onosproject.yangutils.datamodel.YangImport;
34import org.onosproject.yangutils.datamodel.YangInclude;
janani be18b5342016-07-13 21:06:41 +053035import org.onosproject.yangutils.datamodel.YangInput;
36import org.onosproject.yangutils.datamodel.YangLeaf;
37import org.onosproject.yangutils.datamodel.YangLeafList;
38import org.onosproject.yangutils.datamodel.YangLeafRef;
39import org.onosproject.yangutils.datamodel.YangLeavesHolder;
40import org.onosproject.yangutils.datamodel.YangList;
41import org.onosproject.yangutils.datamodel.YangModule;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053042import org.onosproject.yangutils.datamodel.YangNode;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053043import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
janani be18b5342016-07-13 21:06:41 +053044import org.onosproject.yangutils.datamodel.YangOutput;
45import org.onosproject.yangutils.datamodel.YangPathArgType;
46import org.onosproject.yangutils.datamodel.YangPathPredicate;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053047import org.onosproject.yangutils.datamodel.YangReferenceResolver;
janani be18b5342016-07-13 21:06:41 +053048import org.onosproject.yangutils.datamodel.YangRelativePath;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053049import org.onosproject.yangutils.datamodel.YangResolutionInfo;
janani be18b5342016-07-13 21:06:41 +053050import org.onosproject.yangutils.datamodel.YangRpc;
51import org.onosproject.yangutils.datamodel.YangSubModule;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053052import org.onosproject.yangutils.datamodel.YangType;
53import org.onosproject.yangutils.datamodel.YangTypeDef;
54import org.onosproject.yangutils.datamodel.YangUses;
55import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Bharat saraswal96dfef02016-06-16 00:29:12 +053056import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
janani be18b5342016-07-13 21:06:41 +053057import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053058import org.onosproject.yangutils.linker.YangLinkingPhase;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053059
Bharat saraswal96dfef02016-06-16 00:29:12 +053060import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTER_FILE_LINKED;
61import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
62import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.LINKED;
63import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053064import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNDEFINED;
Bharat saraswal96dfef02016-06-16 00:29:12 +053065import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNRESOLVED;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053066import static org.onosproject.yangutils.linker.YangLinkingPhase.INTER_FILE;
67import static org.onosproject.yangutils.linker.YangLinkingPhase.INTRA_FILE;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053068import static org.onosproject.yangutils.utils.UtilConstants.FEATURE_LINKER_ERROR;
Vidyashree Rama210c01d2016-05-20 16:29:25 +053069import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +053070import static org.onosproject.yangutils.utils.UtilConstants.INPUT;
71import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF;
72import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF_LINKER_ERROR;
73import static org.onosproject.yangutils.utils.UtilConstants.OUTPUT;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053074import static org.onosproject.yangutils.utils.UtilConstants.TYPEDEF_LINKER_ERROR;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053075
76/**
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053077 * Represents implementation of resolution object which will be resolved by
78 * linker.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053079 *
80 * @param <T> type of resolution entity uses / type
81 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053082public class YangResolutionInfoImpl<T>
Bharat saraswal96dfef02016-06-16 00:29:12 +053083 implements YangResolutionInfo<T>, Serializable {
84
85 private static final long serialVersionUID = 806201658L;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053086
87 /**
88 * Information about the entity that needs to be resolved.
89 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053090 private YangEntityToResolveInfoImpl<T> entityToResolveInfo;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053091
92 /**
93 * Error line number.
94 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053095 private transient int lineNumber;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053096
97 /**
98 * Error character position in number.
99 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530100 private transient int charPosition;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530101
102 /**
103 * Current module/sub-module reference, will be used in inter-file/
104 * inter-jar scenario to get the import/include list.
105 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530106 private transient YangReferenceResolver curReferenceResolver;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530107
108 /**
109 * Stack for type/uses is maintained for hierarchical references, this is
110 * used during resolution.
111 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530112 private Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530113
114 /**
115 * It is private to ensure the overloaded method be invoked to create an
116 * object.
117 */
118 @SuppressWarnings("unused")
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530119 private YangResolutionInfoImpl() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530120
121 }
122
123 /**
124 * Creates a resolution information object with all the inputs.
125 *
126 * @param dataNode current parsable data node
127 * @param holderNode parent YANG node
128 * @param lineNumber error line number
129 * @param charPositionInLine error character position in line
130 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530131 public YangResolutionInfoImpl(T dataNode, YangNode holderNode, int lineNumber, int charPositionInLine) {
132 setEntityToResolveInfo(new YangEntityToResolveInfoImpl<>());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530133 getEntityToResolveInfo().setEntityToResolve(dataNode);
134 getEntityToResolveInfo().setHolderOfEntityToResolve(holderNode);
135 this.setLineNumber(lineNumber);
136 this.setCharPosition(charPositionInLine);
137 setPartialResolvedStack(new Stack<>());
138 }
139
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530140 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530141 public void resolveLinkingForResolutionInfo(YangReferenceResolver dataModelRootNode)
142 throws DataModelException {
143
144 setCurReferenceResolver(dataModelRootNode);
145
janani be18b5342016-07-13 21:06:41 +0530146 // Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature or YANG leafref.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530147 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
148
149 // Check if linking is already done
150 if (entityToResolve instanceof Resolvable) {
151 Resolvable resolvable = (Resolvable) entityToResolve;
152 if (resolvable.getResolvableStatus() == RESOLVED) {
153 /**
154 * entity is already resolved, so nothing to do
155 */
156 return;
157 }
158 } else {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530159 throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
janani be18b5342016-07-13 21:06:41 +0530160 "type/uses/if-feature/leafref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530161 }
162
163 // Push the initial entity to resolve in stack.
164 addInPartialResolvedStack(getEntityToResolveInfo());
165
166 linkAndResolvePartialResolvedStack();
janani be18b5342016-07-13 21:06:41 +0530167
168 addDerivedRefTypeToRefTypeResolutionList();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530169 }
170
171 /**
172 * Resolves linking with ancestors.
173 *
174 * @throws DataModelException a violation of data model rules
175 */
176 private void linkAndResolvePartialResolvedStack()
177 throws DataModelException {
178
179 while (getPartialResolvedStack().size() != 0) {
180
181 // Current node to resolve, it can be a YANG type or YANG uses.
182 T entityToResolve = getCurrentEntityToResolveFromStack();
183 // Check if linking is already done
184 if (entityToResolve instanceof Resolvable) {
185
186 Resolvable resolvable = (Resolvable) entityToResolve;
187 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530188 case RESOLVED: {
189 /*
190 * If the entity is already resolved in the stack, then pop
191 * it and continue with the remaining stack elements to
192 * resolve
193 */
194 getPartialResolvedStack().pop();
195 break;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530196 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530197
198 case LINKED: {
199 /*
200 * If the top of the stack is already linked then resolve
201 * the references and pop the entity and continue with
202 * remaining stack elements to resolve.
203 */
204 resolveTopOfStack(INTRA_FILE);
205 getPartialResolvedStack().pop();
206 break;
207 }
208
209 case INTRA_FILE_RESOLVED: {
210 /*
211 * Pop the top of the stack.
212 */
213 getPartialResolvedStack().pop();
214 break;
215 }
216
217 case UNRESOLVED: {
218 linkTopOfStackReferenceUpdateStack();
219
220 if (resolvable.getResolvableStatus() == UNRESOLVED) {
221 // If current entity is still not resolved, then
222 // linking/resolution has failed.
223 String errorInfo;
224 if (resolvable instanceof YangType) {
225 errorInfo = TYPEDEF_LINKER_ERROR;
226 } else if (resolvable instanceof YangUses) {
227 errorInfo = GROUPING_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +0530228 } else if (resolvable instanceof YangIfFeature) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530229 errorInfo = FEATURE_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +0530230 } else {
231 errorInfo = LEAFREF_LINKER_ERROR;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530232 }
233 DataModelException dataModelException =
234 new DataModelException(errorInfo);
235 dataModelException.setLine(getLineNumber());
236 dataModelException.setCharPosition(getCharPosition());
237 throw dataModelException;
238 }
239 break;
240 }
241 default: {
242 throw new DataModelException("Data Model Exception: Unsupported, linker state");
243 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530244
245 }
246
247 } else {
janani be18b5342016-07-13 21:06:41 +0530248 throw new DataModelException(
249 "Data Model Exception: Entity to resolved is other than type/uses/if-feature/leafref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530250 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530251 }
252
253 }
254
255 /**
janani be18b5342016-07-13 21:06:41 +0530256 * Adds the leafref type to the type, which has derived type referring to typedef with leafref type.
257 */
258 private void addDerivedRefTypeToRefTypeResolutionList() throws DataModelException {
259
260 YangNode potentialAncestorWithReferredNode = getEntityToResolveInfo().getHolderOfEntityToResolve();
261
262 // If holder is typedef return.
263 if (potentialAncestorWithReferredNode instanceof YangTypeDef) {
264 return;
265 }
266
267 // If entity is not type return.
268 if (!(getEntityToResolveInfo().getEntityToResolve() instanceof YangType)) {
269 return;
270 }
271
272 YangType yangType = (YangType) getEntityToResolveInfo().getEntityToResolve();
273
274 // If type is not resolved return.
275 if (yangType.getResolvableStatus() != RESOLVED) {
276 return;
277 }
278
279 YangDerivedInfo derivedInfo = (YangDerivedInfo) yangType.getDataTypeExtendedInfo();
280
281 /*
282 * If the derived types referred type is not leaf ref return
283 */
284 if (derivedInfo.getEffectiveBuiltInType() != YangDataTypes.LEAFREF) {
285 return;
286 }
287
288 T extendedInfo = (T) derivedInfo.getReferredTypeDef().getTypeDefBaseType().getDataTypeExtendedInfo();
289
290 while (extendedInfo instanceof YangDerivedInfo) {
291 YangDerivedInfo derivedInfoFromTypedef = (YangDerivedInfo) extendedInfo;
292 extendedInfo = (T) derivedInfoFromTypedef.getReferredTypeDef().getTypeDefBaseType()
293 .getDataTypeExtendedInfo();
294 }
295 /*
296 * Backup the derived types leaf ref info, delete all the info in
297 * current type, but for resolution status as resolved. Copy the backed
298 * up leaf ref to types extended info, create a leaf ref resolution info
299 * using the current resolution info and add to leaf ref resolution
300 * list.
301 */
302 YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
303 yangType.resetYangType();
304
305 yangType.setResolvableStatus(RESOLVED);
306 yangType.setDataType(YangDataTypes.LEAFREF);
307 yangType.setDataTypeName(LEAFREF);
308 yangType.setDataTypeExtendedInfo(leafRefInTypeDef);
309 leafRefInTypeDef.setResolvableStatus(UNRESOLVED);
310
311 // Add resolution information to the list.
312 YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(leafRefInTypeDef,
313 potentialAncestorWithReferredNode, getLineNumber(), getCharPosition());
314 getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
315 ResolvableType.YANG_LEAFREF);
316 getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_LEAFREF);
317 }
318
319 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530320 * Resolves the current entity in the stack.
321 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530322 private void resolveTopOfStack(YangLinkingPhase linkingPhase)
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530323 throws DataModelException {
324 ((Resolvable) getCurrentEntityToResolveFromStack()).resolve();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530325 if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != INTRA_FILE_RESOLVED
326 && ((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != UNDEFINED) {
janani be18b5342016-07-13 21:06:41 +0530327 // Sets the resolution status in inside the type/uses/if-feature/leafref.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530328 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(RESOLVED);
329 }
330 }
331
332 /**
333 * Resolves linking for a node child and siblings.
334 *
335 * @throws DataModelException data model error
336 */
337 private void linkTopOfStackReferenceUpdateStack()
338 throws DataModelException {
339
340 /*
341 * Check if self file reference is there, this will not check for the
342 * scenario when prefix is not present and type/uses is present in
343 * sub-module from include list.
344 */
345 if (!isCandidateForSelfFileReference()) {
346 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
347 return;
348 }
349
350 /**
351 * Try to resolve the top of the stack and update partial resolved stack
352 * if there is recursive references
353 */
354 YangNode potentialAncestorWithReferredNode = getPartialResolvedStack().peek()
355 .getHolderOfEntityToResolve();
356
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530357 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
358 resolveSelfFileLinkingForIfFeature(potentialAncestorWithReferredNode);
359 return;
janani be18b5342016-07-13 21:06:41 +0530360 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
361 resolveSelfFileLinkingForLeafref(potentialAncestorWithReferredNode);
362 return;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530363 } else {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530364
365 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530366 * Traverse up in the ancestor tree to check if the referred node is
367 * defined
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530368 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530369 while (potentialAncestorWithReferredNode != null) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530370
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530371 /**
372 * Check for the referred node defined in a ancestor scope
373 */
374 YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
375 if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
376 return;
377 }
378
379 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
380 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530381 }
382
383 /*
384 * In case prefix is not present it's a candidate for inter-file
385 * resolution via include list.
386 */
387 if (getRefPrefix() == null) {
388 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
389 }
390 }
391
392 /**
janani be18b5342016-07-13 21:06:41 +0530393 * Resolves self file linking for leafref.
394 *
395 * @param potentialAncestorWithReferredNode leafref holder node
396 * @throws DataModelException a violation of data model rules
397 */
398 private void resolveSelfFileLinkingForLeafref(YangNode potentialAncestorWithReferredNode)
399 throws DataModelException {
400
401 YangNode ancestorWithTheReferredNode = potentialAncestorWithReferredNode;
402 YangLeafRef leafref = (YangLeafRef) getCurrentEntityToResolveFromStack();
403 boolean referredLeafFound = false;
404
405 /*
406 * Takes absolute path and takes the root node as module/sub-module,
407 * then sends the list of nodes for finding the target leaf.
408 */
409 if (leafref.getPathType() == YangPathArgType.ABSOLUTE_PATH) {
410 List<YangAtomicPath> atomicPathList = leafref.getAtomicPath();
411 if (atomicPathList != null && !atomicPathList.isEmpty()) {
412 Iterator<YangAtomicPath> listOfYangAtomicPath = atomicPathList.listIterator();
413 if (getCurReferenceResolver() instanceof YangModule) {
414 YangModule rootNode = (YangModule) getCurReferenceResolver();
415 // Sends list of nodes for finding the target leaf.
416 referredLeafFound = isLeafReferenceFound(listOfYangAtomicPath, rootNode,
417 referredLeafFound, potentialAncestorWithReferredNode);
418 } else if (getCurReferenceResolver() instanceof YangSubModule) {
419 YangSubModule rootNode = (YangSubModule) getCurReferenceResolver();
420 // Sends list of nodes for finding the target leaf.
421 referredLeafFound = isLeafReferenceFound(listOfYangAtomicPath, rootNode,
422 referredLeafFound, potentialAncestorWithReferredNode);
423 }
424 }
425 /*
426 * Takes relative path, goes to the parent node by using the
427 * ancestor count and sends the list of nodes for finding the target
428 * leaf.
429 */
430 } else if (leafref.getPathType() == YangPathArgType.RELATIVE_PATH) {
431 YangRelativePath yangRelativePath = leafref.getRelativePath();
432 int parentNodes = yangRelativePath.getAncestorNodeCount();
433 List<YangAtomicPath> atomicPathList = yangRelativePath.getAtomicPathList();
434 if (atomicPathList != null && !atomicPathList.isEmpty()) {
435 Iterator<YangAtomicPath> listOfAtomicPath = atomicPathList.listIterator();
436 // Gets the root node from ancestor count.
437 YangNode rootparentNode = getRootNodeWithAncestorCount(parentNodes, ancestorWithTheReferredNode);
438 // Sends list of nodes for finding the target leaf.
439 referredLeafFound = isLeafReferenceFound(listOfAtomicPath, rootparentNode,
440 referredLeafFound, potentialAncestorWithReferredNode);
441 }
442 }
443 if (referredLeafFound) {
444 return;
445 }
446 /*
447 * In case prefix is not present it's a candidate for inter-file
448 * resolution via include list.
449 */
450 if (getRefPrefix() == null) {
451 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
452 }
453 }
454
455 /**
456 * Returns the root parent with respect to the ancestor count from leafref.
457 *
458 * @param ancestorCount count of node where parent node can be reached
459 * @param currentParent current parent node
460 * @return root node
461 * @throws DataModelException a violation of data model rules
462 */
463 private YangNode getRootNodeWithAncestorCount(int ancestorCount, YangNode currentParent)
464 throws DataModelException {
465
466 int currentParentCount = 1;
467 while (currentParentCount < ancestorCount) {
468 if (currentParent.getParent() == null) {
469 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
470 }
471 currentParent = currentParent.getParent();
472 currentParentCount = currentParentCount + 1;
473 }
474 return currentParent;
475 }
476
477 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530478 * Resolves self file linking for if-feature.
479 *
480 * @param potentialAncestorWithReferredNode if-feature holder node
481 * @throws DataModelException DataModelException a violation of data model
482 * rules
483 */
484 private void resolveSelfFileLinkingForIfFeature(YangNode potentialAncestorWithReferredNode)
485 throws DataModelException {
486
487 YangFeatureHolder featureHolder = getFeatureHolder(potentialAncestorWithReferredNode);
488 YangNode potentialReferredNode = (YangNode) featureHolder;
489 if (isReferredNode(potentialReferredNode)) {
490
491 // Adds reference link of entity to the node under resolution.
492 addReferredEntityLink(potentialReferredNode, LINKED);
493
494 /**
495 * resolve the reference and update the partial resolution stack
496 * with any further recursive references
497 */
498 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
499 return;
500 }
501
502 /*
503 * In case prefix is not present it's a candidate for inter-file
504 * resolution via include list.
505 */
506 if (getRefPrefix() == null) {
507 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
508 }
509 }
510
janani be18b5342016-07-13 21:06:41 +0530511 /**
512 * Returns the status of the referred leaf/leaf-list found for leafref.
513 *
514 * @param listOfYangAtomicPath list of atomic paths
515 * @param ancestorWithTheReferredNode the parent node of leafref
516 * @param referredLeafFound status of referred leaf/leaf-list
517 * @param potentialAncestorWithReferredNode holder of the leafref leaf
518 * @return status of referred leaf
519 * @throws DataModelException a violation of data model rules
520 */
521 private boolean isLeafReferenceFound(Iterator<YangAtomicPath> listOfYangAtomicPath,
522 YangNode ancestorWithTheReferredNode, boolean referredLeafFound, YangNode potentialAncestorWithReferredNode)
523 throws DataModelException {
524
525 while (listOfYangAtomicPath.hasNext()) {
526 YangAtomicPath atomicPath = listOfYangAtomicPath.next();
527 String nodeName = atomicPath.getNodeIdentifier().getName();
528
529 // When child is not present, only leaf/leaf-list is available in the node.
530 if (ancestorWithTheReferredNode.getChild() == null) {
531 referredLeafFound = isReferredLeafOrLeafListFound(ancestorWithTheReferredNode, nodeName, (T) LINKED);
532 break;
533 }
534 ancestorWithTheReferredNode = ancestorWithTheReferredNode.getChild();
535
536 // Checks all the siblings under the node and returns the matched node.
537 YangNode nodeFound = isReferredNodeInSiblingProcessedForLeafref(ancestorWithTheReferredNode, nodeName);
538
539 // When node is not found in all the siblings, leaf-list may be the node we have to find.
540 if (nodeFound == null) {
541 referredLeafFound = isReferredLeafOrLeafListFound(ancestorWithTheReferredNode.getParent(), nodeName,
542 (T) LINKED);
543 } else {
544 ancestorWithTheReferredNode = nodeFound;
545
546 // For the node check if path predicate is present and fill its values.
547 List<YangPathPredicate> pathPredicateList = atomicPath.getPathPredicatesList();
548 if (pathPredicateList != null && !pathPredicateList.isEmpty()) {
549 Iterator<YangPathPredicate> listOfYangPathPredicate = pathPredicateList.listIterator();
550 fillPathPredicatesForTheNode(ancestorWithTheReferredNode, listOfYangPathPredicate,
551 potentialAncestorWithReferredNode);
552 }
553 }
554
555 // If leaf is also not found and node is also not found return the status as false.
556 if (!referredLeafFound && nodeFound == null) {
557 break;
558 }
559 }
560 return referredLeafFound;
561 }
562
563 /**
564 * Fills the referred leaf or leaf-list inside the path predicates.
565 *
566 * @param ancestorWithTheReferredNode the actual node where YANG list will be present
567 * @param listOfYangPathPredicate the path predicates present for the node
568 * @param potentialAncestorWithReferredNode the current leaf node parent
569 * @throws DataModelException a violation of data model rules
570 */
571 private void fillPathPredicatesForTheNode(YangNode ancestorWithTheReferredNode,
572 Iterator<YangPathPredicate> listOfYangPathPredicate, YangNode potentialAncestorWithReferredNode)
573 throws DataModelException {
574
575 while (listOfYangPathPredicate.hasNext()) {
576 if (!(ancestorWithTheReferredNode instanceof YangList)) {
577 throw new DataModelException("YANG file error: The path predicates are applicable only for list");
578 }
579 YangPathPredicate pathPredicate = listOfYangPathPredicate.next();
580 YangNodeIdentifier leftNode = pathPredicate.getNodeIdentifier();
581 YangRelativePath relativePath = pathPredicate.getRightRelativePath();
582
583 // Checks that the left axis is filled in the path predicate.
584 boolean isLeftLeafOrLeafListSetForLeftAxis = getLeftLeafOrLeafListInPredicate(
585 (YangList) ancestorWithTheReferredNode, pathPredicate, leftNode);
586 if (!isLeftLeafOrLeafListSetForLeftAxis) {
587 throw new DataModelException(
588 "YANG file error: The path predicate is not referring to an existing leaf/leaflist");
589 }
590 int parentNodes = relativePath.getAncestorNodeCount();
591
592 // Finds the root node for the right relative path.
593 YangNode rootParentNode = getRootNodeWithAncestorCount(parentNodes, potentialAncestorWithReferredNode);
594
595 // Finds the leaf/leaf-list from the right side relative path.
596 resolveRightAxisNodeInPathPredicate(relativePath, rootParentNode, pathPredicate);
597 }
598 }
599
600 /**
601 * Resolves the right axis node in the path predicate.
602 *
603 * @param relativePath the relative path in the path predicate
604 * @param rootParentNode parent node from where the node has to be found
605 * @param pathPredicate data tree reference in YANG list
606 * @throws DataModelException a violation of data model rules
607 */
608 private void resolveRightAxisNodeInPathPredicate(YangRelativePath relativePath, YangNode rootParentNode,
609 YangPathPredicate pathPredicate) throws DataModelException {
610
611 List<YangAtomicPath> absolutePathList = relativePath.getAtomicPathList();
612 if (absolutePathList != null && !absolutePathList.isEmpty()) {
613 Iterator<YangAtomicPath> listOfYangAtomicPathForRightRelative = absolutePathList.listIterator();
614 while (listOfYangAtomicPathForRightRelative.hasNext()) {
615 boolean isRightAxisNodeFound = false;
616 YangAtomicPath absolutePathInPredicate = listOfYangAtomicPathForRightRelative.next();
617 String nodeNameInAtomicPath = absolutePathInPredicate.getNodeIdentifier().getName();
618
619 // When child is not there check the leaf/leaf-list.
620 if (rootParentNode.getChild() == null) {
621 isRightAxisNodeFound = isReferredLeafOrLeafListFound(rootParentNode,
622 nodeNameInAtomicPath, (T) pathPredicate);
623 if (!isRightAxisNodeFound) {
624 throw new DataModelException(
625 "YANG file error: The path predicates is not referring to an existing leaf/leaflist");
626 }
627 break;
628 }
629 rootParentNode = rootParentNode.getChild();
630 YangNode nodeFoundInTheRelativePath = isReferredNodeInSiblingProcessedForLeafref(
631 rootParentNode, nodeNameInAtomicPath);
632
633 if (nodeFoundInTheRelativePath == null) {
634
635 // When node is not found check the leaf/leaf-list.
636 isRightAxisNodeFound = isReferredLeafOrLeafListFound(rootParentNode.getParent(),
637 nodeNameInAtomicPath, (T) pathPredicate);
638 } else {
639 rootParentNode = nodeFoundInTheRelativePath;
640 }
641 if (!isRightAxisNodeFound && nodeFoundInTheRelativePath == null) {
642 throw new DataModelException(
643 "YANG file error: The path predicates is not referring to an existing leaf/leaflist");
644 }
645 }
646 }
647 }
648
649 /**
650 * Returns the status, if referred leaf/leaf-list is found.
651 *
652 * @param ancestorWithTheReferredNode the parent node of leaf/leaf-list
653 * @param nodeName the name of the leaf/leaf-list
654 * @param statusOrPathPredicate the status to be set for the leaf-ref or the path predicate
655 * @return status of the target node is found
656 * @throws DataModelException a violation of data model rules
657 */
658 private boolean isReferredLeafOrLeafListFound(YangNode ancestorWithTheReferredNode, String nodeName,
659 T statusOrPathPredicate) throws DataModelException {
660
661 if (!(ancestorWithTheReferredNode instanceof YangLeavesHolder)) {
662 throw new DataModelException("Yang file error: The target node of leafref is invalid.");
663 }
664 YangLeavesHolder leavesHolder = (YangLeavesHolder) ancestorWithTheReferredNode;
665 if (leavesHolder.getListOfLeaf() != null) {
666 Iterator<YangLeaf> yangLeavesList = leavesHolder.getListOfLeaf().listIterator();
667 while (yangLeavesList.hasNext()) {
668 YangLeaf yangleaf = yangLeavesList.next();
669 if (yangleaf.getName().contentEquals(nodeName)) {
670 if (statusOrPathPredicate instanceof ResolvableStatus) {
671 ResolvableStatus status = (ResolvableStatus) statusOrPathPredicate;
672
673 // Sets the referred leaf to YANG leafref.
674 ((YangLeafRef) getCurrentEntityToResolveFromStack()).setReferredLeafOrLeafList(yangleaf);
675
676 // Adds reference link of entity to the node under resolution.
677 addReferredEntityLink(ancestorWithTheReferredNode, status);
678 addUnResolvedLeafRefTypeToStack((T) yangleaf, ancestorWithTheReferredNode);
679 return true;
680 } else if (statusOrPathPredicate instanceof YangPathPredicate) {
681 YangPathPredicate pathPredicate = (YangPathPredicate) statusOrPathPredicate;
682
683 // Sets the right axis node.
684 pathPredicate.setRightAxisNode(yangleaf);
685 return true;
686 } else {
687 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
688 }
689 }
690 }
691 }
692 if (leavesHolder.getListOfLeafList() != null) {
693 Iterator<YangLeafList> yangLeafListList = leavesHolder.getListOfLeafList().listIterator();
694 while (yangLeafListList.hasNext()) {
695 YangLeafList yangLeaflist = yangLeafListList.next();
696 if (yangLeaflist.getName().contentEquals(nodeName)) {
697 if (statusOrPathPredicate instanceof ResolvableStatus) {
698 ResolvableStatus status = (ResolvableStatus) statusOrPathPredicate;
699
700 // Sets the referred leaf-list to YANG leafref.
701 ((YangLeafRef) getCurrentEntityToResolveFromStack()).setReferredLeafOrLeafList(yangLeaflist);
702
703 // Adds reference link of entity to the node under resolution.
704 addReferredEntityLink(ancestorWithTheReferredNode, status);
705 addUnResolvedLeafRefTypeToStack((T) yangLeaflist, ancestorWithTheReferredNode);
706 return true;
707 } else if (statusOrPathPredicate instanceof YangPathPredicate) {
708 YangPathPredicate pathPredicate = (YangPathPredicate) statusOrPathPredicate;
709 pathPredicate.setRightAxisNode(yangLeaflist);
710 return true;
711 } else {
712 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
713 }
714 }
715 }
716 }
717 return false;
718 }
719
720 /**
721 * Adds the unresolved constructs to stack which has to be resolved for leafref.
722 *
723 * @param yangleafOrLeafList YANG leaf or leaf list which holds the type
724 * @param ancestorWithTheReferredNode holder of the YANG leaf or leaf list
725 */
726 private void addUnResolvedLeafRefTypeToStack(T yangleafOrLeafList, YangNode ancestorWithTheReferredNode) {
727
728 YangType referredTypeInLeafOrLeafList;
729 if (yangleafOrLeafList instanceof YangLeaf) {
730 YangLeaf leaf = (YangLeaf) yangleafOrLeafList;
731 referredTypeInLeafOrLeafList = leaf.getDataType();
732 if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
733 YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
734 unResolvedEntityInfo.setEntityToResolve((YangLeafRef<?>) leaf.getDataType().getDataTypeExtendedInfo());
735 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
736 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
737 } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
738 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
739 unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
740 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
741 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
742 }
743 } else {
744 YangLeafList leafList = (YangLeafList) yangleafOrLeafList;
745 referredTypeInLeafOrLeafList = leafList.getDataType();
746 if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
747 YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
748 unResolvedEntityInfo
749 .setEntityToResolve((YangLeafRef<?>) leafList.getDataType().getDataTypeExtendedInfo());
750 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
751 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
752 } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
753 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
754 unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
755 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
756 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
757 }
758 }
759 }
760
761 /**
762 * Returns true if referred leaf/leaf-list is found in a particular node. This is for path in path predicate.
763 *
764 * @param listForLeaf list node where referred leaf is found
765 * @param pathPredicate path predicate instance where the value of nodes to be found are available
766 * @param leftNode node identifier of the left side parameter in path predicate
767 * @return status of the leaf/leaf-list found
768 */
769 private boolean getLeftLeafOrLeafListInPredicate(YangList listForLeaf, YangPathPredicate pathPredicate,
770 YangNodeIdentifier leftNode) {
771
772 if (listForLeaf.getListOfLeaf() != null) {
773 Iterator<YangLeaf> yangLeavesUnderList = listForLeaf.getListOfLeaf().listIterator();
774 while (yangLeavesUnderList.hasNext()) {
775 YangLeaf yangleafUnderList = yangLeavesUnderList.next();
776 if (yangleafUnderList.getName().contentEquals(leftNode.getName())) {
777 pathPredicate.setLeftAxisNode(yangleafUnderList);
778 return true;
779 }
780 }
781 }
782 if (listForLeaf.getListOfLeafList() != null) {
783 Iterator<YangLeafList> yangLeavesListUnderList = listForLeaf.getListOfLeafList().listIterator();
784 while (yangLeavesListUnderList.hasNext()) {
785 YangLeafList yangleafListUnderList = yangLeavesListUnderList.next();
786 if (yangleafListUnderList.getName().contentEquals(leftNode.getName())) {
787 pathPredicate.setLeftAxisNode(yangleafListUnderList);
788 return true;
789 }
790 }
791 }
792 return false;
793 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530794
795 /**
796 * Returns feature holder(module/sub-module node) .
797 *
798 * @param potentialAncestorWithReferredNode if-feature holder node
799 */
800 private YangFeatureHolder getFeatureHolder(YangNode potentialAncestorWithReferredNode) {
801 while (potentialAncestorWithReferredNode != null) {
802 if (potentialAncestorWithReferredNode instanceof YangFeatureHolder) {
803 return (YangFeatureHolder) potentialAncestorWithReferredNode;
804 }
805 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
806 }
807 return null;
808 }
809
810 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530811 * Checks if the reference in self file or in external file.
812 *
813 * @return true if self file reference, false otherwise
814 * @throws DataModelException a violation of data model rules
815 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530816 private boolean isCandidateForSelfFileReference()
817 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530818 String prefix = getRefPrefix();
819 return prefix == null || prefix.contentEquals(getCurReferenceResolver().getPrefix());
820 }
821
822 /**
janani be18b5342016-07-13 21:06:41 +0530823 * Checks for the referred parent node for the leafref path.
824 *
825 * @param potentialReferredNode potential referred node
826 * @return the reffered parent node of leaf/leaf-list
827 * @throws DataModelException data model errors
828 */
829 private YangNode isReferredNodeInSiblingProcessedForLeafref(YangNode potentialReferredNode, String referredNodeName)
830 throws DataModelException {
831
832 while (potentialReferredNode != null) {
833 if (potentialReferredNode instanceof YangInput) {
834 if (referredNodeName.equalsIgnoreCase(INPUT)) {
835 return potentialReferredNode;
836 }
837 } else if (potentialReferredNode instanceof YangOutput) {
838 if (referredNodeName.equalsIgnoreCase(OUTPUT)) {
839 return potentialReferredNode;
840 }
841 }
842 // Check if the potential referred node is the actual referred node
843 if (isReferredNodeForLeafref(potentialReferredNode, referredNodeName)) {
844 if (potentialReferredNode instanceof YangGrouping || potentialReferredNode instanceof YangTypeDef) {
845 if (potentialReferredNode.getParent() instanceof YangRpc) {
846 potentialReferredNode = potentialReferredNode.getNextSibling();
847 } else {
848 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
849 }
850 }
851 return potentialReferredNode;
852 }
853 potentialReferredNode = potentialReferredNode.getNextSibling();
854 }
855 return null;
856 }
857
858 /**
859 * Checks if the current reference node name and the name in the path are equal.
860 *
861 * @param currentReferredNode the node where the reference is pointed
862 * @param nameOfNodeinPath name of the node in the path
863 * @return status of the match between the name
864 * @throws DataModelException a violation of data model rules
865 */
866 private boolean isReferredNodeForLeafref(YangNode currentReferredNode, String nameOfNodeinPath)
867 throws DataModelException {
868
869 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
870 /*
871 * Check if name of node name matches with the current reference
872 * node.
873 */
874 return currentReferredNode.getName().contentEquals(nameOfNodeinPath);
875 } else {
876 throw new DataModelException("Data Model Exception: Entity to resolved is other than leafref");
877 }
878 }
879
880 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530881 * Checks for the referred node defined in a ancestor scope.
882 *
883 * @param potentialReferredNode potential referred node
884 * @return status of resolution and updating the partial resolved stack with
885 * the any recursive references
janani be18b5342016-07-13 21:06:41 +0530886 * @throws DataModelException a violation of data model rules
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530887 */
888 private boolean isReferredNodeInSiblingListProcessed(YangNode potentialReferredNode)
889 throws DataModelException {
890 while (potentialReferredNode != null) {
891
892 // Check if the potential referred node is the actual referred node
893 if (isReferredNode(potentialReferredNode)) {
894
895 // Adds reference link of entity to the node under resolution.
896 addReferredEntityLink(potentialReferredNode, LINKED);
897
898 /**
899 * resolve the reference and update the partial resolution stack
900 * with any further recursive references
901 */
902 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
903
904 /*
905 * return true, since the reference is linked and any recursive
906 * unresolved references is added to the stack
907 */
908 return true;
909 }
910
911 potentialReferredNode = potentialReferredNode.getNextSibling();
912 }
913 return false;
914 }
915
916 /**
917 * Checks if the potential referred node is the actual referred node.
918 *
919 * @param potentialReferredNode typedef/grouping node
920 * @return true if node is of resolve type otherwise false
921 * @throws DataModelException a violation of data model rules
922 */
923 private boolean isReferredNode(YangNode potentialReferredNode)
924 throws DataModelException {
925 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
926 if (potentialReferredNode instanceof YangTypeDef) {
927 /*
928 * Check if name of node name matches with the entity being
929 * resolved
930 */
931 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
932 }
933 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
934 if (potentialReferredNode instanceof YangGrouping) {
935 /*
936 * Check if name of node name matches with the entity being
937 * resolved
938 */
939 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
940 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530941 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
942 if (potentialReferredNode instanceof YangFeatureHolder) {
943 /*
944 * Check if name of node name matches with the entity being
945 * resolved
946 */
947 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
948 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530949 } else {
950 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
951 }
952 return false;
953 }
954
955 /**
956 * Checks if node name is same as name in resolution info, i.e. name of
957 * typedef/grouping is same as name of type/uses.
958 *
959 * @param node typedef/grouping node
960 * @return true if node name is same as name in resolution info, otherwise
961 * false
962 * @throws DataModelException a violation of data model rules
963 */
964
965 private boolean isNodeNameSameAsResolutionInfoName(YangNode node)
966 throws DataModelException {
967 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
968 if (node.getName().contentEquals(
969 ((YangType<?>) getCurrentEntityToResolveFromStack())
970 .getDataTypeName())) {
971 return true;
972 }
973 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
974 if (node.getName().contentEquals(
975 ((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
976 return true;
977 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530978 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
979 return isFeatureDefinedInNode(node);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530980 } else {
981 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
982 }
983 return false;
984 }
985
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530986 private boolean isFeatureDefinedInNode(YangNode node) throws DataModelException {
987 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
988 List<YangFeature> featureList = ((YangFeatureHolder) node).getFeatureList();
989 if (featureList != null && !featureList.isEmpty()) {
990 Iterator<YangFeature> iterator = featureList.iterator();
991 while (iterator.hasNext()) {
992 YangFeature feature = iterator.next();
993 if (ifFeature.getName().equals(feature.getName())) {
994 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
995 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeatureHolder(node);
996 return true;
997 }
998 }
999 }
1000 return false;
1001 }
1002
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301003 /**
1004 * Adds reference of grouping/typedef in uses/type.
1005 *
1006 * @param referredNode grouping/typedef node being referred
1007 * @param linkedStatus linked status if success.
1008 * @throws DataModelException a violation of data model rules
1009 */
1010 private void addReferredEntityLink(YangNode referredNode, ResolvableStatus linkedStatus)
1011 throws DataModelException {
1012 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +05301013 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
1014 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301015 derivedInfo.setReferredTypeDef((YangTypeDef) referredNode);
1016 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1017 ((YangUses) getCurrentEntityToResolveFromStack())
1018 .setRefGroup((YangGrouping) referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301019 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1020 // do nothing , referred node is already set
janani be18b5342016-07-13 21:06:41 +05301021 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1022 // do nothing , referred node is already set
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301023 } else {
1024 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
1025 }
1026
1027 // Sets the resolution status in inside the type/uses.
1028 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(linkedStatus);
1029 }
1030
1031 /**
1032 * Checks if type/grouping has further reference to typedef/ unresolved
1033 * uses. Add it to the partial resolve stack and return the status of
1034 * addition to stack.
1035 *
1036 * @param referredNode grouping/typedef node
1037 * @throws DataModelException a violation of data model rules
1038 */
1039 private void addUnresolvedRecursiveReferenceToStack(YangNode referredNode)
1040 throws DataModelException {
1041 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1042 /*
1043 * Checks if typedef type is derived
1044 */
Bharat saraswal96dfef02016-06-16 00:29:12 +05301045 if (((YangTypeDef) referredNode).getTypeDefBaseType().getDataType() == YangDataTypes.DERIVED) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301046
Bharat saraswal96dfef02016-06-16 00:29:12 +05301047 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301048 unResolvedEntityInfo.setEntityToResolve(((YangTypeDef) referredNode)
1049 .getTypeDefBaseType());
1050 unResolvedEntityInfo.setHolderOfEntityToResolve(referredNode);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301051 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301052 }
1053
1054 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1055 /*
1056 * Search if the grouping has any un resolved uses child, if so
1057 * return true, else return false.
1058 */
1059 addUnResolvedUsesToStack(referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301060 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1061 addUnResolvedIfFeatureToStack(referredNode);
janani be18b5342016-07-13 21:06:41 +05301062 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1063 // do nothing , referred node is already set
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301064 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
1065 }
1066 }
1067
1068 /**
1069 * Returns if there is any unresolved uses in grouping.
1070 *
1071 * @param node grouping/typedef node
1072 */
1073 private void addUnResolvedUsesToStack(YangNode node) {
1074
1075 /**
1076 * Search the grouping node's children for presence of uses node.
1077 */
1078 YangNode curNode = node.getChild();
1079 while (curNode != null) {
1080 if (curNode instanceof YangUses) {
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301081 YangEntityToResolveInfoImpl<YangUses> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301082 unResolvedEntityInfo.setEntityToResolve((YangUses) curNode);
1083 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301084 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301085
1086 }
1087 curNode = curNode.getNextSibling();
1088 }
1089 }
1090
1091 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301092 * Returns if there is any unresolved if-feature in feature.
1093 *
1094 * @param node module/submodule node
1095 */
1096 private void addUnResolvedIfFeatureToStack(YangNode node) {
1097 YangFeature refFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeature();
1098 List<YangIfFeature> ifFeatureList = refFeature.getIfFeatureList();
1099 if (ifFeatureList != null && !ifFeatureList.isEmpty()) {
1100 Iterator<YangIfFeature> ifFeatureIterator = ifFeatureList.iterator();
1101 while (ifFeatureIterator.hasNext()) {
1102 YangIfFeature ifFeature = ifFeatureIterator.next();
1103 YangEntityToResolveInfo<YangIfFeature> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
1104 unResolvedEntityInfo.setEntityToResolve(ifFeature);
1105 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
1106 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
1107 }
1108 }
1109 }
1110
1111 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301112 * Returns stack of YANG type with partially resolved YANG construct
1113 * hierarchy.
1114 *
1115 * @return partial resolved YANG construct stack
1116 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301117 private Stack<YangEntityToResolveInfoImpl<T>> getPartialResolvedStack() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301118 return partialResolvedStack;
1119 }
1120
1121 /**
1122 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
1123 *
1124 * @param partialResolvedStack partial resolved YANG construct stack
1125 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301126 private void setPartialResolvedStack(Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301127 this.partialResolvedStack = partialResolvedStack;
1128 }
1129
1130 /**
1131 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
1132 *
1133 * @param partialResolvedInfo partial resolved YANG construct stack
1134 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301135 private void addInPartialResolvedStack(YangEntityToResolveInfoImpl<T> partialResolvedInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301136 getPartialResolvedStack().push(partialResolvedInfo);
1137 }
1138
1139 /**
1140 * Retrieves the next entity in the stack that needs to be resolved. It is
1141 * assumed that the caller ensures that the stack is not empty.
1142 *
1143 * @return next entity in the stack that needs to be resolved
1144 */
1145 private T getCurrentEntityToResolveFromStack() {
1146 return getPartialResolvedStack().peek().getEntityToResolve();
1147 }
1148
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301149 @Override
1150 public YangEntityToResolveInfoImpl<T> getEntityToResolveInfo() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301151 return entityToResolveInfo;
1152 }
1153
1154 /**
1155 * Sets information about the entity that needs to be resolved.
1156 *
1157 * @param entityToResolveInfo information about the entity that needs to be
1158 * resolved
1159 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301160 private void setEntityToResolveInfo(YangEntityToResolveInfoImpl<T> entityToResolveInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301161 this.entityToResolveInfo = entityToResolveInfo;
1162 }
1163
1164 @Override
1165 public int getLineNumber() {
1166 return lineNumber;
1167 }
1168
1169 @Override
1170 public int getCharPosition() {
1171 return charPosition;
1172 }
1173
1174 @Override
1175 public void setLineNumber(int lineNumber) {
1176 this.lineNumber = lineNumber;
1177 }
1178
1179 @Override
1180 public void setCharPosition(int charPositionInLine) {
1181 this.charPosition = charPositionInLine;
1182 }
1183
1184 /**
1185 * Returns current module/sub-module reference, will be used in inter-file/
1186 * inter-jar scenario to get the import/include list.
1187 *
1188 * @return current module/sub-module reference
1189 */
1190 private YangReferenceResolver getCurReferenceResolver() {
1191 return curReferenceResolver;
1192 }
1193
1194 /**
1195 * Sets current module/sub-module reference, will be used in inter-file/
1196 * inter-jar scenario to get the import/include list.
1197 *
1198 * @param curReferenceResolver current module/sub-module reference
1199 */
1200 private void setCurReferenceResolver(YangReferenceResolver curReferenceResolver) {
1201 this.curReferenceResolver = curReferenceResolver;
1202 }
1203
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301204 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301205 public void linkInterFile(YangReferenceResolver dataModelRootNode)
1206 throws DataModelException {
1207
1208 setCurReferenceResolver(dataModelRootNode);
1209
1210 // Current node to resolve, it can be a YANG type or YANG uses.
1211 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
1212
1213 // Check if linking is already done
1214 if (entityToResolve instanceof Resolvable) {
1215 Resolvable resolvable = (Resolvable) entityToResolve;
1216 if (resolvable.getResolvableStatus() == RESOLVED) {
1217 return;
1218 }
1219 } else {
1220 throw new DataModelException("Data Model Exception: Entity to resolved is not Resolvable");
1221 }
1222
1223 // Push the initial entity to resolve in stack.
1224 addInPartialResolvedStack(getEntityToResolveInfo());
1225
1226 // Inter file linking and resolution.
1227 linkInterFileAndResolve();
janani be18b5342016-07-13 21:06:41 +05301228
1229 // Resolve the derived types having leafref.
1230 addDerivedRefTypeToRefTypeResolutionList();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301231 }
1232
1233 /**
1234 * Returns the referenced prefix of entity under resolution.
1235 *
1236 * @return referenced prefix of entity under resolution
1237 * @throws DataModelException a violation in data model rule
1238 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301239 private String getRefPrefix()
1240 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301241 String refPrefix;
1242 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1243 refPrefix = ((YangType<?>) getCurrentEntityToResolveFromStack()).getPrefix();
1244 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1245 refPrefix = ((YangUses) getCurrentEntityToResolveFromStack()).getPrefix();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301246 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1247 refPrefix = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getPrefix();
janani be18b5342016-07-13 21:06:41 +05301248 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1249 refPrefix = refPrefixForLeafRef();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301250 } else {
1251 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
1252 }
1253 return refPrefix;
1254 }
1255
1256 /**
janani be18b5342016-07-13 21:06:41 +05301257 * Returns the referenced prefix for leafref under resolution.
1258 *
1259 * @return referenced prefix of leafref under resolution
1260 */
1261 private String refPrefixForLeafRef() {
1262
1263 String refPrefix;
1264 if (((YangLeafRef) getCurrentEntityToResolveFromStack()).getPathType() == YangPathArgType.ABSOLUTE_PATH) {
1265 List<YangAtomicPath> theList = ((YangLeafRef) getCurrentEntityToResolveFromStack()).getAtomicPath();
1266 YangAtomicPath absPath = theList.iterator().next();
1267 refPrefix = absPath.getNodeIdentifier().getPrefix();
1268 } else {
1269 YangRelativePath relativePath = ((YangLeafRef) getCurrentEntityToResolveFromStack()).getRelativePath();
1270 List<YangAtomicPath> theList = relativePath.getAtomicPathList();
1271 YangAtomicPath absPath = theList.iterator().next();
1272 refPrefix = absPath.getNodeIdentifier().getPrefix();
1273 }
1274 return refPrefix;
1275 }
1276
1277 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301278 * Performs inter file linking and resolution.
1279 *
1280 * @throws DataModelException a violation in data model rule
1281 */
1282 private void linkInterFileAndResolve()
1283 throws DataModelException {
1284
1285 while (getPartialResolvedStack().size() != 0) {
1286
1287 // Current node to resolve, it can be a YANG type or YANG uses.
1288 T entityToResolve = getCurrentEntityToResolveFromStack();
1289 // Check if linking is already done
1290 if (entityToResolve instanceof Resolvable) {
1291
1292 Resolvable resolvable = (Resolvable) entityToResolve;
1293 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301294 case RESOLVED: {
1295 /*
1296 * If the entity is already resolved in the stack, then pop
1297 * it and continue with the remaining stack elements to
1298 * resolve
1299 */
1300 getPartialResolvedStack().pop();
1301 break;
1302 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301303
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301304 case INTER_FILE_LINKED: {
1305 /*
1306 * If the top of the stack is already linked then resolve
1307 * the references and pop the entity and continue with
1308 * remaining stack elements to resolve
1309 */
1310 resolveTopOfStack(INTER_FILE);
1311 getPartialResolvedStack().pop();
1312 break;
1313 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301314
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301315 case INTRA_FILE_RESOLVED: {
1316 /*
1317 * If the top of the stack is intra file resolved then check
1318 * if top of stack is linked, if not link it using
1319 * import/include list and push the linked referred entity
1320 * to the stack, otherwise only push it to the stack.
1321 */
1322 linkInterFileTopOfStackRefUpdateStack();
1323 break;
1324 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301325
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301326 case UNDEFINED: {
1327 /*
1328 * In case of if-feature resolution, if referred "feature" is not
1329 * defined then the resolvable status will be undefined.
1330 */
1331 getPartialResolvedStack().pop();
1332 break;
1333 }
1334
1335 default: {
1336 throw new DataModelException("Data Model Exception: Unsupported, linker state");
1337 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301338
1339 }
1340
1341 } else {
1342 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
1343 }
1344
1345 }
1346
1347 }
1348
1349 /**
1350 * Links the top of the stack if it's inter-file and update stack.
1351 *
1352 * @throws DataModelException data model error
1353 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301354 private void linkInterFileTopOfStackRefUpdateStack()
1355 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301356
1357 /*
1358 * Obtain the referred node of top of stack entity under resolution
1359 */
1360 T referredNode = getRefNode();
1361
1362 /*
1363 * Check for null for scenario when it's not linked and inter-file
1364 * linking is required.
1365 */
1366 if (referredNode == null) {
1367
1368 /*
Bharat saraswal96dfef02016-06-16 00:29:12 +05301369 * Check if prefix is null or not, to identify whether to search in
1370 * import list or include list.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301371 */
Bharat saraswalcad0e652016-05-26 23:48:38 +05301372 if (getRefPrefix() != null && !getRefPrefix().contentEquals(getCurReferenceResolver().getPrefix())) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301373 if (resolveWithImport()) {
1374 return;
1375 }
1376 } else {
1377 if (resolveWithInclude()) {
1378 return;
1379 }
1380 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301381
1382 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1383 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setResolvableStatus(UNDEFINED);
1384 return;
1385 }
janani be18b5342016-07-13 21:06:41 +05301386 // If current entity is still not resolved, then
1387 // linking/resolution has failed.
1388 String errorInfo;
1389 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1390 errorInfo = TYPEDEF_LINKER_ERROR;
1391 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1392 errorInfo = GROUPING_LINKER_ERROR;
1393 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1394 errorInfo = FEATURE_LINKER_ERROR;
1395 } else {
1396 errorInfo = LEAFREF_LINKER_ERROR;
1397 }
1398 DataModelException dataModelException = new DataModelException(errorInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301399 dataModelException.setLine(getLineNumber());
1400 dataModelException.setCharPosition(getCharPosition());
1401 throw dataModelException;
1402 } else {
1403 /*
1404 * If referred node is already linked, then just change the status
1405 * and push to the stack.
1406 */
janani be18b5342016-07-13 21:06:41 +05301407 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1408 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
1409 if (referredNode instanceof YangLeaf) {
1410 YangLeaf yangleaf = (YangLeaf) referredNode;
1411 addUnResolvedLeafRefTypeToStack((T) yangleaf, (YangNode) yangleaf.getContainedIn());
1412 } else if (referredNode instanceof YangLeafList) {
1413 YangLeafList yangLeafList = (YangLeafList) referredNode;
1414 addUnResolvedLeafRefTypeToStack((T) yangLeafList, (YangNode) yangLeafList.getContainedIn());
1415 }
1416 } else {
1417 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
1418 addUnresolvedRecursiveReferenceToStack((YangNode) referredNode);
1419 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301420 }
1421 }
1422
1423 /**
1424 * Finds and resolves with include list.
1425 *
1426 * @return true if resolved, false otherwise
1427 * @throws DataModelException a violation in data model rule
1428 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301429 private boolean resolveWithInclude()
1430 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301431 /*
1432 * Run through all the nodes in include list and search for referred
1433 * typedef/grouping at the root level.
1434 */
1435 for (YangInclude yangInclude : getCurReferenceResolver().getIncludeList()) {
1436 YangNode linkedNode = null;
1437 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1438 linkedNode = findRefTypedef(yangInclude.getIncludedNode());
1439 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1440 linkedNode = findRefGrouping(yangInclude.getIncludedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301441 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1442 linkedNode = findRefFeature(yangInclude.getIncludedNode());
janani be18b5342016-07-13 21:06:41 +05301443 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1444 boolean referredNode = findRefLeaf(yangInclude.getIncludedNode());
1445 /*
1446 * Update the current reference resolver to external
1447 * module/sub-module containing the referred typedef/grouping.
1448 */
1449 setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());
1450
1451 return referredNode;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301452 }
1453 if (linkedNode != null) {
1454 // Add the link to external entity.
1455 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
1456 /*
1457 * Update the current reference resolver to external
1458 * module/sub-module containing the referred typedef/grouping.
1459 */
1460 setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());
1461 // Add the type/uses of referred typedef/grouping to the stack.
1462 addUnresolvedRecursiveReferenceToStack(linkedNode);
1463 return true;
1464 }
1465 }
1466 // If referred node can't be found return false.
1467 return false;
1468 }
1469
1470 /**
1471 * Finds and resolves with import list.
1472 *
1473 * @return true if resolved, false otherwise
1474 * @throws DataModelException a violation in data model rule
1475 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301476 private boolean resolveWithImport()
1477 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301478 /*
1479 * Run through import list to find the referred typedef/grouping.
1480 */
1481 for (YangImport yangImport : getCurReferenceResolver().getImportList()) {
1482 /*
1483 * Match the prefix attached to entity under resolution with the
1484 * imported/included module/sub-module's prefix. If found, search
1485 * for the referred typedef/grouping at the root level.
1486 */
1487 if (yangImport.getPrefixId().contentEquals(getRefPrefix())) {
1488 YangNode linkedNode = null;
1489 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1490 linkedNode = findRefTypedef(yangImport.getImportedNode());
1491 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1492 linkedNode = findRefGrouping(yangImport.getImportedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301493 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1494 linkedNode = findRefFeature(yangImport.getImportedNode());
janani be18b5342016-07-13 21:06:41 +05301495 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1496 boolean referredNode = findRefLeaf(yangImport.getImportedNode());
1497 /*
1498 * Update the current reference resolver to external
1499 * module/sub-module containing the referred
1500 * typedef/grouping.
1501 */
1502 setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());
1503
1504 return referredNode;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301505 }
1506 if (linkedNode != null) {
1507 // Add the link to external entity.
1508 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
1509 /*
1510 * Update the current reference resolver to external
Bharat saraswal96dfef02016-06-16 00:29:12 +05301511 * module/sub-module containing the referred
1512 * typedef/grouping.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301513 */
1514 setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());
Bharat saraswal96dfef02016-06-16 00:29:12 +05301515 // Add the type/uses of referred typedef/grouping to the
1516 // stack.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301517 addUnresolvedRecursiveReferenceToStack(linkedNode);
1518 return true;
1519 }
1520 /*
1521 * If referred node can't be found at root level break for loop,
1522 * and return false.
1523 */
1524 break;
1525 }
1526 }
1527 // If referred node can't be found return false.
1528 return false;
1529 }
1530
1531 /**
janani be18b5342016-07-13 21:06:41 +05301532 * Returns the status of referred leaf.
1533 *
1534 * @param importedNode the root node from a YANG file
1535 * @return status of the referred leaf
1536 * @throws DataModelException
1537 */
1538 private boolean findRefLeaf(YangNode importedNode) throws DataModelException {
1539
1540 boolean isReferredNodeFound = false;
1541 List<YangAtomicPath> absolutePathList = ((YangLeafRef) getCurrentEntityToResolveFromStack())
1542 .getAtomicPath();
1543 if (absolutePathList != null && !absolutePathList.isEmpty()) {
1544 Iterator<YangAtomicPath> listOfYangAtomicPath = absolutePathList.listIterator();
1545
1546 while (listOfYangAtomicPath.hasNext()) {
1547 YangAtomicPath absolutePath = listOfYangAtomicPath.next();
1548 String nodeName = absolutePath.getNodeIdentifier().getName();
1549
1550 if (importedNode.getChild() == null) {
1551 isReferredNodeFound = isReferredLeafOrLeafListFound(importedNode, nodeName, (T) INTER_FILE_LINKED);
1552 break;
1553 }
1554 importedNode = importedNode.getChild();
1555
1556 YangNode nodeFound = isReferredNodeInSiblingProcessedForLeafref(importedNode, nodeName);
1557 if (nodeFound == null) {
1558 isReferredNodeFound = isReferredLeafOrLeafListFound(importedNode.getParent(), nodeName,
1559 (T) INTER_FILE_LINKED);
1560 } else {
1561 importedNode = nodeFound;
1562 }
1563 }
1564 }
1565 // TODO: Path predicates filling for inter file has to be done.
1566 return isReferredNodeFound;
1567 }
1568
1569 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301570 * Returns referred typedef/grouping node.
1571 *
1572 * @return referred typedef/grouping node
1573 * @throws DataModelException a violation in data model rule
1574 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301575 private T getRefNode()
1576 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301577 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +05301578 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
1579 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301580 return (T) derivedInfo.getReferredTypeDef();
1581 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1582 return (T) ((YangUses) getCurrentEntityToResolveFromStack()).getRefGroup();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301583 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1584 return (T) ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeatureHolder();
janani be18b5342016-07-13 21:06:41 +05301585 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1586 return (T) ((YangLeafRef) getCurrentEntityToResolveFromStack()).getReferredLeafOrLeafList();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301587 } else {
1588 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
1589 }
1590 }
1591
1592 /**
1593 * Finds the referred grouping node at the root level of imported/included node.
1594 *
1595 * @param refNode module/sub-module node
1596 * @return referred grouping
1597 */
1598 private YangNode findRefGrouping(YangNode refNode) {
1599 YangNode tmpNode = refNode.getChild();
1600 while (tmpNode != null) {
1601 if (tmpNode instanceof YangGrouping) {
1602 if (tmpNode.getName()
1603 .equals(((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
1604 return tmpNode;
1605 }
1606 }
1607 tmpNode = tmpNode.getNextSibling();
1608 }
1609 return null;
1610 }
1611
1612 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301613 * Finds the referred feature node at the root level of imported/included node.
1614 *
1615 * @param refNode module/sub-module node
1616 * @return referred feature
1617 */
1618 private YangNode findRefFeature(YangNode refNode) {
1619 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
1620 List<YangFeature> featureList = ((YangFeatureHolder) refNode).getFeatureList();
1621
1622 if (featureList != null && !featureList.isEmpty()) {
1623 Iterator<YangFeature> iterator = featureList.iterator();
1624 while (iterator.hasNext()) {
1625 YangFeature feature = iterator.next();
1626 if (ifFeature.getName().equals(feature.getName())) {
1627 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
1628 return refNode;
1629 }
1630 }
1631 }
1632 return null;
1633 }
1634
1635 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301636 * Finds the referred typedef node at the root level of imported/included node.
1637 *
1638 * @param refNode module/sub-module node
1639 * @return referred typedef
1640 */
1641 private YangNode findRefTypedef(YangNode refNode) {
1642 YangNode tmpNode = refNode.getChild();
1643 while (tmpNode != null) {
1644 if (tmpNode instanceof YangTypeDef) {
1645 if (tmpNode.getName()
1646 .equals(((YangType) getCurrentEntityToResolveFromStack()).getDataTypeName())) {
1647 return tmpNode;
1648 }
1649 }
1650 tmpNode = tmpNode.getNextSibling();
1651 }
1652 return null;
1653 }
1654}