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 * @deprecated Pre-Beryllium implementation, scheduled for removal.
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<>();
34 public TypeConstraints(final String moduleName, final int line) {
35 this.moduleName = moduleName;
39 public List<RangeConstraint> getRange() {
40 if (ranges.size() < 2) {
41 return Collections.emptyList();
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();
50 if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
51 if (ranges.size() > 1) {
52 validateRange(resolved);
57 if (firstRange.equals(lastRange)) {
58 if (min instanceof UnknownBoundaryNumber) {
59 min = resolveMinRange(min);
61 if (max instanceof UnknownBoundaryNumber) {
62 max = resolveMaxRange(max);
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);
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);
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);
88 if (this.ranges.size() > 1) {
89 validateRange(resolved);
94 private Number resolveMinRange(final Number min) {
97 while (newMin instanceof UnknownBoundaryNumber) {
98 final List<RangeConstraint> act = ranges.get(i);
99 newMin = act.get(0).getMin();
105 private Number resolveMaxRange(final Number max) {
108 while (newMax instanceof UnknownBoundaryNumber) {
109 final List<RangeConstraint> act = ranges.get(i);
110 newMax = act.get(act.size() - 1).getMax();
116 public void addRanges(final List<RangeConstraint> ranges) {
117 if (ranges != null && !(ranges.isEmpty())) {
118 this.ranges.add(ranges);
122 public List<List<LengthConstraint>> getAllLengths() {
126 public List<LengthConstraint> getLength() {
127 if (lengths.size() < 2) {
128 return Collections.emptyList();
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();
137 if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
138 if (lengths.size() > 1) {
139 validateLength(resolved);
144 if (firstLength.equals(lastLength)) {
145 if (min instanceof UnknownBoundaryNumber) {
146 min = resolveMinLength(min);
148 if (max instanceof UnknownBoundaryNumber) {
149 max = resolveMaxLength(max);
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);
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);
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);
176 if (lengths.size() > 1) {
177 validateLength(resolved);
182 private Number resolveMinLength(final Number min) {
185 while (newMin instanceof UnknownBoundaryNumber) {
186 final List<LengthConstraint> act = lengths.get(i);
187 newMin = act.get(0).getMin();
193 private Number resolveMaxLength(final Number max) {
196 while (newMax instanceof UnknownBoundaryNumber) {
197 final List<LengthConstraint> act = lengths.get(i);
198 newMax = act.get(act.size() - 1).getMax();
204 public void addLengths(final List<LengthConstraint> lengths) {
205 if (lengths != null && !(lengths.isEmpty())) {
206 this.lengths.add(lengths);
210 public List<PatternConstraint> getPatterns() {
211 if (patterns.isEmpty()) {
212 return Collections.emptyList();
214 return patterns.get(0);
217 public void addPatterns(final List<PatternConstraint> patterns) {
218 this.patterns.add(patterns);
221 public Integer getFractionDigits() {
222 if (fractionDigits.isEmpty()) {
225 return fractionDigits.get(0);
228 public void addFractionDigits(final Integer fractionDigits) {
229 this.fractionDigits.add(fractionDigits);
232 public void validateConstraints() {
237 private void validateRange() {
238 validateRange(getRange());
241 private void validateRange(final List<RangeConstraint> typeRange) {
242 if (ranges.size() < 2) {
246 for (RangeConstraint range : typeRange) {
247 if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
248 throw new YangParseException(moduleName, line, "Unresolved range constraints");
250 final BigDecimal min = new BigDecimal(range.getMin().toString());
251 final BigDecimal max = new BigDecimal(range.getMax().toString());
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 + ").");
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);
269 BigDecimal parentMin = new BigDecimal(parentMinNumber.toString());
271 Number parentMaxNumber = r.getMax();
272 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
273 parentMaxNumber = resolveMaxRange(parentMaxNumber);
275 BigDecimal parentMax = new BigDecimal(parentMaxNumber.toString());
277 if (parentMin.compareTo(min) <= 0 && parentMax.compareTo(max) >= 0) {
285 private void validateLength() {
286 validateLength(getLength());
289 private void validateLength(final List<LengthConstraint> typeLength) {
290 if (lengths.size() < 2) {
294 for (LengthConstraint length : typeLength) {
295 if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
296 throw new YangParseException(moduleName, line, "Unresolved length constraints");
298 final long min = length.getMin().longValue();
299 final long max = length.getMax().longValue();
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 + ").");
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);
317 long parentMin = parentMinNumber.longValue();
319 Number parentMaxNumber = lc.getMax();
320 if (parentMaxNumber instanceof UnknownBoundaryNumber) {
321 parentMaxNumber = resolveMaxLength(parentMaxNumber);
323 long parentMax = parentMaxNumber.longValue();
325 if (parentMin <= min && parentMax >= max) {