blob: 923bdfe7bf1cc2560f00028ef6ab5088a9410318 [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 org.onosproject.yangutils.datamodel.Resolvable;
janani be18b5342016-07-13 21:06:41 +053020import org.onosproject.yangutils.datamodel.ResolvableType;
21import org.onosproject.yangutils.datamodel.YangAtomicPath;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053022import org.onosproject.yangutils.datamodel.YangAugment;
23import org.onosproject.yangutils.datamodel.YangAugmentableNode;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +053024import org.onosproject.yangutils.datamodel.YangBase;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053025import org.onosproject.yangutils.datamodel.YangDerivedInfo;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053026import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
janani b23ccc312016-07-14 19:35:22 +053027import org.onosproject.yangutils.datamodel.YangEntityToResolveInfoImpl;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053028import org.onosproject.yangutils.datamodel.YangFeature;
29import org.onosproject.yangutils.datamodel.YangFeatureHolder;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053030import org.onosproject.yangutils.datamodel.YangGrouping;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +053031import org.onosproject.yangutils.datamodel.YangIdentity;
32import org.onosproject.yangutils.datamodel.YangIdentityRef;
Bharat saraswalb551aae2016-07-14 15:18:20 +053033import org.onosproject.yangutils.datamodel.YangIfFeature;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053034import org.onosproject.yangutils.datamodel.YangImport;
35import org.onosproject.yangutils.datamodel.YangInclude;
janani be18b5342016-07-13 21:06:41 +053036import org.onosproject.yangutils.datamodel.YangInput;
37import org.onosproject.yangutils.datamodel.YangLeaf;
38import org.onosproject.yangutils.datamodel.YangLeafList;
39import org.onosproject.yangutils.datamodel.YangLeafRef;
janani be18b5342016-07-13 21:06:41 +053040import org.onosproject.yangutils.datamodel.YangModule;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053041import org.onosproject.yangutils.datamodel.YangNode;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053042import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
janani be18b5342016-07-13 21:06:41 +053043import org.onosproject.yangutils.datamodel.YangOutput;
44import org.onosproject.yangutils.datamodel.YangPathArgType;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053045import org.onosproject.yangutils.datamodel.YangReferenceResolver;
janani be18b5342016-07-13 21:06:41 +053046import org.onosproject.yangutils.datamodel.YangRelativePath;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053047import org.onosproject.yangutils.datamodel.YangResolutionInfo;
janani be18b5342016-07-13 21:06:41 +053048import org.onosproject.yangutils.datamodel.YangRpc;
49import org.onosproject.yangutils.datamodel.YangSubModule;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053050import org.onosproject.yangutils.datamodel.YangType;
51import org.onosproject.yangutils.datamodel.YangTypeDef;
52import org.onosproject.yangutils.datamodel.YangUses;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053053import org.onosproject.yangutils.datamodel.YangXPathResolver;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053054import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Bharat saraswal96dfef02016-06-16 00:29:12 +053055import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
janani b23ccc312016-07-14 19:35:22 +053056import org.onosproject.yangutils.datamodel.utils.YangConstructType;
janani be18b5342016-07-13 21:06:41 +053057import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053058import org.onosproject.yangutils.linker.YangLinkingPhase;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053059import org.onosproject.yangutils.linker.exceptions.LinkerException;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053060
janani b23ccc312016-07-14 19:35:22 +053061import java.io.Serializable;
62import java.util.Iterator;
63import java.util.LinkedList;
64import java.util.List;
65import java.util.Stack;
66
67import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.addResolutionInfo;
Bharat saraswal96dfef02016-06-16 00:29:12 +053068import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTER_FILE_LINKED;
69import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
70import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.LINKED;
71import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053072import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNDEFINED;
Bharat saraswal96dfef02016-06-16 00:29:12 +053073import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNRESOLVED;
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +053074import static org.onosproject.yangutils.linker.YangLinkingPhase.INTER_FILE;
75import static org.onosproject.yangutils.linker.YangLinkingPhase.INTRA_FILE;
Bharat saraswalb1170bd2016-07-14 13:26:18 +053076import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.detectCollisionForAugmentedNode;
janani b23ccc312016-07-14 19:35:22 +053077import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getPathWithAugment;
78import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getValidNodeIdentifier;
79import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.skipInvalidDataNodes;
Bharat saraswalb551aae2016-07-14 15:18:20 +053080import static org.onosproject.yangutils.utils.UtilConstants.BASE_LINKER_ERROR;
janani b23ccc312016-07-14 19:35:22 +053081import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +053082import static org.onosproject.yangutils.utils.UtilConstants.FEATURE_LINKER_ERROR;
Vidyashree Rama210c01d2016-05-20 16:29:25 +053083import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
Bharat saraswalb551aae2016-07-14 15:18:20 +053084import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF;
85import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +053086import static org.onosproject.yangutils.utils.UtilConstants.INPUT;
87import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF;
88import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF_LINKER_ERROR;
89import static org.onosproject.yangutils.utils.UtilConstants.OUTPUT;
janani b23ccc312016-07-14 19:35:22 +053090import static org.onosproject.yangutils.utils.UtilConstants.SLASH_FOR_STRING;
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053091import static org.onosproject.yangutils.utils.UtilConstants.TYPEDEF_LINKER_ERROR;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053092
93/**
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053094 * Represents implementation of resolution object which will be resolved by
95 * linker.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +053096 *
97 * @param <T> type of resolution entity uses / type
98 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +053099public class YangResolutionInfoImpl<T>
Bharat saraswal96dfef02016-06-16 00:29:12 +0530100 implements YangResolutionInfo<T>, Serializable {
101
102 private static final long serialVersionUID = 806201658L;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530103
104 /**
105 * Information about the entity that needs to be resolved.
106 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530107 private YangEntityToResolveInfoImpl<T> entityToResolveInfo;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530108
109 /**
110 * Error line number.
111 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530112 private transient int lineNumber;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530113
114 /**
115 * Error character position in number.
116 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530117 private transient int charPosition;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530118
119 /**
120 * Current module/sub-module reference, will be used in inter-file/
121 * inter-jar scenario to get the import/include list.
122 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530123 private transient YangReferenceResolver curReferenceResolver;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530124
125 /**
126 * Stack for type/uses is maintained for hierarchical references, this is
127 * used during resolution.
128 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530129 private Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530130
131 /**
132 * It is private to ensure the overloaded method be invoked to create an
133 * object.
134 */
135 @SuppressWarnings("unused")
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530136 private YangResolutionInfoImpl() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530137 }
138
139 /**
140 * Creates a resolution information object with all the inputs.
141 *
142 * @param dataNode current parsable data node
143 * @param holderNode parent YANG node
144 * @param lineNumber error line number
145 * @param charPositionInLine error character position in line
146 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530147 public YangResolutionInfoImpl(T dataNode, YangNode holderNode, int lineNumber, int charPositionInLine) {
148 setEntityToResolveInfo(new YangEntityToResolveInfoImpl<>());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530149 getEntityToResolveInfo().setEntityToResolve(dataNode);
150 getEntityToResolveInfo().setHolderOfEntityToResolve(holderNode);
151 this.setLineNumber(lineNumber);
152 this.setCharPosition(charPositionInLine);
153 setPartialResolvedStack(new Stack<>());
154 }
155
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530156 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530157 public void resolveLinkingForResolutionInfo(YangReferenceResolver dataModelRootNode)
158 throws DataModelException {
159
160 setCurReferenceResolver(dataModelRootNode);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530161 /**
162 * Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature or
163 * YANG leafref or YANG base or YANG identityref.
164 */
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530165 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
166
167 // Check if linking is already done
168 if (entityToResolve instanceof Resolvable) {
169 Resolvable resolvable = (Resolvable) entityToResolve;
170 if (resolvable.getResolvableStatus() == RESOLVED) {
171 /**
172 * entity is already resolved, so nothing to do
173 */
174 return;
175 }
176 } else {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530177 throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530178 "type/uses/if-feature/leafref/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530179 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530180 // Push the initial entity to resolve in stack.
181 addInPartialResolvedStack(getEntityToResolveInfo());
182
183 linkAndResolvePartialResolvedStack();
janani be18b5342016-07-13 21:06:41 +0530184
185 addDerivedRefTypeToRefTypeResolutionList();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530186 }
187
188 /**
189 * Resolves linking with ancestors.
190 *
191 * @throws DataModelException a violation of data model rules
192 */
193 private void linkAndResolvePartialResolvedStack()
194 throws DataModelException {
195
196 while (getPartialResolvedStack().size() != 0) {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530197 /**
198 * Current node to resolve, it can be a YANG type or YANG uses or
199 * YANG if-feature or YANG leafref or YANG base or YANG identityref.
200 */
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530201 T entityToResolve = getCurrentEntityToResolveFromStack();
202 // Check if linking is already done
203 if (entityToResolve instanceof Resolvable) {
204
205 Resolvable resolvable = (Resolvable) entityToResolve;
206 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530207 case RESOLVED: {
208 /*
209 * If the entity is already resolved in the stack, then pop
210 * it and continue with the remaining stack elements to
211 * resolve
212 */
213 getPartialResolvedStack().pop();
214 break;
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530215 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530216
217 case LINKED: {
218 /*
219 * If the top of the stack is already linked then resolve
220 * the references and pop the entity and continue with
221 * remaining stack elements to resolve.
222 */
223 resolveTopOfStack(INTRA_FILE);
224 getPartialResolvedStack().pop();
225 break;
226 }
227
228 case INTRA_FILE_RESOLVED: {
229 /*
230 * Pop the top of the stack.
231 */
232 getPartialResolvedStack().pop();
233 break;
234 }
235
236 case UNRESOLVED: {
237 linkTopOfStackReferenceUpdateStack();
238
239 if (resolvable.getResolvableStatus() == UNRESOLVED) {
240 // If current entity is still not resolved, then
241 // linking/resolution has failed.
242 String errorInfo;
243 if (resolvable instanceof YangType) {
244 errorInfo = TYPEDEF_LINKER_ERROR;
245 } else if (resolvable instanceof YangUses) {
246 errorInfo = GROUPING_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +0530247 } else if (resolvable instanceof YangIfFeature) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530248 errorInfo = FEATURE_LINKER_ERROR;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530249 } else if (resolvable instanceof YangBase) {
250 errorInfo = BASE_LINKER_ERROR;
251 } else if (resolvable instanceof YangIdentityRef) {
252 errorInfo = IDENTITYREF_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +0530253 } else {
254 errorInfo = LEAFREF_LINKER_ERROR;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530255 }
256 DataModelException dataModelException =
257 new DataModelException(errorInfo);
258 dataModelException.setLine(getLineNumber());
259 dataModelException.setCharPosition(getCharPosition());
260 throw dataModelException;
261 }
262 break;
263 }
264 default: {
265 throw new DataModelException("Data Model Exception: Unsupported, linker state");
266 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530267
268 }
269
270 } else {
janani be18b5342016-07-13 21:06:41 +0530271 throw new DataModelException(
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530272 "Data Model Exception: Entity to resolved is other than type/uses/if-feature" +
273 "/leafref/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530274 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530275 }
276
277 }
278
279 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530280 * Adds the leafref/identityref type to the type, which has derived type referring to
281 * typedef with leafref/identityref type.
janani be18b5342016-07-13 21:06:41 +0530282 */
283 private void addDerivedRefTypeToRefTypeResolutionList() throws DataModelException {
284
285 YangNode potentialAncestorWithReferredNode = getEntityToResolveInfo().getHolderOfEntityToResolve();
286
287 // If holder is typedef return.
288 if (potentialAncestorWithReferredNode instanceof YangTypeDef) {
289 return;
290 }
291
292 // If entity is not type return.
293 if (!(getEntityToResolveInfo().getEntityToResolve() instanceof YangType)) {
294 return;
295 }
296
297 YangType yangType = (YangType) getEntityToResolveInfo().getEntityToResolve();
298
299 // If type is not resolved return.
300 if (yangType.getResolvableStatus() != RESOLVED) {
301 return;
302 }
303
304 YangDerivedInfo derivedInfo = (YangDerivedInfo) yangType.getDataTypeExtendedInfo();
305
306 /*
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530307 * If the derived types referred type is not leafref/identityref return
janani be18b5342016-07-13 21:06:41 +0530308 */
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530309 if ((derivedInfo.getEffectiveBuiltInType() != YangDataTypes.LEAFREF) &&
310 (derivedInfo.getEffectiveBuiltInType() != YangDataTypes.IDENTITYREF)) {
janani be18b5342016-07-13 21:06:41 +0530311 return;
312 }
313
314 T extendedInfo = (T) derivedInfo.getReferredTypeDef().getTypeDefBaseType().getDataTypeExtendedInfo();
315
316 while (extendedInfo instanceof YangDerivedInfo) {
317 YangDerivedInfo derivedInfoFromTypedef = (YangDerivedInfo) extendedInfo;
318 extendedInfo = (T) derivedInfoFromTypedef.getReferredTypeDef().getTypeDefBaseType()
319 .getDataTypeExtendedInfo();
320 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530321
janani be18b5342016-07-13 21:06:41 +0530322 /*
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530323 * Backup the derived types leafref/identityref info, delete all the info in current type,
324 * but for resolution status as resolved. Copy the backed up leafref/identityref to types extended info,
325 * create a leafref/identityref resolution info using the current resolution info and
326 * add to leafref/identityref resolution list.
janani be18b5342016-07-13 21:06:41 +0530327 */
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530328 if (derivedInfo.getEffectiveBuiltInType() == YangDataTypes.LEAFREF) {
329 YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
330 yangType.resetYangType();
janani be18b5342016-07-13 21:06:41 +0530331
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530332 yangType.setResolvableStatus(RESOLVED);
333 yangType.setDataType(YangDataTypes.LEAFREF);
334 yangType.setDataTypeName(LEAFREF);
335 yangType.setDataTypeExtendedInfo(leafRefInTypeDef);
336 leafRefInTypeDef.setResolvableStatus(UNRESOLVED);
janani b23ccc312016-07-14 19:35:22 +0530337 leafRefInTypeDef.setParentNodeOfLeafref(potentialAncestorWithReferredNode);
janani be18b5342016-07-13 21:06:41 +0530338
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530339 // Add resolution information to the list.
340 YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(leafRefInTypeDef,
janani b23ccc312016-07-14 19:35:22 +0530341 potentialAncestorWithReferredNode,
342 getLineNumber(), getCharPosition());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530343 getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
janani b23ccc312016-07-14 19:35:22 +0530344 ResolvableType.YANG_LEAFREF);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530345 getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_LEAFREF);
346
347 } else if (derivedInfo.getEffectiveBuiltInType() == YangDataTypes.IDENTITYREF) {
348
349 YangIdentityRef identityRefInTypeDef = (YangIdentityRef) extendedInfo;
350 yangType.resetYangType();
351
352 yangType.setResolvableStatus(RESOLVED);
353 yangType.setDataType(YangDataTypes.IDENTITYREF);
354 yangType.setDataTypeName(IDENTITYREF);
355 yangType.setDataTypeExtendedInfo(identityRefInTypeDef);
356 identityRefInTypeDef.setResolvableStatus(UNRESOLVED);
357
358 // Add resolution information to the list.
359 YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(identityRefInTypeDef,
janani b23ccc312016-07-14 19:35:22 +0530360 potentialAncestorWithReferredNode, getLineNumber(), getCharPosition());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530361 getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
janani b23ccc312016-07-14 19:35:22 +0530362 ResolvableType.YANG_IDENTITYREF);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530363 getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_IDENTITYREF);
364 }
janani be18b5342016-07-13 21:06:41 +0530365 }
366
367 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530368 * Resolves the current entity in the stack.
369 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530370 private void resolveTopOfStack(YangLinkingPhase linkingPhase)
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530371 throws DataModelException {
janani b23ccc312016-07-14 19:35:22 +0530372 List<T> entityToResolve = (List<T>) ((Resolvable) getCurrentEntityToResolveFromStack()).resolve();
373 if (entityToResolve != null && !entityToResolve.isEmpty()) {
374 Iterator<T> entityToResolveIterator = entityToResolve.listIterator();
375 while (entityToResolveIterator.hasNext()) {
376 addUnresolvedEntitiesToStack(entityToResolveIterator.next());
377 }
378 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530379 if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != INTRA_FILE_RESOLVED
380 && ((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != UNDEFINED) {
janani be18b5342016-07-13 21:06:41 +0530381 // Sets the resolution status in inside the type/uses/if-feature/leafref.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530382 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(RESOLVED);
383 }
384 }
385
386 /**
janani b23ccc312016-07-14 19:35:22 +0530387 * Adds the unresolved entities to the resolution list.
388 *
389 * @param entityToResolve entity to resolve
390 * @throws DataModelException a violation of data model rules
391 */
392 private void addUnresolvedEntitiesToStack(T entityToResolve) throws DataModelException {
393 if (entityToResolve instanceof YangEntityToResolveInfoImpl) {
394 YangEntityToResolveInfoImpl entityToResolveInfo = (YangEntityToResolveInfoImpl) entityToResolve;
395 if (entityToResolveInfo.getEntityToResolve() instanceof YangLeafRef) {
396 YangLeafRef leafref = (YangLeafRef) entityToResolveInfo.getEntityToResolve();
397 YangNode parentNodeOfLeafref = entityToResolveInfo.getHolderOfEntityToResolve();
398 leafref.setParentNodeOfLeafref(parentNodeOfLeafref);
399 if (leafref.getResolvableStatus() == UNRESOLVED) {
400 leafref.setResolvableStatus(INTRA_FILE_RESOLVED);
401 }
402 // Add resolution information to the list.
403 YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<YangLeafRef>(leafref,
404 parentNodeOfLeafref, entityToResolveInfo.getLineNumber(),
405 entityToResolveInfo.getCharPosition());
406 addResolutionInfo(resolutionInfoImpl);
407 }
408 }
409 }
410
411 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530412 * Resolves linking for a node child and siblings.
413 *
414 * @throws DataModelException data model error
415 */
416 private void linkTopOfStackReferenceUpdateStack()
417 throws DataModelException {
418
janani b23ccc312016-07-14 19:35:22 +0530419 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
420 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
421 return;
422 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530423 /*
424 * Check if self file reference is there, this will not check for the
425 * scenario when prefix is not present and type/uses is present in
426 * sub-module from include list.
427 */
428 if (!isCandidateForSelfFileReference()) {
429 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
430 return;
431 }
432
433 /**
434 * Try to resolve the top of the stack and update partial resolved stack
435 * if there is recursive references
436 */
437 YangNode potentialAncestorWithReferredNode = getPartialResolvedStack().peek()
438 .getHolderOfEntityToResolve();
439
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530440 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
441 resolveSelfFileLinkingForIfFeature(potentialAncestorWithReferredNode);
442 return;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530443 } else if ((getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) ||
444 (getCurrentEntityToResolveFromStack() instanceof YangBase)) {
445 resolveSelfFileLinkingForBaseAndIdentityref();
446 return;
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530447 } else {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530448
449 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530450 * Traverse up in the ancestor tree to check if the referred node is
451 * defined
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530452 */
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530453 while (potentialAncestorWithReferredNode != null) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530454
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530455 /**
456 * Check for the referred node defined in a ancestor scope
457 */
458 YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
459 if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
460 return;
461 }
462
463 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
464 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530465 }
466
467 /*
468 * In case prefix is not present it's a candidate for inter-file
469 * resolution via include list.
470 */
471 if (getRefPrefix() == null) {
472 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
473 }
474 }
475
476 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530477 * Resolves self file linking for base/identityref.
478 *
479 * @throws DataModelException a violation of data model rules
480 */
481 private void resolveSelfFileLinkingForBaseAndIdentityref()
482 throws DataModelException {
483
484 boolean referredIdentityFound = false;
485 String nodeName = null;
486
487 if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
janani b23ccc312016-07-14 19:35:22 +0530488 nodeName = ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getName();
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530489 }
490
491 if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
492 nodeName = ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName();
493 }
494
495 if (getCurReferenceResolver() instanceof YangModule) {
496 YangModule rootNode = (YangModule) getCurReferenceResolver();
497 // Sends list of nodes for finding the target identity.
498 referredIdentityFound = isIdentityReferenceFound(nodeName, rootNode);
499 } else if (getCurReferenceResolver() instanceof YangSubModule) {
500 YangSubModule rootNode = (YangSubModule) getCurReferenceResolver();
501 // Sends list of nodes for finding the target identity.
502 referredIdentityFound = isIdentityReferenceFound(nodeName, rootNode);
503 }
504
505 if (referredIdentityFound) {
506 return;
507 }
508
509 /*
510 * In case prefix is not present it's a candidate for inter-file resolution via include list.
511 */
512 if (getRefPrefix() == null) {
513 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
514 }
515 }
516
517 /**
janani be18b5342016-07-13 21:06:41 +0530518 * Returns the root parent with respect to the ancestor count from leafref.
519 *
520 * @param ancestorCount count of node where parent node can be reached
521 * @param currentParent current parent node
522 * @return root node
523 * @throws DataModelException a violation of data model rules
524 */
525 private YangNode getRootNodeWithAncestorCount(int ancestorCount, YangNode currentParent)
526 throws DataModelException {
527
528 int currentParentCount = 1;
529 while (currentParentCount < ancestorCount) {
530 if (currentParent.getParent() == null) {
531 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
532 }
533 currentParent = currentParent.getParent();
534 currentParentCount = currentParentCount + 1;
535 }
536 return currentParent;
537 }
538
539 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530540 * Resolves self file linking for if-feature.
541 *
542 * @param potentialAncestorWithReferredNode if-feature holder node
543 * @throws DataModelException DataModelException a violation of data model
544 * rules
545 */
546 private void resolveSelfFileLinkingForIfFeature(YangNode potentialAncestorWithReferredNode)
547 throws DataModelException {
548
549 YangFeatureHolder featureHolder = getFeatureHolder(potentialAncestorWithReferredNode);
550 YangNode potentialReferredNode = (YangNode) featureHolder;
551 if (isReferredNode(potentialReferredNode)) {
552
553 // Adds reference link of entity to the node under resolution.
554 addReferredEntityLink(potentialReferredNode, LINKED);
555
556 /**
557 * resolve the reference and update the partial resolution stack
558 * with any further recursive references
559 */
560 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
561 return;
562 }
563
564 /*
565 * In case prefix is not present it's a candidate for inter-file
566 * resolution via include list.
567 */
568 if (getRefPrefix() == null) {
569 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
570 }
571 }
572
janani be18b5342016-07-13 21:06:41 +0530573 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530574 * Returns the status of the referred identity found for base/identityref.
575 *
janani b23ccc312016-07-14 19:35:22 +0530576 * @param nodeName the name of the base nodeidentifier/identityref nodeidentifier
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530577 * @param ancestorWithTheReferredNode the parent node of base/identityref
578 * @return status of referred base/identityref
579 * @throws DataModelException a violation of data model rules
580 */
581 private boolean isIdentityReferenceFound(String nodeName, YangNode ancestorWithTheReferredNode)
582 throws DataModelException {
583
584 // When child is not present return.
585 if (ancestorWithTheReferredNode.getChild() == null) {
586 return false;
587 }
588
589 ancestorWithTheReferredNode = ancestorWithTheReferredNode.getChild();
590
591 // Checks all the siblings under the node and returns the matched node.
592 YangNode nodeFound = isReferredNodeInSiblingProcessedForIdentity(ancestorWithTheReferredNode, nodeName);
593
594 if (nodeFound != null) {
595 // Adds reference link of entity to the node under resolution.
596 addReferredEntityLink(nodeFound, LINKED);
597
598 /**
599 * resolve the reference and update the partial resolution stack with any further recursive references
600 */
601 addUnresolvedRecursiveReferenceToStack(nodeFound);
602 return true;
603 }
604
605 return false;
606 }
607
608 /**
janani be18b5342016-07-13 21:06:41 +0530609 * Adds the unresolved constructs to stack which has to be resolved for leafref.
610 *
janani b23ccc312016-07-14 19:35:22 +0530611 * @param yangleafOrLeafList YANG leaf or leaf list which holds the type
janani be18b5342016-07-13 21:06:41 +0530612 * @param ancestorWithTheReferredNode holder of the YANG leaf or leaf list
613 */
614 private void addUnResolvedLeafRefTypeToStack(T yangleafOrLeafList, YangNode ancestorWithTheReferredNode) {
615
616 YangType referredTypeInLeafOrLeafList;
617 if (yangleafOrLeafList instanceof YangLeaf) {
618 YangLeaf leaf = (YangLeaf) yangleafOrLeafList;
619 referredTypeInLeafOrLeafList = leaf.getDataType();
620 if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
621 YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
622 unResolvedEntityInfo.setEntityToResolve((YangLeafRef<?>) leaf.getDataType().getDataTypeExtendedInfo());
623 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
624 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
625 } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
626 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
627 unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
628 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
629 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
630 }
631 } else {
632 YangLeafList leafList = (YangLeafList) yangleafOrLeafList;
633 referredTypeInLeafOrLeafList = leafList.getDataType();
634 if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
635 YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
636 unResolvedEntityInfo
637 .setEntityToResolve((YangLeafRef<?>) leafList.getDataType().getDataTypeExtendedInfo());
638 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
639 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
640 } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
641 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
642 unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
643 unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
644 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
645 }
646 }
647 }
648
649 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530650 * Returns feature holder(module/sub-module node) .
651 *
652 * @param potentialAncestorWithReferredNode if-feature holder node
653 */
654 private YangFeatureHolder getFeatureHolder(YangNode potentialAncestorWithReferredNode) {
655 while (potentialAncestorWithReferredNode != null) {
656 if (potentialAncestorWithReferredNode instanceof YangFeatureHolder) {
657 return (YangFeatureHolder) potentialAncestorWithReferredNode;
658 }
659 potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
660 }
661 return null;
662 }
663
664 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530665 * Checks if the reference in self file or in external file.
666 *
667 * @return true if self file reference, false otherwise
668 * @throws DataModelException a violation of data model rules
669 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +0530670 private boolean isCandidateForSelfFileReference()
671 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530672 String prefix = getRefPrefix();
673 return prefix == null || prefix.contentEquals(getCurReferenceResolver().getPrefix());
674 }
675
676 /**
janani be18b5342016-07-13 21:06:41 +0530677 * Checks for the referred parent node for the leafref path.
678 *
679 * @param potentialReferredNode potential referred node
680 * @return the reffered parent node of leaf/leaf-list
681 * @throws DataModelException data model errors
682 */
683 private YangNode isReferredNodeInSiblingProcessedForLeafref(YangNode potentialReferredNode, String referredNodeName)
684 throws DataModelException {
685
686 while (potentialReferredNode != null) {
687 if (potentialReferredNode instanceof YangInput) {
688 if (referredNodeName.equalsIgnoreCase(INPUT)) {
689 return potentialReferredNode;
690 }
691 } else if (potentialReferredNode instanceof YangOutput) {
692 if (referredNodeName.equalsIgnoreCase(OUTPUT)) {
693 return potentialReferredNode;
694 }
695 }
696 // Check if the potential referred node is the actual referred node
697 if (isReferredNodeForLeafref(potentialReferredNode, referredNodeName)) {
698 if (potentialReferredNode instanceof YangGrouping || potentialReferredNode instanceof YangTypeDef) {
699 if (potentialReferredNode.getParent() instanceof YangRpc) {
700 potentialReferredNode = potentialReferredNode.getNextSibling();
701 } else {
702 throw new DataModelException("YANG file error: The target node of leafref is invalid.");
703 }
704 }
705 return potentialReferredNode;
706 }
707 potentialReferredNode = potentialReferredNode.getNextSibling();
708 }
709 return null;
710 }
711
712 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530713 * Checks for the referred parent node for the base/identity.
714 *
715 * @param potentialReferredNode potential referred node
716 * @return the reffered parent node of base/identity.
717 * @throws DataModelException data model errors
718 */
719 private YangNode isReferredNodeInSiblingProcessedForIdentity(YangNode potentialReferredNode,
janani b23ccc312016-07-14 19:35:22 +0530720 String referredNodeName) throws DataModelException {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530721
722 while (potentialReferredNode != null) {
723 if (potentialReferredNode instanceof YangIdentity) {
724 // Check if the potential referred node is the actual referred node
725 if (isReferredNodeForIdentity(potentialReferredNode, referredNodeName)) {
726 return potentialReferredNode;
727 }
728 }
729 potentialReferredNode = potentialReferredNode.getNextSibling();
730 }
731 return null;
732 }
733
734 /**
janani be18b5342016-07-13 21:06:41 +0530735 * Checks if the current reference node name and the name in the path are equal.
736 *
737 * @param currentReferredNode the node where the reference is pointed
janani b23ccc312016-07-14 19:35:22 +0530738 * @param nameOfNodeinPath name of the node in the path
janani be18b5342016-07-13 21:06:41 +0530739 * @return status of the match between the name
740 * @throws DataModelException a violation of data model rules
741 */
742 private boolean isReferredNodeForLeafref(YangNode currentReferredNode, String nameOfNodeinPath)
743 throws DataModelException {
744
745 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
746 /*
747 * Check if name of node name matches with the current reference
748 * node.
749 */
750 return currentReferredNode.getName().contentEquals(nameOfNodeinPath);
751 } else {
752 throw new DataModelException("Data Model Exception: Entity to resolved is other than leafref");
753 }
754 }
755
756 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530757 * Checks if the current reference node name and the name in the base/identityref base are equal.
758 *
janani b23ccc312016-07-14 19:35:22 +0530759 * @param currentReferredNode the node where the reference is pointed
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530760 * @param nameOfIdentityRefBase name of the base in the base/identityref base
761 * @return status of the match between the name
762 * @throws DataModelException a violation of data model rules
763 */
764 private boolean isReferredNodeForIdentity(YangNode currentReferredNode, String nameOfIdentityRefBase)
765 throws DataModelException {
766
767 if ((getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) ||
768 (getCurrentEntityToResolveFromStack() instanceof YangBase)) {
769 /*
770 * Check if name of node name matches with the current reference node.
771 */
772 return currentReferredNode.getName().contentEquals(nameOfIdentityRefBase);
773 } else {
774 throw new DataModelException("Data Model Exception: Entity to resolved is other than identityref");
775 }
776 }
777
778 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530779 * Checks for the referred node defined in a ancestor scope.
780 *
781 * @param potentialReferredNode potential referred node
782 * @return status of resolution and updating the partial resolved stack with
783 * the any recursive references
janani be18b5342016-07-13 21:06:41 +0530784 * @throws DataModelException a violation of data model rules
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530785 */
786 private boolean isReferredNodeInSiblingListProcessed(YangNode potentialReferredNode)
787 throws DataModelException {
788 while (potentialReferredNode != null) {
789
790 // Check if the potential referred node is the actual referred node
791 if (isReferredNode(potentialReferredNode)) {
792
793 // Adds reference link of entity to the node under resolution.
794 addReferredEntityLink(potentialReferredNode, LINKED);
795
796 /**
797 * resolve the reference and update the partial resolution stack
798 * with any further recursive references
799 */
800 addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
801
802 /*
803 * return true, since the reference is linked and any recursive
804 * unresolved references is added to the stack
805 */
806 return true;
807 }
808
809 potentialReferredNode = potentialReferredNode.getNextSibling();
810 }
811 return false;
812 }
813
814 /**
815 * Checks if the potential referred node is the actual referred node.
816 *
817 * @param potentialReferredNode typedef/grouping node
818 * @return true if node is of resolve type otherwise false
819 * @throws DataModelException a violation of data model rules
820 */
821 private boolean isReferredNode(YangNode potentialReferredNode)
822 throws DataModelException {
823 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
824 if (potentialReferredNode instanceof YangTypeDef) {
825 /*
826 * Check if name of node name matches with the entity being
827 * resolved
828 */
829 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
830 }
831 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
832 if (potentialReferredNode instanceof YangGrouping) {
833 /*
834 * Check if name of node name matches with the entity being
835 * resolved
836 */
837 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
838 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530839 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
840 if (potentialReferredNode instanceof YangFeatureHolder) {
841 /*
842 * Check if name of node name matches with the entity being
843 * resolved
844 */
845 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
846 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530847 } else if ((getCurrentEntityToResolveFromStack() instanceof YangBase) ||
848 (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef)) {
849 if (potentialReferredNode instanceof YangIdentity) {
850 /*
851 * Check if name of node name matches with the entity being
852 * resolved
853 */
854 return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
855 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530856 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530857 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/" +
janani b23ccc312016-07-14 19:35:22 +0530858 "uses/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530859 }
860 return false;
861 }
862
863 /**
864 * Checks if node name is same as name in resolution info, i.e. name of
865 * typedef/grouping is same as name of type/uses.
866 *
867 * @param node typedef/grouping node
868 * @return true if node name is same as name in resolution info, otherwise
869 * false
870 * @throws DataModelException a violation of data model rules
871 */
872
873 private boolean isNodeNameSameAsResolutionInfoName(YangNode node)
874 throws DataModelException {
875 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
876 if (node.getName().contentEquals(
877 ((YangType<?>) getCurrentEntityToResolveFromStack())
878 .getDataTypeName())) {
879 return true;
880 }
881 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
882 if (node.getName().contentEquals(
883 ((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
884 return true;
885 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530886 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
887 return isFeatureDefinedInNode(node);
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530888 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
889 if (node.getName().contentEquals(
890 ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName())) {
891 return true;
892 }
893 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
894 if (node.getName().contentEquals(
895 ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getName())) {
896 return true;
897 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530898 } else {
899 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
900 }
901 return false;
902 }
903
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530904 private boolean isFeatureDefinedInNode(YangNode node) throws DataModelException {
905 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
906 List<YangFeature> featureList = ((YangFeatureHolder) node).getFeatureList();
907 if (featureList != null && !featureList.isEmpty()) {
908 Iterator<YangFeature> iterator = featureList.iterator();
909 while (iterator.hasNext()) {
910 YangFeature feature = iterator.next();
911 if (ifFeature.getName().equals(feature.getName())) {
912 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
913 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeatureHolder(node);
914 return true;
915 }
916 }
917 }
918 return false;
919 }
920
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530921 /**
922 * Adds reference of grouping/typedef in uses/type.
923 *
924 * @param referredNode grouping/typedef node being referred
925 * @param linkedStatus linked status if success.
926 * @throws DataModelException a violation of data model rules
927 */
928 private void addReferredEntityLink(YangNode referredNode, ResolvableStatus linkedStatus)
929 throws DataModelException {
930 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +0530931 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
932 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530933 derivedInfo.setReferredTypeDef((YangTypeDef) referredNode);
934 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
935 ((YangUses) getCurrentEntityToResolveFromStack())
936 .setRefGroup((YangGrouping) referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530937 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
938 // do nothing , referred node is already set
janani be18b5342016-07-13 21:06:41 +0530939 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
940 // do nothing , referred node is already set
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530941 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
942 ((YangBase) getCurrentEntityToResolveFromStack()).setReferredIdentity((YangIdentity) referredNode);
943 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
944 ((YangIdentityRef) getCurrentEntityToResolveFromStack()).setReferredIdentity((YangIdentity) referredNode);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530945 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530946 throw new DataModelException("Data Model Exception: Entity to resolved is other than type" +
janani b23ccc312016-07-14 19:35:22 +0530947 "/uses/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530948 }
949
950 // Sets the resolution status in inside the type/uses.
951 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(linkedStatus);
952 }
953
954 /**
955 * Checks if type/grouping has further reference to typedef/ unresolved
956 * uses. Add it to the partial resolve stack and return the status of
957 * addition to stack.
958 *
959 * @param referredNode grouping/typedef node
960 * @throws DataModelException a violation of data model rules
961 */
962 private void addUnresolvedRecursiveReferenceToStack(YangNode referredNode)
963 throws DataModelException {
964 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
965 /*
966 * Checks if typedef type is derived
967 */
Bharat saraswal96dfef02016-06-16 00:29:12 +0530968 if (((YangTypeDef) referredNode).getTypeDefBaseType().getDataType() == YangDataTypes.DERIVED) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530969
Bharat saraswal96dfef02016-06-16 00:29:12 +0530970 YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530971 unResolvedEntityInfo.setEntityToResolve(((YangTypeDef) referredNode)
972 .getTypeDefBaseType());
973 unResolvedEntityInfo.setHolderOfEntityToResolve(referredNode);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +0530974 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530975 }
976
977 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
978 /*
979 * Search if the grouping has any un resolved uses child, if so
980 * return true, else return false.
981 */
982 addUnResolvedUsesToStack(referredNode);
Vidyashree Ramadeac28b2016-06-20 15:12:43 +0530983 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
984 addUnResolvedIfFeatureToStack(referredNode);
janani be18b5342016-07-13 21:06:41 +0530985 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
986 // do nothing , referred node is already set
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530987 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +0530988 } else if ((getCurrentEntityToResolveFromStack() instanceof YangBase) ||
989 (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef)) {
990 /*
991 * Search if the identity has any un resolved base, if so return true, else return false.
992 */
993 addUnResolvedBaseToStack(referredNode);
994 } else {
995 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses/" +
janani b23ccc312016-07-14 19:35:22 +0530996 "base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +0530997 }
998 }
999
1000 /**
1001 * Returns if there is any unresolved uses in grouping.
1002 *
1003 * @param node grouping/typedef node
1004 */
1005 private void addUnResolvedUsesToStack(YangNode node) {
1006
1007 /**
1008 * Search the grouping node's children for presence of uses node.
1009 */
1010 YangNode curNode = node.getChild();
1011 while (curNode != null) {
1012 if (curNode instanceof YangUses) {
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301013 YangEntityToResolveInfoImpl<YangUses> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301014 unResolvedEntityInfo.setEntityToResolve((YangUses) curNode);
1015 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301016 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301017
1018 }
1019 curNode = curNode.getNextSibling();
1020 }
1021 }
1022
1023 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301024 * Returns if there is any unresolved if-feature in feature.
1025 *
1026 * @param node module/submodule node
1027 */
1028 private void addUnResolvedIfFeatureToStack(YangNode node) {
1029 YangFeature refFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeature();
1030 List<YangIfFeature> ifFeatureList = refFeature.getIfFeatureList();
1031 if (ifFeatureList != null && !ifFeatureList.isEmpty()) {
1032 Iterator<YangIfFeature> ifFeatureIterator = ifFeatureList.iterator();
1033 while (ifFeatureIterator.hasNext()) {
1034 YangIfFeature ifFeature = ifFeatureIterator.next();
1035 YangEntityToResolveInfo<YangIfFeature> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
1036 unResolvedEntityInfo.setEntityToResolve(ifFeature);
1037 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
1038 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
1039 }
1040 }
1041 }
1042
1043 /**
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301044 * Returns if there is any unresolved base in identity.
1045 *
1046 * @param node module/submodule node
1047 */
1048 private void addUnResolvedBaseToStack(YangNode node) {
1049
1050 YangIdentity curNode = (YangIdentity) node;
1051 if (curNode.getBaseNode() != null) {
1052 if (curNode.getBaseNode().getResolvableStatus() != RESOLVED) {
1053 YangEntityToResolveInfoImpl<YangBase> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
1054 unResolvedEntityInfo.setEntityToResolve(curNode.getBaseNode());
1055 unResolvedEntityInfo.setHolderOfEntityToResolve(node);
1056 addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
1057
1058 }
1059 }
1060 }
1061
1062
1063 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301064 * Returns stack of YANG type with partially resolved YANG construct
1065 * hierarchy.
1066 *
1067 * @return partial resolved YANG construct stack
1068 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301069 private Stack<YangEntityToResolveInfoImpl<T>> getPartialResolvedStack() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301070 return partialResolvedStack;
1071 }
1072
1073 /**
1074 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
1075 *
1076 * @param partialResolvedStack partial resolved YANG construct stack
1077 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301078 private void setPartialResolvedStack(Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301079 this.partialResolvedStack = partialResolvedStack;
1080 }
1081
1082 /**
1083 * Sets stack of YANG type with partially resolved YANG construct hierarchy.
1084 *
1085 * @param partialResolvedInfo partial resolved YANG construct stack
1086 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301087 private void addInPartialResolvedStack(YangEntityToResolveInfoImpl<T> partialResolvedInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301088 getPartialResolvedStack().push(partialResolvedInfo);
1089 }
1090
1091 /**
1092 * Retrieves the next entity in the stack that needs to be resolved. It is
1093 * assumed that the caller ensures that the stack is not empty.
1094 *
1095 * @return next entity in the stack that needs to be resolved
1096 */
1097 private T getCurrentEntityToResolveFromStack() {
1098 return getPartialResolvedStack().peek().getEntityToResolve();
1099 }
1100
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301101 @Override
1102 public YangEntityToResolveInfoImpl<T> getEntityToResolveInfo() {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301103 return entityToResolveInfo;
1104 }
1105
1106 /**
1107 * Sets information about the entity that needs to be resolved.
1108 *
1109 * @param entityToResolveInfo information about the entity that needs to be
1110 * resolved
1111 */
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301112 private void setEntityToResolveInfo(YangEntityToResolveInfoImpl<T> entityToResolveInfo) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301113 this.entityToResolveInfo = entityToResolveInfo;
1114 }
1115
1116 @Override
1117 public int getLineNumber() {
1118 return lineNumber;
1119 }
1120
1121 @Override
1122 public int getCharPosition() {
1123 return charPosition;
1124 }
1125
1126 @Override
1127 public void setLineNumber(int lineNumber) {
1128 this.lineNumber = lineNumber;
1129 }
1130
1131 @Override
1132 public void setCharPosition(int charPositionInLine) {
1133 this.charPosition = charPositionInLine;
1134 }
1135
1136 /**
1137 * Returns current module/sub-module reference, will be used in inter-file/
1138 * inter-jar scenario to get the import/include list.
1139 *
1140 * @return current module/sub-module reference
1141 */
1142 private YangReferenceResolver getCurReferenceResolver() {
1143 return curReferenceResolver;
1144 }
1145
1146 /**
1147 * Sets current module/sub-module reference, will be used in inter-file/
1148 * inter-jar scenario to get the import/include list.
1149 *
1150 * @param curReferenceResolver current module/sub-module reference
1151 */
1152 private void setCurReferenceResolver(YangReferenceResolver curReferenceResolver) {
1153 this.curReferenceResolver = curReferenceResolver;
1154 }
1155
Gaurav Agrawal95b416c2016-06-07 14:00:26 +05301156 @Override
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301157 public void linkInterFile(YangReferenceResolver dataModelRootNode)
1158 throws DataModelException {
1159
1160 setCurReferenceResolver(dataModelRootNode);
1161
1162 // Current node to resolve, it can be a YANG type or YANG uses.
1163 T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
1164
1165 // Check if linking is already done
1166 if (entityToResolve instanceof Resolvable) {
1167 Resolvable resolvable = (Resolvable) entityToResolve;
1168 if (resolvable.getResolvableStatus() == RESOLVED) {
1169 return;
1170 }
1171 } else {
1172 throw new DataModelException("Data Model Exception: Entity to resolved is not Resolvable");
1173 }
1174
janani b23ccc312016-07-14 19:35:22 +05301175 if (entityToResolve instanceof YangXPathResolver && !(entityToResolve instanceof YangLeafRef)) {
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301176 //Process x-path linking.
janani b23ccc312016-07-14 19:35:22 +05301177 processXPathLinking(entityToResolve, dataModelRootNode);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301178
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301179 } else {
janani be18b5342016-07-13 21:06:41 +05301180
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301181 // Push the initial entity to resolve in stack.
1182 addInPartialResolvedStack(getEntityToResolveInfo());
1183
1184 // Inter file linking and resolution.
1185 linkInterFileAndResolve();
1186
1187 addDerivedRefTypeToRefTypeResolutionList();
1188 }
1189 }
1190
1191 /**
1192 * Process x-path linking for augment and leaf-ref.
1193 *
janani b23ccc312016-07-14 19:35:22 +05301194 * @param entityToResolve entity to resolve
1195 * @param root root node
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301196 */
janani b23ccc312016-07-14 19:35:22 +05301197 private void processXPathLinking(T entityToResolve,
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301198 YangReferenceResolver root) {
janani b23ccc312016-07-14 19:35:22 +05301199
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301200 YangXpathLinker<T> xPathLinker = new YangXpathLinker<T>();
janani b23ccc312016-07-14 19:35:22 +05301201
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301202 if (entityToResolve instanceof YangAugment) {
1203 YangNode targetNode = null;
1204 YangAugment augment = (YangAugment) entityToResolve;
1205 targetNode = xPathLinker.processAugmentXpathLinking(augment.getTargetNode(),
1206 (YangNode) root);
1207 if (targetNode != null) {
1208 if (targetNode instanceof YangAugmentableNode) {
1209 detectCollisionForAugmentedNode(targetNode, augment);
1210 ((YangAugmentableNode) targetNode).addAugmentation(augment);
1211 augment.setAugmentedNode(targetNode);
Bharat saraswalb551aae2016-07-14 15:18:20 +05301212 augment.setResolveNodeInPath(xPathLinker.getResolvedNodes());
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301213 Resolvable resolvable = (Resolvable) entityToResolve;
1214 resolvable.setResolvableStatus(RESOLVED);
1215 } else {
1216 throw new LinkerException("Invalid target node type " + targetNode.getNodeType() + " for "
1217 + augment.getName());
1218 }
1219 } else {
1220 throw new LinkerException("Failed to link " + augment.getName());
1221 }
1222 } else if (entityToResolve instanceof YangLeafRef) {
1223 YangLeafRef leafRef = (YangLeafRef) entityToResolve;
1224 Object target = xPathLinker.processLeafRefXpathLinking(leafRef.getAtomicPath(),
janani b23ccc312016-07-14 19:35:22 +05301225 (YangNode) root, leafRef);
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301226 if (target != null) {
1227 YangLeaf leaf = null;
1228 YangLeafList leafList = null;
1229 leafRef.setReferredLeafOrLeafList(target);
1230 if (target instanceof YangLeaf) {
1231 leaf = (YangLeaf) target;
janani b23ccc312016-07-14 19:35:22 +05301232 leafRef.setResolvableStatus(INTER_FILE_LINKED);
1233 addUnResolvedLeafRefTypeToStack((T) leaf, getEntityToResolveInfo().getHolderOfEntityToResolve());
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301234 } else {
1235 leafList = (YangLeafList) target;
janani b23ccc312016-07-14 19:35:22 +05301236 leafRef.setResolvableStatus(INTER_FILE_LINKED);
1237 addUnResolvedLeafRefTypeToStack((T) leafList,
1238 getEntityToResolveInfo().getHolderOfEntityToResolve());
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301239 }
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301240 //TODO: add logic for leaf-ref for path predicates.
1241 } else {
janani b23ccc312016-07-14 19:35:22 +05301242 LinkerException linkerException = new LinkerException("YANG file error: Unable to find base " +
1243 "leaf/leaf-list for given leafref path "
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301244 + leafRef.getPath());
janani b23ccc312016-07-14 19:35:22 +05301245 linkerException.setCharPosition(leafRef.getCharPosition());
1246 linkerException.setLine(leafRef.getLineNumber());
1247 throw linkerException;
Bharat saraswalb1170bd2016-07-14 13:26:18 +05301248 }
1249 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301250 }
1251
1252 /**
1253 * Returns the referenced prefix of entity under resolution.
1254 *
1255 * @return referenced prefix of entity under resolution
1256 * @throws DataModelException a violation in data model rule
1257 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301258 private String getRefPrefix()
1259 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301260 String refPrefix;
1261 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1262 refPrefix = ((YangType<?>) getCurrentEntityToResolveFromStack()).getPrefix();
1263 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1264 refPrefix = ((YangUses) getCurrentEntityToResolveFromStack()).getPrefix();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301265 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1266 refPrefix = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getPrefix();
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301267 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1268 refPrefix = ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getPrefix();
1269 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1270 refPrefix = ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getPrefix();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301271 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301272 throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
janani b23ccc312016-07-14 19:35:22 +05301273 "type/uses/base/identityref");
janani be18b5342016-07-13 21:06:41 +05301274 }
1275 return refPrefix;
1276 }
1277
1278 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301279 * Performs inter file linking and resolution.
1280 *
1281 * @throws DataModelException a violation in data model rule
1282 */
1283 private void linkInterFileAndResolve()
1284 throws DataModelException {
1285
1286 while (getPartialResolvedStack().size() != 0) {
1287
1288 // Current node to resolve, it can be a YANG type or YANG uses.
1289 T entityToResolve = getCurrentEntityToResolveFromStack();
1290 // Check if linking is already done
1291 if (entityToResolve instanceof Resolvable) {
1292
1293 Resolvable resolvable = (Resolvable) entityToResolve;
1294 switch (resolvable.getResolvableStatus()) {
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301295 case RESOLVED: {
1296 /*
1297 * If the entity is already resolved in the stack, then pop
1298 * it and continue with the remaining stack elements to
1299 * resolve
1300 */
1301 getPartialResolvedStack().pop();
1302 break;
1303 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301304
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301305 case INTER_FILE_LINKED: {
1306 /*
1307 * If the top of the stack is already linked then resolve
1308 * the references and pop the entity and continue with
1309 * remaining stack elements to resolve
1310 */
1311 resolveTopOfStack(INTER_FILE);
1312 getPartialResolvedStack().pop();
1313 break;
1314 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301315
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301316 case INTRA_FILE_RESOLVED: {
1317 /*
1318 * If the top of the stack is intra file resolved then check
1319 * if top of stack is linked, if not link it using
1320 * import/include list and push the linked referred entity
1321 * to the stack, otherwise only push it to the stack.
1322 */
1323 linkInterFileTopOfStackRefUpdateStack();
1324 break;
1325 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301326
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301327 case UNDEFINED: {
1328 /*
1329 * In case of if-feature resolution, if referred "feature" is not
1330 * defined then the resolvable status will be undefined.
1331 */
1332 getPartialResolvedStack().pop();
1333 break;
1334 }
1335
1336 default: {
1337 throw new DataModelException("Data Model Exception: Unsupported, linker state");
1338 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301339
1340 }
1341
1342 } else {
1343 throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
1344 }
1345
1346 }
1347
1348 }
1349
1350 /**
1351 * Links the top of the stack if it's inter-file and update stack.
1352 *
1353 * @throws DataModelException data model error
1354 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301355 private void linkInterFileTopOfStackRefUpdateStack()
1356 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301357
janani b23ccc312016-07-14 19:35:22 +05301358 if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1359 // When leafref path comes with relative path, it will be converted to absolute path.
1360 setAbsolutePathFromRelativePathInLeafref(getCurrentEntityToResolveFromStack());
1361 processXPathLinking(getCurrentEntityToResolveFromStack(), getCurReferenceResolver());
1362 return;
1363 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301364 /*
1365 * Obtain the referred node of top of stack entity under resolution
1366 */
1367 T referredNode = getRefNode();
1368
1369 /*
1370 * Check for null for scenario when it's not linked and inter-file
1371 * linking is required.
1372 */
1373 if (referredNode == null) {
1374
1375 /*
Bharat saraswal96dfef02016-06-16 00:29:12 +05301376 * Check if prefix is null or not, to identify whether to search in
1377 * import list or include list.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301378 */
Bharat saraswalcad0e652016-05-26 23:48:38 +05301379 if (getRefPrefix() != null && !getRefPrefix().contentEquals(getCurReferenceResolver().getPrefix())) {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301380 if (resolveWithImport()) {
1381 return;
1382 }
1383 } else {
1384 if (resolveWithInclude()) {
1385 return;
1386 }
1387 }
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301388
1389 if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1390 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setResolvableStatus(UNDEFINED);
1391 return;
1392 }
janani be18b5342016-07-13 21:06:41 +05301393 // If current entity is still not resolved, then
1394 // linking/resolution has failed.
1395 String errorInfo;
1396 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1397 errorInfo = TYPEDEF_LINKER_ERROR;
1398 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1399 errorInfo = GROUPING_LINKER_ERROR;
1400 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1401 errorInfo = FEATURE_LINKER_ERROR;
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301402 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1403 errorInfo = BASE_LINKER_ERROR;
1404 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1405 errorInfo = IDENTITYREF_LINKER_ERROR;
janani be18b5342016-07-13 21:06:41 +05301406 } else {
1407 errorInfo = LEAFREF_LINKER_ERROR;
1408 }
1409 DataModelException dataModelException = new DataModelException(errorInfo);
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301410 dataModelException.setLine(getLineNumber());
1411 dataModelException.setCharPosition(getCharPosition());
1412 throw dataModelException;
1413 } else {
janani b23ccc312016-07-14 19:35:22 +05301414 ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
1415 addUnresolvedRecursiveReferenceToStack((YangNode) referredNode);
1416 }
1417 }
1418
1419 /**
1420 * Sets the leafref with absolute path from the relative path.
1421 *
1422 * @param resolutionInfo information about the YANG construct which has to be resolved
1423 * @throws DataModelException a violation of data model rules
1424 */
1425 public void setAbsolutePathFromRelativePathInLeafref(T resolutionInfo) throws DataModelException {
1426 if (resolutionInfo instanceof YangLeafRef) {
1427
1428 YangNode parentOfLeafref = ((YangLeafRef) resolutionInfo).getParentNodeOfLeafref();
1429 YangLeafRef leafref = (YangLeafRef) resolutionInfo;
1430
1431 // Checks if the leafref has relative path in it.
1432 if (leafref.getPathType() == YangPathArgType.RELATIVE_PATH) {
1433 YangRelativePath relativePath = leafref.getRelativePath();
1434 List<YangAtomicPath> absoluteInRelative = relativePath.getAtomicPathList();
1435 int numberOfAncestors = relativePath.getAncestorNodeCount();
1436
1437 // Gets the root node from the ancestor count.
1438 T nodeOrAugmentList = getRootNodeWithAncestorCountForLeafref(numberOfAncestors, parentOfLeafref,
1439 leafref);
1440 if (nodeOrAugmentList instanceof YangNode) {
1441 String pathNameToBePrefixed = EMPTY_STRING;
1442 YangNode rootNode = (YangNode) nodeOrAugmentList;
1443 // Forms a new absolute path from the relative path
1444 while (!(rootNode instanceof YangReferenceResolver)) {
1445 pathNameToBePrefixed = rootNode.getName() + SLASH_FOR_STRING + pathNameToBePrefixed;
1446 rootNode = rootNode.getParent();
1447 if (rootNode == null) {
1448 throw new DataModelException("Internal datamodel error: Datamodel tree is not correct");
1449 }
1450 }
1451 fillAbsolutePathValuesInLeafref(leafref, pathNameToBePrefixed, absoluteInRelative);
1452 } else {
1453 List<String> listOfAugment = (List<String>) nodeOrAugmentList;
1454 Iterator<String> listOfAugmentIterator = listOfAugment.listIterator();
1455 String augment = EMPTY_STRING;
1456 while (listOfAugmentIterator.hasNext()) {
1457 augment = augment + SLASH_FOR_STRING + listOfAugmentIterator.next();
1458 }
1459 fillAbsolutePathValuesInLeafref(leafref, augment, absoluteInRelative);
janani be18b5342016-07-13 21:06:41 +05301460 }
janani be18b5342016-07-13 21:06:41 +05301461 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301462 }
1463 }
1464
1465 /**
janani b23ccc312016-07-14 19:35:22 +05301466 * Fills the absolute path values in the leafref from relative path.
1467 *
1468 * @param leafref instance of YANG leafref
1469 * @param pathNameToBePrefixed path name which has to be prefixed to relative path
1470 * @param atomicPathsInRelative atomic paths in relative
1471 * @throws DataModelException a violation of data model rules
1472 */
1473 private void fillAbsolutePathValuesInLeafref(YangLeafRef leafref, String pathNameToBePrefixed,
1474 List<YangAtomicPath> atomicPathsInRelative) throws DataModelException {
1475
1476 leafref.setPathType(YangPathArgType.ABSOLUTE_PATH);
1477 String[] pathName = new String[0];
1478 if (pathNameToBePrefixed != EMPTY_STRING && pathNameToBePrefixed != null) {
1479 pathName = pathNameToBePrefixed.split(SLASH_FOR_STRING);
1480 }
1481 List<YangAtomicPath> finalListForAbsolute = new LinkedList<>();
1482 for (String value : pathName) {
1483 if (value != null && !value.isEmpty() && value != EMPTY_STRING) {
1484 YangNodeIdentifier nodeIdentifier = getValidNodeIdentifier(value, YangConstructType.PATH_DATA);
1485 YangAtomicPath atomicPath = new YangAtomicPath();
1486 atomicPath.setNodeIdentifier(nodeIdentifier);
1487 finalListForAbsolute.add(atomicPath);
1488 }
1489 }
1490 if (atomicPathsInRelative != null && !atomicPathsInRelative.isEmpty()) {
1491 Iterator<YangAtomicPath> atomicPathIterator = atomicPathsInRelative.listIterator();
1492 while (atomicPathIterator.hasNext()) {
1493 YangAtomicPath yangAtomicPath = atomicPathIterator.next();
1494 finalListForAbsolute.add(yangAtomicPath);
1495 }
1496 leafref.setAtomicPath(finalListForAbsolute);
1497 } else {
1498 DataModelException dataModelException = new DataModelException("YANG file error: The target node, in the " +
1499 "leafref path " + leafref.getPath() + ", is invalid.");
1500 dataModelException.setCharPosition(leafref.getCharPosition());
1501 dataModelException.setLine(leafref.getLineNumber());
1502 throw dataModelException;
1503 }
1504 }
1505
1506 /**
1507 * Returns the root parent with respect to the ancestor count from leafref.
1508 *
1509 * @param ancestorCount count of node where parent node can be reached
1510 * @param currentParent current parent node
1511 * @param leafref instance of YANG leafref
1512 * @return node where the ancestor count stops or augment path name list
1513 * @throws DataModelException a violation of data model rules
1514 */
1515 private T getRootNodeWithAncestorCountForLeafref(int ancestorCount, YangNode currentParent, YangLeafRef leafref)
1516 throws DataModelException {
1517
1518 int currentParentCount = 1;
1519 currentParent = skipInvalidDataNodes(currentParent, leafref);
1520 if (currentParent instanceof YangAugment) {
1521 YangAugment augment = (YangAugment) currentParent;
1522 List<String> valueInAugment = getPathWithAugment(augment, ancestorCount - currentParentCount);
1523 return (T) valueInAugment;
1524 } else {
1525 while (currentParentCount < ancestorCount) {
1526 YangNode currentSkippedParent = skipInvalidDataNodes(currentParent, leafref);
1527 if (currentSkippedParent == currentParent) {
1528 if (currentParent.getParent() == null) {
1529 throw new DataModelException("YANG file error: The target node, in the leafref path "
1530 + leafref.getPath() + ", is invalid.");
1531 }
1532 currentParent = currentParent.getParent();
1533 } else {
1534 currentParent = currentSkippedParent;
1535 continue;
1536 }
1537 currentParentCount = currentParentCount + 1;
1538 if (currentParent instanceof YangAugment) {
1539 YangAugment augment = (YangAugment) currentParent;
1540 List<String> valueInAugment = getPathWithAugment(augment, ancestorCount - currentParentCount);
1541 return (T) valueInAugment;
1542 }
1543 }
1544 }
1545 return (T) currentParent;
1546 }
1547
1548 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301549 * Finds and resolves with include list.
1550 *
1551 * @return true if resolved, false otherwise
1552 * @throws DataModelException a violation in data model rule
1553 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301554 private boolean resolveWithInclude()
1555 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301556 /*
1557 * Run through all the nodes in include list and search for referred
1558 * typedef/grouping at the root level.
1559 */
1560 for (YangInclude yangInclude : getCurReferenceResolver().getIncludeList()) {
1561 YangNode linkedNode = null;
1562 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1563 linkedNode = findRefTypedef(yangInclude.getIncludedNode());
1564 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1565 linkedNode = findRefGrouping(yangInclude.getIncludedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301566 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1567 linkedNode = findRefFeature(yangInclude.getIncludedNode());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301568 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1569 linkedNode = findRefIdentity(yangInclude.getIncludedNode());
1570 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1571 linkedNode = findRefIdentityRef(yangInclude.getIncludedNode());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301572 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301573
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301574 if (linkedNode != null) {
1575 // Add the link to external entity.
1576 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
1577 /*
1578 * Update the current reference resolver to external
1579 * module/sub-module containing the referred typedef/grouping.
1580 */
1581 setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());
1582 // Add the type/uses of referred typedef/grouping to the stack.
1583 addUnresolvedRecursiveReferenceToStack(linkedNode);
1584 return true;
1585 }
1586 }
1587 // If referred node can't be found return false.
1588 return false;
1589 }
1590
1591 /**
1592 * Finds and resolves with import list.
1593 *
1594 * @return true if resolved, false otherwise
1595 * @throws DataModelException a violation in data model rule
1596 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301597 private boolean resolveWithImport()
1598 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301599 /*
1600 * Run through import list to find the referred typedef/grouping.
1601 */
1602 for (YangImport yangImport : getCurReferenceResolver().getImportList()) {
1603 /*
1604 * Match the prefix attached to entity under resolution with the
1605 * imported/included module/sub-module's prefix. If found, search
1606 * for the referred typedef/grouping at the root level.
1607 */
1608 if (yangImport.getPrefixId().contentEquals(getRefPrefix())) {
1609 YangNode linkedNode = null;
1610 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
1611 linkedNode = findRefTypedef(yangImport.getImportedNode());
1612 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1613 linkedNode = findRefGrouping(yangImport.getImportedNode());
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301614 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1615 linkedNode = findRefFeature(yangImport.getImportedNode());
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301616 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1617 linkedNode = findRefIdentity(yangImport.getImportedNode());
1618 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1619 linkedNode = findRefIdentityRef(yangImport.getImportedNode());
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301620 }
1621 if (linkedNode != null) {
1622 // Add the link to external entity.
1623 addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
1624 /*
1625 * Update the current reference resolver to external
Bharat saraswal96dfef02016-06-16 00:29:12 +05301626 * module/sub-module containing the referred
1627 * typedef/grouping.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301628 */
1629 setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());
Bharat saraswal96dfef02016-06-16 00:29:12 +05301630 // Add the type/uses of referred typedef/grouping to the
1631 // stack.
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301632 addUnresolvedRecursiveReferenceToStack(linkedNode);
1633 return true;
1634 }
1635 /*
1636 * If referred node can't be found at root level break for loop,
1637 * and return false.
1638 */
1639 break;
1640 }
1641 }
1642 // If referred node can't be found return false.
1643 return false;
1644 }
1645
1646 /**
1647 * Returns referred typedef/grouping node.
1648 *
1649 * @return referred typedef/grouping node
1650 * @throws DataModelException a violation in data model rule
1651 */
VinodKumarS-Huawei2ee9e7e2016-06-01 14:30:22 +05301652 private T getRefNode()
1653 throws DataModelException {
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301654 if (getCurrentEntityToResolveFromStack() instanceof YangType) {
Bharat saraswal96dfef02016-06-16 00:29:12 +05301655 YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
1656 .getDataTypeExtendedInfo();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301657 return (T) derivedInfo.getReferredTypeDef();
1658 } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
1659 return (T) ((YangUses) getCurrentEntityToResolveFromStack()).getRefGroup();
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301660 } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
1661 return (T) ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeatureHolder();
janani be18b5342016-07-13 21:06:41 +05301662 } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
1663 return (T) ((YangLeafRef) getCurrentEntityToResolveFromStack()).getReferredLeafOrLeafList();
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301664 } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
1665 return (T) ((YangBase) getCurrentEntityToResolveFromStack()).getReferredIdentity();
1666 } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
1667 return (T) ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getReferredIdentity();
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301668 } else {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301669 throw new DataModelException("Data Model Exception: Entity to resolved is other than type" +
janani b23ccc312016-07-14 19:35:22 +05301670 "/uses/base/identityref");
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301671 }
1672 }
1673
1674 /**
1675 * Finds the referred grouping node at the root level of imported/included node.
1676 *
1677 * @param refNode module/sub-module node
1678 * @return referred grouping
1679 */
1680 private YangNode findRefGrouping(YangNode refNode) {
1681 YangNode tmpNode = refNode.getChild();
1682 while (tmpNode != null) {
1683 if (tmpNode instanceof YangGrouping) {
1684 if (tmpNode.getName()
1685 .equals(((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
1686 return tmpNode;
1687 }
1688 }
1689 tmpNode = tmpNode.getNextSibling();
1690 }
1691 return null;
1692 }
1693
1694 /**
Vidyashree Ramadeac28b2016-06-20 15:12:43 +05301695 * Finds the referred feature node at the root level of imported/included node.
1696 *
1697 * @param refNode module/sub-module node
1698 * @return referred feature
1699 */
1700 private YangNode findRefFeature(YangNode refNode) {
1701 YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
1702 List<YangFeature> featureList = ((YangFeatureHolder) refNode).getFeatureList();
1703
1704 if (featureList != null && !featureList.isEmpty()) {
1705 Iterator<YangFeature> iterator = featureList.iterator();
1706 while (iterator.hasNext()) {
1707 YangFeature feature = iterator.next();
1708 if (ifFeature.getName().equals(feature.getName())) {
1709 ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
1710 return refNode;
1711 }
1712 }
1713 }
1714 return null;
1715 }
1716
1717 /**
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301718 * Finds the referred typedef node at the root level of imported/included node.
1719 *
1720 * @param refNode module/sub-module node
1721 * @return referred typedef
1722 */
1723 private YangNode findRefTypedef(YangNode refNode) {
1724 YangNode tmpNode = refNode.getChild();
1725 while (tmpNode != null) {
1726 if (tmpNode instanceof YangTypeDef) {
1727 if (tmpNode.getName()
1728 .equals(((YangType) getCurrentEntityToResolveFromStack()).getDataTypeName())) {
1729 return tmpNode;
1730 }
1731 }
1732 tmpNode = tmpNode.getNextSibling();
1733 }
1734 return null;
1735 }
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301736
1737 /**
1738 * Finds the referred identity node at the root level of imported/included node.
1739 *
1740 * @param refNode module/sub-module node
1741 * @return referred identity
1742 */
1743 private YangNode findRefIdentity(YangNode refNode) {
1744 YangNode tmpNode = refNode.getChild();
1745 while (tmpNode != null) {
1746 if (tmpNode instanceof YangIdentity) {
1747 if (tmpNode.getName()
1748 .equals(((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName())) {
1749 return tmpNode;
1750 }
1751 }
1752 tmpNode = tmpNode.getNextSibling();
1753 }
1754 return null;
1755 }
1756
1757 /**
1758 * Finds the referred identity node at the root level of imported/included node.
1759 *
1760 * @param refNode module/sub-module node
1761 * @return referred identity
1762 */
1763 private YangNode findRefIdentityRef(YangNode refNode) {
1764 YangNode tmpNode = refNode.getChild();
1765 while (tmpNode != null) {
1766 if (tmpNode instanceof YangIdentity) {
1767 if (tmpNode.getName()
1768 .equals(((YangIdentityRef) getCurrentEntityToResolveFromStack())
janani b23ccc312016-07-14 19:35:22 +05301769 .getBaseIdentity().getName())) {
Shankara-Huaweidf7b9ca2016-07-14 11:35:34 +05301770 return tmpNode;
1771 }
1772 }
1773 tmpNode = tmpNode.getNextSibling();
1774 }
1775 return null;
1776 }
Gaurav Agrawal0d43bb52016-05-17 18:06:38 +05301777}