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 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;
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<>();
27 private final List<List<LengthConstraint>> lengths = new ArrayList<>();
28 private final List<List<PatternConstraint>> patterns = new ArrayList<>();
29 private final List<Integer> fractionDigits = new ArrayList<>();
31 public TypeConstraints(final String moduleName, final int line) {
32 this.moduleName = moduleName;
36 public List<RangeConstraint> getRange() {
37 if (ranges.size() < 2) {
38 return Collections.emptyList();
41 final List<RangeConstraint> resolved = ranges.get(0);
42 RangeConstraint firstRange = resolved.get(0);
43 RangeConstraint lastRange = resolved.get(resolved.size() - 1);
44 Number min = firstRange.getMin();
45 Number max = lastRange.getMax();
47 if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
48 if (ranges.size() > 1) {
49 validateRange(resolved);
54 if (firstRange.equals(lastRange)) {
55 if (min instanceof UnknownBoundaryNumber) {
56 min = resolveMinRange(min);
58 if (max instanceof UnknownBoundaryNumber) {
59 max = resolveMaxRange(max);
61 firstRange = BaseConstraints.newRangeConstraint(min, max,
62 Optional.fromNullable(firstRange.getDescription()),
63 Optional.fromNullable(firstRange.getReference()));
64 resolved.set(0, firstRange);
65 lastRange = BaseConstraints.newRangeConstraint(min, max,
66 Optional.fromNullable(lastRange.getDescription()),
67 Optional.fromNullable(lastRange.getReference()));
68 resolved.set(resolved.size() - 1, lastRange);
70 if (min instanceof UnknownBoundaryNumber) {
71 min = resolveMinRange(min);
72 firstRange = BaseConstraints.newRangeConstraint(min, firstRange.getMax(),
73 Optional.fromNullable(firstRange.getDescription()),
74 Optional.fromNullable(firstRange.getReference()));
75 resolved.set(0, firstRange);
77 if (max instanceof UnknownBoundaryNumber) {
78 max = resolveMaxRange(max);
79 lastRange = BaseConstraints.newRangeConstraint(lastRange.getMin(), max,
80 Optional.fromNullable(lastRange.getDescription()),
81 Optional.fromNullable(lastRange.getReference()));
82 resolved.set(resolved.size() - 1, lastRange);
85 if (this.ranges.size() > 1) {
86 validateRange(resolved);
91 private Number resolveMinRange(final Number min) {
94 while (newMin instanceof UnknownBoundaryNumber) {
95 final List<RangeConstraint> act = ranges.get(i);
96 newMin = act.get(0).getMin();
102 private Number resolveMaxRange(final Number max) {
105 while (newMax instanceof UnknownBoundaryNumber) {
106 final List<RangeConstraint> act = ranges.get(i);
107 newMax = act.get(act.size() - 1).getMax();
113 public void addRanges(final List<RangeConstraint> ranges) {
114 if (ranges != null && !(ranges.isEmpty())) {
115 this.ranges.add(ranges);
119 public List<List<LengthConstraint>> getAllLengths() {
123 public List<LengthConstraint> getLength() {
124 if (lengths.size() < 2) {
125 return Collections.emptyList();
128 final List<LengthConstraint> resolved = lengths.get(0);
129 LengthConstraint firstLength = resolved.get(0);
130 LengthConstraint lastLength = resolved.get(resolved.size() - 1);
131 Number min = firstLength.getMin();
132 Number max = lastLength.getMax();
134 if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
135 if (lengths.size() > 1) {
136 validateLength(resolved);
141 if (firstLength.equals(lastLength)) {
142 if (min instanceof UnknownBoundaryNumber) {
143 min = resolveMinLength(min);
145 if (max instanceof UnknownBoundaryNumber) {
146 max = resolveMaxLength(max);
148 firstLength = BaseConstraints.newLengthConstraint(min, max,
149 Optional.fromNullable(firstLength.getDescription()),
150 Optional.fromNullable(firstLength.getReference()));
151 resolved.set(0, firstLength);
152 lastLength = BaseConstraints.newLengthConstraint(min, max,
153 Optional.fromNullable(lastLength.getDescription()),
154 Optional.fromNullable(lastLength.getReference()));
155 resolved.set(resolved.size() - 1, lastLength);
157 if (min instanceof UnknownBoundaryNumber) {
158 min = resolveMinLength(min);
159 firstLength = BaseConstraints.newLengthConstraint(min, firstLength.getMax(),
160 Optional.fromNullable(firstLength.getDescription()),
161 Optional.fromNullable(firstLength.getReference()));
162 resolved.set(0, firstLength);
164 if (max instanceof UnknownBoundaryNumber) {
165 max = resolveMaxLength(max);
166 lastLength = BaseConstraints.newLengthConstraint(lastLength.getMin(), max,
167 Optional.fromNullable(lastLength.getDescription()),
168 Optional.fromNullable(lastLength.getReference()));
169 resolved.set(resolved.size() - 1, lastLength);
173 if (lengths.size() > 1) {
174 validateLength(resolved);
179 private Number resolveMinLength(final Number min) {
182 while (newMin instanceof UnknownBoundaryNumber) {
183 final List<LengthConstraint> act = lengths.get(i);
184 newMin = act.get(0).getMin();
190 private Number resolveMaxLength(final Number max) {
193 while (newMax instanceof UnknownBoundaryNumber) {
194 final List<LengthConstraint> act = lengths.get(i);
195 newMax = act.get(act.size() - 1).getMax();
201 public void addLengths(final List<LengthConstraint> lengths) {
202 if (lengths != null && !(lengths.isEmpty())) {
203 this.lengths.add(lengths);
207 public List<PatternConstraint> getPatterns() {
208 if (patterns.isEmpty()) {
209 return Collections.emptyList();
211 return patterns.get(0);
214 public void addPatterns(final List<PatternConstraint> patterns) {
215 this.patterns.add(patterns);
218 public Integer getFractionDigits() {
219 if (fractionDigits.isEmpty()) {
222 return fractionDigits.get(0);
225 public void addFractionDigits(final Integer fractionDigits) {
226 this.fractionDigits.add(fractionDigits);
229 public void validateConstraints() {
234 private void validateRange() {
235 validateRange(getRange());
238 private void validateRange(final List<RangeConstraint> typeRange) {
239 if (ranges.size() < 2) {
243 for (RangeConstraint range : typeRange) {
244 if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
245 throw new YangParseException(moduleName, line, "Unresolved range constraints");
247 final BigDecimal min = new BigDecimal(range.getMin().toString());
248 final BigDecimal max = new BigDecimal(range.getMax().toString());
250 List<RangeConstraint> parentRanges = ranges.get(1);
251 if (!areRangesSubintervalsOfParentRanges(parentRanges, min, max)) {
252 throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
253 + "> (parent: " + parentRanges + ").");
258 private boolean areRangesSubintervalsOfParentRanges(final List<RangeConstraint> parentRanges, final BigDecimal min,
259 final BigDecimal max) {
260 boolean check = false;
261 for (RangeConstraint r : parentRanges) {
262 Number parentMinNumber = r.getMin();
263 if (parentMinNumber instanceof UnknownBoundaryNumber) {
264 parentMinNumber = resolveMinRange(parentMinNumber);
266 BigDecimal parentMin = new BigDecimal(parentMinNumber.toString());
268 Number parentMaxNumber = r.getMax();
269 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
270 parentMaxNumber = resolveMaxRange(parentMaxNumber);
272 BigDecimal parentMax = new BigDecimal(parentMaxNumber.toString());
274 if (parentMin.compareTo(min) <= 0 && parentMax.compareTo(max) >= 0) {
282 private void validateLength() {
283 validateLength(getLength());
286 private void validateLength(final List<LengthConstraint> typeLength) {
287 if (lengths.size() < 2) {
291 for (LengthConstraint length : typeLength) {
292 if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
293 throw new YangParseException(moduleName, line, "Unresolved length constraints");
295 final long min = length.getMin().longValue();
296 final long max = length.getMax().longValue();
298 List<LengthConstraint> parentLengths = lengths.get(1);
299 if (!areLengthRangesSubintervalsOfParentLengthRanges(parentLengths, min, max)) {
300 throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
301 + "> (parent: " + parentLengths + ").");
306 private boolean areLengthRangesSubintervalsOfParentLengthRanges(final List<LengthConstraint> parentLengths,
307 final long min, final long max) {
308 boolean check = false;
309 for (LengthConstraint lc : parentLengths) {
310 Number parentMinNumber = lc.getMin();
311 if (parentMinNumber instanceof UnknownBoundaryNumber) {
312 parentMinNumber = resolveMinLength(parentMinNumber);
314 long parentMin = parentMinNumber.longValue();
316 Number parentMaxNumber = lc.getMax();
317 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
318 parentMaxNumber = resolveMaxLength(parentMaxNumber);
320 long parentMax = parentMaxNumber.longValue();
322 if (parentMin <= min && parentMax >= max) {