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