blob: d83844005335af2684607ad06b16c0c4bf685542 [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
19import java.util.Stack;
20import org.onosproject.yangutils.datamodel.LocationInfo;
21import org.onosproject.yangutils.datamodel.YangDataTypes;
22import org.onosproject.yangutils.datamodel.YangDerivedInfo;
23import org.onosproject.yangutils.datamodel.YangGrouping;
24import org.onosproject.yangutils.datamodel.YangImport;
25import org.onosproject.yangutils.datamodel.YangInclude;
26import org.onosproject.yangutils.datamodel.YangNode;
27import org.onosproject.yangutils.datamodel.YangType;
28import org.onosproject.yangutils.datamodel.YangTypeDef;
29import org.onosproject.yangutils.datamodel.YangUses;
30import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
31
32import static org.onosproject.yangutils.linker.impl.ResolvableStatus.INTER_FILE_LINKED;
33import static org.onosproject.yangutils.linker.impl.ResolvableStatus.INTRA_FILE_RESOLVED;
34import static org.onosproject.yangutils.linker.impl.ResolvableStatus.LINKED;
35import static org.onosproject.yangutils.linker.impl.ResolvableStatus.RESOLVED;
36import static org.onosproject.yangutils.linker.impl.ResolvableStatus.UNRESOLVED;
37
38/**
39 * Represents resolution object which will be resolved by linker.
40 *
41 * @param <T> type of resolution entity uses / type
42 */
43public class YangResolutionInfo<T> implements LocationInfo {
44
45 /**
46 * Information about the entity that needs to be resolved.
47 */
48 private YangEntityToResolveInfo<T> entityToResolveInfo;
49
50 /**
51 * Error line number.
52 */
53 private int lineNumber;
54
55 /**
56 * Error character position in number.
57 */
58 private int charPosition;
59
60 /**
61 * Current module/sub-module reference, will be used in inter-file/
62 * inter-jar scenario to get the import/include list.
63 */
64 private YangReferenceResolver curReferenceResolver;
65
66 /**
67 * Stack for type/uses is maintained for hierarchical references, this is
68 * used during resolution.
69 */
70 private Stack<YangEntityToResolveInfo<T>> partialResolvedStack;
71
72 /**
73 * It is private to ensure the overloaded method be invoked to create an
74 * object.
75 */
76 @SuppressWarnings("unused")
77 private YangResolutionInfo() {
78
79 }
80
81 /**
82 * Creates a resolution information object with all the inputs.
83 *
84 * @param dataNode current parsable data node
85 * @param holderNode parent YANG node
86 * @param lineNumber error line number
87 * @param charPositionInLine error character position in line
88 */
89 public YangResolutionInfo(T dataNode, YangNode holderNode, int lineNumber, int charPositionInLine) {
90 setEntityToResolveInfo(new YangEntityToResolveInfo<>());
91 getEntityToResolveInfo().setEntityToResolve(dataNode);
92 getEntityToResolveInfo().setHolderOfEntityToResolve(holderNode);
93 this.setLineNumber(lineNumber);
94 this.setCharPosition(charPositionInLine);
95 setPartialResolvedStack(new Stack<>());
96 }
97
98 /**
99 * Resolves linking with all the ancestors node for a resolution info.
100 *
101 * @param dataModelRootNode module/sub-module node
102 * @throws DataModelException DataModelException a violation of data model
103 * rules
104 */
105 public void resolveLinkingForResolutionInfo(YangReferenceResolver dataModelRootNode)
106 throws DataModelException {
107
108 setCurReferenceResolver(dataModelRootNode);
109
110 // Current node to resolve, it can be a YANG type or YANG uses.
111 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
112
113 // Check if linking is already done
114 if (entityToResolve instanceof Resolvable) {
115 Resolvable resolvable = (Resolvable) entityToResolve;
116 if (resolvable.getResolvableStatus() == RESOLVED) {
117 /**
118 * entity is already resolved, so nothing to do
119 */
120 return;
121 }
122 } else {
123 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
124 }
125
126 // Push the initial entity to resolve in stack.
127 addInPartialResolvedStack(getEntityToResolveInfo());
128
129 linkAndResolvePartialResolvedStack();
130 }
131
132 /**
133 * Resolves linking with ancestors.
134 *
135 * @throws DataModelException a violation of data model rules
136 */
137 private void linkAndResolvePartialResolvedStack()
138 throws DataModelException {
139
140 while (getPartialResolvedStack().size() != 0) {
141
142 // Current node to resolve, it can be a YANG type or YANG uses.
143 T entityToResolve = getCurrentEntityToResolveFromStack();
144 // Check if linking is already done
145 if (entityToResolve instanceof Resolvable) {
146
147 Resolvable resolvable = (Resolvable) entityToResolve;
148 switch (resolvable.getResolvableStatus()) {
149 case RESOLVED: {
150 /*
151 * If the entity is already resolved in the stack, then
152 * pop it and continue with the remaining stack elements
153 * to resolve
154 */
155 getPartialResolvedStack().pop();
156 break;
157 }
158
159 case LINKED: {
160 /*
161 * If the top of the stack is already linked then
162 * resolve the references and pop the entity and
163 * continue with remaining stack elements to resolve.
164 */
165 resolveTopOfStack();
166 getPartialResolvedStack().pop();
167 break;
168 }
169
170 case INTRA_FILE_RESOLVED: {
171 /*
172 * Pop the top of the stack.
173 */
174 getPartialResolvedStack().pop();
175 break;
176 }
177
178 case UNRESOLVED: {
179 linkTopOfStackReferenceUpdateStack();
180
181 if (resolvable.getResolvableStatus() == UNRESOLVED) {
182 // If current entity is still not resolved, then linking/resolution has failed.
183 DataModelException dataModelException =
184 new DataModelException("YANG file error: Unable to find base "
185 + "typedef/grouping for given type/uses");
186 dataModelException.setLine(getLineNumber());
187 dataModelException.setCharPosition(getCharPosition());
188 throw dataModelException;
189 }
190 break;
191 }
192 default: {
193 throw new DataModelException("Data Model Exception: Unsupported, linker state");
194 }
195
196 }
197
198 } else {
199 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
200 }
201
202 }
203
204 }
205
206 /**
207 * Resolves the current entity in the stack.
208 */
209 private void resolveTopOfStack()
210 throws DataModelException {
211 ((Resolvable) getCurrentEntityToResolveFromStack()).resolve();
212 if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus()
213 != INTRA_FILE_RESOLVED) {
214 // Sets the resolution status in inside the type/uses.
215 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(RESOLVED);
216 }
217 }
218
219 /**
220 * Resolves linking for a node child and siblings.
221 *
222 * @throws DataModelException data model error
223 */
224 private void linkTopOfStackReferenceUpdateStack()
225 throws DataModelException {
226
227 /*
228 * Check if self file reference is there, this will not check for the
229 * scenario when prefix is not present and type/uses is present in
230 * sub-module from include list.
231 */
232 if (!isCandidateForSelfFileReference()) {
233 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
234 return;
235 }
236
237 /**
238 * Try to resolve the top of the stack and update partial resolved stack
239 * if there is recursive references
240 */
241 YangNode potentialAncestorWithReferredNode = getPartialResolvedStack().peek()
242 .getHolderOfEntityToResolve();
243
244 /**
245 * Traverse up in the ancestor tree to check if the referred node is
246 * defined
247 */
248 while (potentialAncestorWithReferredNode != null) {
249
250 /**
251 * Check for the referred node defined in a ancestor scope
252 */
253 YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
254 if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
255 return;
256 }
257
258 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
259 }
260
261 /*
262 * In case prefix is not present it's a candidate for inter-file
263 * resolution via include list.
264 */
265 if (getRefPrefix() == null) {
266 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
267 }
268 }
269
270 /**
271 * Checks if the reference in self file or in external file.
272 *
273 * @return true if self file reference, false otherwise
274 * @throws DataModelException a violation of data model rules
275 */
276 private boolean isCandidateForSelfFileReference() throws DataModelException {
277 String prefix = getRefPrefix();
278 return prefix == null || prefix.contentEquals(getCurReferenceResolver().getPrefix());
279 }
280
281 /**
282 * Checks for the referred node defined in a ancestor scope.
283 *
284 * @param potentialReferredNode potential referred node
285 * @return status of resolution and updating the partial resolved stack with
286 * the any recursive references
287 * @throws DataModelException data model errors
288 */
289 private boolean isReferredNodeInSiblingListProcessed(YangNode potentialReferredNode)
290 throws DataModelException {
291 while (potentialReferredNode != null) {
292
293 // Check if the potential referred node is the actual referred node
294 if (isReferredNode(potentialReferredNode)) {
295
296 // Adds reference link of entity to the node under resolution.
297 addReferredEntityLink(potentialReferredNode, LINKED);
298
299 /**
300 * resolve the reference and update the partial resolution stack
301 * with any further recursive references
302 */
303 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
304
305 /*
306 * return true, since the reference is linked and any recursive
307 * unresolved references is added to the stack
308 */
309 return true;
310 }
311
312 potentialReferredNode = potentialReferredNode.getNextSibling();
313 }
314 return false;
315 }
316
317 /**
318 * Checks if the potential referred node is the actual referred node.
319 *
320 * @param potentialReferredNode typedef/grouping node
321 * @return true if node is of resolve type otherwise false
322 * @throws DataModelException a violation of data model rules
323 */
324 private boolean isReferredNode(YangNode potentialReferredNode)
325 throws DataModelException {
326 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
327 if (potentialReferredNode instanceof YangTypeDef) {
328 /*
329 * Check if name of node name matches with the entity being
330 * resolved
331 */
332 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
333 }
334 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
335 if (potentialReferredNode instanceof YangGrouping) {
336 /*
337 * Check if name of node name matches with the entity being
338 * resolved
339 */
340 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
341 }
342 } else {
343 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
344 }
345 return false;
346 }
347
348 /**
349 * Checks if node name is same as name in resolution info, i.e. name of
350 * typedef/grouping is same as name of type/uses.
351 *
352 * @param node typedef/grouping node
353 * @return true if node name is same as name in resolution info, otherwise
354 * false
355 * @throws DataModelException a violation of data model rules
356 */
357
358 private boolean isNodeNameSameAsResolutionInfoName(YangNode node)
359 throws DataModelException {
360 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
361 if (node.getName().contentEquals(
362 ((YangType<?>) getCurrentEntityToResolveFromStack())
363 .getDataTypeName())) {
364 return true;
365 }
366 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
367 if (node.getName().contentEquals(
368 ((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
369 return true;
370 }
371 } else {
372 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
373 }
374 return false;
375 }
376
377 /**
378 * Adds reference of grouping/typedef in uses/type.
379 *
380 * @param referredNode grouping/typedef node being referred
381 * @param linkedStatus linked status if success.
382 * @throws DataModelException a violation of data model rules
383 */
384 private void addReferredEntityLink(YangNode referredNode, ResolvableStatus linkedStatus)
385 throws DataModelException {
386 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
387 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>)
388 ((YangType<?>) getCurrentEntityToResolveFromStack()).getDataTypeExtendedInfo();
389 derivedInfo.setReferredTypeDef((YangTypeDef) referredNode);
390 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
391 ((YangUses) getCurrentEntityToResolveFromStack())
392 .setRefGroup((YangGrouping) referredNode);
393 } else {
394 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
395 }
396
397 // Sets the resolution status in inside the type/uses.
398 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(linkedStatus);
399 }
400
401 /**
402 * Checks if type/grouping has further reference to typedef/ unresolved
403 * uses. Add it to the partial resolve stack and return the status of
404 * addition to stack.
405 *
406 * @param referredNode grouping/typedef node
407 * @throws DataModelException a violation of data model rules
408 */
409 private void addUnresolvedRecursiveReferenceToStack(YangNode referredNode)
410 throws DataModelException {
411 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
412 /*
413 * Checks if typedef type is derived
414 */
415 if (((YangTypeDef) referredNode).getTypeDefBaseType().getDataType()
416 == YangDataTypes.DERIVED) {
417
418 YangEntityToResolveInfo<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfo<>();
419 unResolvedEntityInfo.setEntityToResolve(((YangTypeDef) referredNode)
420 .getTypeDefBaseType());
421 unResolvedEntityInfo.setHolderOfEntityToResolve(referredNode);
422 addInPartialResolvedStack((YangEntityToResolveInfo<T>) unResolvedEntityInfo);
423 }
424
425 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
426 /*
427 * Search if the grouping has any un resolved uses child, if so
428 * return true, else return false.
429 */
430 addUnResolvedUsesToStack(referredNode);
431 } else {
432 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
433 }
434 }
435
436 /**
437 * Returns if there is any unresolved uses in grouping.
438 *
439 * @param node grouping/typedef node
440 */
441 private void addUnResolvedUsesToStack(YangNode node) {
442
443 /**
444 * Search the grouping node's children for presence of uses node.
445 */
446 YangNode curNode = node.getChild();
447 while (curNode != null) {
448 if (curNode instanceof YangUses) {
449 YangEntityToResolveInfo<YangUses> unResolvedEntityInfo = new YangEntityToResolveInfo<>();
450 unResolvedEntityInfo.setEntityToResolve((YangUses) curNode);
451 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
452 addInPartialResolvedStack((YangEntityToResolveInfo<T>) unResolvedEntityInfo);
453
454 }
455 curNode = curNode.getNextSibling();
456 }
457 }
458
459 /**
460 * Returns stack of YANG type with partially resolved YANG construct
461 * hierarchy.
462 *
463 * @return partial resolved YANG construct stack
464 */
465 private Stack<YangEntityToResolveInfo<T>> getPartialResolvedStack() {
466 return partialResolvedStack;
467 }
468
469 /**
470 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
471 *
472 * @param partialResolvedStack partial resolved YANG construct stack
473 */
474 private void setPartialResolvedStack(Stack<YangEntityToResolveInfo<T>> partialResolvedStack) {
475 this.partialResolvedStack = partialResolvedStack;
476 }
477
478 /**
479 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
480 *
481 * @param partialResolvedInfo partial resolved YANG construct stack
482 */
483 private void addInPartialResolvedStack(YangEntityToResolveInfo<T> partialResolvedInfo) {
484 getPartialResolvedStack().push(partialResolvedInfo);
485 }
486
487 /**
488 * Retrieves the next entity in the stack that needs to be resolved. It is
489 * assumed that the caller ensures that the stack is not empty.
490 *
491 * @return next entity in the stack that needs to be resolved
492 */
493 private T getCurrentEntityToResolveFromStack() {
494 return getPartialResolvedStack().peek().getEntityToResolve();
495 }
496
497 /**
498 * Retrieves information about the entity that needs to be resolved.
499 *
500 * @return information about the entity that needs to be resolved
501 */
502 public YangEntityToResolveInfo<T> getEntityToResolveInfo() {
503 return entityToResolveInfo;
504 }
505
506 /**
507 * Sets information about the entity that needs to be resolved.
508 *
509 * @param entityToResolveInfo information about the entity that needs to be
510 * resolved
511 */
512 private void setEntityToResolveInfo(YangEntityToResolveInfo<T> entityToResolveInfo) {
513 this.entityToResolveInfo = entityToResolveInfo;
514 }
515
516 @Override
517 public int getLineNumber() {
518 return lineNumber;
519 }
520
521 @Override
522 public int getCharPosition() {
523 return charPosition;
524 }
525
526 @Override
527 public void setLineNumber(int lineNumber) {
528 this.lineNumber = lineNumber;
529 }
530
531 @Override
532 public void setCharPosition(int charPositionInLine) {
533 this.charPosition = charPositionInLine;
534 }
535
536 /**
537 * Returns current module/sub-module reference, will be used in inter-file/
538 * inter-jar scenario to get the import/include list.
539 *
540 * @return current module/sub-module reference
541 */
542 private YangReferenceResolver getCurReferenceResolver() {
543 return curReferenceResolver;
544 }
545
546 /**
547 * Sets current module/sub-module reference, will be used in inter-file/
548 * inter-jar scenario to get the import/include list.
549 *
550 * @param curReferenceResolver current module/sub-module reference
551 */
552 private void setCurReferenceResolver(YangReferenceResolver curReferenceResolver) {
553 this.curReferenceResolver = curReferenceResolver;
554 }
555
556 /**
557 * Performs inter file linking of uses/type referring to typedef/grouping
558 * of other YANG file.
559 *
560 * @param dataModelRootNode module/sub-module node
561 * @throws DataModelException a violation in data model rule
562 */
563 public void linkInterFile(YangReferenceResolver dataModelRootNode)
564 throws DataModelException {
565
566 setCurReferenceResolver(dataModelRootNode);
567
568 // Current node to resolve, it can be a YANG type or YANG uses.
569 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
570
571 // Check if linking is already done
572 if (entityToResolve instanceof Resolvable) {
573 Resolvable resolvable = (Resolvable) entityToResolve;
574 if (resolvable.getResolvableStatus() == RESOLVED) {
575 return;
576 }
577 } else {
578 throw new DataModelException("Data Model Exception: Entity to resolved is not Resolvable");
579 }
580
581 // Push the initial entity to resolve in stack.
582 addInPartialResolvedStack(getEntityToResolveInfo());
583
584 // Inter file linking and resolution.
585 linkInterFileAndResolve();
586 }
587
588 /**
589 * Returns the referenced prefix of entity under resolution.
590 *
591 * @return referenced prefix of entity under resolution
592 * @throws DataModelException a violation in data model rule
593 */
594 private String getRefPrefix() throws DataModelException {
595 String refPrefix;
596 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
597 refPrefix = ((YangType<?>) getCurrentEntityToResolveFromStack()).getPrefix();
598 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
599 refPrefix = ((YangUses) getCurrentEntityToResolveFromStack()).getPrefix();
600 } else {
601 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
602 }
603 return refPrefix;
604 }
605
606 /**
607 * Performs inter file linking and resolution.
608 *
609 * @throws DataModelException a violation in data model rule
610 */
611 private void linkInterFileAndResolve()
612 throws DataModelException {
613
614 while (getPartialResolvedStack().size() != 0) {
615
616 // Current node to resolve, it can be a YANG type or YANG uses.
617 T entityToResolve = getCurrentEntityToResolveFromStack();
618 // Check if linking is already done
619 if (entityToResolve instanceof Resolvable) {
620
621 Resolvable resolvable = (Resolvable) entityToResolve;
622 switch (resolvable.getResolvableStatus()) {
623 case RESOLVED: {
624 /*
625 * If the entity is already resolved in the stack, then
626 * pop it and continue with the remaining stack elements
627 * to resolve
628 */
629 getPartialResolvedStack().pop();
630 break;
631 }
632
633 case INTER_FILE_LINKED: {
634 /*
635 * If the top of the stack is already linked then
636 * resolve the references and pop the entity and
637 * continue with remaining stack elements to resolve
638 */
639 resolveTopOfStack();
640 getPartialResolvedStack().pop();
641 break;
642 }
643
644 case INTRA_FILE_RESOLVED: {
645 /*
646 * If the top of the stack is intra file resolved
647 * then check if top of stack is linked, if not
648 * link it using import/include list and push the
649 * linked referred entity to the stack, otherwise
650 * only push it to the stack.
651 */
652 linkInterFileTopOfStackRefUpdateStack();
653 break;
654 }
655
656 default: {
657 throw new DataModelException("Data Model Exception: Unsupported, linker state");
658 }
659
660 }
661
662 } else {
663 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
664 }
665
666 }
667
668 }
669
670 /**
671 * Links the top of the stack if it's inter-file and update stack.
672 *
673 * @throws DataModelException data model error
674 */
675 private void linkInterFileTopOfStackRefUpdateStack() throws DataModelException {
676
677 /*
678 * Obtain the referred node of top of stack entity under resolution
679 */
680 T referredNode = getRefNode();
681
682 /*
683 * Check for null for scenario when it's not linked and inter-file
684 * linking is required.
685 */
686 if (referredNode == null) {
687
688 /*
689 * Check if prefix is null or not, to identify whether to search
690 * in import list or include list.
691 */
692 if (getRefPrefix() != null && !(getRefPrefix().contentEquals(getCurReferenceResolver().getPrefix()))) {
693 if (resolveWithImport()) {
694 return;
695 }
696 } else {
697 if (resolveWithInclude()) {
698 return;
699 }
700 }
701 // Exception when referred typedef/grouping is not found.
702 DataModelException dataModelException = new DataModelException("YANG file error: Referred " +
703 "typedef/grouping for a given type/uses can't be found.");
704 dataModelException.setLine(getLineNumber());
705 dataModelException.setCharPosition(getCharPosition());
706 throw dataModelException;
707 } else {
708 /*
709 * If referred node is already linked, then just change the status
710 * and push to the stack.
711 */
712 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
713 addUnresolvedRecursiveReferenceToStack((YangNode) referredNode);
714 }
715 }
716
717 /**
718 * Finds and resolves with include list.
719 *
720 * @return true if resolved, false otherwise
721 * @throws DataModelException a violation in data model rule
722 */
723 private boolean resolveWithInclude() throws DataModelException {
724 /*
725 * Run through all the nodes in include list and search for referred
726 * typedef/grouping at the root level.
727 */
728 for (YangInclude yangInclude : getCurReferenceResolver().getIncludeList()) {
729 YangNode linkedNode = null;
730 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
731 linkedNode = findRefTypedef(yangInclude.getIncludedNode());
732 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
733 linkedNode = findRefGrouping(yangInclude.getIncludedNode());
734 }
735 if (linkedNode != null) {
736 // Add the link to external entity.
737 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
738 /*
739 * Update the current reference resolver to external
740 * module/sub-module containing the referred typedef/grouping.
741 */
742 setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());
743 // Add the type/uses of referred typedef/grouping to the stack.
744 addUnresolvedRecursiveReferenceToStack(linkedNode);
745 return true;
746 }
747 }
748 // If referred node can't be found return false.
749 return false;
750 }
751
752 /**
753 * Finds and resolves with import list.
754 *
755 * @return true if resolved, false otherwise
756 * @throws DataModelException a violation in data model rule
757 */
758 private boolean resolveWithImport() throws DataModelException {
759 /*
760 * Run through import list to find the referred typedef/grouping.
761 */
762 for (YangImport yangImport : getCurReferenceResolver().getImportList()) {
763 /*
764 * Match the prefix attached to entity under resolution with the
765 * imported/included module/sub-module's prefix. If found, search
766 * for the referred typedef/grouping at the root level.
767 */
768 if (yangImport.getPrefixId().contentEquals(getRefPrefix())) {
769 YangNode linkedNode = null;
770 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
771 linkedNode = findRefTypedef(yangImport.getImportedNode());
772 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
773 linkedNode = findRefGrouping(yangImport.getImportedNode());
774 }
775 if (linkedNode != null) {
776 // Add the link to external entity.
777 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
778 /*
779 * Update the current reference resolver to external
780 * module/sub-module containing the referred typedef/grouping.
781 */
782 setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());
783 // Add the type/uses of referred typedef/grouping to the stack.
784 addUnresolvedRecursiveReferenceToStack(linkedNode);
785 return true;
786 }
787 /*
788 * If referred node can't be found at root level break for loop,
789 * and return false.
790 */
791 break;
792 }
793 }
794 // If referred node can't be found return false.
795 return false;
796 }
797
798 /**
799 * Returns referred typedef/grouping node.
800 *
801 * @return referred typedef/grouping node
802 * @throws DataModelException a violation in data model rule
803 */
804 private T getRefNode() throws DataModelException {
805 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
806 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>)
807 ((YangType<?>) getCurrentEntityToResolveFromStack()).getDataTypeExtendedInfo();
808 return (T) derivedInfo.getReferredTypeDef();
809 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
810 return (T) ((YangUses) getCurrentEntityToResolveFromStack()).getRefGroup();
811 } else {
812 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
813 }
814 }
815
816 /**
817 * Finds the referred grouping node at the root level of imported/included node.
818 *
819 * @param refNode module/sub-module node
820 * @return referred grouping
821 */
822 private YangNode findRefGrouping(YangNode refNode) {
823 YangNode tmpNode = refNode.getChild();
824 while (tmpNode != null) {
825 if (tmpNode instanceof YangGrouping) {
826 if (tmpNode.getName()
827 .equals(((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
828 return tmpNode;
829 }
830 }
831 tmpNode = tmpNode.getNextSibling();
832 }
833 return null;
834 }
835
836 /**
837 * Finds the referred typedef node at the root level of imported/included node.
838 *
839 * @param refNode module/sub-module node
840 * @return referred typedef
841 */
842 private YangNode findRefTypedef(YangNode refNode) {
843 YangNode tmpNode = refNode.getChild();
844 while (tmpNode != null) {
845 if (tmpNode instanceof YangTypeDef) {
846 if (tmpNode.getName()
847 .equals(((YangType) getCurrentEntityToResolveFromStack()).getDataTypeName())) {
848 return tmpNode;
849 }
850 }
851 tmpNode = tmpNode.getNextSibling();
852 }
853 return null;
854 }
855}