BUG-865: deprecate pre-Beryllium parser elements
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / 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.yangtools.yang.parser.util;
9
10 import com.google.common.base.Optional;
11 import java.math.BigDecimal;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
16 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
17 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
18 import org.opendaylight.yangtools.yang.model.util.BaseConstraints;
19
20 /**
21  * Holder object for holding YANG type constraints.
22  *
23  * @deprecated Pre-Beryllium implementation, scheduled for removal.
24  */
25 @Deprecated
26 public final class TypeConstraints {
27     private final String moduleName;
28     private final int line;
29     private final List<List<RangeConstraint>> ranges = new ArrayList<>();
30     private final List<List<LengthConstraint>> lengths = new ArrayList<>();
31     private final List<List<PatternConstraint>> patterns = new ArrayList<>();
32     private final List<Integer> fractionDigits = new ArrayList<>();
33
34     public TypeConstraints(final String moduleName, final int line) {
35         this.moduleName = moduleName;
36         this.line = line;
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.newRangeConstraint(min, max,
65                 Optional.fromNullable(firstRange.getDescription()),
66                 Optional.fromNullable(firstRange.getReference()));
67             resolved.set(0, firstRange);
68             lastRange = BaseConstraints.newRangeConstraint(min, max,
69                 Optional.fromNullable(lastRange.getDescription()),
70                 Optional.fromNullable(lastRange.getReference()));
71             resolved.set(resolved.size() - 1, lastRange);
72         } else {
73             if (min instanceof UnknownBoundaryNumber) {
74                 min = resolveMinRange(min);
75                 firstRange = BaseConstraints.newRangeConstraint(min, firstRange.getMax(),
76                     Optional.fromNullable(firstRange.getDescription()),
77                     Optional.fromNullable(firstRange.getReference()));
78                 resolved.set(0, firstRange);
79             }
80             if (max instanceof UnknownBoundaryNumber) {
81                 max = resolveMaxRange(max);
82                 lastRange = BaseConstraints.newRangeConstraint(lastRange.getMin(), max,
83                     Optional.fromNullable(lastRange.getDescription()),
84                     Optional.fromNullable(lastRange.getReference()));
85                 resolved.set(resolved.size() - 1, lastRange);
86             }
87         }
88         if (this.ranges.size() > 1) {
89             validateRange(resolved);
90         }
91         return resolved;
92     }
93
94     private Number resolveMinRange(final Number min) {
95         int i = 1;
96         Number newMin = min;
97         while (newMin instanceof UnknownBoundaryNumber) {
98             final List<RangeConstraint> act = ranges.get(i);
99             newMin = act.get(0).getMin();
100             i++;
101         }
102         return newMin;
103     }
104
105     private Number resolveMaxRange(final Number max) {
106         int i = 1;
107         Number newMax = max;
108         while (newMax instanceof UnknownBoundaryNumber) {
109             final List<RangeConstraint> act = ranges.get(i);
110             newMax = act.get(act.size() - 1).getMax();
111             i++;
112         }
113         return newMax;
114     }
115
116     public void addRanges(final List<RangeConstraint> ranges) {
117         if (ranges != null && !(ranges.isEmpty())) {
118             this.ranges.add(ranges);
119         }
120     }
121
122     public List<List<LengthConstraint>> getAllLengths() {
123         return lengths;
124     }
125
126     public List<LengthConstraint> getLength() {
127         if (lengths.size() < 2) {
128             return Collections.emptyList();
129         }
130
131         final List<LengthConstraint> resolved = lengths.get(0);
132         LengthConstraint firstLength = resolved.get(0);
133         LengthConstraint lastLength = resolved.get(resolved.size() - 1);
134         Number min = firstLength.getMin();
135         Number max = lastLength.getMax();
136
137         if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
138             if (lengths.size() > 1) {
139                 validateLength(resolved);
140             }
141             return resolved;
142         }
143
144         if (firstLength.equals(lastLength)) {
145             if (min instanceof UnknownBoundaryNumber) {
146                 min = resolveMinLength(min);
147             }
148             if (max instanceof UnknownBoundaryNumber) {
149                 max = resolveMaxLength(max);
150             }
151             firstLength = BaseConstraints.newLengthConstraint(min, max,
152                 Optional.fromNullable(firstLength.getDescription()),
153                 Optional.fromNullable(firstLength.getReference()));
154             resolved.set(0, firstLength);
155             lastLength = BaseConstraints.newLengthConstraint(min, max,
156                 Optional.fromNullable(lastLength.getDescription()),
157                 Optional.fromNullable(lastLength.getReference()));
158             resolved.set(resolved.size() - 1, lastLength);
159         } else {
160             if (min instanceof UnknownBoundaryNumber) {
161                 min = resolveMinLength(min);
162                 firstLength = BaseConstraints.newLengthConstraint(min, firstLength.getMax(),
163                     Optional.fromNullable(firstLength.getDescription()),
164                     Optional.fromNullable(firstLength.getReference()));
165                 resolved.set(0, firstLength);
166             }
167             if (max instanceof UnknownBoundaryNumber) {
168                 max = resolveMaxLength(max);
169                 lastLength = BaseConstraints.newLengthConstraint(lastLength.getMin(), max,
170                     Optional.fromNullable(lastLength.getDescription()),
171                     Optional.fromNullable(lastLength.getReference()));
172                 resolved.set(resolved.size() - 1, lastLength);
173             }
174         }
175
176         if (lengths.size() > 1) {
177             validateLength(resolved);
178         }
179         return resolved;
180     }
181
182     private Number resolveMinLength(final Number min) {
183         int i = 1;
184         Number newMin = min;
185         while (newMin instanceof UnknownBoundaryNumber) {
186             final List<LengthConstraint> act = lengths.get(i);
187             newMin = act.get(0).getMin();
188             i++;
189         }
190         return newMin;
191     }
192
193     private Number resolveMaxLength(final Number max) {
194         int i = 1;
195         Number newMax = max;
196         while (newMax instanceof UnknownBoundaryNumber) {
197             final List<LengthConstraint> act = lengths.get(i);
198             newMax = act.get(act.size() - 1).getMax();
199             i++;
200         }
201         return newMax;
202     }
203
204     public void addLengths(final List<LengthConstraint> lengths) {
205         if (lengths != null && !(lengths.isEmpty())) {
206             this.lengths.add(lengths);
207         }
208     }
209
210     public List<PatternConstraint> getPatterns() {
211         if (patterns.isEmpty()) {
212             return Collections.emptyList();
213         }
214         return patterns.get(0);
215     }
216
217     public void addPatterns(final List<PatternConstraint> patterns) {
218         this.patterns.add(patterns);
219     }
220
221     public Integer getFractionDigits() {
222         if (fractionDigits.isEmpty()) {
223             return null;
224         }
225         return fractionDigits.get(0);
226     }
227
228     public void addFractionDigits(final Integer fractionDigits) {
229         this.fractionDigits.add(fractionDigits);
230     }
231
232     public void validateConstraints() {
233         validateLength();
234         validateRange();
235     }
236
237     private void validateRange() {
238         validateRange(getRange());
239     }
240
241     private void validateRange(final List<RangeConstraint> typeRange) {
242         if (ranges.size() < 2) {
243             return;
244         }
245
246         for (RangeConstraint range : typeRange) {
247             if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
248                 throw new YangParseException(moduleName, line, "Unresolved range constraints");
249             }
250             final BigDecimal min = new BigDecimal(range.getMin().toString());
251             final BigDecimal max = new BigDecimal(range.getMax().toString());
252
253             List<RangeConstraint> parentRanges = ranges.get(1);
254             if (!areRangesSubintervalsOfParentRanges(parentRanges, min, max)) {
255                 throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
256                         + "> (parent: " + parentRanges + ").");
257             }
258         }
259     }
260
261     private boolean areRangesSubintervalsOfParentRanges(final List<RangeConstraint> parentRanges, final BigDecimal min,
262             final BigDecimal max) {
263         boolean check = false;
264         for (RangeConstraint r : parentRanges) {
265             Number parentMinNumber = r.getMin();
266             if (parentMinNumber instanceof UnknownBoundaryNumber) {
267                 parentMinNumber = resolveMinRange(parentMinNumber);
268             }
269             BigDecimal parentMin = new BigDecimal(parentMinNumber.toString());
270
271             Number parentMaxNumber = r.getMax();
272             if (parentMaxNumber instanceof UnknownBoundaryNumber) {
273                 parentMaxNumber = resolveMaxRange(parentMaxNumber);
274             }
275             BigDecimal parentMax = new BigDecimal(parentMaxNumber.toString());
276
277             if (parentMin.compareTo(min) <= 0 && parentMax.compareTo(max) >= 0) {
278                 check = true;
279                 break;
280             }
281         }
282         return check;
283     }
284
285     private void validateLength() {
286         validateLength(getLength());
287     }
288
289     private void validateLength(final List<LengthConstraint> typeLength) {
290         if (lengths.size() < 2) {
291             return;
292         }
293
294         for (LengthConstraint length : typeLength) {
295             if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
296                 throw new YangParseException(moduleName, line, "Unresolved length constraints");
297             }
298             final long min = length.getMin().longValue();
299             final long max = length.getMax().longValue();
300
301             List<LengthConstraint> parentLengths = lengths.get(1);
302             if (!areLengthRangesSubintervalsOfParentLengthRanges(parentLengths, min, max)) {
303                 throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
304                         + "> (parent: " + parentLengths + ").");
305             }
306         }
307     }
308
309     private boolean areLengthRangesSubintervalsOfParentLengthRanges(final List<LengthConstraint> parentLengths,
310             final long min, final long max) {
311         boolean check = false;
312         for (LengthConstraint lc : parentLengths) {
313             Number parentMinNumber = lc.getMin();
314             if (parentMinNumber instanceof UnknownBoundaryNumber) {
315                 parentMinNumber = resolveMinLength(parentMinNumber);
316             }
317             long parentMin = parentMinNumber.longValue();
318
319             Number parentMaxNumber = lc.getMax();
320             if (parentMaxNumber instanceof UnknownBoundaryNumber) {
321                 parentMaxNumber = resolveMaxLength(parentMaxNumber);
322             }
323             long parentMax = parentMaxNumber.longValue();
324
325             if (parentMin <= min && parentMax >= max) {
326                 check = true;
327                 break;
328             }
329         }
330         return check;
331     }
332
333 }