Merge "When a node is going down, remove edges in both directions associated with...
[controller.git] / opendaylight / sal / yang-prototype / yang / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / parser / util / TypeConstraints.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.yang.parser.util;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.List;
13
14 import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
15 import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
16 import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
17 import org.opendaylight.controller.yang.model.util.BaseConstraints;
18
19 /**
20  * Holder object for holding YANG type constraints.
21  */
22 public final class TypeConstraints {
23     private final String moduleName;
24     private final int line;
25     private final List<List<RangeConstraint>> ranges = new ArrayList<List<RangeConstraint>>();
26     private final List<List<LengthConstraint>> lengths = new ArrayList<List<LengthConstraint>>();
27     private final List<List<PatternConstraint>> patterns = new ArrayList<List<PatternConstraint>>();
28     private final List<Integer> fractionDigits = new ArrayList<Integer>();
29
30     public TypeConstraints(final String moduleName, final int line) {
31         this.moduleName = moduleName;
32         this.line = line;
33     }
34
35     List<List<RangeConstraint>> getAllRanges() {
36         return ranges;
37     }
38
39     public List<RangeConstraint> getRange() {
40         if (ranges.size() < 2) {
41             return Collections.emptyList();
42         }
43
44         final List<RangeConstraint> resolved = ranges.get(0);
45         RangeConstraint firstRange = resolved.get(0);
46         RangeConstraint lastRange = resolved.get(resolved.size() - 1);
47         Number min = firstRange.getMin();
48         Number max = lastRange.getMax();
49
50         if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
51             if (ranges.size() > 1) {
52                 validateRange(resolved);
53             }
54             return resolved;
55         }
56
57         if (firstRange.equals(lastRange)) {
58             if (min instanceof UnknownBoundaryNumber) {
59                 min = resolveMinRange(min);
60             }
61             if (max instanceof UnknownBoundaryNumber) {
62                 max = resolveMaxRange(max);
63             }
64             firstRange = BaseConstraints.rangeConstraint(min, max, firstRange.getDescription(),
65                     firstRange.getReference());
66             resolved.set(0, firstRange);
67             lastRange = BaseConstraints.rangeConstraint(min, max, lastRange.getDescription(), lastRange.getReference());
68             resolved.set(resolved.size() - 1, lastRange);
69         } else {
70             if (min instanceof UnknownBoundaryNumber) {
71                 min = resolveMinRange(min);
72                 firstRange = BaseConstraints.rangeConstraint(min, firstRange.getMax(), firstRange.getDescription(),
73                         firstRange.getReference());
74                 resolved.set(0, firstRange);
75             }
76             if (max instanceof UnknownBoundaryNumber) {
77                 max = resolveMaxRange(max);
78                 lastRange = BaseConstraints.rangeConstraint(lastRange.getMin(), max, lastRange.getDescription(),
79                         lastRange.getReference());
80                 resolved.set(resolved.size() - 1, lastRange);
81             }
82         }
83         if (this.ranges.size() > 1) {
84             validateRange(resolved);
85         }
86         return resolved;
87     }
88
89     private Number resolveMinRange(Number min) {
90         int i = 1;
91         while (min instanceof UnknownBoundaryNumber) {
92             final List<RangeConstraint> act = ranges.get(i);
93             min = act.get(0).getMin();
94             i++;
95         }
96         return min;
97     }
98
99     private Number resolveMaxRange(Number max) {
100         int i = 1;
101         while (max instanceof UnknownBoundaryNumber) {
102             final List<RangeConstraint> act = ranges.get(i);
103             max = act.get(act.size() - 1).getMax();
104             i++;
105         }
106         return max;
107     }
108
109     public void addRanges(final List<RangeConstraint> ranges) {
110         if (ranges != null && !(ranges.isEmpty())) {
111             this.ranges.add(ranges);
112         }
113     }
114
115     public List<List<LengthConstraint>> getAllLengths() {
116         return lengths;
117     }
118
119     public List<LengthConstraint> getLength() {
120         if (lengths.size() < 2) {
121             return Collections.emptyList();
122         }
123
124         final List<LengthConstraint> resolved = lengths.get(0);
125         LengthConstraint firstLength = resolved.get(0);
126         LengthConstraint lastLength = resolved.get(resolved.size() - 1);
127         Number min = firstLength.getMin();
128         Number max = lastLength.getMax();
129
130         if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
131             if (lengths.size() > 1) {
132                 validateLength(resolved);
133             }
134             return resolved;
135         }
136
137         if (firstLength.equals(lastLength)) {
138             if (min instanceof UnknownBoundaryNumber) {
139                 min = resolveMinLength(min);
140             }
141             if (max instanceof UnknownBoundaryNumber) {
142                 max = resolveMaxLength(max);
143             }
144             firstLength = BaseConstraints.lengthConstraint(min, max, firstLength.getDescription(),
145                     firstLength.getReference());
146             resolved.set(0, firstLength);
147             lastLength = BaseConstraints.lengthConstraint(min, max, lastLength.getDescription(),
148                     lastLength.getReference());
149             resolved.set(resolved.size() - 1, lastLength);
150         } else {
151             if (min instanceof UnknownBoundaryNumber) {
152                 min = resolveMinLength(min);
153                 firstLength = BaseConstraints.lengthConstraint(min, firstLength.getMax(), firstLength.getDescription(),
154                         firstLength.getReference());
155                 resolved.set(0, firstLength);
156             }
157             if (max instanceof UnknownBoundaryNumber) {
158                 max = resolveMaxLength(max);
159                 lastLength = BaseConstraints.lengthConstraint(lastLength.getMin(), max, lastLength.getDescription(),
160                         lastLength.getReference());
161                 resolved.set(resolved.size() - 1, lastLength);
162             }
163         }
164
165         if (lengths.size() > 1) {
166             validateLength(resolved);
167         }
168         return resolved;
169     }
170
171     private Number resolveMinLength(Number min) {
172         int i = 1;
173         while (min instanceof UnknownBoundaryNumber) {
174             final List<LengthConstraint> act = lengths.get(i);
175             min = act.get(0).getMin();
176             i++;
177         }
178         return min;
179     }
180
181     private Number resolveMaxLength(Number max) {
182         int i = 1;
183         while (max instanceof UnknownBoundaryNumber) {
184             final List<LengthConstraint> act = lengths.get(i);
185             max = act.get(act.size() - 1).getMax();
186             i++;
187         }
188         return max;
189     }
190
191     public void addLengths(final List<LengthConstraint> lengths) {
192         if (lengths != null && !(lengths.isEmpty())) {
193             this.lengths.add(lengths);
194         }
195     }
196
197     public List<PatternConstraint> getPatterns() {
198         if(patterns.isEmpty()) {
199             return Collections.emptyList();
200         }
201         return patterns.get(0);
202     }
203
204     public void addPatterns(final List<PatternConstraint> patterns) {
205         this.patterns.add(patterns);
206     }
207
208     public Integer getFractionDigits() {
209         if (fractionDigits.isEmpty()) {
210             return null;
211         }
212         return fractionDigits.get(0);
213     }
214
215     public void addFractionDigits(final Integer fractionDigits) {
216         this.fractionDigits.add(fractionDigits);
217     }
218
219     public void validateConstraints() {
220         validateLength();
221         validateRange();
222     }
223
224     private void validateRange() {
225         if (ranges.size() < 2) {
226             return;
227         }
228         List<RangeConstraint> typeRange = getRange();
229
230         for (RangeConstraint range : typeRange) {
231             if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
232                 throw new YangParseException(moduleName, line, "Unresolved range constraints");
233             }
234             final long min = range.getMin().longValue();
235             final long max = range.getMax().longValue();
236
237             List<RangeConstraint> parentRanges = ranges.get(1);
238             boolean check = false;
239             for (RangeConstraint r : parentRanges) {
240                 Number parentMinNumber = r.getMin();
241                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
242                     parentMinNumber = resolveMinRange(parentMinNumber);
243                 }
244                 long parentMin = parentMinNumber.longValue();
245
246                 Number parentMaxNumber = r.getMax();
247                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
248                     parentMaxNumber = resolveMaxRange(parentMaxNumber);
249                 }
250                 long parentMax = parentMaxNumber.longValue();
251
252                 if (parentMin <= min && parentMax >= max) {
253                     check = true;
254                     break;
255                 }
256             }
257             if (!check) {
258                 throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
259                         + "> (parent: " + parentRanges + ").");
260             }
261         }
262     }
263
264     private void validateRange(List<RangeConstraint> typeRange) {
265         if (ranges.size() < 2) {
266             return;
267         }
268
269         for (RangeConstraint range : typeRange) {
270             if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
271                 throw new YangParseException(moduleName, line, "Unresolved range constraints");
272             }
273             final long min = range.getMin().longValue();
274             final long max = range.getMax().longValue();
275
276             List<RangeConstraint> parentRanges = ranges.get(1);
277             boolean check = false;
278             for (RangeConstraint r : parentRanges) {
279                 Number parentMinNumber = r.getMin();
280                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
281                     parentMinNumber = resolveMinRange(parentMinNumber);
282                 }
283                 long parentMin = parentMinNumber.longValue();
284
285                 Number parentMaxNumber = r.getMax();
286                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
287                     parentMaxNumber = resolveMaxRange(parentMaxNumber);
288                 }
289                 long parentMax = parentMaxNumber.longValue();
290
291                 if (parentMin <= min && parentMax >= max) {
292                     check = true;
293                     break;
294                 }
295             }
296             if (!check) {
297                 throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
298                         + "> (parent: " + parentRanges + ").");
299             }
300         }
301     }
302
303     private void validateLength() {
304         if (lengths.size() < 2) {
305             return;
306         }
307         List<LengthConstraint> typeLength = getLength();
308
309         for (LengthConstraint length : typeLength) {
310             if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
311                 throw new YangParseException(moduleName, line, "Unresolved length constraints");
312             }
313             final long min = length.getMin().longValue();
314             final long max = length.getMax().longValue();
315
316             List<LengthConstraint> parentLengths = lengths.get(1);
317             boolean check = false;
318             for (LengthConstraint lc : parentLengths) {
319                 Number parentMinNumber = lc.getMin();
320                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
321                     parentMinNumber = resolveMinLength(parentMinNumber);
322                 }
323                 long parentMin = parentMinNumber.longValue();
324
325                 Number parentMaxNumber = lc.getMax();
326                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
327                     parentMaxNumber = resolveMaxLength(parentMaxNumber);
328                 }
329                 long parentMax = parentMaxNumber.longValue();
330
331                 if (parentMin <= min && parentMax >= max) {
332                     check = true;
333                     break;
334                 }
335             }
336             if (!check) {
337                 throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
338                         + "> (parent: " + parentLengths + ").");
339             }
340         }
341     }
342
343     private void validateLength(List<LengthConstraint> typeLength) {
344         if (lengths.size() < 2) {
345             return;
346         }
347
348         for (LengthConstraint length : typeLength) {
349             if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
350                 throw new YangParseException(moduleName, line, "Unresolved length constraints");
351             }
352             final long min = length.getMin().longValue();
353             final long max = length.getMax().longValue();
354
355             List<LengthConstraint> parentLengths = lengths.get(1);
356             boolean check = false;
357             for (LengthConstraint lc : parentLengths) {
358                 Number parentMinNumber = lc.getMin();
359                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
360                     parentMinNumber = resolveMinLength(parentMinNumber);
361                 }
362                 long parentMin = parentMinNumber.longValue();
363
364                 Number parentMaxNumber = lc.getMax();
365                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
366                     parentMaxNumber = resolveMaxLength(parentMaxNumber);
367                 }
368                 long parentMax = parentMaxNumber.longValue();
369
370                 if (parentMin <= min && parentMax >= max) {
371                     check = true;
372                     break;
373                 }
374             }
375             if (!check) {
376                 throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
377                         + "> (parent: " + parentLengths + ").");
378             }
379         }
380     }
381
382 }