17307b46ee29f8aedc8a8dcc58e4113a1d9c84f2
[controller.git] / opendaylight / sal / yang-prototype / code-generator / 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<PatternConstraint> patterns = new ArrayList<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         return patterns;
199     }
200
201     public void addPatterns(final List<PatternConstraint> patterns) {
202         this.patterns.addAll(patterns);
203     }
204
205     public Integer getFractionDigits() {
206         if (fractionDigits.isEmpty()) {
207             return null;
208         }
209         return fractionDigits.get(0);
210     }
211
212     public void addFractionDigits(final Integer fractionDigits) {
213         this.fractionDigits.add(fractionDigits);
214     }
215
216     public void validateConstraints() {
217         validateLength();
218         validateRange();
219     }
220
221     private void validateRange() {
222         if (ranges.size() < 2) {
223             return;
224         }
225         List<RangeConstraint> typeRange = getRange();
226
227         for (RangeConstraint range : typeRange) {
228             if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
229                 throw new YangParseException(line, "Unresolved range constraints");
230             }
231             final long min = range.getMin().longValue();
232             final long max = range.getMax().longValue();
233
234             List<RangeConstraint> parentRanges = ranges.get(1);
235             boolean check = false;
236             for (RangeConstraint r : parentRanges) {
237                 Number parentMinNumber = r.getMin();
238                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
239                     parentMinNumber = resolveMinRange(parentMinNumber);
240                 }
241                 long parentMin = parentMinNumber.longValue();
242
243                 Number parentMaxNumber = r.getMax();
244                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
245                     parentMaxNumber = resolveMaxRange(parentMaxNumber);
246                 }
247                 long parentMax = parentMaxNumber.longValue();
248
249                 if (parentMin <= min && parentMax >= max) {
250                     check = true;
251                     break;
252                 }
253             }
254             if (!check) {
255                 throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
256                         + "> (parent: " + parentRanges + ").");
257             }
258         }
259     }
260
261     private void validateRange(List<RangeConstraint> typeRange) {
262         if (ranges.size() < 2) {
263             return;
264         }
265
266         for (RangeConstraint range : typeRange) {
267             if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
268                 throw new YangParseException(line, "Unresolved range constraints");
269             }
270             final long min = range.getMin().longValue();
271             final long max = range.getMax().longValue();
272
273             List<RangeConstraint> parentRanges = ranges.get(1);
274             boolean check = false;
275             for (RangeConstraint r : parentRanges) {
276                 Number parentMinNumber = r.getMin();
277                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
278                     parentMinNumber = resolveMinRange(parentMinNumber);
279                 }
280                 long parentMin = parentMinNumber.longValue();
281
282                 Number parentMaxNumber = r.getMax();
283                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
284                     parentMaxNumber = resolveMaxRange(parentMaxNumber);
285                 }
286                 long parentMax = parentMaxNumber.longValue();
287
288                 if (parentMin <= min && parentMax >= max) {
289                     check = true;
290                     break;
291                 }
292             }
293             if (!check) {
294                 throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
295                         + "> (parent: " + parentRanges + ").");
296             }
297         }
298     }
299
300     private void validateLength() {
301         if (lengths.size() < 2) {
302             return;
303         }
304         List<LengthConstraint> typeLength = getLength();
305
306         for (LengthConstraint length : typeLength) {
307             if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
308                 throw new YangParseException(line, "Unresolved length constraints");
309             }
310             final long min = length.getMin().longValue();
311             final long max = length.getMax().longValue();
312
313             List<LengthConstraint> parentLengths = lengths.get(1);
314             boolean check = false;
315             for (LengthConstraint lc : parentLengths) {
316                 Number parentMinNumber = lc.getMin();
317                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
318                     parentMinNumber = resolveMinLength(parentMinNumber);
319                 }
320                 long parentMin = parentMinNumber.longValue();
321
322                 Number parentMaxNumber = lc.getMax();
323                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
324                     parentMaxNumber = resolveMaxLength(parentMaxNumber);
325                 }
326                 long parentMax = parentMaxNumber.longValue();
327
328                 if (parentMin <= min && parentMax >= max) {
329                     check = true;
330                     break;
331                 }
332             }
333             if (!check) {
334                 throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
335                         + "> (parent: " + parentLengths + ").");
336             }
337         }
338     }
339
340     private void validateLength(List<LengthConstraint> typeLength) {
341         if (lengths.size() < 2) {
342             return;
343         }
344
345         for (LengthConstraint length : typeLength) {
346             if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
347                 throw new YangParseException(line, "Unresolved length constraints");
348             }
349             final long min = length.getMin().longValue();
350             final long max = length.getMax().longValue();
351
352             List<LengthConstraint> parentLengths = lengths.get(1);
353             boolean check = false;
354             for (LengthConstraint lc : parentLengths) {
355                 Number parentMinNumber = lc.getMin();
356                 if (parentMinNumber instanceof UnknownBoundaryNumber) {
357                     parentMinNumber = resolveMinLength(parentMinNumber);
358                 }
359                 long parentMin = parentMinNumber.longValue();
360
361                 Number parentMaxNumber = lc.getMax();
362                 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
363                     parentMaxNumber = resolveMaxLength(parentMaxNumber);
364                 }
365                 long parentMax = parentMaxNumber.longValue();
366
367                 if (parentMin <= min && parentMax >= max) {
368                     check = true;
369                     break;
370                 }
371             }
372             if (!check) {
373                 throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
374                         + "> (parent: " + parentLengths + ").");
375             }
376         }
377     }
378
379 }