blob: d7f0428b475591b1b44bc80f18f441c06cb62e0c [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
Vidyashree Rama36f2fab2016-07-15 14:06:56 +053019import java.io.Serializable;
20import java.util.Iterator;
21import java.util.LinkedList;
22import java.util.List;
23import java.util.Stack;
Bharat saraswal96dfef02016-06-16 00:29:12 +053024import org.onosproject.yangutils.datamodel.Resolvable;
janani be18b5342016-07-13 21:06:41 +053025import org.onosproject.yangutils.datamodel.ResolvableType;
Vidyashree Rama36f2fab2016-07-15 14:06:56 +053026import org.onosproject.yangutils.datamodel.TraversalType;
janani be18b5342016-07-13 21:06:41 +053027import org.onosproject.yangutils.datamodel.YangAtomicPath;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053028import org.onosproject.yangutils.datamodel.YangAugment;
29import org.onosproject.yangutils.datamodel.YangAugmentableNode;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +053030import org.onosproject.yangutils.datamodel.YangBase;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053031import org.onosproject.yangutils.datamodel.YangDerivedInfo;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053032import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
janani b23ccc312016-07-14 19:35:22 +053033import org.onosproject.yangutils.datamodel.YangEntityToResolveInfoImpl;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053034import org.onosproject.yangutils.datamodel.YangFeature;
35import org.onosproject.yangutils.datamodel.YangFeatureHolder;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053036import org.onosproject.yangutils.datamodel.YangGrouping;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +053037import org.onosproject.yangutils.datamodel.YangIdentity;
38import org.onosproject.yangutils.datamodel.YangIdentityRef;
Bharat saraswalb551aae2016-07-14 15:18:20 +053039import org.onosproject.yangutils.datamodel.YangIfFeature;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053040import org.onosproject.yangutils.datamodel.YangImport;
41import org.onosproject.yangutils.datamodel.YangInclude;
janani be18b5342016-07-13 21:06:41 +053042import org.onosproject.yangutils.datamodel.YangInput;
43import org.onosproject.yangutils.datamodel.YangLeaf;
44import org.onosproject.yangutils.datamodel.YangLeafList;
45import org.onosproject.yangutils.datamodel.YangLeafRef;
janani be18b5342016-07-13 21:06:41 +053046import org.onosproject.yangutils.datamodel.YangModule;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053047import org.onosproject.yangutils.datamodel.YangNode;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053048import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
janani be18b5342016-07-13 21:06:41 +053049import org.onosproject.yangutils.datamodel.YangOutput;
50import org.onosproject.yangutils.datamodel.YangPathArgType;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053051import org.onosproject.yangutils.datamodel.YangReferenceResolver;
janani be18b5342016-07-13 21:06:41 +053052import org.onosproject.yangutils.datamodel.YangRelativePath;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053053import org.onosproject.yangutils.datamodel.YangResolutionInfo;
janani be18b5342016-07-13 21:06:41 +053054import org.onosproject.yangutils.datamodel.YangRpc;
55import org.onosproject.yangutils.datamodel.YangSubModule;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053056import org.onosproject.yangutils.datamodel.YangType;
57import org.onosproject.yangutils.datamodel.YangTypeDef;
58import org.onosproject.yangutils.datamodel.YangUses;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053059import org.onosproject.yangutils.datamodel.YangXPathResolver;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053060import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Bharat saraswal96dfef02016-06-16 00:29:12 +053061import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
janani b23ccc312016-07-14 19:35:22 +053062import org.onosproject.yangutils.datamodel.utils.YangConstructType;
janani be18b5342016-07-13 21:06:41 +053063import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053064import org.onosproject.yangutils.linker.YangLinkingPhase;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053065import org.onosproject.yangutils.linker.exceptions.LinkerException;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053066
Vidyashree Rama36f2fab2016-07-15 14:06:56 +053067import static org.onosproject.yangutils.datamodel.TraversalType.CHILD;
68import static org.onosproject.yangutils.datamodel.TraversalType.PARENT;
69import static org.onosproject.yangutils.datamodel.TraversalType.ROOT;
70import static org.onosproject.yangutils.datamodel.TraversalType.SIBILING;
janani b23ccc312016-07-14 19:35:22 +053071import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.addResolutionInfo;
Bharat saraswal96dfef02016-06-16 00:29:12 +053072import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTER_FILE_LINKED;
73import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
74import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.LINKED;
75import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053076import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNDEFINED;
Bharat saraswal96dfef02016-06-16 00:29:12 +053077import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNRESOLVED;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053078import static org.onosproject.yangutils.linker.YangLinkingPhase.INTER_FILE;
79import static org.onosproject.yangutils.linker.YangLinkingPhase.INTRA_FILE;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053080import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.detectCollisionForAugmentedNode;
janani b23ccc312016-07-14 19:35:22 +053081import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getPathWithAugment;
82import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getValidNodeIdentifier;
83import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.skipInvalidDataNodes;
Bharat saraswalb551aae2016-07-14 15:18:20 +053084import static org.onosproject.yangutils.utils.UtilConstants.BASE_LINKER_ERROR;
janani b23ccc312016-07-14 19:35:22 +053085import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053086import static org.onosproject.yangutils.utils.UtilConstants.FEATURE_LINKER_ERROR;
Vidyashree Rama210c01d2016-05-20 16:29:25 +053087import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
Bharat saraswalb551aae2016-07-14 15:18:20 +053088import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF;
89import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +053090import static org.onosproject.yangutils.utils.UtilConstants.INPUT;
91import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF;
92import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF_LINKER_ERROR;
93import static org.onosproject.yangutils.utils.UtilConstants.OUTPUT;
janani b23ccc312016-07-14 19:35:22 +053094import static org.onosproject.yangutils.utils.UtilConstants.SLASH_FOR_STRING;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053095import static org.onosproject.yangutils.utils.UtilConstants.TYPEDEF_LINKER_ERROR;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053096
97/**
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053098 * Represents implementation of resolution object which will be resolved by
99 * linker.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530100 *
101 * @param <T> type of resolution entity uses / type
102 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530103public class YangResolutionInfoImpl<T>
Bharat saraswal96dfef02016-06-16 00:29:12 +0530104 implements YangResolutionInfo<T>, Serializable {
105
106 private static final long serialVersionUID = 806201658L;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530107
108 /**
109 * Information about the entity that needs to be resolved.
110 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530111 private YangEntityToResolveInfoImpl<T> entityToResolveInfo;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530112
113 /**
114 * Error line number.
115 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530116 private transient int lineNumber;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530117
118 /**
119 * Error character position in number.
120 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530121 private transient int charPosition;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530122
123 /**
124 * Current module/sub-module reference, will be used in inter-file/
125 * inter-jar scenario to get the import/include list.
126 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530127 private transient YangReferenceResolver curReferenceResolver;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530128
129 /**
130 * Stack for type/uses is maintained for hierarchical references, this is
131 * used during resolution.
132 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530133 private Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530134
135 /**
136 * It is private to ensure the overloaded method be invoked to create an
137 * object.
138 */
139 @SuppressWarnings("unused")
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530140 private YangResolutionInfoImpl() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530141 }
142
143 /**
144 * Creates a resolution information object with all the inputs.
145 *
146 * @param dataNode current parsable data node
147 * @param holderNode parent YANG node
148 * @param lineNumber error line number
149 * @param charPositionInLine error character position in line
150 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530151 public YangResolutionInfoImpl(T dataNode, YangNode holderNode, int lineNumber, int charPositionInLine) {
152 setEntityToResolveInfo(new YangEntityToResolveInfoImpl<>());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530153 getEntityToResolveInfo().setEntityToResolve(dataNode);
154 getEntityToResolveInfo().setHolderOfEntityToResolve(holderNode);
155 this.setLineNumber(lineNumber);
156 this.setCharPosition(charPositionInLine);
157 setPartialResolvedStack(new Stack<>());
158 }
159
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530160 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530161 public void resolveLinkingForResolutionInfo(YangReferenceResolver dataModelRootNode)
162 throws DataModelException {
163
164 setCurReferenceResolver(dataModelRootNode);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530165 /**
166 * Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature or
167 * YANG leafref or YANG base or YANG identityref.
168 */
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530169 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
170
171 // Check if linking is already done
172 if (entityToResolve instanceof Resolvable) {
173 Resolvable resolvable = (Resolvable) entityToResolve;
174 if (resolvable.getResolvableStatus() == RESOLVED) {
175 /**
176 * entity is already resolved, so nothing to do
177 */
178 return;
179 }
180 } else {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530181 throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530182 "type/uses/if-feature/leafref/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530183 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530184 // Push the initial entity to resolve in stack.
185 addInPartialResolvedStack(getEntityToResolveInfo());
186
187 linkAndResolvePartialResolvedStack();
janani be18b5342016-07-13 21:06:41 +0530188
189 addDerivedRefTypeToRefTypeResolutionList();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530190 }
191
192 /**
193 * Resolves linking with ancestors.
194 *
195 * @throws DataModelException a violation of data model rules
196 */
197 private void linkAndResolvePartialResolvedStack()
198 throws DataModelException {
199
200 while (getPartialResolvedStack().size() != 0) {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530201 /**
202 * Current node to resolve, it can be a YANG type or YANG uses or
203 * YANG if-feature or YANG leafref or YANG base or YANG identityref.
204 */
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530205 T entityToResolve = getCurrentEntityToResolveFromStack();
206 // Check if linking is already done
207 if (entityToResolve instanceof Resolvable) {
208
209 Resolvable resolvable = (Resolvable) entityToResolve;
210 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530211 case RESOLVED: {
212 /*
213 * If the entity is already resolved in the stack, then pop
214 * it and continue with the remaining stack elements to
215 * resolve
216 */
217 getPartialResolvedStack().pop();
218 break;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530219 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530220
221 case LINKED: {
222 /*
223 * If the top of the stack is already linked then resolve
224 * the references and pop the entity and continue with
225 * remaining stack elements to resolve.
226 */
227 resolveTopOfStack(INTRA_FILE);
228 getPartialResolvedStack().pop();
229 break;
230 }
231
232 case INTRA_FILE_RESOLVED: {
233 /*
234 * Pop the top of the stack.
235 */
236 getPartialResolvedStack().pop();
237 break;
238 }
239
240 case UNRESOLVED: {
241 linkTopOfStackReferenceUpdateStack();
242
243 if (resolvable.getResolvableStatus() == UNRESOLVED) {
244 // If current entity is still not resolved, then
245 // linking/resolution has failed.
246 String errorInfo;
247 if (resolvable instanceof YangType) {
248 errorInfo = TYPEDEF_LINKER_ERROR;
249 } else if (resolvable instanceof YangUses) {
250 errorInfo = GROUPING_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +0530251 } else if (resolvable instanceof YangIfFeature) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530252 errorInfo = FEATURE_LINKER_ERROR;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530253 } else if (resolvable instanceof YangBase) {
254 errorInfo = BASE_LINKER_ERROR;
255 } else if (resolvable instanceof YangIdentityRef) {
256 errorInfo = IDENTITYREF_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +0530257 } else {
258 errorInfo = LEAFREF_LINKER_ERROR;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530259 }
260 DataModelException dataModelException =
261 new DataModelException(errorInfo);
262 dataModelException.setLine(getLineNumber());
263 dataModelException.setCharPosition(getCharPosition());
264 throw dataModelException;
265 }
266 break;
267 }
268 default: {
269 throw new DataModelException("Data Model Exception: Unsupported, linker state");
270 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530271
272 }
273
274 } else {
janani be18b5342016-07-13 21:06:41 +0530275 throw new DataModelException(
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530276 "Data Model Exception: Entity to resolved is other than type/uses/if-feature" +
277 "/leafref/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530278 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530279 }
280
281 }
282
283 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530284 * Adds the leafref/identityref type to the type, which has derived type referring to
285 * typedef with leafref/identityref type.
janani be18b5342016-07-13 21:06:41 +0530286 */
287 private void addDerivedRefTypeToRefTypeResolutionList() throws DataModelException {
288
289 YangNode potentialAncestorWithReferredNode = getEntityToResolveInfo().getHolderOfEntityToResolve();
290
291 // If holder is typedef return.
292 if (potentialAncestorWithReferredNode instanceof YangTypeDef) {
293 return;
294 }
295
296 // If entity is not type return.
297 if (!(getEntityToResolveInfo().getEntityToResolve() instanceof YangType)) {
298 return;
299 }
300
301 YangType yangType = (YangType) getEntityToResolveInfo().getEntityToResolve();
302
303 // If type is not resolved return.
304 if (yangType.getResolvableStatus() != RESOLVED) {
305 return;
306 }
307
308 YangDerivedInfo derivedInfo = (YangDerivedInfo) yangType.getDataTypeExtendedInfo();
309
310 /*
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530311 * If the derived types referred type is not leafref/identityref return
janani be18b5342016-07-13 21:06:41 +0530312 */
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530313 if ((derivedInfo.getEffectiveBuiltInType() != YangDataTypes.LEAFREF) &&
314 (derivedInfo.getEffectiveBuiltInType() != YangDataTypes.IDENTITYREF)) {
janani be18b5342016-07-13 21:06:41 +0530315 return;
316 }
317
318 T extendedInfo = (T) derivedInfo.getReferredTypeDef().getTypeDefBaseType().getDataTypeExtendedInfo();
319
320 while (extendedInfo instanceof YangDerivedInfo) {
321 YangDerivedInfo derivedInfoFromTypedef = (YangDerivedInfo) extendedInfo;
322 extendedInfo = (T) derivedInfoFromTypedef.getReferredTypeDef().getTypeDefBaseType()
323 .getDataTypeExtendedInfo();
324 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530325
janani be18b5342016-07-13 21:06:41 +0530326 /*
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530327 * Backup the derived types leafref/identityref info, delete all the info in current type,
328 * but for resolution status as resolved. Copy the backed up leafref/identityref to types extended info,
329 * create a leafref/identityref resolution info using the current resolution info and
330 * add to leafref/identityref resolution list.
janani be18b5342016-07-13 21:06:41 +0530331 */
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530332 if (derivedInfo.getEffectiveBuiltInType() == YangDataTypes.LEAFREF) {
333 YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
334 yangType.resetYangType();
janani be18b5342016-07-13 21:06:41 +0530335
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530336 yangType.setResolvableStatus(RESOLVED);
337 yangType.setDataType(YangDataTypes.LEAFREF);
338 yangType.setDataTypeName(LEAFREF);
339 yangType.setDataTypeExtendedInfo(leafRefInTypeDef);
340 leafRefInTypeDef.setResolvableStatus(UNRESOLVED);
janani b23ccc312016-07-14 19:35:22 +0530341 leafRefInTypeDef.setParentNodeOfLeafref(potentialAncestorWithReferredNode);
janani be18b5342016-07-13 21:06:41 +0530342
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530343 // Add resolution information to the list.
344 YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(leafRefInTypeDef,
janani b23ccc312016-07-14 19:35:22 +0530345 potentialAncestorWithReferredNode,
346 getLineNumber(), getCharPosition());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530347 getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
janani b23ccc312016-07-14 19:35:22 +0530348 ResolvableType.YANG_LEAFREF);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530349 getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_LEAFREF);
350
351 } else if (derivedInfo.getEffectiveBuiltInType() == YangDataTypes.IDENTITYREF) {
352
353 YangIdentityRef identityRefInTypeDef = (YangIdentityRef) extendedInfo;
354 yangType.resetYangType();
355
356 yangType.setResolvableStatus(RESOLVED);
357 yangType.setDataType(YangDataTypes.IDENTITYREF);
358 yangType.setDataTypeName(IDENTITYREF);
359 yangType.setDataTypeExtendedInfo(identityRefInTypeDef);
360 identityRefInTypeDef.setResolvableStatus(UNRESOLVED);
361
362 // Add resolution information to the list.
363 YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(identityRefInTypeDef,
janani b23ccc312016-07-14 19:35:22 +0530364 potentialAncestorWithReferredNode, getLineNumber(), getCharPosition());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530365 getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
janani b23ccc312016-07-14 19:35:22 +0530366 ResolvableType.YANG_IDENTITYREF);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530367 getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_IDENTITYREF);
368 }
janani be18b5342016-07-13 21:06:41 +0530369 }
370
371 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530372 * Resolves the current entity in the stack.
373 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530374 private void resolveTopOfStack(YangLinkingPhase linkingPhase)
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530375 throws DataModelException {
janani b23ccc312016-07-14 19:35:22 +0530376 List<T> entityToResolve = (List<T>) ((Resolvable) getCurrentEntityToResolveFromStack()).resolve();
377 if (entityToResolve != null && !entityToResolve.isEmpty()) {
378 Iterator<T> entityToResolveIterator = entityToResolve.listIterator();
379 while (entityToResolveIterator.hasNext()) {
380 addUnresolvedEntitiesToStack(entityToResolveIterator.next());
381 }
382 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530383 if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != INTRA_FILE_RESOLVED
384 && ((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != UNDEFINED) {
janani be18b5342016-07-13 21:06:41 +0530385 // Sets the resolution status in inside the type/uses/if-feature/leafref.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530386 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(RESOLVED);
387 }
388 }
389
390 /**
janani b23ccc312016-07-14 19:35:22 +0530391 * Adds the unresolved entities to the resolution list.
392 *
393 * @param entityToResolve entity to resolve
394 * @throws DataModelException a violation of data model rules
395 */
396 private void addUnresolvedEntitiesToStack(T entityToResolve) throws DataModelException {
397 if (entityToResolve instanceof YangEntityToResolveInfoImpl) {
398 YangEntityToResolveInfoImpl entityToResolveInfo = (YangEntityToResolveInfoImpl) entityToResolve;
399 if (entityToResolveInfo.getEntityToResolve() instanceof YangLeafRef) {
400 YangLeafRef leafref = (YangLeafRef) entityToResolveInfo.getEntityToResolve();
401 YangNode parentNodeOfLeafref = entityToResolveInfo.getHolderOfEntityToResolve();
402 leafref.setParentNodeOfLeafref(parentNodeOfLeafref);
403 if (leafref.getResolvableStatus() == UNRESOLVED) {
404 leafref.setResolvableStatus(INTRA_FILE_RESOLVED);
405 }
406 // Add resolution information to the list.
407 YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<YangLeafRef>(leafref,
408 parentNodeOfLeafref, entityToResolveInfo.getLineNumber(),
409 entityToResolveInfo.getCharPosition());
410 addResolutionInfo(resolutionInfoImpl);
411 }
412 }
413 }
414
415 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530416 * Resolves linking for a node child and siblings.
417 *
418 * @throws DataModelException data model error
419 */
420 private void linkTopOfStackReferenceUpdateStack()
421 throws DataModelException {
422
janani b23ccc312016-07-14 19:35:22 +0530423 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
424 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
425 return;
426 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530427 /*
428 * Check if self file reference is there, this will not check for the
429 * scenario when prefix is not present and type/uses is present in
430 * sub-module from include list.
431 */
432 if (!isCandidateForSelfFileReference()) {
433 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
434 return;
435 }
436
437 /**
438 * Try to resolve the top of the stack and update partial resolved stack
439 * if there is recursive references
440 */
441 YangNode potentialAncestorWithReferredNode = getPartialResolvedStack().peek()
442 .getHolderOfEntityToResolve();
443
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530444 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
445 resolveSelfFileLinkingForIfFeature(potentialAncestorWithReferredNode);
446 return;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530447 } else if ((getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) ||
448 (getCurrentEntityToResolveFromStack() instanceof YangBase)) {
449 resolveSelfFileLinkingForBaseAndIdentityref();
450 return;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530451 } else {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530452
453 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530454 * Traverse up in the ancestor tree to check if the referred node is
455 * defined
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530456 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530457 while (potentialAncestorWithReferredNode != null) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530458
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530459 /**
460 * Check for the referred node defined in a ancestor scope
461 */
462 YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
463 if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
464 return;
465 }
466
467 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
468 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530469 }
470
471 /*
472 * In case prefix is not present it's a candidate for inter-file
473 * resolution via include list.
474 */
475 if (getRefPrefix() == null) {
476 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
477 }
478 }
479
480 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530481 * Resolves self file linking for base/identityref.
482 *
483 * @throws DataModelException a violation of data model rules
484 */
485 private void resolveSelfFileLinkingForBaseAndIdentityref()
486 throws DataModelException {
487
488 boolean referredIdentityFound = false;
489 String nodeName = null;
490
491 if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
janani b23ccc312016-07-14 19:35:22 +0530492 nodeName = ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getName();
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530493 }
494
495 if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
496 nodeName = ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName();
497 }
498
499 if (getCurReferenceResolver() instanceof YangModule) {
500 YangModule rootNode = (YangModule) getCurReferenceResolver();
501 // Sends list of nodes for finding the target identity.
502 referredIdentityFound = isIdentityReferenceFound(nodeName, rootNode);
503 } else if (getCurReferenceResolver() instanceof YangSubModule) {
504 YangSubModule rootNode = (YangSubModule) getCurReferenceResolver();
505 // Sends list of nodes for finding the target identity.
506 referredIdentityFound = isIdentityReferenceFound(nodeName, rootNode);
507 }
508
509 if (referredIdentityFound) {
510 return;
511 }
512
513 /*
514 * In case prefix is not present it's a candidate for inter-file resolution via include list.
515 */
516 if (getRefPrefix() == null) {
517 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
518 }
519 }
520
521 /**
janani be18b5342016-07-13 21:06:41 +0530522 * Returns the root parent with respect to the ancestor count from leafref.
523 *
524 * @param ancestorCount count of node where parent node can be reached
525 * @param currentParent current parent node
526 * @return root node
527 * @throws DataModelException a violation of data model rules
528 */
529 private YangNode getRootNodeWithAncestorCount(int ancestorCount, YangNode currentParent)
530 throws DataModelException {
531
532 int currentParentCount = 1;
533 while (currentParentCount < ancestorCount) {
534 if (currentParent.getParent() == null) {
535 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
536 }
537 currentParent = currentParent.getParent();
538 currentParentCount = currentParentCount + 1;
539 }
540 return currentParent;
541 }
542
543 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530544 * Resolves self file linking for if-feature.
545 *
546 * @param potentialAncestorWithReferredNode if-feature holder node
547 * @throws DataModelException DataModelException a violation of data model
548 * rules
549 */
550 private void resolveSelfFileLinkingForIfFeature(YangNode potentialAncestorWithReferredNode)
551 throws DataModelException {
552
553 YangFeatureHolder featureHolder = getFeatureHolder(potentialAncestorWithReferredNode);
554 YangNode potentialReferredNode = (YangNode) featureHolder;
555 if (isReferredNode(potentialReferredNode)) {
556
557 // Adds reference link of entity to the node under resolution.
558 addReferredEntityLink(potentialReferredNode, LINKED);
559
560 /**
561 * resolve the reference and update the partial resolution stack
562 * with any further recursive references
563 */
564 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
565 return;
566 }
567
568 /*
569 * In case prefix is not present it's a candidate for inter-file
570 * resolution via include list.
571 */
572 if (getRefPrefix() == null) {
573 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
574 }
575 }
576
janani be18b5342016-07-13 21:06:41 +0530577 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530578 * Returns the status of the referred identity found for base/identityref.
579 *
janani b23ccc312016-07-14 19:35:22 +0530580 * @param nodeName the name of the base nodeidentifier/identityref nodeidentifier
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530581 * @param ancestorWithTheReferredNode the parent node of base/identityref
582 * @return status of referred base/identityref
583 * @throws DataModelException a violation of data model rules
584 */
585 private boolean isIdentityReferenceFound(String nodeName, YangNode ancestorWithTheReferredNode)
586 throws DataModelException {
587
588 // When child is not present return.
589 if (ancestorWithTheReferredNode.getChild() == null) {
590 return false;
591 }
592
593 ancestorWithTheReferredNode = ancestorWithTheReferredNode.getChild();
594
595 // Checks all the siblings under the node and returns the matched node.
596 YangNode nodeFound = isReferredNodeInSiblingProcessedForIdentity(ancestorWithTheReferredNode, nodeName);
597
598 if (nodeFound != null) {
599 // Adds reference link of entity to the node under resolution.
600 addReferredEntityLink(nodeFound, LINKED);
601
602 /**
603 * resolve the reference and update the partial resolution stack with any further recursive references
604 */
605 addUnresolvedRecursiveReferenceToStack(nodeFound);
606 return true;
607 }
608
609 return false;
610 }
611
612 /**
janani be18b5342016-07-13 21:06:41 +0530613 * Adds the unresolved constructs to stack which has to be resolved for leafref.
614 *
janani b23ccc312016-07-14 19:35:22 +0530615 * @param yangleafOrLeafList YANG leaf or leaf list which holds the type
janani be18b5342016-07-13 21:06:41 +0530616 * @param ancestorWithTheReferredNode holder of the YANG leaf or leaf list
617 */
618 private void addUnResolvedLeafRefTypeToStack(T yangleafOrLeafList, YangNode ancestorWithTheReferredNode) {
619
620 YangType referredTypeInLeafOrLeafList;
621 if (yangleafOrLeafList instanceof YangLeaf) {
622 YangLeaf leaf = (YangLeaf) yangleafOrLeafList;
623 referredTypeInLeafOrLeafList = leaf.getDataType();
624 if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
625 YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
626 unResolvedEntityInfo.setEntityToResolve((YangLeafRef<?>) leaf.getDataType().getDataTypeExtendedInfo());
627 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
628 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
629 } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
630 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
631 unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
632 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
633 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
634 }
635 } else {
636 YangLeafList leafList = (YangLeafList) yangleafOrLeafList;
637 referredTypeInLeafOrLeafList = leafList.getDataType();
638 if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
639 YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
640 unResolvedEntityInfo
641 .setEntityToResolve((YangLeafRef<?>) leafList.getDataType().getDataTypeExtendedInfo());
642 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
643 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
644 } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
645 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
646 unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
647 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
648 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
649 }
650 }
651 }
652
653 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530654 * Returns feature holder(module/sub-module node) .
655 *
656 * @param potentialAncestorWithReferredNode if-feature holder node
657 */
658 private YangFeatureHolder getFeatureHolder(YangNode potentialAncestorWithReferredNode) {
659 while (potentialAncestorWithReferredNode != null) {
660 if (potentialAncestorWithReferredNode instanceof YangFeatureHolder) {
661 return (YangFeatureHolder) potentialAncestorWithReferredNode;
662 }
663 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
664 }
665 return null;
666 }
667
668 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530669 * Checks if the reference in self file or in external file.
670 *
671 * @return true if self file reference, false otherwise
672 * @throws DataModelException a violation of data model rules
673 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530674 private boolean isCandidateForSelfFileReference()
675 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530676 String prefix = getRefPrefix();
677 return prefix == null || prefix.contentEquals(getCurReferenceResolver().getPrefix());
678 }
679
680 /**
janani be18b5342016-07-13 21:06:41 +0530681 * Checks for the referred parent node for the leafref path.
682 *
683 * @param potentialReferredNode potential referred node
684 * @return the reffered parent node of leaf/leaf-list
685 * @throws DataModelException data model errors
686 */
687 private YangNode isReferredNodeInSiblingProcessedForLeafref(YangNode potentialReferredNode, String referredNodeName)
688 throws DataModelException {
689
690 while (potentialReferredNode != null) {
691 if (potentialReferredNode instanceof YangInput) {
692 if (referredNodeName.equalsIgnoreCase(INPUT)) {
693 return potentialReferredNode;
694 }
695 } else if (potentialReferredNode instanceof YangOutput) {
696 if (referredNodeName.equalsIgnoreCase(OUTPUT)) {
697 return potentialReferredNode;
698 }
699 }
700 // Check if the potential referred node is the actual referred node
701 if (isReferredNodeForLeafref(potentialReferredNode, referredNodeName)) {
702 if (potentialReferredNode instanceof YangGrouping || potentialReferredNode instanceof YangTypeDef) {
703 if (potentialReferredNode.getParent() instanceof YangRpc) {
704 potentialReferredNode = potentialReferredNode.getNextSibling();
705 } else {
706 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
707 }
708 }
709 return potentialReferredNode;
710 }
711 potentialReferredNode = potentialReferredNode.getNextSibling();
712 }
713 return null;
714 }
715
716 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530717 * Checks for the referred parent node for the base/identity.
718 *
719 * @param potentialReferredNode potential referred node
720 * @return the reffered parent node of base/identity.
721 * @throws DataModelException data model errors
722 */
723 private YangNode isReferredNodeInSiblingProcessedForIdentity(YangNode potentialReferredNode,
janani b23ccc312016-07-14 19:35:22 +0530724 String referredNodeName) throws DataModelException {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530725
726 while (potentialReferredNode != null) {
727 if (potentialReferredNode instanceof YangIdentity) {
728 // Check if the potential referred node is the actual referred node
729 if (isReferredNodeForIdentity(potentialReferredNode, referredNodeName)) {
730 return potentialReferredNode;
731 }
732 }
733 potentialReferredNode = potentialReferredNode.getNextSibling();
734 }
735 return null;
736 }
737
738 /**
janani be18b5342016-07-13 21:06:41 +0530739 * Checks if the current reference node name and the name in the path are equal.
740 *
741 * @param currentReferredNode the node where the reference is pointed
janani b23ccc312016-07-14 19:35:22 +0530742 * @param nameOfNodeinPath name of the node in the path
janani be18b5342016-07-13 21:06:41 +0530743 * @return status of the match between the name
744 * @throws DataModelException a violation of data model rules
745 */
746 private boolean isReferredNodeForLeafref(YangNode currentReferredNode, String nameOfNodeinPath)
747 throws DataModelException {
748
749 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
750 /*
751 * Check if name of node name matches with the current reference
752 * node.
753 */
754 return currentReferredNode.getName().contentEquals(nameOfNodeinPath);
755 } else {
756 throw new DataModelException("Data Model Exception: Entity to resolved is other than leafref");
757 }
758 }
759
760 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530761 * Checks if the current reference node name and the name in the base/identityref base are equal.
762 *
janani b23ccc312016-07-14 19:35:22 +0530763 * @param currentReferredNode the node where the reference is pointed
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530764 * @param nameOfIdentityRefBase name of the base in the base/identityref base
765 * @return status of the match between the name
766 * @throws DataModelException a violation of data model rules
767 */
768 private boolean isReferredNodeForIdentity(YangNode currentReferredNode, String nameOfIdentityRefBase)
769 throws DataModelException {
770
771 if ((getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) ||
772 (getCurrentEntityToResolveFromStack() instanceof YangBase)) {
773 /*
774 * Check if name of node name matches with the current reference node.
775 */
776 return currentReferredNode.getName().contentEquals(nameOfIdentityRefBase);
777 } else {
778 throw new DataModelException("Data Model Exception: Entity to resolved is other than identityref");
779 }
780 }
781
782 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530783 * Checks for the referred node defined in a ancestor scope.
784 *
785 * @param potentialReferredNode potential referred node
786 * @return status of resolution and updating the partial resolved stack with
787 * the any recursive references
janani be18b5342016-07-13 21:06:41 +0530788 * @throws DataModelException a violation of data model rules
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530789 */
790 private boolean isReferredNodeInSiblingListProcessed(YangNode potentialReferredNode)
791 throws DataModelException {
792 while (potentialReferredNode != null) {
793
794 // Check if the potential referred node is the actual referred node
795 if (isReferredNode(potentialReferredNode)) {
796
797 // Adds reference link of entity to the node under resolution.
798 addReferredEntityLink(potentialReferredNode, LINKED);
799
800 /**
801 * resolve the reference and update the partial resolution stack
802 * with any further recursive references
803 */
804 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
805
806 /*
807 * return true, since the reference is linked and any recursive
808 * unresolved references is added to the stack
809 */
810 return true;
811 }
812
813 potentialReferredNode = potentialReferredNode.getNextSibling();
814 }
815 return false;
816 }
817
818 /**
819 * Checks if the potential referred node is the actual referred node.
820 *
821 * @param potentialReferredNode typedef/grouping node
822 * @return true if node is of resolve type otherwise false
823 * @throws DataModelException a violation of data model rules
824 */
825 private boolean isReferredNode(YangNode potentialReferredNode)
826 throws DataModelException {
827 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
828 if (potentialReferredNode instanceof YangTypeDef) {
829 /*
830 * Check if name of node name matches with the entity being
831 * resolved
832 */
833 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
834 }
835 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
836 if (potentialReferredNode instanceof YangGrouping) {
837 /*
838 * Check if name of node name matches with the entity being
839 * resolved
840 */
841 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
842 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530843 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
844 if (potentialReferredNode instanceof YangFeatureHolder) {
845 /*
846 * Check if name of node name matches with the entity being
847 * resolved
848 */
849 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
850 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530851 } else if ((getCurrentEntityToResolveFromStack() instanceof YangBase) ||
852 (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef)) {
853 if (potentialReferredNode instanceof YangIdentity) {
854 /*
855 * Check if name of node name matches with the entity being
856 * resolved
857 */
858 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
859 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530860 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530861 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/" +
janani b23ccc312016-07-14 19:35:22 +0530862 "uses/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530863 }
864 return false;
865 }
866
867 /**
868 * Checks if node name is same as name in resolution info, i.e. name of
869 * typedef/grouping is same as name of type/uses.
870 *
871 * @param node typedef/grouping node
872 * @return true if node name is same as name in resolution info, otherwise
873 * false
874 * @throws DataModelException a violation of data model rules
875 */
876
877 private boolean isNodeNameSameAsResolutionInfoName(YangNode node)
878 throws DataModelException {
879 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
880 if (node.getName().contentEquals(
881 ((YangType<?>) getCurrentEntityToResolveFromStack())
882 .getDataTypeName())) {
883 return true;
884 }
885 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
886 if (node.getName().contentEquals(
887 ((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
888 return true;
889 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530890 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
891 return isFeatureDefinedInNode(node);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530892 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
893 if (node.getName().contentEquals(
894 ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName())) {
895 return true;
896 }
897 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
898 if (node.getName().contentEquals(
899 ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getName())) {
900 return true;
901 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530902 } else {
903 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
904 }
905 return false;
906 }
907
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530908 private boolean isFeatureDefinedInNode(YangNode node) throws DataModelException {
909 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
910 List<YangFeature> featureList = ((YangFeatureHolder) node).getFeatureList();
911 if (featureList != null && !featureList.isEmpty()) {
912 Iterator<YangFeature> iterator = featureList.iterator();
913 while (iterator.hasNext()) {
914 YangFeature feature = iterator.next();
915 if (ifFeature.getName().equals(feature.getName())) {
916 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
917 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeatureHolder(node);
918 return true;
919 }
920 }
921 }
922 return false;
923 }
924
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530925 /**
926 * Adds reference of grouping/typedef in uses/type.
927 *
928 * @param referredNode grouping/typedef node being referred
929 * @param linkedStatus linked status if success.
930 * @throws DataModelException a violation of data model rules
931 */
932 private void addReferredEntityLink(YangNode referredNode, ResolvableStatus linkedStatus)
933 throws DataModelException {
934 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +0530935 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
936 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530937 derivedInfo.setReferredTypeDef((YangTypeDef) referredNode);
938 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
939 ((YangUses) getCurrentEntityToResolveFromStack())
940 .setRefGroup((YangGrouping) referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530941 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
942 // do nothing , referred node is already set
janani be18b5342016-07-13 21:06:41 +0530943 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
944 // do nothing , referred node is already set
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530945 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
946 ((YangBase) getCurrentEntityToResolveFromStack()).setReferredIdentity((YangIdentity) referredNode);
947 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
948 ((YangIdentityRef) getCurrentEntityToResolveFromStack()).setReferredIdentity((YangIdentity) referredNode);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530949 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530950 throw new DataModelException("Data Model Exception: Entity to resolved is other than type" +
janani b23ccc312016-07-14 19:35:22 +0530951 "/uses/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530952 }
953
954 // Sets the resolution status in inside the type/uses.
955 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(linkedStatus);
956 }
957
958 /**
959 * Checks if type/grouping has further reference to typedef/ unresolved
960 * uses. Add it to the partial resolve stack and return the status of
961 * addition to stack.
962 *
963 * @param referredNode grouping/typedef node
964 * @throws DataModelException a violation of data model rules
965 */
966 private void addUnresolvedRecursiveReferenceToStack(YangNode referredNode)
967 throws DataModelException {
968 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
969 /*
970 * Checks if typedef type is derived
971 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530972 if (((YangTypeDef) referredNode).getTypeDefBaseType().getDataType() == YangDataTypes.DERIVED) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530973
Bharat saraswal96dfef02016-06-16 00:29:12 +0530974 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530975 unResolvedEntityInfo.setEntityToResolve(((YangTypeDef) referredNode)
976 .getTypeDefBaseType());
977 unResolvedEntityInfo.setHolderOfEntityToResolve(referredNode);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530978 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530979 }
980
981 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
982 /*
983 * Search if the grouping has any un resolved uses child, if so
984 * return true, else return false.
985 */
986 addUnResolvedUsesToStack(referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530987 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
988 addUnResolvedIfFeatureToStack(referredNode);
janani be18b5342016-07-13 21:06:41 +0530989 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
990 // do nothing , referred node is already set
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530991 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530992 } else if ((getCurrentEntityToResolveFromStack() instanceof YangBase) ||
993 (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef)) {
994 /*
995 * Search if the identity has any un resolved base, if so return true, else return false.
996 */
997 addUnResolvedBaseToStack(referredNode);
998 } else {
999 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses/" +
janani b23ccc312016-07-14 19:35:22 +05301000 "base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301001 }
1002 }
1003
1004 /**
1005 * Returns if there is any unresolved uses in grouping.
1006 *
1007 * @param node grouping/typedef node
1008 */
1009 private void addUnResolvedUsesToStack(YangNode node) {
1010
1011 /**
1012 * Search the grouping node's children for presence of uses node.
1013 */
Vidyashree Rama36f2fab2016-07-15 14:06:56 +05301014 TraversalType curTraversal = ROOT;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301015 YangNode curNode = node.getChild();
1016 while (curNode != null) {
Vidyashree Rama36f2fab2016-07-15 14:06:56 +05301017 if (curNode.getName().equals(node.getName())) {
1018 // if we have traversed all the child nodes, then exit from loop
1019 return;
1020 }
1021
1022 // if child nodes has uses, then add it to resolution stack
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301023 if (curNode instanceof YangUses) {
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301024 YangEntityToResolveInfoImpl<YangUses> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301025 unResolvedEntityInfo.setEntityToResolve((YangUses) curNode);
1026 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301027 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301028 }
Vidyashree Rama36f2fab2016-07-15 14:06:56 +05301029
1030 // Traversing all the child nodes of grouping
1031 if (curTraversal != PARENT && curNode.getChild() != null) {
1032 curTraversal = CHILD;
1033 curNode = curNode.getChild();
1034 } else if (curNode.getNextSibling() != null) {
1035 curTraversal = SIBILING;
1036 curNode = curNode.getNextSibling();
1037 } else {
1038 curTraversal = PARENT;
1039 curNode = curNode.getParent();
1040 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301041 }
1042 }
1043
1044 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301045 * Returns if there is any unresolved if-feature in feature.
1046 *
1047 * @param node module/submodule node
1048 */
1049 private void addUnResolvedIfFeatureToStack(YangNode node) {
1050 YangFeature refFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeature();
1051 List<YangIfFeature> ifFeatureList = refFeature.getIfFeatureList();
1052 if (ifFeatureList != null && !ifFeatureList.isEmpty()) {
1053 Iterator<YangIfFeature> ifFeatureIterator = ifFeatureList.iterator();
1054 while (ifFeatureIterator.hasNext()) {
1055 YangIfFeature ifFeature = ifFeatureIterator.next();
1056 YangEntityToResolveInfo<YangIfFeature> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
1057 unResolvedEntityInfo.setEntityToResolve(ifFeature);
1058 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
1059 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
1060 }
1061 }
1062 }
1063
1064 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301065 * Returns if there is any unresolved base in identity.
1066 *
1067 * @param node module/submodule node
1068 */
1069 private void addUnResolvedBaseToStack(YangNode node) {
1070
1071 YangIdentity curNode = (YangIdentity) node;
1072 if (curNode.getBaseNode() != null) {
1073 if (curNode.getBaseNode().getResolvableStatus() != RESOLVED) {
1074 YangEntityToResolveInfoImpl<YangBase> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
1075 unResolvedEntityInfo.setEntityToResolve(curNode.getBaseNode());
1076 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
1077 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
1078
1079 }
1080 }
1081 }
1082
1083
1084 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301085 * Returns stack of YANG type with partially resolved YANG construct
1086 * hierarchy.
1087 *
1088 * @return partial resolved YANG construct stack
1089 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301090 private Stack<YangEntityToResolveInfoImpl<T>> getPartialResolvedStack() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301091 return partialResolvedStack;
1092 }
1093
1094 /**
1095 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
1096 *
1097 * @param partialResolvedStack partial resolved YANG construct stack
1098 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301099 private void setPartialResolvedStack(Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301100 this.partialResolvedStack = partialResolvedStack;
1101 }
1102
1103 /**
1104 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
1105 *
1106 * @param partialResolvedInfo partial resolved YANG construct stack
1107 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301108 private void addInPartialResolvedStack(YangEntityToResolveInfoImpl<T> partialResolvedInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301109 getPartialResolvedStack().push(partialResolvedInfo);
1110 }
1111
1112 /**
1113 * Retrieves the next entity in the stack that needs to be resolved. It is
1114 * assumed that the caller ensures that the stack is not empty.
1115 *
1116 * @return next entity in the stack that needs to be resolved
1117 */
1118 private T getCurrentEntityToResolveFromStack() {
1119 return getPartialResolvedStack().peek().getEntityToResolve();
1120 }
1121
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301122 @Override
1123 public YangEntityToResolveInfoImpl<T> getEntityToResolveInfo() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301124 return entityToResolveInfo;
1125 }
1126
1127 /**
1128 * Sets information about the entity that needs to be resolved.
1129 *
1130 * @param entityToResolveInfo information about the entity that needs to be
1131 * resolved
1132 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301133 private void setEntityToResolveInfo(YangEntityToResolveInfoImpl<T> entityToResolveInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301134 this.entityToResolveInfo = entityToResolveInfo;
1135 }
1136
1137 @Override
1138 public int getLineNumber() {
1139 return lineNumber;
1140 }
1141
1142 @Override
1143 public int getCharPosition() {
1144 return charPosition;
1145 }
1146
1147 @Override
1148 public void setLineNumber(int lineNumber) {
1149 this.lineNumber = lineNumber;
1150 }
1151
1152 @Override
1153 public void setCharPosition(int charPositionInLine) {
1154 this.charPosition = charPositionInLine;
1155 }
1156
1157 /**
1158 * Returns current module/sub-module reference, will be used in inter-file/
1159 * inter-jar scenario to get the import/include list.
1160 *
1161 * @return current module/sub-module reference
1162 */
1163 private YangReferenceResolver getCurReferenceResolver() {
1164 return curReferenceResolver;
1165 }
1166
1167 /**
1168 * Sets current module/sub-module reference, will be used in inter-file/
1169 * inter-jar scenario to get the import/include list.
1170 *
1171 * @param curReferenceResolver current module/sub-module reference
1172 */
1173 private void setCurReferenceResolver(YangReferenceResolver curReferenceResolver) {
1174 this.curReferenceResolver = curReferenceResolver;
1175 }
1176
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301177 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301178 public void linkInterFile(YangReferenceResolver dataModelRootNode)
1179 throws DataModelException {
1180
1181 setCurReferenceResolver(dataModelRootNode);
1182
1183 // Current node to resolve, it can be a YANG type or YANG uses.
1184 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
1185
1186 // Check if linking is already done
1187 if (entityToResolve instanceof Resolvable) {
1188 Resolvable resolvable = (Resolvable) entityToResolve;
1189 if (resolvable.getResolvableStatus() == RESOLVED) {
1190 return;
1191 }
1192 } else {
1193 throw new DataModelException("Data Model Exception: Entity to resolved is not Resolvable");
1194 }
1195
janani b23ccc312016-07-14 19:35:22 +05301196 if (entityToResolve instanceof YangXPathResolver && !(entityToResolve instanceof YangLeafRef)) {
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301197 //Process x-path linking.
janani b23ccc312016-07-14 19:35:22 +05301198 processXPathLinking(entityToResolve, dataModelRootNode);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301199
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301200 } else {
janani be18b5342016-07-13 21:06:41 +05301201
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301202 // Push the initial entity to resolve in stack.
1203 addInPartialResolvedStack(getEntityToResolveInfo());
1204
1205 // Inter file linking and resolution.
1206 linkInterFileAndResolve();
1207
1208 addDerivedRefTypeToRefTypeResolutionList();
1209 }
1210 }
1211
1212 /**
1213 * Process x-path linking for augment and leaf-ref.
1214 *
janani b23ccc312016-07-14 19:35:22 +05301215 * @param entityToResolve entity to resolve
1216 * @param root root node
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301217 */
janani b23ccc312016-07-14 19:35:22 +05301218 private void processXPathLinking(T entityToResolve,
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301219 YangReferenceResolver root) {
janani b23ccc312016-07-14 19:35:22 +05301220
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301221 YangXpathLinker<T> xPathLinker = new YangXpathLinker<T>();
janani b23ccc312016-07-14 19:35:22 +05301222
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301223 if (entityToResolve instanceof YangAugment) {
1224 YangNode targetNode = null;
1225 YangAugment augment = (YangAugment) entityToResolve;
1226 targetNode = xPathLinker.processAugmentXpathLinking(augment.getTargetNode(),
1227 (YangNode) root);
1228 if (targetNode != null) {
1229 if (targetNode instanceof YangAugmentableNode) {
1230 detectCollisionForAugmentedNode(targetNode, augment);
1231 ((YangAugmentableNode) targetNode).addAugmentation(augment);
1232 augment.setAugmentedNode(targetNode);
1233 Resolvable resolvable = (Resolvable) entityToResolve;
1234 resolvable.setResolvableStatus(RESOLVED);
1235 } else {
1236 throw new LinkerException("Invalid target node type " + targetNode.getNodeType() + " for "
1237 + augment.getName());
1238 }
1239 } else {
1240 throw new LinkerException("Failed to link " + augment.getName());
1241 }
1242 } else if (entityToResolve instanceof YangLeafRef) {
1243 YangLeafRef leafRef = (YangLeafRef) entityToResolve;
1244 Object target = xPathLinker.processLeafRefXpathLinking(leafRef.getAtomicPath(),
janani b23ccc312016-07-14 19:35:22 +05301245 (YangNode) root, leafRef);
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301246 if (target != null) {
1247 YangLeaf leaf = null;
1248 YangLeafList leafList = null;
1249 leafRef.setReferredLeafOrLeafList(target);
1250 if (target instanceof YangLeaf) {
1251 leaf = (YangLeaf) target;
janani b23ccc312016-07-14 19:35:22 +05301252 leafRef.setResolvableStatus(INTER_FILE_LINKED);
1253 addUnResolvedLeafRefTypeToStack((T) leaf, getEntityToResolveInfo().getHolderOfEntityToResolve());
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301254 } else {
1255 leafList = (YangLeafList) target;
janani b23ccc312016-07-14 19:35:22 +05301256 leafRef.setResolvableStatus(INTER_FILE_LINKED);
1257 addUnResolvedLeafRefTypeToStack((T) leafList,
1258 getEntityToResolveInfo().getHolderOfEntityToResolve());
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301259 }
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301260 //TODO: add logic for leaf-ref for path predicates.
1261 } else {
janani b23ccc312016-07-14 19:35:22 +05301262 LinkerException linkerException = new LinkerException("YANG file error: Unable to find base " +
1263 "leaf/leaf-list for given leafref path "
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301264 + leafRef.getPath());
janani b23ccc312016-07-14 19:35:22 +05301265 linkerException.setCharPosition(leafRef.getCharPosition());
1266 linkerException.setLine(leafRef.getLineNumber());
1267 throw linkerException;
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301268 }
1269 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301270 }
1271
1272 /**
1273 * Returns the referenced prefix of entity under resolution.
1274 *
1275 * @return referenced prefix of entity under resolution
1276 * @throws DataModelException a violation in data model rule
1277 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301278 private String getRefPrefix()
1279 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301280 String refPrefix;
1281 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1282 refPrefix = ((YangType<?>) getCurrentEntityToResolveFromStack()).getPrefix();
1283 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1284 refPrefix = ((YangUses) getCurrentEntityToResolveFromStack()).getPrefix();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301285 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1286 refPrefix = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getPrefix();
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301287 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1288 refPrefix = ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getPrefix();
1289 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1290 refPrefix = ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getPrefix();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301291 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301292 throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
janani b23ccc312016-07-14 19:35:22 +05301293 "type/uses/base/identityref");
janani be18b5342016-07-13 21:06:41 +05301294 }
1295 return refPrefix;
1296 }
1297
1298 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301299 * Performs inter file linking and resolution.
1300 *
1301 * @throws DataModelException a violation in data model rule
1302 */
1303 private void linkInterFileAndResolve()
1304 throws DataModelException {
1305
1306 while (getPartialResolvedStack().size() != 0) {
1307
1308 // Current node to resolve, it can be a YANG type or YANG uses.
1309 T entityToResolve = getCurrentEntityToResolveFromStack();
1310 // Check if linking is already done
1311 if (entityToResolve instanceof Resolvable) {
1312
1313 Resolvable resolvable = (Resolvable) entityToResolve;
1314 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301315 case RESOLVED: {
1316 /*
1317 * If the entity is already resolved in the stack, then pop
1318 * it and continue with the remaining stack elements to
1319 * resolve
1320 */
1321 getPartialResolvedStack().pop();
1322 break;
1323 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301324
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301325 case INTER_FILE_LINKED: {
1326 /*
1327 * If the top of the stack is already linked then resolve
1328 * the references and pop the entity and continue with
1329 * remaining stack elements to resolve
1330 */
1331 resolveTopOfStack(INTER_FILE);
1332 getPartialResolvedStack().pop();
1333 break;
1334 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301335
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301336 case INTRA_FILE_RESOLVED: {
1337 /*
1338 * If the top of the stack is intra file resolved then check
1339 * if top of stack is linked, if not link it using
1340 * import/include list and push the linked referred entity
1341 * to the stack, otherwise only push it to the stack.
1342 */
1343 linkInterFileTopOfStackRefUpdateStack();
1344 break;
1345 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301346
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301347 case UNDEFINED: {
1348 /*
1349 * In case of if-feature resolution, if referred "feature" is not
1350 * defined then the resolvable status will be undefined.
1351 */
1352 getPartialResolvedStack().pop();
1353 break;
1354 }
1355
1356 default: {
1357 throw new DataModelException("Data Model Exception: Unsupported, linker state");
1358 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301359
1360 }
1361
1362 } else {
1363 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
1364 }
1365
1366 }
1367
1368 }
1369
1370 /**
1371 * Links the top of the stack if it's inter-file and update stack.
1372 *
1373 * @throws DataModelException data model error
1374 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301375 private void linkInterFileTopOfStackRefUpdateStack()
1376 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301377
janani b23ccc312016-07-14 19:35:22 +05301378 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1379 // When leafref path comes with relative path, it will be converted to absolute path.
1380 setAbsolutePathFromRelativePathInLeafref(getCurrentEntityToResolveFromStack());
1381 processXPathLinking(getCurrentEntityToResolveFromStack(), getCurReferenceResolver());
1382 return;
1383 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301384 /*
1385 * Obtain the referred node of top of stack entity under resolution
1386 */
1387 T referredNode = getRefNode();
1388
1389 /*
1390 * Check for null for scenario when it's not linked and inter-file
1391 * linking is required.
1392 */
1393 if (referredNode == null) {
1394
1395 /*
Bharat saraswal96dfef02016-06-16 00:29:12 +05301396 * Check if prefix is null or not, to identify whether to search in
1397 * import list or include list.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301398 */
Bharat saraswalcad0e652016-05-26 23:48:38 +05301399 if (getRefPrefix() != null && !getRefPrefix().contentEquals(getCurReferenceResolver().getPrefix())) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301400 if (resolveWithImport()) {
1401 return;
1402 }
1403 } else {
1404 if (resolveWithInclude()) {
1405 return;
1406 }
1407 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301408
1409 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1410 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setResolvableStatus(UNDEFINED);
1411 return;
1412 }
janani be18b5342016-07-13 21:06:41 +05301413 // If current entity is still not resolved, then
1414 // linking/resolution has failed.
1415 String errorInfo;
1416 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1417 errorInfo = TYPEDEF_LINKER_ERROR;
1418 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1419 errorInfo = GROUPING_LINKER_ERROR;
1420 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1421 errorInfo = FEATURE_LINKER_ERROR;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301422 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1423 errorInfo = BASE_LINKER_ERROR;
1424 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1425 errorInfo = IDENTITYREF_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +05301426 } else {
1427 errorInfo = LEAFREF_LINKER_ERROR;
1428 }
1429 DataModelException dataModelException = new DataModelException(errorInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301430 dataModelException.setLine(getLineNumber());
1431 dataModelException.setCharPosition(getCharPosition());
1432 throw dataModelException;
1433 } else {
janani b23ccc312016-07-14 19:35:22 +05301434 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
1435 addUnresolvedRecursiveReferenceToStack((YangNode) referredNode);
1436 }
1437 }
1438
1439 /**
1440 * Sets the leafref with absolute path from the relative path.
1441 *
1442 * @param resolutionInfo information about the YANG construct which has to be resolved
1443 * @throws DataModelException a violation of data model rules
1444 */
Vidyashree Rama36f2fab2016-07-15 14:06:56 +05301445 public void setAbsolutePathFromRelativePathInLeafref(T resolutionInfo) throws DataModelException {
janani b23ccc312016-07-14 19:35:22 +05301446 if (resolutionInfo instanceof YangLeafRef) {
1447
1448 YangNode parentOfLeafref = ((YangLeafRef) resolutionInfo).getParentNodeOfLeafref();
1449 YangLeafRef leafref = (YangLeafRef) resolutionInfo;
1450
1451 // Checks if the leafref has relative path in it.
1452 if (leafref.getPathType() == YangPathArgType.RELATIVE_PATH) {
1453 YangRelativePath relativePath = leafref.getRelativePath();
1454 List<YangAtomicPath> absoluteInRelative = relativePath.getAtomicPathList();
1455 int numberOfAncestors = relativePath.getAncestorNodeCount();
1456
1457 // Gets the root node from the ancestor count.
1458 T nodeOrAugmentList = getRootNodeWithAncestorCountForLeafref(numberOfAncestors, parentOfLeafref,
1459 leafref);
1460 if (nodeOrAugmentList instanceof YangNode) {
1461 String pathNameToBePrefixed = EMPTY_STRING;
1462 YangNode rootNode = (YangNode) nodeOrAugmentList;
1463 // Forms a new absolute path from the relative path
1464 while (!(rootNode instanceof YangReferenceResolver)) {
1465 pathNameToBePrefixed = rootNode.getName() + SLASH_FOR_STRING + pathNameToBePrefixed;
1466 rootNode = rootNode.getParent();
1467 if (rootNode == null) {
1468 throw new DataModelException("Internal datamodel error: Datamodel tree is not correct");
1469 }
1470 }
1471 fillAbsolutePathValuesInLeafref(leafref, pathNameToBePrefixed, absoluteInRelative);
1472 } else {
1473 List<String> listOfAugment = (List<String>) nodeOrAugmentList;
1474 Iterator<String> listOfAugmentIterator = listOfAugment.listIterator();
1475 String augment = EMPTY_STRING;
1476 while (listOfAugmentIterator.hasNext()) {
1477 augment = augment + SLASH_FOR_STRING + listOfAugmentIterator.next();
1478 }
1479 fillAbsolutePathValuesInLeafref(leafref, augment, absoluteInRelative);
janani be18b5342016-07-13 21:06:41 +05301480 }
janani be18b5342016-07-13 21:06:41 +05301481 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301482 }
1483 }
1484
1485 /**
janani b23ccc312016-07-14 19:35:22 +05301486 * Fills the absolute path values in the leafref from relative path.
1487 *
1488 * @param leafref instance of YANG leafref
1489 * @param pathNameToBePrefixed path name which has to be prefixed to relative path
1490 * @param atomicPathsInRelative atomic paths in relative
1491 * @throws DataModelException a violation of data model rules
1492 */
1493 private void fillAbsolutePathValuesInLeafref(YangLeafRef leafref, String pathNameToBePrefixed,
1494 List<YangAtomicPath> atomicPathsInRelative) throws DataModelException {
1495
1496 leafref.setPathType(YangPathArgType.ABSOLUTE_PATH);
1497 String[] pathName = new String[0];
1498 if (pathNameToBePrefixed != EMPTY_STRING && pathNameToBePrefixed != null) {
1499 pathName = pathNameToBePrefixed.split(SLASH_FOR_STRING);
1500 }
1501 List<YangAtomicPath> finalListForAbsolute = new LinkedList<>();
1502 for (String value : pathName) {
1503 if (value != null && !value.isEmpty() && value != EMPTY_STRING) {
1504 YangNodeIdentifier nodeIdentifier = getValidNodeIdentifier(value, YangConstructType.PATH_DATA);
1505 YangAtomicPath atomicPath = new YangAtomicPath();
1506 atomicPath.setNodeIdentifier(nodeIdentifier);
1507 finalListForAbsolute.add(atomicPath);
1508 }
1509 }
1510 if (atomicPathsInRelative != null && !atomicPathsInRelative.isEmpty()) {
1511 Iterator<YangAtomicPath> atomicPathIterator = atomicPathsInRelative.listIterator();
1512 while (atomicPathIterator.hasNext()) {
1513 YangAtomicPath yangAtomicPath = atomicPathIterator.next();
1514 finalListForAbsolute.add(yangAtomicPath);
1515 }
1516 leafref.setAtomicPath(finalListForAbsolute);
1517 } else {
1518 DataModelException dataModelException = new DataModelException("YANG file error: The target node, in the " +
1519 "leafref path " + leafref.getPath() + ", is invalid.");
1520 dataModelException.setCharPosition(leafref.getCharPosition());
1521 dataModelException.setLine(leafref.getLineNumber());
1522 throw dataModelException;
1523 }
1524 }
1525
1526 /**
1527 * Returns the root parent with respect to the ancestor count from leafref.
1528 *
1529 * @param ancestorCount count of node where parent node can be reached
1530 * @param currentParent current parent node
1531 * @param leafref instance of YANG leafref
1532 * @return node where the ancestor count stops or augment path name list
1533 * @throws DataModelException a violation of data model rules
1534 */
1535 private T getRootNodeWithAncestorCountForLeafref(int ancestorCount, YangNode currentParent, YangLeafRef leafref)
1536 throws DataModelException {
1537
1538 int currentParentCount = 1;
1539 currentParent = skipInvalidDataNodes(currentParent, leafref);
1540 if (currentParent instanceof YangAugment) {
1541 YangAugment augment = (YangAugment) currentParent;
1542 List<String> valueInAugment = getPathWithAugment(augment, ancestorCount - currentParentCount);
1543 return (T) valueInAugment;
1544 } else {
1545 while (currentParentCount < ancestorCount) {
1546 YangNode currentSkippedParent = skipInvalidDataNodes(currentParent, leafref);
1547 if (currentSkippedParent == currentParent) {
1548 if (currentParent.getParent() == null) {
1549 throw new DataModelException("YANG file error: The target node, in the leafref path "
1550 + leafref.getPath() + ", is invalid.");
1551 }
1552 currentParent = currentParent.getParent();
1553 } else {
1554 currentParent = currentSkippedParent;
1555 continue;
1556 }
1557 currentParentCount = currentParentCount + 1;
1558 if (currentParent instanceof YangAugment) {
1559 YangAugment augment = (YangAugment) currentParent;
1560 List<String> valueInAugment = getPathWithAugment(augment, ancestorCount - currentParentCount);
1561 return (T) valueInAugment;
1562 }
1563 }
1564 }
1565 return (T) currentParent;
1566 }
1567
1568 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301569 * Finds and resolves with include list.
1570 *
1571 * @return true if resolved, false otherwise
1572 * @throws DataModelException a violation in data model rule
1573 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301574 private boolean resolveWithInclude()
1575 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301576 /*
1577 * Run through all the nodes in include list and search for referred
1578 * typedef/grouping at the root level.
1579 */
1580 for (YangInclude yangInclude : getCurReferenceResolver().getIncludeList()) {
1581 YangNode linkedNode = null;
1582 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1583 linkedNode = findRefTypedef(yangInclude.getIncludedNode());
1584 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1585 linkedNode = findRefGrouping(yangInclude.getIncludedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301586 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1587 linkedNode = findRefFeature(yangInclude.getIncludedNode());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301588 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1589 linkedNode = findRefIdentity(yangInclude.getIncludedNode());
1590 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1591 linkedNode = findRefIdentityRef(yangInclude.getIncludedNode());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301592 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301593
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301594 if (linkedNode != null) {
1595 // Add the link to external entity.
1596 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
Vidyashree Rama07c26bb2016-07-28 17:33:15 +05301597
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301598 // Add the type/uses of referred typedef/grouping to the stack.
1599 addUnresolvedRecursiveReferenceToStack(linkedNode);
1600 return true;
1601 }
1602 }
1603 // If referred node can't be found return false.
1604 return false;
1605 }
1606
1607 /**
1608 * Finds and resolves with import list.
1609 *
1610 * @return true if resolved, false otherwise
1611 * @throws DataModelException a violation in data model rule
1612 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301613 private boolean resolveWithImport()
1614 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301615 /*
1616 * Run through import list to find the referred typedef/grouping.
1617 */
1618 for (YangImport yangImport : getCurReferenceResolver().getImportList()) {
1619 /*
1620 * Match the prefix attached to entity under resolution with the
1621 * imported/included module/sub-module's prefix. If found, search
1622 * for the referred typedef/grouping at the root level.
1623 */
1624 if (yangImport.getPrefixId().contentEquals(getRefPrefix())) {
1625 YangNode linkedNode = null;
1626 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1627 linkedNode = findRefTypedef(yangImport.getImportedNode());
1628 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1629 linkedNode = findRefGrouping(yangImport.getImportedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301630 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1631 linkedNode = findRefFeature(yangImport.getImportedNode());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301632 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1633 linkedNode = findRefIdentity(yangImport.getImportedNode());
1634 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1635 linkedNode = findRefIdentityRef(yangImport.getImportedNode());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301636 }
1637 if (linkedNode != null) {
1638 // Add the link to external entity.
1639 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
Vidyashree Rama07c26bb2016-07-28 17:33:15 +05301640
Bharat saraswal96dfef02016-06-16 00:29:12 +05301641 // Add the type/uses of referred typedef/grouping to the
1642 // stack.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301643 addUnresolvedRecursiveReferenceToStack(linkedNode);
1644 return true;
1645 }
1646 /*
1647 * If referred node can't be found at root level break for loop,
1648 * and return false.
1649 */
1650 break;
1651 }
1652 }
1653 // If referred node can't be found return false.
1654 return false;
1655 }
1656
1657 /**
1658 * Returns referred typedef/grouping node.
1659 *
1660 * @return referred typedef/grouping node
1661 * @throws DataModelException a violation in data model rule
1662 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301663 private T getRefNode()
1664 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301665 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +05301666 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
1667 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301668 return (T) derivedInfo.getReferredTypeDef();
1669 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1670 return (T) ((YangUses) getCurrentEntityToResolveFromStack()).getRefGroup();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301671 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1672 return (T) ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeatureHolder();
janani be18b5342016-07-13 21:06:41 +05301673 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1674 return (T) ((YangLeafRef) getCurrentEntityToResolveFromStack()).getReferredLeafOrLeafList();
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301675 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1676 return (T) ((YangBase) getCurrentEntityToResolveFromStack()).getReferredIdentity();
1677 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1678 return (T) ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getReferredIdentity();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301679 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301680 throw new DataModelException("Data Model Exception: Entity to resolved is other than type" +
janani b23ccc312016-07-14 19:35:22 +05301681 "/uses/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301682 }
1683 }
1684
1685 /**
1686 * Finds the referred grouping node at the root level of imported/included node.
1687 *
1688 * @param refNode module/sub-module node
1689 * @return referred grouping
1690 */
1691 private YangNode findRefGrouping(YangNode refNode) {
1692 YangNode tmpNode = refNode.getChild();
1693 while (tmpNode != null) {
1694 if (tmpNode instanceof YangGrouping) {
1695 if (tmpNode.getName()
1696 .equals(((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
1697 return tmpNode;
1698 }
1699 }
1700 tmpNode = tmpNode.getNextSibling();
1701 }
1702 return null;
1703 }
1704
1705 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301706 * Finds the referred feature node at the root level of imported/included node.
1707 *
1708 * @param refNode module/sub-module node
1709 * @return referred feature
1710 */
1711 private YangNode findRefFeature(YangNode refNode) {
1712 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
1713 List<YangFeature> featureList = ((YangFeatureHolder) refNode).getFeatureList();
1714
1715 if (featureList != null && !featureList.isEmpty()) {
1716 Iterator<YangFeature> iterator = featureList.iterator();
1717 while (iterator.hasNext()) {
1718 YangFeature feature = iterator.next();
1719 if (ifFeature.getName().equals(feature.getName())) {
1720 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
1721 return refNode;
1722 }
1723 }
1724 }
1725 return null;
1726 }
1727
1728 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301729 * Finds the referred typedef node at the root level of imported/included node.
1730 *
1731 * @param refNode module/sub-module node
1732 * @return referred typedef
1733 */
1734 private YangNode findRefTypedef(YangNode refNode) {
1735 YangNode tmpNode = refNode.getChild();
1736 while (tmpNode != null) {
1737 if (tmpNode instanceof YangTypeDef) {
1738 if (tmpNode.getName()
1739 .equals(((YangType) getCurrentEntityToResolveFromStack()).getDataTypeName())) {
1740 return tmpNode;
1741 }
1742 }
1743 tmpNode = tmpNode.getNextSibling();
1744 }
1745 return null;
1746 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301747
1748 /**
1749 * Finds the referred identity node at the root level of imported/included node.
1750 *
1751 * @param refNode module/sub-module node
1752 * @return referred identity
1753 */
1754 private YangNode findRefIdentity(YangNode refNode) {
1755 YangNode tmpNode = refNode.getChild();
1756 while (tmpNode != null) {
1757 if (tmpNode instanceof YangIdentity) {
1758 if (tmpNode.getName()
1759 .equals(((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName())) {
1760 return tmpNode;
1761 }
1762 }
1763 tmpNode = tmpNode.getNextSibling();
1764 }
1765 return null;
1766 }
1767
1768 /**
1769 * Finds the referred identity node at the root level of imported/included node.
1770 *
1771 * @param refNode module/sub-module node
1772 * @return referred identity
1773 */
1774 private YangNode findRefIdentityRef(YangNode refNode) {
1775 YangNode tmpNode = refNode.getChild();
1776 while (tmpNode != null) {
1777 if (tmpNode instanceof YangIdentity) {
1778 if (tmpNode.getName()
1779 .equals(((YangIdentityRef) getCurrentEntityToResolveFromStack())
janani b23ccc312016-07-14 19:35:22 +05301780 .getBaseIdentity().getName())) {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301781 return tmpNode;
1782 }
1783 }
1784 tmpNode = tmpNode.getNextSibling();
1785 }
1786 return null;
1787 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301788}