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