blob: 0c3a98fc02f7618421bf4288a6160381af7ef1b1 [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
19import java.io.Serializable;
20import java.util.Iterator;
21import java.util.LinkedList;
22import java.util.List;
23
24import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
25import org.onosproject.yangutils.datamodel.utils.Parsable;
26import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
27import org.onosproject.yangutils.datamodel.utils.YangConstructType;
28import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
29
30import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
31import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
32
33/*
34 * Reference:RFC 6020.
35 * The leafref type is used to reference a particular leaf instance in
36 * the data tree. The "path" substatement (Section 9.9.2) selects a set
37 * of leaf instances, and the leafref value space is the set of values
38 * of these leaf instances.
39 */
40
41/**
42 * Represents the leafref information.
43 *
44 * @param <T> YANG leafref info
45 */
Bharat saraswalb1170bd2016-07-14 13:26:18 +053046public class YangLeafRef<T> implements Parsable, Resolvable, Serializable, YangIfFeatureHolder,
47 YangXPathResolver {
janani be18b5342016-07-13 21:06:41 +053048
49 private static final long serialVersionUID = 286201644L;
50
51 /**
52 * YANG data type.
53 */
54 private YangType effectiveDataType;
55
56 /**
57 * Referred leaf/leaf-list for the path specified in the leafref type.
58 */
59 private T referredLeafOrLeafList;
60
61 /**
62 * Path of the leafref.
63 */
64 private String path;
65
66 /**
67 * Leafref path type. Either absolute or relative path.
68 */
69 private YangPathArgType pathType;
70
71 /**
72 * List of atomic paths in absolute Path.
73 */
74 private List<YangAtomicPath> atomicPath;
75
76 /**
77 * YANG relative path.
78 */
79 private YangRelativePath relativePath;
80
81 /**
82 * Status of resolution. If completely resolved enum value is "RESOLVED",
83 * if not enum value is "UNRESOLVED", in case reference of grouping/typedef/leafref
84 * is added to uses/type/leafref but it's not resolved value of enum should be
85 * "INTRA_FILE_RESOLVED".
86 */
87 private ResolvableStatus resolvableStatus;
88
89 /**
90 * Require instance status in leafref type.
91 */
92 private boolean requireInstance;
93
94 /**
95 * List of if-feature.
96 */
97 private List<YangIfFeature> ifFeatureList;
98
99 /**
100 * Returns the status of the require instance in leafref.
101 *
102 * @return status of the require instance
103 */
104 public boolean getRequireInstance() {
105 return requireInstance;
106 }
107
108 /**
109 * Sets the status of the require instance in leafref.
110 *
111 * @param requireInstance status of the require instance
112 */
113 public void setRequireInstance(boolean requireInstance) {
114 this.requireInstance = requireInstance;
115 }
116
117 /**
118 * Returns the type of data.
119 *
120 * @return the data type
121 */
122 public YangType getEffectiveDataType() {
123 return effectiveDataType;
124 }
125
126 /**
127 * Sets the type of data.
128 *
129 * @param effectiveDataType data type
130 */
131 public void setEffectiveDataType(YangType effectiveDataType) {
132 this.effectiveDataType = effectiveDataType;
133 }
134
135 /**
136 * Returns the path of the leafref.
137 *
138 * @return path of the leafref
139 */
140 public String getPath() {
141 return path;
142 }
143
144 /**
145 * Sets the path of the leafref.
146 *
147 * @param path leafref path
148 */
149 public void setPath(String path) {
150 this.path = path;
151 }
152
153 /**
154 * Returns the type of path in the leafref.
155 *
156 * @return type of path
157 */
158 public YangPathArgType getPathType() {
159 return pathType;
160 }
161
162 /**
163 * Sets the type of path in the leafref. It can be either absolute or relative type.
164 *
165 * @param pathType type of path
166 */
167 public void setPathType(YangPathArgType pathType) {
168 this.pathType = pathType;
169 }
170
171 /**
172 * Returns the list of atomic path.
173 *
174 * @return list of atomic path
175 */
176 public List<YangAtomicPath> getAtomicPath() {
177 return atomicPath;
178 }
179
180 /**
181 * Sets the list of atomic path.
182 *
183 * @param atomicPath list of atomic path.
184 */
185 public void setAtomicPath(List<YangAtomicPath> atomicPath) {
186 this.atomicPath = atomicPath;
187 }
188
189 /**
190 * Returns the object of relative path.
191 *
192 * @return object of relative path
193 */
194 public YangRelativePath getRelativePath() {
195 return relativePath;
196 }
197
198 /**
199 * Sets the object of relative path.
200 *
201 * @param relativePath object of relative path.
202 */
203 public void setRelativePath(YangRelativePath relativePath) {
204 this.relativePath = relativePath;
205 }
206
207 /**
208 * Returns the object of referred leaf/leaf-list.
209 *
210 * @return object of referred leaf/leaf-list
211 */
212 public T getReferredLeafOrLeafList() {
213 return referredLeafOrLeafList;
214 }
215
216 /**
217 * Sets the object of referred leaf/leaf-list.
218 *
219 * @param targetExtendedInfo object of referred leaf/leaf-list
220 */
221 public void setReferredLeafOrLeafList(T targetExtendedInfo) {
222 this.referredLeafOrLeafList = targetExtendedInfo;
223 }
224
225 @Override
226 public List<YangIfFeature> getIfFeatureList() {
227 return ifFeatureList;
228 }
229
230 @Override
231 public void addIfFeatureList(YangIfFeature ifFeature) {
232 if (getIfFeatureList() == null) {
233 setIfFeatureList(new LinkedList<>());
234 }
235 getIfFeatureList().add(ifFeature);
236 }
237
238 @Override
239 public void setIfFeatureList(List<YangIfFeature> ifFeatureList) {
240 this.ifFeatureList = ifFeatureList;
241 }
242
243 @Override
244 public YangConstructType getYangConstructType() {
245 return YangConstructType.LEAFREF_DATA;
246 }
247
248 @Override
249 public void validateDataOnEntry() throws DataModelException {
250 // TODO auto-generated method stub, to be implemented by parser
251 }
252
253 @Override
254 public void validateDataOnExit() throws DataModelException {
255 // TODO auto-generated method stub, to be implemented by parser
256 }
257
258 @Override
259 public ResolvableStatus getResolvableStatus() {
260 return resolvableStatus;
261 }
262
263 @Override
264 public void setResolvableStatus(ResolvableStatus resolvableStatus) {
265 this.resolvableStatus = resolvableStatus;
266 }
267
268 @Override
269 public void resolve() throws DataModelException {
270
271 if (getReferredLeafOrLeafList() == null) {
272 throw new DataModelException("Linker Error: The leafref does not refer to any leaf/leaf-list.");
273 }
274
275 // Initiate the resolution
276 try {
277 setResolvableStatus(getResolution());
278 } catch (DataModelException e) {
279 throw new DataModelException(e.getMessage());
280 }
281 }
282
283 /**
284 * Returns the resolution status by getting the effective built-in type.
285 *
286 * @return status of resolution
287 * @throws DataModelException a violation of data model rules
288 */
289 private ResolvableStatus getResolution() throws DataModelException {
290
291 if (getReferredLeafOrLeafList() instanceof YangLeaf) {
292 YangLeaf yangLeaf = ((YangLeaf) getReferredLeafOrLeafList());
293 YangType baseType = yangLeaf.getDataType();
294
295 if (baseType.getDataType() == YangDataTypes.LEAFREF) {
296 YangLeafRef referredLeafRefInfo = (YangLeafRef) (yangLeaf.getDataType().getDataTypeExtendedInfo());
297 /*
298 * Check whether the referred typedef is resolved.
299 */
300 if (referredLeafRefInfo.getResolvableStatus() != INTRA_FILE_RESOLVED
301 && referredLeafRefInfo.getResolvableStatus() != RESOLVED) {
302 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
303 }
304
305 /*
306 * Check if the referred typedef is intra file resolved, if yes
307 * sets current status also to intra file resolved .
308 */
309 if ((referredLeafRefInfo.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
310 return INTRA_FILE_RESOLVED;
311 }
312
313 // Add the if-feature list from referred leafref to current leafref.
314 List<YangIfFeature> referredLeafIfFeatureListFromLeafref = referredLeafRefInfo.getIfFeatureList();
315 if (referredLeafIfFeatureListFromLeafref != null && !referredLeafIfFeatureListFromLeafref.isEmpty()) {
316 Iterator<YangIfFeature> referredLeafIfFeature = referredLeafIfFeatureListFromLeafref.iterator();
317 while (referredLeafIfFeature.hasNext()) {
318 YangIfFeature ifFeature = referredLeafIfFeature.next();
319 addIfFeatureList(ifFeature);
320 }
321 }
322 setEffectiveDataType(referredLeafRefInfo.getEffectiveDataType());
323 } else if (baseType.getDataType() == YangDataTypes.DERIVED) {
324 /*
325 * Check whether the referred typedef is resolved.
326 */
327 if (baseType.getResolvableStatus() != INTRA_FILE_RESOLVED
328 && baseType.getResolvableStatus() != RESOLVED) {
329 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
330 }
331 /*
332 * Check if the referred typedef is intra file resolved, if yes
333 * sets current status also to intra file resolved .
334 */
335 if ((baseType.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
336 return INTRA_FILE_RESOLVED;
337 }
338 setEffectiveDataType(baseType);
339 } else {
340 setEffectiveDataType(baseType);
341 }
342
343 // Add the if-feature list from referred leaf to current leafref.
344 List<YangIfFeature> referredLeafIfFeatureList = yangLeaf.getIfFeatureList();
345 if (referredLeafIfFeatureList != null && !referredLeafIfFeatureList.isEmpty()) {
346 Iterator<YangIfFeature> referredLeafIfFeature = referredLeafIfFeatureList.iterator();
347 while (referredLeafIfFeature.hasNext()) {
348 YangIfFeature ifFeature = referredLeafIfFeature.next();
349 addIfFeatureList(ifFeature);
350 }
351 }
352 return RESOLVED;
353 } else if (getReferredLeafOrLeafList() instanceof YangLeafList) {
354 YangLeafList yangLeafList = ((YangLeafList) getReferredLeafOrLeafList());
355 YangType baseType = yangLeafList.getDataType();
356
357 if (baseType.getDataType() == YangDataTypes.LEAFREF) {
358 YangLeafRef referredLeafRefInfo = (YangLeafRef) yangLeafList.getDataType().getDataTypeExtendedInfo();
359 /*
360 * Check whether the referred typedef is resolved.
361 */
362 if (referredLeafRefInfo.getResolvableStatus() != INTRA_FILE_RESOLVED
363 && referredLeafRefInfo.getResolvableStatus() != RESOLVED) {
364 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
365 }
366 /*
367 * Check if the referred typedef is intra file resolved, if yes
368 * sets current status also to intra file resolved .
369 */
370 if ((referredLeafRefInfo.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
371 return INTRA_FILE_RESOLVED;
372 }
373 // Add the if-feature list from referred leafref to current leafref.
374 List<YangIfFeature> referredLeafListIfFeatureListFromLeafref = referredLeafRefInfo.getIfFeatureList();
375 if (referredLeafListIfFeatureListFromLeafref != null
376 && !referredLeafListIfFeatureListFromLeafref.isEmpty()) {
377 Iterator<YangIfFeature> referredLeafListIfFeature = referredLeafListIfFeatureListFromLeafref
378 .iterator();
379 while (referredLeafListIfFeature.hasNext()) {
380 YangIfFeature ifFeature = referredLeafListIfFeature.next();
381 addIfFeatureList(ifFeature);
382 }
383 }
384 setEffectiveDataType(referredLeafRefInfo.getEffectiveDataType());
385 } else if (baseType.getDataType() == YangDataTypes.DERIVED) {
386 /*
387 * Check whether the referred typedef is resolved.
388 */
389 if (baseType.getResolvableStatus() != INTRA_FILE_RESOLVED
390 && baseType.getResolvableStatus() != RESOLVED) {
391 throw new DataModelException("Linker Error: Referred typedef is not resolved for type.");
392 }
393 /*
394 * Check if the referred typedef is intra file resolved, if yes
395 * sets current status also to intra file resolved .
396 */
397 if ((baseType.getResolvableStatus() == INTRA_FILE_RESOLVED)) {
398 return INTRA_FILE_RESOLVED;
399 }
400 setEffectiveDataType(baseType);
401 } else {
402 setEffectiveDataType(baseType);
403 }
404 // Add the if-feature list from referred leaf-list to current leafref.
405 List<YangIfFeature> referredLeafListIfFeatureList = yangLeafList.getIfFeatureList();
406 if (referredLeafListIfFeatureList != null && !referredLeafListIfFeatureList.isEmpty()) {
407 Iterator<YangIfFeature> referredLeafListIfFeature = referredLeafListIfFeatureList.iterator();
408 while (referredLeafListIfFeature.hasNext()) {
409 YangIfFeature ifFeature = referredLeafListIfFeature.next();
410 addIfFeatureList(ifFeature);
411 }
412 }
413 return RESOLVED;
414 } else {
415 throw new DataModelException("Linker Error: The leafref must refer only to leaf/leaf-list.");
416 }
417 }
418}