blob: 5786224ddcc97c2472ca7ed32b22ac8b01cfc6e4 [file] [log] [blame]
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.yangutils.linker.impl;
18
Bharat saraswal96dfef02016-06-16 00:29:12 +053019import java.io.Serializable;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053020import java.util.Iterator;
21import java.util.List;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053022import java.util.Stack;
Bharat saraswal96dfef02016-06-16 00:29:12 +053023
24import org.onosproject.yangutils.datamodel.Resolvable;
Gaurav Agrawal72cd1b72016-06-30 13:28:14 +053025import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053026import org.onosproject.yangutils.datamodel.YangDerivedInfo;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053027import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
28import org.onosproject.yangutils.datamodel.YangFeature;
29import org.onosproject.yangutils.datamodel.YangFeatureHolder;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053030import org.onosproject.yangutils.datamodel.YangGrouping;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053031import org.onosproject.yangutils.datamodel.YangIfFeature;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053032import org.onosproject.yangutils.datamodel.YangImport;
33import org.onosproject.yangutils.datamodel.YangInclude;
34import org.onosproject.yangutils.datamodel.YangNode;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053035import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053036import org.onosproject.yangutils.datamodel.YangReferenceResolver;
37import org.onosproject.yangutils.datamodel.YangResolutionInfo;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053038import org.onosproject.yangutils.datamodel.YangType;
39import org.onosproject.yangutils.datamodel.YangTypeDef;
40import org.onosproject.yangutils.datamodel.YangUses;
41import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Bharat saraswal96dfef02016-06-16 00:29:12 +053042import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053043import org.onosproject.yangutils.linker.YangLinkingPhase;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053044
Bharat saraswal96dfef02016-06-16 00:29:12 +053045import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTER_FILE_LINKED;
46import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
47import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.LINKED;
48import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053049import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNDEFINED;
Bharat saraswal96dfef02016-06-16 00:29:12 +053050import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNRESOLVED;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053051import static org.onosproject.yangutils.linker.YangLinkingPhase.INTER_FILE;
52import static org.onosproject.yangutils.linker.YangLinkingPhase.INTRA_FILE;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053053import static org.onosproject.yangutils.utils.UtilConstants.FEATURE_LINKER_ERROR;
Vidyashree Rama210c01d2016-05-20 16:29:25 +053054import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053055import static org.onosproject.yangutils.utils.UtilConstants.TYPEDEF_LINKER_ERROR;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053056
57/**
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053058 * Represents implementation of resolution object which will be resolved by
59 * linker.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053060 *
61 * @param <T> type of resolution entity uses / type
62 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053063public class YangResolutionInfoImpl<T>
Bharat saraswal96dfef02016-06-16 00:29:12 +053064 implements YangResolutionInfo<T>, Serializable {
65
66 private static final long serialVersionUID = 806201658L;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053067
68 /**
69 * Information about the entity that needs to be resolved.
70 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053071 private YangEntityToResolveInfoImpl<T> entityToResolveInfo;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053072
73 /**
74 * Error line number.
75 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053076 private transient int lineNumber;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053077
78 /**
79 * Error character position in number.
80 */
Bharat saraswal96dfef02016-06-16 00:29:12 +053081 private transient int charPosition;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053082
83 /**
84 * Current module/sub-module reference, will be used in inter-file/
85 * inter-jar scenario to get the import/include list.
86 */
Bharat saraswal96dfef02016-06-16 00:29:12 +053087 private transient YangReferenceResolver curReferenceResolver;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053088
89 /**
90 * Stack for type/uses is maintained for hierarchical references, this is
91 * used during resolution.
92 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053093 private Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053094
95 /**
96 * It is private to ensure the overloaded method be invoked to create an
97 * object.
98 */
99 @SuppressWarnings("unused")
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530100 private YangResolutionInfoImpl() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530101
102 }
103
104 /**
105 * Creates a resolution information object with all the inputs.
106 *
107 * @param dataNode current parsable data node
108 * @param holderNode parent YANG node
109 * @param lineNumber error line number
110 * @param charPositionInLine error character position in line
111 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530112 public YangResolutionInfoImpl(T dataNode, YangNode holderNode, int lineNumber, int charPositionInLine) {
113 setEntityToResolveInfo(new YangEntityToResolveInfoImpl<>());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530114 getEntityToResolveInfo().setEntityToResolve(dataNode);
115 getEntityToResolveInfo().setHolderOfEntityToResolve(holderNode);
116 this.setLineNumber(lineNumber);
117 this.setCharPosition(charPositionInLine);
118 setPartialResolvedStack(new Stack<>());
119 }
120
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530121 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530122 public void resolveLinkingForResolutionInfo(YangReferenceResolver dataModelRootNode)
123 throws DataModelException {
124
125 setCurReferenceResolver(dataModelRootNode);
126
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530127 // Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530128 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
129
130 // Check if linking is already done
131 if (entityToResolve instanceof Resolvable) {
132 Resolvable resolvable = (Resolvable) entityToResolve;
133 if (resolvable.getResolvableStatus() == RESOLVED) {
134 /**
135 * entity is already resolved, so nothing to do
136 */
137 return;
138 }
139 } else {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530140 throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
141 "type/uses/if-feature");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530142 }
143
144 // Push the initial entity to resolve in stack.
145 addInPartialResolvedStack(getEntityToResolveInfo());
146
147 linkAndResolvePartialResolvedStack();
148 }
149
150 /**
151 * Resolves linking with ancestors.
152 *
153 * @throws DataModelException a violation of data model rules
154 */
155 private void linkAndResolvePartialResolvedStack()
156 throws DataModelException {
157
158 while (getPartialResolvedStack().size() != 0) {
159
160 // Current node to resolve, it can be a YANG type or YANG uses.
161 T entityToResolve = getCurrentEntityToResolveFromStack();
162 // Check if linking is already done
163 if (entityToResolve instanceof Resolvable) {
164
165 Resolvable resolvable = (Resolvable) entityToResolve;
166 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530167 case RESOLVED: {
168 /*
169 * If the entity is already resolved in the stack, then pop
170 * it and continue with the remaining stack elements to
171 * resolve
172 */
173 getPartialResolvedStack().pop();
174 break;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530175 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530176
177 case LINKED: {
178 /*
179 * If the top of the stack is already linked then resolve
180 * the references and pop the entity and continue with
181 * remaining stack elements to resolve.
182 */
183 resolveTopOfStack(INTRA_FILE);
184 getPartialResolvedStack().pop();
185 break;
186 }
187
188 case INTRA_FILE_RESOLVED: {
189 /*
190 * Pop the top of the stack.
191 */
192 getPartialResolvedStack().pop();
193 break;
194 }
195
196 case UNRESOLVED: {
197 linkTopOfStackReferenceUpdateStack();
198
199 if (resolvable.getResolvableStatus() == UNRESOLVED) {
200 // If current entity is still not resolved, then
201 // linking/resolution has failed.
202 String errorInfo;
203 if (resolvable instanceof YangType) {
204 errorInfo = TYPEDEF_LINKER_ERROR;
205 } else if (resolvable instanceof YangUses) {
206 errorInfo = GROUPING_LINKER_ERROR;
207 } else {
208 errorInfo = FEATURE_LINKER_ERROR;
209 }
210 DataModelException dataModelException =
211 new DataModelException(errorInfo);
212 dataModelException.setLine(getLineNumber());
213 dataModelException.setCharPosition(getCharPosition());
214 throw dataModelException;
215 }
216 break;
217 }
218 default: {
219 throw new DataModelException("Data Model Exception: Unsupported, linker state");
220 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530221
222 }
223
224 } else {
225 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
226 }
227
228 }
229
230 }
231
232 /**
233 * Resolves the current entity in the stack.
234 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530235 private void resolveTopOfStack(YangLinkingPhase linkingPhase)
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530236 throws DataModelException {
237 ((Resolvable) getCurrentEntityToResolveFromStack()).resolve();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530238 if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != INTRA_FILE_RESOLVED
239 && ((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != UNDEFINED) {
240 // Sets the resolution status in inside the type/uses/if-feature.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530241 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(RESOLVED);
242 }
243 }
244
245 /**
246 * Resolves linking for a node child and siblings.
247 *
248 * @throws DataModelException data model error
249 */
250 private void linkTopOfStackReferenceUpdateStack()
251 throws DataModelException {
252
253 /*
254 * Check if self file reference is there, this will not check for the
255 * scenario when prefix is not present and type/uses is present in
256 * sub-module from include list.
257 */
258 if (!isCandidateForSelfFileReference()) {
259 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
260 return;
261 }
262
263 /**
264 * Try to resolve the top of the stack and update partial resolved stack
265 * if there is recursive references
266 */
267 YangNode potentialAncestorWithReferredNode = getPartialResolvedStack().peek()
268 .getHolderOfEntityToResolve();
269
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530270 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
271 resolveSelfFileLinkingForIfFeature(potentialAncestorWithReferredNode);
272 return;
273 } else {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530274
275 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530276 * Traverse up in the ancestor tree to check if the referred node is
277 * defined
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530278 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530279 while (potentialAncestorWithReferredNode != null) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530280
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530281 /**
282 * Check for the referred node defined in a ancestor scope
283 */
284 YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
285 if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
286 return;
287 }
288
289 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
290 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530291 }
292
293 /*
294 * In case prefix is not present it's a candidate for inter-file
295 * resolution via include list.
296 */
297 if (getRefPrefix() == null) {
298 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
299 }
300 }
301
302 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530303 * Resolves self file linking for if-feature.
304 *
305 * @param potentialAncestorWithReferredNode if-feature holder node
306 * @throws DataModelException DataModelException a violation of data model
307 * rules
308 */
309 private void resolveSelfFileLinkingForIfFeature(YangNode potentialAncestorWithReferredNode)
310 throws DataModelException {
311
312 YangFeatureHolder featureHolder = getFeatureHolder(potentialAncestorWithReferredNode);
313 YangNode potentialReferredNode = (YangNode) featureHolder;
314 if (isReferredNode(potentialReferredNode)) {
315
316 // Adds reference link of entity to the node under resolution.
317 addReferredEntityLink(potentialReferredNode, LINKED);
318
319 /**
320 * resolve the reference and update the partial resolution stack
321 * with any further recursive references
322 */
323 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
324 return;
325 }
326
327 /*
328 * In case prefix is not present it's a candidate for inter-file
329 * resolution via include list.
330 */
331 if (getRefPrefix() == null) {
332 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
333 }
334 }
335
336
337 /**
338 * Returns feature holder(module/sub-module node) .
339 *
340 * @param potentialAncestorWithReferredNode if-feature holder node
341 */
342 private YangFeatureHolder getFeatureHolder(YangNode potentialAncestorWithReferredNode) {
343 while (potentialAncestorWithReferredNode != null) {
344 if (potentialAncestorWithReferredNode instanceof YangFeatureHolder) {
345 return (YangFeatureHolder) potentialAncestorWithReferredNode;
346 }
347 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
348 }
349 return null;
350 }
351
352 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530353 * Checks if the reference in self file or in external file.
354 *
355 * @return true if self file reference, false otherwise
356 * @throws DataModelException a violation of data model rules
357 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530358 private boolean isCandidateForSelfFileReference()
359 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530360 String prefix = getRefPrefix();
361 return prefix == null || prefix.contentEquals(getCurReferenceResolver().getPrefix());
362 }
363
364 /**
365 * Checks for the referred node defined in a ancestor scope.
366 *
367 * @param potentialReferredNode potential referred node
368 * @return status of resolution and updating the partial resolved stack with
369 * the any recursive references
370 * @throws DataModelException data model errors
371 */
372 private boolean isReferredNodeInSiblingListProcessed(YangNode potentialReferredNode)
373 throws DataModelException {
374 while (potentialReferredNode != null) {
375
376 // Check if the potential referred node is the actual referred node
377 if (isReferredNode(potentialReferredNode)) {
378
379 // Adds reference link of entity to the node under resolution.
380 addReferredEntityLink(potentialReferredNode, LINKED);
381
382 /**
383 * resolve the reference and update the partial resolution stack
384 * with any further recursive references
385 */
386 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
387
388 /*
389 * return true, since the reference is linked and any recursive
390 * unresolved references is added to the stack
391 */
392 return true;
393 }
394
395 potentialReferredNode = potentialReferredNode.getNextSibling();
396 }
397 return false;
398 }
399
400 /**
401 * Checks if the potential referred node is the actual referred node.
402 *
403 * @param potentialReferredNode typedef/grouping node
404 * @return true if node is of resolve type otherwise false
405 * @throws DataModelException a violation of data model rules
406 */
407 private boolean isReferredNode(YangNode potentialReferredNode)
408 throws DataModelException {
409 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
410 if (potentialReferredNode instanceof YangTypeDef) {
411 /*
412 * Check if name of node name matches with the entity being
413 * resolved
414 */
415 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
416 }
417 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
418 if (potentialReferredNode instanceof YangGrouping) {
419 /*
420 * Check if name of node name matches with the entity being
421 * resolved
422 */
423 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
424 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530425 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
426 if (potentialReferredNode instanceof YangFeatureHolder) {
427 /*
428 * Check if name of node name matches with the entity being
429 * resolved
430 */
431 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
432 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530433 } else {
434 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
435 }
436 return false;
437 }
438
439 /**
440 * Checks if node name is same as name in resolution info, i.e. name of
441 * typedef/grouping is same as name of type/uses.
442 *
443 * @param node typedef/grouping node
444 * @return true if node name is same as name in resolution info, otherwise
445 * false
446 * @throws DataModelException a violation of data model rules
447 */
448
449 private boolean isNodeNameSameAsResolutionInfoName(YangNode node)
450 throws DataModelException {
451 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
452 if (node.getName().contentEquals(
453 ((YangType<?>) getCurrentEntityToResolveFromStack())
454 .getDataTypeName())) {
455 return true;
456 }
457 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
458 if (node.getName().contentEquals(
459 ((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
460 return true;
461 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530462 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
463 return isFeatureDefinedInNode(node);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530464 } else {
465 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
466 }
467 return false;
468 }
469
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530470 private boolean isFeatureDefinedInNode(YangNode node) throws DataModelException {
471 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
472 List<YangFeature> featureList = ((YangFeatureHolder) node).getFeatureList();
473 if (featureList != null && !featureList.isEmpty()) {
474 Iterator<YangFeature> iterator = featureList.iterator();
475 while (iterator.hasNext()) {
476 YangFeature feature = iterator.next();
477 if (ifFeature.getName().equals(feature.getName())) {
478 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
479 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeatureHolder(node);
480 return true;
481 }
482 }
483 }
484 return false;
485 }
486
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530487 /**
488 * Adds reference of grouping/typedef in uses/type.
489 *
490 * @param referredNode grouping/typedef node being referred
491 * @param linkedStatus linked status if success.
492 * @throws DataModelException a violation of data model rules
493 */
494 private void addReferredEntityLink(YangNode referredNode, ResolvableStatus linkedStatus)
495 throws DataModelException {
496 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +0530497 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
498 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530499 derivedInfo.setReferredTypeDef((YangTypeDef) referredNode);
500 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
501 ((YangUses) getCurrentEntityToResolveFromStack())
502 .setRefGroup((YangGrouping) referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530503 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
504 // do nothing , referred node is already set
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530505 } else {
506 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
507 }
508
509 // Sets the resolution status in inside the type/uses.
510 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(linkedStatus);
511 }
512
513 /**
514 * Checks if type/grouping has further reference to typedef/ unresolved
515 * uses. Add it to the partial resolve stack and return the status of
516 * addition to stack.
517 *
518 * @param referredNode grouping/typedef node
519 * @throws DataModelException a violation of data model rules
520 */
521 private void addUnresolvedRecursiveReferenceToStack(YangNode referredNode)
522 throws DataModelException {
523 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
524 /*
525 * Checks if typedef type is derived
526 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530527 if (((YangTypeDef) referredNode).getTypeDefBaseType().getDataType() == YangDataTypes.DERIVED) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530528
Bharat saraswal96dfef02016-06-16 00:29:12 +0530529 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530530 unResolvedEntityInfo.setEntityToResolve(((YangTypeDef) referredNode)
531 .getTypeDefBaseType());
532 unResolvedEntityInfo.setHolderOfEntityToResolve(referredNode);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530533 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530534 }
535
536 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
537 /*
538 * Search if the grouping has any un resolved uses child, if so
539 * return true, else return false.
540 */
541 addUnResolvedUsesToStack(referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530542 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
543 addUnResolvedIfFeatureToStack(referredNode);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530544 } else {
545 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
546 }
547 }
548
549 /**
550 * Returns if there is any unresolved uses in grouping.
551 *
552 * @param node grouping/typedef node
553 */
554 private void addUnResolvedUsesToStack(YangNode node) {
555
556 /**
557 * Search the grouping node's children for presence of uses node.
558 */
559 YangNode curNode = node.getChild();
560 while (curNode != null) {
561 if (curNode instanceof YangUses) {
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530562 YangEntityToResolveInfoImpl<YangUses> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530563 unResolvedEntityInfo.setEntityToResolve((YangUses) curNode);
564 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530565 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530566
567 }
568 curNode = curNode.getNextSibling();
569 }
570 }
571
572 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530573 * Returns if there is any unresolved if-feature in feature.
574 *
575 * @param node module/submodule node
576 */
577 private void addUnResolvedIfFeatureToStack(YangNode node) {
578 YangFeature refFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeature();
579 List<YangIfFeature> ifFeatureList = refFeature.getIfFeatureList();
580 if (ifFeatureList != null && !ifFeatureList.isEmpty()) {
581 Iterator<YangIfFeature> ifFeatureIterator = ifFeatureList.iterator();
582 while (ifFeatureIterator.hasNext()) {
583 YangIfFeature ifFeature = ifFeatureIterator.next();
584 YangEntityToResolveInfo<YangIfFeature> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
585 unResolvedEntityInfo.setEntityToResolve(ifFeature);
586 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
587 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
588 }
589 }
590 }
591
592 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530593 * Returns stack of YANG type with partially resolved YANG construct
594 * hierarchy.
595 *
596 * @return partial resolved YANG construct stack
597 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530598 private Stack<YangEntityToResolveInfoImpl<T>> getPartialResolvedStack() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530599 return partialResolvedStack;
600 }
601
602 /**
603 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
604 *
605 * @param partialResolvedStack partial resolved YANG construct stack
606 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530607 private void setPartialResolvedStack(Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530608 this.partialResolvedStack = partialResolvedStack;
609 }
610
611 /**
612 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
613 *
614 * @param partialResolvedInfo partial resolved YANG construct stack
615 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530616 private void addInPartialResolvedStack(YangEntityToResolveInfoImpl<T> partialResolvedInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530617 getPartialResolvedStack().push(partialResolvedInfo);
618 }
619
620 /**
621 * Retrieves the next entity in the stack that needs to be resolved. It is
622 * assumed that the caller ensures that the stack is not empty.
623 *
624 * @return next entity in the stack that needs to be resolved
625 */
626 private T getCurrentEntityToResolveFromStack() {
627 return getPartialResolvedStack().peek().getEntityToResolve();
628 }
629
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530630 @Override
631 public YangEntityToResolveInfoImpl<T> getEntityToResolveInfo() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530632 return entityToResolveInfo;
633 }
634
635 /**
636 * Sets information about the entity that needs to be resolved.
637 *
638 * @param entityToResolveInfo information about the entity that needs to be
639 * resolved
640 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530641 private void setEntityToResolveInfo(YangEntityToResolveInfoImpl<T> entityToResolveInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530642 this.entityToResolveInfo = entityToResolveInfo;
643 }
644
645 @Override
646 public int getLineNumber() {
647 return lineNumber;
648 }
649
650 @Override
651 public int getCharPosition() {
652 return charPosition;
653 }
654
655 @Override
656 public void setLineNumber(int lineNumber) {
657 this.lineNumber = lineNumber;
658 }
659
660 @Override
661 public void setCharPosition(int charPositionInLine) {
662 this.charPosition = charPositionInLine;
663 }
664
665 /**
666 * Returns current module/sub-module reference, will be used in inter-file/
667 * inter-jar scenario to get the import/include list.
668 *
669 * @return current module/sub-module reference
670 */
671 private YangReferenceResolver getCurReferenceResolver() {
672 return curReferenceResolver;
673 }
674
675 /**
676 * Sets current module/sub-module reference, will be used in inter-file/
677 * inter-jar scenario to get the import/include list.
678 *
679 * @param curReferenceResolver current module/sub-module reference
680 */
681 private void setCurReferenceResolver(YangReferenceResolver curReferenceResolver) {
682 this.curReferenceResolver = curReferenceResolver;
683 }
684
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530685 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530686 public void linkInterFile(YangReferenceResolver dataModelRootNode)
687 throws DataModelException {
688
689 setCurReferenceResolver(dataModelRootNode);
690
691 // Current node to resolve, it can be a YANG type or YANG uses.
692 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
693
694 // Check if linking is already done
695 if (entityToResolve instanceof Resolvable) {
696 Resolvable resolvable = (Resolvable) entityToResolve;
697 if (resolvable.getResolvableStatus() == RESOLVED) {
698 return;
699 }
700 } else {
701 throw new DataModelException("Data Model Exception: Entity to resolved is not Resolvable");
702 }
703
704 // Push the initial entity to resolve in stack.
705 addInPartialResolvedStack(getEntityToResolveInfo());
706
707 // Inter file linking and resolution.
708 linkInterFileAndResolve();
709 }
710
711 /**
712 * Returns the referenced prefix of entity under resolution.
713 *
714 * @return referenced prefix of entity under resolution
715 * @throws DataModelException a violation in data model rule
716 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530717 private String getRefPrefix()
718 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530719 String refPrefix;
720 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
721 refPrefix = ((YangType<?>) getCurrentEntityToResolveFromStack()).getPrefix();
722 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
723 refPrefix = ((YangUses) getCurrentEntityToResolveFromStack()).getPrefix();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530724 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
725 refPrefix = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getPrefix();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530726 } else {
727 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
728 }
729 return refPrefix;
730 }
731
732 /**
733 * Performs inter file linking and resolution.
734 *
735 * @throws DataModelException a violation in data model rule
736 */
737 private void linkInterFileAndResolve()
738 throws DataModelException {
739
740 while (getPartialResolvedStack().size() != 0) {
741
742 // Current node to resolve, it can be a YANG type or YANG uses.
743 T entityToResolve = getCurrentEntityToResolveFromStack();
744 // Check if linking is already done
745 if (entityToResolve instanceof Resolvable) {
746
747 Resolvable resolvable = (Resolvable) entityToResolve;
748 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530749 case RESOLVED: {
750 /*
751 * If the entity is already resolved in the stack, then pop
752 * it and continue with the remaining stack elements to
753 * resolve
754 */
755 getPartialResolvedStack().pop();
756 break;
757 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530758
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530759 case INTER_FILE_LINKED: {
760 /*
761 * If the top of the stack is already linked then resolve
762 * the references and pop the entity and continue with
763 * remaining stack elements to resolve
764 */
765 resolveTopOfStack(INTER_FILE);
766 getPartialResolvedStack().pop();
767 break;
768 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530769
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530770 case INTRA_FILE_RESOLVED: {
771 /*
772 * If the top of the stack is intra file resolved then check
773 * if top of stack is linked, if not link it using
774 * import/include list and push the linked referred entity
775 * to the stack, otherwise only push it to the stack.
776 */
777 linkInterFileTopOfStackRefUpdateStack();
778 break;
779 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530780
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530781 case UNDEFINED: {
782 /*
783 * In case of if-feature resolution, if referred "feature" is not
784 * defined then the resolvable status will be undefined.
785 */
786 getPartialResolvedStack().pop();
787 break;
788 }
789
790 default: {
791 throw new DataModelException("Data Model Exception: Unsupported, linker state");
792 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530793
794 }
795
796 } else {
797 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
798 }
799
800 }
801
802 }
803
804 /**
805 * Links the top of the stack if it's inter-file and update stack.
806 *
807 * @throws DataModelException data model error
808 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530809 private void linkInterFileTopOfStackRefUpdateStack()
810 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530811
812 /*
813 * Obtain the referred node of top of stack entity under resolution
814 */
815 T referredNode = getRefNode();
816
817 /*
818 * Check for null for scenario when it's not linked and inter-file
819 * linking is required.
820 */
821 if (referredNode == null) {
822
823 /*
Bharat saraswal96dfef02016-06-16 00:29:12 +0530824 * Check if prefix is null or not, to identify whether to search in
825 * import list or include list.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530826 */
Bharat saraswalcad0e652016-05-26 23:48:38 +0530827 if (getRefPrefix() != null && !getRefPrefix().contentEquals(getCurReferenceResolver().getPrefix())) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530828 if (resolveWithImport()) {
829 return;
830 }
831 } else {
832 if (resolveWithInclude()) {
833 return;
834 }
835 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530836
837 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
838 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setResolvableStatus(UNDEFINED);
839 return;
840 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530841 // Exception when referred typedef/grouping is not found.
842 DataModelException dataModelException = new DataModelException("YANG file error: Referred " +
843 "typedef/grouping for a given type/uses can't be found.");
844 dataModelException.setLine(getLineNumber());
845 dataModelException.setCharPosition(getCharPosition());
846 throw dataModelException;
847 } else {
848 /*
849 * If referred node is already linked, then just change the status
850 * and push to the stack.
851 */
852 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
853 addUnresolvedRecursiveReferenceToStack((YangNode) referredNode);
854 }
855 }
856
857 /**
858 * Finds and resolves with include list.
859 *
860 * @return true if resolved, false otherwise
861 * @throws DataModelException a violation in data model rule
862 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530863 private boolean resolveWithInclude()
864 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530865 /*
866 * Run through all the nodes in include list and search for referred
867 * typedef/grouping at the root level.
868 */
869 for (YangInclude yangInclude : getCurReferenceResolver().getIncludeList()) {
870 YangNode linkedNode = null;
871 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
872 linkedNode = findRefTypedef(yangInclude.getIncludedNode());
873 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
874 linkedNode = findRefGrouping(yangInclude.getIncludedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530875 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
876 linkedNode = findRefFeature(yangInclude.getIncludedNode());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530877 }
878 if (linkedNode != null) {
879 // Add the link to external entity.
880 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
881 /*
882 * Update the current reference resolver to external
883 * module/sub-module containing the referred typedef/grouping.
884 */
885 setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());
886 // Add the type/uses of referred typedef/grouping to the stack.
887 addUnresolvedRecursiveReferenceToStack(linkedNode);
888 return true;
889 }
890 }
891 // If referred node can't be found return false.
892 return false;
893 }
894
895 /**
896 * Finds and resolves with import list.
897 *
898 * @return true if resolved, false otherwise
899 * @throws DataModelException a violation in data model rule
900 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530901 private boolean resolveWithImport()
902 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530903 /*
904 * Run through import list to find the referred typedef/grouping.
905 */
906 for (YangImport yangImport : getCurReferenceResolver().getImportList()) {
907 /*
908 * Match the prefix attached to entity under resolution with the
909 * imported/included module/sub-module's prefix. If found, search
910 * for the referred typedef/grouping at the root level.
911 */
912 if (yangImport.getPrefixId().contentEquals(getRefPrefix())) {
913 YangNode linkedNode = null;
914 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
915 linkedNode = findRefTypedef(yangImport.getImportedNode());
916 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
917 linkedNode = findRefGrouping(yangImport.getImportedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530918 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
919 linkedNode = findRefFeature(yangImport.getImportedNode());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530920 }
921 if (linkedNode != null) {
922 // Add the link to external entity.
923 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
924 /*
925 * Update the current reference resolver to external
Bharat saraswal96dfef02016-06-16 00:29:12 +0530926 * module/sub-module containing the referred
927 * typedef/grouping.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530928 */
929 setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());
Bharat saraswal96dfef02016-06-16 00:29:12 +0530930 // Add the type/uses of referred typedef/grouping to the
931 // stack.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530932 addUnresolvedRecursiveReferenceToStack(linkedNode);
933 return true;
934 }
935 /*
936 * If referred node can't be found at root level break for loop,
937 * and return false.
938 */
939 break;
940 }
941 }
942 // If referred node can't be found return false.
943 return false;
944 }
945
946 /**
947 * Returns referred typedef/grouping node.
948 *
949 * @return referred typedef/grouping node
950 * @throws DataModelException a violation in data model rule
951 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530952 private T getRefNode()
953 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530954 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +0530955 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
956 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530957 return (T) derivedInfo.getReferredTypeDef();
958 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
959 return (T) ((YangUses) getCurrentEntityToResolveFromStack()).getRefGroup();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530960 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
961 return (T) ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeatureHolder();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530962 } else {
963 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
964 }
965 }
966
967 /**
968 * Finds the referred grouping node at the root level of imported/included node.
969 *
970 * @param refNode module/sub-module node
971 * @return referred grouping
972 */
973 private YangNode findRefGrouping(YangNode refNode) {
974 YangNode tmpNode = refNode.getChild();
975 while (tmpNode != null) {
976 if (tmpNode instanceof YangGrouping) {
977 if (tmpNode.getName()
978 .equals(((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
979 return tmpNode;
980 }
981 }
982 tmpNode = tmpNode.getNextSibling();
983 }
984 return null;
985 }
986
987 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530988 * Finds the referred feature node at the root level of imported/included node.
989 *
990 * @param refNode module/sub-module node
991 * @return referred feature
992 */
993 private YangNode findRefFeature(YangNode refNode) {
994 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
995 List<YangFeature> featureList = ((YangFeatureHolder) refNode).getFeatureList();
996
997 if (featureList != null && !featureList.isEmpty()) {
998 Iterator<YangFeature> iterator = featureList.iterator();
999 while (iterator.hasNext()) {
1000 YangFeature feature = iterator.next();
1001 if (ifFeature.getName().equals(feature.getName())) {
1002 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
1003 return refNode;
1004 }
1005 }
1006 }
1007 return null;
1008 }
1009
1010 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301011 * Finds the referred typedef node at the root level of imported/included node.
1012 *
1013 * @param refNode module/sub-module node
1014 * @return referred typedef
1015 */
1016 private YangNode findRefTypedef(YangNode refNode) {
1017 YangNode tmpNode = refNode.getChild();
1018 while (tmpNode != null) {
1019 if (tmpNode instanceof YangTypeDef) {
1020 if (tmpNode.getName()
1021 .equals(((YangType) getCurrentEntityToResolveFromStack()).getDataTypeName())) {
1022 return tmpNode;
1023 }
1024 }
1025 tmpNode = tmpNode.getNextSibling();
1026 }
1027 return null;
1028 }
1029}