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