blob: 104d7016bbd0eff574688b571a58948e078d306b [file] [log] [blame]
janani be18b5342016-07-13 21:06:41 +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.datamodel;
18
janani be18b5342016-07-13 21:06:41 +053019import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
20import org.onosproject.yangutils.datamodel.utils.Parsable;
21import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
22import org.onosproject.yangutils.datamodel.utils.YangConstructType;
23import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
24
janani b23ccc312016-07-14 19:35:22 +053025import java.io.Serializable;
26import java.util.Iterator;
27import java.util.LinkedList;
28import java.util.List;
29import java.util.Map;
30
janani be18b5342016-07-13 21:06:41 +053031import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
32import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
rama-huawei6c728a92016-07-11 14:48:12 +053033import static org.onosproject.yangutils.datamodel.utils.YangErrMsgConstants.DATA_MISSING_ERROR_TAG;
34import static org.onosproject.yangutils.datamodel.utils.YangErrMsgConstants.ERROR_PATH_LEAFREF_LEAF;
35import static org.onosproject.yangutils.datamodel.utils.YangErrMsgConstants.INSTANCE_REQUIRED_ERROR_APP_TAG;
janani be18b5342016-07-13 21:06:41 +053036
37/*
38 * Reference:RFC 6020.
39 * The leafref type is used to reference a particular leaf instance in
40 * the data tree. The "path" substatement (Section 9.9.2) selects a set
41 * of leaf instances, and the leafref value space is the set of values
42 * of these leaf instances.
43 */
44
45/**
46 * Represents the leafref information.
47 *
48 * @param <T> YANG leafref info
49 */
Bharat saraswalb1170bd2016-07-14 13:26:18 +053050public class YangLeafRef<T> implements Parsable, Resolvable, Serializable, YangIfFeatureHolder,
janani b23ccc312016-07-14 19:35:22 +053051 YangXPathResolver, YangAppErrorHolder, LocationInfo {
janani be18b5342016-07-13 21:06:41 +053052
53 private static final long serialVersionUID = 286201644L;
54
55 /**
56 * YANG data type.
57 */
58 private YangType effectiveDataType;
59
60 /**
61 * Referred leaf/leaf-list for the path specified in the leafref type.
62 */
63 private T referredLeafOrLeafList;
64
65 /**
66 * Path of the leafref.
67 */
68 private String path;
69
70 /**
71 * Leafref path type. Either absolute or relative path.
72 */
73 private YangPathArgType pathType;
74
75 /**
76 * List of atomic paths in absolute Path.
77 */
78 private List<YangAtomicPath> atomicPath;
79
80 /**
81 * YANG relative path.
82 */
83 private YangRelativePath relativePath;
84
85 /**
86 * Status of resolution. If completely resolved enum value is "RESOLVED",
87 * if not enum value is "UNRESOLVED", in case reference of grouping/typedef/leafref
88 * is added to uses/type/leafref but it's not resolved value of enum should be
89 * "INTRA_FILE_RESOLVED".
90 */
91 private ResolvableStatus resolvableStatus;
92
93 /**
94 * Require instance status in leafref type.
95 */
96 private boolean requireInstance;
97
98 /**
99 * List of if-feature.
100 */
101 private List<YangIfFeature> ifFeatureList;
102
103 /**
janani b23ccc312016-07-14 19:35:22 +0530104 * Parent node of the leafref's leaf.
105 */
106 private YangNode parentNodeOfLeafref;
107
108 /**
109 * Error line number.
110 */
111 private transient int lineNumber;
112
113 /**
114 * Error character position in number.
115 */
116 private transient int charPositionInLine;
117
118 /**
119 * Prefix in the nodes of the leafref path and its imported node name.
120 */
121 private Map<String, String> prefixAndItsImportedModule;
122
123 /**
124 * Returns the prefix in the leafref path and its imported node name.
125 *
126 * @return the list of leafref prefix and imported node name
127 */
128 public Map<String, String> getPrefixAndItsImportedModule() {
129 return prefixAndItsImportedModule;
130 }
131
132 /**
133 * Sets the prefix in the leafref path and its imported node name.
134 *
135 * @param prefixAndItsImportedModule the list of leafref prefix and imported node name
136 */
137 public void setPrefixAndItsImportedModule(Map<String, String> prefixAndItsImportedModule) {
138 this.prefixAndItsImportedModule = prefixAndItsImportedModule;
139 }
140
141 /**
142 * Returns the parent node from the leafref's leaf.
143 *
144 * @return parent node of the leafref
145 */
146 public YangNode getParentNodeOfLeafref() {
147 return parentNodeOfLeafref;
148 }
149
150 /**
151 * Sets the parent node from the leafref's leaf.
152 *
153 * @param parentNodeOfLeafref parent node of the leafref
154 */
155 public void setParentNodeOfLeafref(YangNode parentNodeOfLeafref) {
156 this.parentNodeOfLeafref = parentNodeOfLeafref;
157 }
158 /**
rama-huawei6c728a92016-07-11 14:48:12 +0530159 * YANG application error information.
160 */
161 private YangAppErrorInfo yangAppErrorInfo;
162
163 /**
164 * Creates a YANG leaf ref.
165 */
166 public YangLeafRef() {
167 yangAppErrorInfo = new YangAppErrorInfo();
168 yangAppErrorInfo.setErrorTag(DATA_MISSING_ERROR_TAG);
169 yangAppErrorInfo.setErrorAppTag(INSTANCE_REQUIRED_ERROR_APP_TAG);
170 yangAppErrorInfo.setErrorAppPath(ERROR_PATH_LEAFREF_LEAF);
171 }
172
173 /**
janani be18b5342016-07-13 21:06:41 +0530174 * Returns the status of the require instance in leafref.
175 *
176 * @return status of the require instance
177 */
178 public boolean getRequireInstance() {
179 return requireInstance;
180 }
181
182 /**
183 * Sets the status of the require instance in leafref.
184 *
185 * @param requireInstance status of the require instance
186 */
187 public void setRequireInstance(boolean requireInstance) {
188 this.requireInstance = requireInstance;
189 }
190
191 /**
192 * Returns the type of data.
193 *
194 * @return the data type
195 */
196 public YangType getEffectiveDataType() {
197 return effectiveDataType;
198 }
199
200 /**
201 * Sets the type of data.
202 *
203 * @param effectiveDataType data type
204 */
205 public void setEffectiveDataType(YangType effectiveDataType) {
206 this.effectiveDataType = effectiveDataType;
207 }
208
209 /**
210 * Returns the path of the leafref.
211 *
212 * @return path of the leafref
213 */
214 public String getPath() {
215 return path;
216 }
217
218 /**
219 * Sets the path of the leafref.
220 *
221 * @param path leafref path
222 */
223 public void setPath(String path) {
224 this.path = path;
225 }
226
227 /**
228 * Returns the type of path in the leafref.
229 *
230 * @return type of path
231 */
232 public YangPathArgType getPathType() {
233 return pathType;
234 }
235
236 /**
237 * Sets the type of path in the leafref. It can be either absolute or relative type.
238 *
239 * @param pathType type of path
240 */
241 public void setPathType(YangPathArgType pathType) {
242 this.pathType = pathType;
243 }
244
245 /**
246 * Returns the list of atomic path.
247 *
248 * @return list of atomic path
249 */
250 public List<YangAtomicPath> getAtomicPath() {
251 return atomicPath;
252 }
253
254 /**
255 * Sets the list of atomic path.
256 *
257 * @param atomicPath list of atomic path.
258 */
259 public void setAtomicPath(List<YangAtomicPath> atomicPath) {
260 this.atomicPath = atomicPath;
261 }
262
263 /**
264 * Returns the object of relative path.
265 *
266 * @return object of relative path
267 */
268 public YangRelativePath getRelativePath() {
269 return relativePath;
270 }
271
272 /**
273 * Sets the object of relative path.
274 *
275 * @param relativePath object of relative path.
276 */
277 public void setRelativePath(YangRelativePath relativePath) {
278 this.relativePath = relativePath;
279 }
280
281 /**
282 * Returns the object of referred leaf/leaf-list.
283 *
284 * @return object of referred leaf/leaf-list
285 */
286 public T getReferredLeafOrLeafList() {
287 return referredLeafOrLeafList;
288 }
289
290 /**
291 * Sets the object of referred leaf/leaf-list.
292 *
293 * @param targetExtendedInfo object of referred leaf/leaf-list
294 */
295 public void setReferredLeafOrLeafList(T targetExtendedInfo) {
296 this.referredLeafOrLeafList = targetExtendedInfo;
297 }
298
299 @Override
300 public List<YangIfFeature> getIfFeatureList() {
301 return ifFeatureList;
302 }
303
304 @Override
305 public void addIfFeatureList(YangIfFeature ifFeature) {
306 if (getIfFeatureList() == null) {
307 setIfFeatureList(new LinkedList<>());
308 }
309 getIfFeatureList().add(ifFeature);
310 }
311
312 @Override
313 public void setIfFeatureList(List<YangIfFeature> ifFeatureList) {
314 this.ifFeatureList = ifFeatureList;
315 }
316
317 @Override
318 public YangConstructType getYangConstructType() {
319 return YangConstructType.LEAFREF_DATA;
320 }
321
322 @Override
323 public void validateDataOnEntry() throws DataModelException {
324 // TODO auto-generated method stub, to be implemented by parser
325 }
326
327 @Override
328 public void validateDataOnExit() throws DataModelException {
329 // TODO auto-generated method stub, to be implemented by parser
330 }
331
332 @Override
333 public ResolvableStatus getResolvableStatus() {
334 return resolvableStatus;
335 }
336
337 @Override
338 public void setResolvableStatus(ResolvableStatus resolvableStatus) {
339 this.resolvableStatus = resolvableStatus;
340 }
341
342 @Override
rama-huawei6c728a92016-07-11 14:48:12 +0530343 public void setAppErrorInfo(YangAppErrorInfo yangAppErrorInfo) {
344 this.yangAppErrorInfo = yangAppErrorInfo;
345 }
346
347 @Override
348 public YangAppErrorInfo getAppErrorInfo() {
349 return yangAppErrorInfo;
350 }
351
352 @Override
janani b23ccc312016-07-14 19:35:22 +0530353 public Object resolve() throws DataModelException {
janani be18b5342016-07-13 21:06:41 +0530354
355 if (getReferredLeafOrLeafList() == null) {
356 throw new DataModelException("Linker Error: The leafref does not refer to any leaf/leaf-list.");
357 }
358
359 // Initiate the resolution
360 try {
361 setResolvableStatus(getResolution());
362 } catch (DataModelException e) {
363 throw new DataModelException(e.getMessage());
364 }
janani b23ccc312016-07-14 19:35:22 +0530365 return null;
janani be18b5342016-07-13 21:06:41 +0530366 }
367
368 /**
369 * Returns the resolution status by getting the effective built-in type.
370 *
371 * @return status of resolution
372 * @throws DataModelException a violation of data model rules
373 */
374 private ResolvableStatus getResolution() throws DataModelException {
375
376 if (getReferredLeafOrLeafList() instanceof YangLeaf) {
377 YangLeaf yangLeaf = ((YangLeaf) getReferredLeafOrLeafList());
378 YangType baseType = yangLeaf.getDataType();
379
380 if (baseType.getDataType() == YangDataTypes.LEAFREF) {
381 YangLeafRef referredLeafRefInfo = (YangLeafRef) (yangLeaf.getDataType().getDataTypeExtendedInfo());
382 /*
383 * Check whether the referred typedef is resolved.
384 */
385 if (referredLeafRefInfo.getResolvableStatus() != INTRA_FILE_RESOLVED
386 && referredLeafRefInfo.getResolvableStatus() != RESOLVED) {
387 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
388 }
389
390 /*
391 * Check if the referred typedef is intra file resolved, if yes
392 * sets current status also to intra file resolved .
393 */
394 if ((referredLeafRefInfo.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
395 return INTRA_FILE_RESOLVED;
396 }
397
398 // Add the if-feature list from referred leafref to current leafref.
399 List<YangIfFeature> referredLeafIfFeatureListFromLeafref = referredLeafRefInfo.getIfFeatureList();
400 if (referredLeafIfFeatureListFromLeafref != null && !referredLeafIfFeatureListFromLeafref.isEmpty()) {
401 Iterator<YangIfFeature> referredLeafIfFeature = referredLeafIfFeatureListFromLeafref.iterator();
402 while (referredLeafIfFeature.hasNext()) {
403 YangIfFeature ifFeature = referredLeafIfFeature.next();
404 addIfFeatureList(ifFeature);
405 }
406 }
407 setEffectiveDataType(referredLeafRefInfo.getEffectiveDataType());
408 } else if (baseType.getDataType() == YangDataTypes.DERIVED) {
409 /*
410 * Check whether the referred typedef is resolved.
411 */
412 if (baseType.getResolvableStatus() != INTRA_FILE_RESOLVED
413 && baseType.getResolvableStatus() != RESOLVED) {
414 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
415 }
416 /*
417 * Check if the referred typedef is intra file resolved, if yes
418 * sets current status also to intra file resolved .
419 */
420 if ((baseType.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
421 return INTRA_FILE_RESOLVED;
422 }
423 setEffectiveDataType(baseType);
424 } else {
425 setEffectiveDataType(baseType);
426 }
427
428 // Add the if-feature list from referred leaf to current leafref.
429 List<YangIfFeature> referredLeafIfFeatureList = yangLeaf.getIfFeatureList();
430 if (referredLeafIfFeatureList != null && !referredLeafIfFeatureList.isEmpty()) {
431 Iterator<YangIfFeature> referredLeafIfFeature = referredLeafIfFeatureList.iterator();
432 while (referredLeafIfFeature.hasNext()) {
433 YangIfFeature ifFeature = referredLeafIfFeature.next();
434 addIfFeatureList(ifFeature);
435 }
436 }
437 return RESOLVED;
438 } else if (getReferredLeafOrLeafList() instanceof YangLeafList) {
439 YangLeafList yangLeafList = ((YangLeafList) getReferredLeafOrLeafList());
440 YangType baseType = yangLeafList.getDataType();
441
442 if (baseType.getDataType() == YangDataTypes.LEAFREF) {
443 YangLeafRef referredLeafRefInfo = (YangLeafRef) yangLeafList.getDataType().getDataTypeExtendedInfo();
444 /*
445 * Check whether the referred typedef is resolved.
446 */
447 if (referredLeafRefInfo.getResolvableStatus() != INTRA_FILE_RESOLVED
448 && referredLeafRefInfo.getResolvableStatus() != RESOLVED) {
449 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
450 }
451 /*
452 * Check if the referred typedef is intra file resolved, if yes
453 * sets current status also to intra file resolved .
454 */
455 if ((referredLeafRefInfo.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
456 return INTRA_FILE_RESOLVED;
457 }
458 // Add the if-feature list from referred leafref to current leafref.
459 List<YangIfFeature> referredLeafListIfFeatureListFromLeafref = referredLeafRefInfo.getIfFeatureList();
460 if (referredLeafListIfFeatureListFromLeafref != null
461 && !referredLeafListIfFeatureListFromLeafref.isEmpty()) {
462 Iterator<YangIfFeature> referredLeafListIfFeature = referredLeafListIfFeatureListFromLeafref
463 .iterator();
464 while (referredLeafListIfFeature.hasNext()) {
465 YangIfFeature ifFeature = referredLeafListIfFeature.next();
466 addIfFeatureList(ifFeature);
467 }
468 }
469 setEffectiveDataType(referredLeafRefInfo.getEffectiveDataType());
470 } else if (baseType.getDataType() == YangDataTypes.DERIVED) {
471 /*
472 * Check whether the referred typedef is resolved.
473 */
474 if (baseType.getResolvableStatus() != INTRA_FILE_RESOLVED
475 && baseType.getResolvableStatus() != RESOLVED) {
476 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
477 }
478 /*
479 * Check if the referred typedef is intra file resolved, if yes
480 * sets current status also to intra file resolved .
481 */
482 if ((baseType.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
483 return INTRA_FILE_RESOLVED;
484 }
485 setEffectiveDataType(baseType);
486 } else {
487 setEffectiveDataType(baseType);
488 }
489 // Add the if-feature list from referred leaf-list to current leafref.
490 List<YangIfFeature> referredLeafListIfFeatureList = yangLeafList.getIfFeatureList();
491 if (referredLeafListIfFeatureList != null && !referredLeafListIfFeatureList.isEmpty()) {
492 Iterator<YangIfFeature> referredLeafListIfFeature = referredLeafListIfFeatureList.iterator();
493 while (referredLeafListIfFeature.hasNext()) {
494 YangIfFeature ifFeature = referredLeafListIfFeature.next();
495 addIfFeatureList(ifFeature);
496 }
497 }
498 return RESOLVED;
499 } else {
500 throw new DataModelException("Linker Error: The leafref must refer only to leaf/leaf-list.");
501 }
502 }
janani b23ccc312016-07-14 19:35:22 +0530503
504 @Override
505 public int getLineNumber() {
506 return lineNumber;
507 }
508
509 @Override
510 public int getCharPosition() {
511 return charPositionInLine;
512 }
513
514 @Override
515 public void setLineNumber(int lineNumber) {
516 this.lineNumber = lineNumber;
517 }
518
519 @Override
520 public void setCharPosition(int charPositionInLine) {
521 this.charPositionInLine = charPositionInLine;
522 }
janani be18b5342016-07-13 21:06:41 +0530523}