2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.util;
10 import java.math.BigDecimal;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 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;
21 * Holder object for holding YANG type constraints.
23 public final class TypeConstraints {
24 private final String moduleName;
25 private final int line;
26 private final List<List<RangeConstraint>> ranges = new ArrayList<List<RangeConstraint>>();
27 private final List<List<LengthConstraint>> lengths = new ArrayList<List<LengthConstraint>>();
28 private final List<List<PatternConstraint>> patterns = new ArrayList<List<PatternConstraint>>();
29 private final List<Integer> fractionDigits = new ArrayList<Integer>();
31 public TypeConstraints(final String moduleName, final int line) {
32 this.moduleName = moduleName;
36 List<List<RangeConstraint>> getAllRanges() {
40 public List<RangeConstraint> getRange() {
41 if (ranges.size() < 2) {
42 return Collections.emptyList();
45 final List<RangeConstraint> resolved = ranges.get(0);
46 RangeConstraint firstRange = resolved.get(0);
47 RangeConstraint lastRange = resolved.get(resolved.size() - 1);
48 Number min = firstRange.getMin();
49 Number max = lastRange.getMax();
51 if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
52 if (ranges.size() > 1) {
53 validateRange(resolved);
58 if (firstRange.equals(lastRange)) {
59 if (min instanceof UnknownBoundaryNumber) {
60 min = resolveMinRange(min);
62 if (max instanceof UnknownBoundaryNumber) {
63 max = resolveMaxRange(max);
65 firstRange = BaseConstraints.rangeConstraint(min, max, firstRange.getDescription(),
66 firstRange.getReference());
67 resolved.set(0, firstRange);
68 lastRange = BaseConstraints.rangeConstraint(min, max, lastRange.getDescription(), lastRange.getReference());
69 resolved.set(resolved.size() - 1, lastRange);
71 if (min instanceof UnknownBoundaryNumber) {
72 min = resolveMinRange(min);
73 firstRange = BaseConstraints.rangeConstraint(min, firstRange.getMax(), firstRange.getDescription(),
74 firstRange.getReference());
75 resolved.set(0, firstRange);
77 if (max instanceof UnknownBoundaryNumber) {
78 max = resolveMaxRange(max);
79 lastRange = BaseConstraints.rangeConstraint(lastRange.getMin(), max, lastRange.getDescription(),
80 lastRange.getReference());
81 resolved.set(resolved.size() - 1, lastRange);
84 if (this.ranges.size() > 1) {
85 validateRange(resolved);
90 private Number resolveMinRange(final Number min) {
93 while (newMin instanceof UnknownBoundaryNumber) {
94 final List<RangeConstraint> act = ranges.get(i);
95 newMin = act.get(0).getMin();
101 private Number resolveMaxRange(final Number max) {
104 while (newMax instanceof UnknownBoundaryNumber) {
105 final List<RangeConstraint> act = ranges.get(i);
106 newMax = act.get(act.size() - 1).getMax();
112 public void addRanges(final List<RangeConstraint> ranges) {
113 if (ranges != null && !(ranges.isEmpty())) {
114 this.ranges.add(ranges);
118 public List<List<LengthConstraint>> getAllLengths() {
122 public List<LengthConstraint> getLength() {
123 if (lengths.size() < 2) {
124 return Collections.emptyList();
127 final List<LengthConstraint> resolved = lengths.get(0);
128 LengthConstraint firstLength = resolved.get(0);
129 LengthConstraint lastLength = resolved.get(resolved.size() - 1);
130 Number min = firstLength.getMin();
131 Number max = lastLength.getMax();
133 if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
134 if (lengths.size() > 1) {
135 validateLength(resolved);
140 if (firstLength.equals(lastLength)) {
141 if (min instanceof UnknownBoundaryNumber) {
142 min = resolveMinLength(min);
144 if (max instanceof UnknownBoundaryNumber) {
145 max = resolveMaxLength(max);
147 firstLength = BaseConstraints.lengthConstraint(min, max, firstLength.getDescription(),
148 firstLength.getReference());
149 resolved.set(0, firstLength);
150 lastLength = BaseConstraints.lengthConstraint(min, max, lastLength.getDescription(),
151 lastLength.getReference());
152 resolved.set(resolved.size() - 1, lastLength);
154 if (min instanceof UnknownBoundaryNumber) {
155 min = resolveMinLength(min);
156 firstLength = BaseConstraints.lengthConstraint(min, firstLength.getMax(), firstLength.getDescription(),
157 firstLength.getReference());
158 resolved.set(0, firstLength);
160 if (max instanceof UnknownBoundaryNumber) {
161 max = resolveMaxLength(max);
162 lastLength = BaseConstraints.lengthConstraint(lastLength.getMin(), max, lastLength.getDescription(),
163 lastLength.getReference());
164 resolved.set(resolved.size() - 1, lastLength);
168 if (lengths.size() > 1) {
169 validateLength(resolved);
174 private Number resolveMinLength(final Number min) {
177 while (newMin instanceof UnknownBoundaryNumber) {
178 final List<LengthConstraint> act = lengths.get(i);
179 newMin = act.get(0).getMin();
185 private Number resolveMaxLength(final Number max) {
188 while (newMax instanceof UnknownBoundaryNumber) {
189 final List<LengthConstraint> act = lengths.get(i);
190 newMax = act.get(act.size() - 1).getMax();
196 public void addLengths(final List<LengthConstraint> lengths) {
197 if (lengths != null && !(lengths.isEmpty())) {
198 this.lengths.add(lengths);
202 public List<PatternConstraint> getPatterns() {
203 if (patterns.isEmpty()) {
204 return Collections.emptyList();
206 return patterns.get(0);
209 public void addPatterns(final List<PatternConstraint> patterns) {
210 this.patterns.add(patterns);
213 public Integer getFractionDigits() {
214 if (fractionDigits.isEmpty()) {
217 return fractionDigits.get(0);
220 public void addFractionDigits(final Integer fractionDigits) {
221 this.fractionDigits.add(fractionDigits);
224 public void validateConstraints() {
229 private void validateRange() {
230 validateRange(getRange());
233 private void validateRange(List<RangeConstraint> typeRange) {
234 if (ranges.size() < 2) {
238 for (RangeConstraint range : typeRange) {
239 if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
240 throw new YangParseException(moduleName, line, "Unresolved range constraints");
242 final BigDecimal min = new BigDecimal(range.getMin().toString());
243 final BigDecimal max = new BigDecimal(range.getMax().toString());
245 List<RangeConstraint> parentRanges = ranges.get(1);
246 if (!areRangesSubintervalsOfParentRanges(parentRanges, min, max)) {
247 throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
248 + "> (parent: " + parentRanges + ").");
253 private boolean areRangesSubintervalsOfParentRanges(List<RangeConstraint> parentRanges, final BigDecimal min,
254 final BigDecimal max) {
255 boolean check = false;
256 for (RangeConstraint r : parentRanges) {
257 Number parentMinNumber = r.getMin();
258 if (parentMinNumber instanceof UnknownBoundaryNumber) {
259 parentMinNumber = resolveMinRange(parentMinNumber);
261 BigDecimal parentMin = new BigDecimal(parentMinNumber.toString());
263 Number parentMaxNumber = r.getMax();
264 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
265 parentMaxNumber = resolveMaxRange(parentMaxNumber);
267 BigDecimal parentMax = new BigDecimal(parentMaxNumber.toString());
269 if (parentMin.compareTo(min) <= 0 && parentMax.compareTo(max) >= 0) {
277 private void validateLength() {
278 validateLength(getLength());
281 private void validateLength(List<LengthConstraint> typeLength) {
282 if (lengths.size() < 2) {
286 for (LengthConstraint length : typeLength) {
287 if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
288 throw new YangParseException(moduleName, line, "Unresolved length constraints");
290 final long min = length.getMin().longValue();
291 final long max = length.getMax().longValue();
293 List<LengthConstraint> parentLengths = lengths.get(1);
294 if (!areLengthRangesSubintervalsOfParentLengthRanges(parentLengths, min, max)) {
295 throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
296 + "> (parent: " + parentLengths + ").");
301 private boolean areLengthRangesSubintervalsOfParentLengthRanges(final List<LengthConstraint> parentLengths,
302 final long min, final long max) {
303 boolean check = false;
304 for (LengthConstraint lc : parentLengths) {
305 Number parentMinNumber = lc.getMin();
306 if (parentMinNumber instanceof UnknownBoundaryNumber) {
307 parentMinNumber = resolveMinLength(parentMinNumber);
309 long parentMin = parentMinNumber.longValue();
311 Number parentMaxNumber = lc.getMax();
312 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
313 parentMaxNumber = resolveMaxLength(parentMaxNumber);
315 long parentMax = parentMaxNumber.longValue();
317 if (parentMin <= min && parentMax >= max) {