BUG-8043: correct LengthConstraint definition 19/62319/13
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 29 Aug 2017 07:19:57 +0000 (09:19 +0200)
committerRobert Varga <nite@hq.sk>
Tue, 24 Oct 2017 10:55:23 +0000 (10:55 +0000)
Each type has at most one length constraint attached to it, reflect
that fact in yang-model-api hiearchy.

This has implications on LengthStatement: it should not be exposing
LengthConstraints, as that is not what the argument holds. Define
ValueRange construct to hold the parsed-out (but unresolved) ranges
as parsed from length argument.

Change-Id: I38e1e5a40a0b7562d202816f126cc1ecec414d0e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
44 files changed:
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/BinaryStringCodec.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/StringStringCodec.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/package-info.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/LengthStatement.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/UnresolvedNumber.java [moved from yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnresolvedNumber.java with 82% similarity]
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ValueRange.java [new file with mode: 0644]
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthConstraint.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthRestrictedTypeDefinition.java
yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/SchemaContextEmitter.java
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BaseConstraints.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java [deleted file]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedBaseType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedDerivedType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/InvalidLengthConstraintException.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/JavaLengthConstraints.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/LengthRestrictedTypeBuilder.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtil.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RangeRestrictedTypeBuilder.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/ResolvedLengthConstraint.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedBinaryType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedStringType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedTypes.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/StringTypeBuilder.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/TypeDefinitions.java
yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BaseConstraintsTest.java [deleted file]
yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BinaryTypeTest.java
yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImplTest.java [deleted file]
yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtilTest.java
yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/TypeTest.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LengthStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/TypeUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/BinaryTypeEffectiveStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthConstraintEffectiveImpl.java [deleted file]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthEffectiveStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/StringTypeEffectiveStatementImpl.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug4623Test.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/EffectiveStatementTypeTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/TypesResolutionTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5200Test.java

index 7d30edfa3b2e78edb8cba18f26b66dd209724490..912283c2eed03c2873023d07bc0273d794cfbf31 100644 (file)
@@ -8,12 +8,9 @@
 package org.opendaylight.yangtools.yang.data.impl.codec;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableRangeSet;
-import com.google.common.collect.Range;
-import com.google.common.collect.RangeSet;
-import com.google.common.collect.TreeRangeSet;
 import com.google.common.io.BaseEncoding;
 import java.util.Optional;
 import javax.xml.bind.DatatypeConverter;
@@ -28,23 +25,18 @@ import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 public abstract class BinaryStringCodec extends TypeDefinitionAwareCodec<byte[], BinaryTypeDefinition>
         implements BinaryCodec<String> {
     private static final class Restricted extends BinaryStringCodec {
-        private final RangeSet<Integer> ranges;
+        private final LengthConstraint lengthConstraint;
 
-        Restricted(final BinaryTypeDefinition typeDef) {
+        Restricted(final BinaryTypeDefinition typeDef, final LengthConstraint lengthConstraint) {
             super(typeDef);
-
-            final RangeSet<Integer> r = TreeRangeSet.create();
-            for (LengthConstraint c : typeDef.getLengthConstraints()) {
-                r.add(Range.closed(c.getMin().intValue(), c.getMax().intValue()));
-            }
-
-            ranges = ImmutableRangeSet.copyOf(r);
+            this.lengthConstraint = requireNonNull(lengthConstraint);
         }
 
         @Override
         void validate(final byte[] value) {
-            checkArgument(ranges.contains(value.length), "Value length %s does not match constraints %s", value.length,
-                ranges);
+            // FIXME: throw an exception capturing the constraint violation
+            checkArgument(lengthConstraint.getAllowedRanges().contains(value.length),
+                "Value length %s does not match constraint %s", value.length, lengthConstraint);
         }
     }
 
@@ -64,7 +56,8 @@ public abstract class BinaryStringCodec extends TypeDefinitionAwareCodec<byte[],
     }
 
     public static BinaryStringCodec from(final BinaryTypeDefinition type) {
-        return type.getLengthConstraints().isEmpty() ? new Unrestricted(type) : new Restricted(type);
+        final java.util.Optional<LengthConstraint> optConstraint = type.getLengthConstraint();
+        return optConstraint.isPresent() ? new Restricted(type, optConstraint.get()) : new Unrestricted(type);
     }
 
     @Override
index d05f57c5b9c41b6848185293848f0383d5fc1243..b905305b018234f67f1b38cb44b089e034db9dda 100644 (file)
@@ -11,11 +11,6 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableRangeSet;
-import com.google.common.collect.Range;
-import com.google.common.collect.RangeSet;
-import com.google.common.collect.TreeRangeSet;
-import java.util.Collection;
 import java.util.Optional;
 import org.opendaylight.yangtools.yang.data.api.codec.StringCodec;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
@@ -28,22 +23,11 @@ import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 public class StringStringCodec extends TypeDefinitionAwareCodec<String, StringTypeDefinition>
         implements StringCodec<String> {
 
-    private final RangeSet<Integer> lengths;
+    private final LengthConstraint lengthConstraint;
 
     StringStringCodec(final StringTypeDefinition typeDef) {
         super(Optional.of(typeDef), String.class);
-
-        final Collection<LengthConstraint> constraints = typeDef.getLengthConstraints();
-        if (!constraints.isEmpty()) {
-            final RangeSet<Integer> tmp = TreeRangeSet.create();
-            for (LengthConstraint c : constraints) {
-                tmp.add(Range.closed(c.getMin().intValue(), c.getMax().intValue()));
-            }
-
-            lengths = ImmutableRangeSet.copyOf(tmp);
-        } else {
-            lengths = null;
-        }
+        lengthConstraint = typeDef.getLengthConstraint().orElse(null);
     }
 
     public static StringStringCodec from(final StringTypeDefinition normalizedType) {
@@ -66,8 +50,9 @@ public class StringStringCodec extends TypeDefinitionAwareCodec<String, StringTy
     }
 
     void validate(final String str) {
-        if (lengths != null) {
-            checkArgument(lengths.contains(str.length()), "String '%s' does not match allowed lengths %s", lengths);
+        if (lengthConstraint != null) {
+            checkArgument(lengthConstraint.getAllowedRanges().contains(str.length()),
+                    "String '%s' does not match allowed length constraint %s", lengthConstraint);
         }
     }
 }
index 9c8fc6245671055c38857832a1daa4cd0c98c6c5..7f2a6e6a697108e2cc55cb5d397f9d8f0bd8228e 100644 (file)
  *
  * <dt>length
  *   <dd>{@link org.opendaylight.yangtools.yang.model.api.type.LengthConstraint}
- *   <dd>{@link org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition#getLengthConstraints()}
+ *   <dd>{@link org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition#getLengthConstraint()}
  *
  * <dt>list
  *   <dd>{@link org.opendaylight.yangtools.yang.model.api.ListSchemaNode}
index 6585a48a6eb433e1c74005a2fbf013d3f47a6877..c5dcdcf1f2b55f3e17b055ca610bff8885ed7d42 100644 (file)
@@ -10,10 +10,9 @@ package org.opendaylight.yangtools.yang.model.api.stmt;
 import java.util.List;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 
-public interface LengthStatement extends DeclaredStatement<List<LengthConstraint>>, DocumentedConstraintGroup {
+public interface LengthStatement extends DeclaredStatement<List<ValueRange>>, DocumentedConstraintGroup {
     @Nonnull
     @Override
-    List<LengthConstraint> argument();
+    List<ValueRange> argument();
 }
similarity index 82%
rename from yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnresolvedNumber.java
rename to yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/UnresolvedNumber.java
index 3cdb7df9f685e642f73adb21b6a15865a6635825..987a6466a8d1cfb9075ae2e2f98aee38f3e64316 100644 (file)
@@ -5,14 +5,14 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.yangtools.yang.model.util;
+package org.opendaylight.yangtools.yang.model.api.stmt;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
 import com.google.common.annotations.Beta;
+import com.google.common.collect.Range;
 import java.util.List;
 import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 
 @Beta
@@ -22,8 +22,8 @@ public abstract class UnresolvedNumber extends Number implements Immutable {
         private static final long serialVersionUID = 1L;
 
         @Override
-        public Number resolveLength(final List<LengthConstraint> constraints) {
-            return resolve(constraints.get(constraints.size() - 1).getMax());
+        public <T extends Number & Comparable<T>> T resolveLength(final Range<T> span) {
+            return resolve(span.upperEndpoint());
         }
 
         @Override
@@ -45,8 +45,8 @@ public abstract class UnresolvedNumber extends Number implements Immutable {
         private static final long serialVersionUID = 1L;
 
         @Override
-        public Number resolveLength(final List<LengthConstraint> constraints) {
-            return resolve(constraints.get(0).getMin());
+        public <T extends Number & Comparable<T>> T resolveLength(final Range<T> span) {
+            return resolve(span.lowerEndpoint());
         }
 
         @Override
@@ -92,12 +92,12 @@ public abstract class UnresolvedNumber extends Number implements Immutable {
         throw new UnsupportedOperationException();
     }
 
-    private static Number resolve(final Number number) {
+    private static <T extends Number> T resolve(final T number) {
         checkArgument(!(number instanceof UnresolvedNumber));
         return number;
     }
 
-    public abstract Number resolveLength(List<LengthConstraint> constraints);
+    public abstract <T extends Number & Comparable<T>> T resolveLength(Range<T> span);
 
     public abstract Number resolveRange(List<RangeConstraint> constraints);
 
diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ValueRange.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ValueRange.java
new file mode 100644 (file)
index 0000000..e124a5c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.model.api.stmt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.util.Objects;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * YANG specification of a numeric value range. This object is used for {@link LengthStatement} and
+ * {@link RangeStatement}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public abstract class ValueRange {
+    private static final class Singleton extends ValueRange {
+        private final @NonNull Number value;
+
+        Singleton(final @NonNull Number value) {
+            this.value = requireNonNull(value);
+        }
+
+        @Override
+        public @NonNull Number lowerBound() {
+            return value;
+        }
+
+        @Override
+        public @NonNull Number upperBound() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return value.toString();
+        }
+    }
+
+    private static final class Range extends ValueRange {
+        private final @NonNull Number lower;
+        private final @NonNull Number upper;
+
+        Range(final Number lower, final Number upper) {
+            this.lower = requireNonNull(lower);
+            this.upper = requireNonNull(upper);
+        }
+
+        @Override
+        public @NonNull Number lowerBound() {
+            return lower;
+        }
+
+        @Override
+        public @NonNull Number upperBound() {
+            return upper;
+        }
+
+        @Override
+        public String toString() {
+            return lower + ".." + upper;
+        }
+    }
+
+    public static ValueRange of(final @NonNull Number value) {
+        return new Singleton(value);
+    }
+
+    public static ValueRange of(final @NonNull Number lower, final @NonNull Number upper) {
+        return lower.equals(upper) ? of(lower) : new Range(lower, upper);
+    }
+
+    public abstract @NonNull Number lowerBound();
+
+    public abstract @NonNull Number upperBound();
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(lowerBound(), upperBound());
+    }
+
+    @Override
+    public final boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof ValueRange)) {
+            return false;
+        }
+        final ValueRange other = (ValueRange) obj;
+        return lowerBound().equals(other.lowerBound()) && upperBound().equals(other.upperBound());
+    }
+}
index b7d64aa8e2b903ffe328f3d1e52a61e3a86465bd..e3f59ab43797ad5775e245f2aa0cc813d9691f2a 100644 (file)
@@ -7,44 +7,18 @@
  */
 package org.opendaylight.yangtools.yang.model.api.type;
 
+import com.google.common.collect.RangeSet;
 import org.opendaylight.yangtools.yang.model.api.ConstraintMetaDefinition;
 
 /**
- * The Lenght Constraint value consists of an explicit value, or a lower bound
- * returned by {@link #getMin()} and an upper bound returned by
- * {@link #getMax()}. <br>
- * <br>
- * Length-restricting values MUST NOT be negative. A length value is a
- * non-negative integer, or one of the special values <code>min</code> or
- * <code>max</code>. The defined <code>min</code> and <code>max</code> mean the
- * minimum and maximum length accepted for the type being restricted,
- * respectively. <br>
- * An implementation is not required to support a length value larger than
- * {@link Long#MAX_VALUE} <br>
- * <br>
- * The interface extends definitions from {@link ConstraintMetaDefinition} <br>
- * <br>
- * This interface was modeled according to definition in <a
- * href="https://tools.ietf.org/html/rfc6020#section-9.4.4">[RFC-6020] The
- * length Statement</a>.
- *
- * @see ConstraintMetaDefinition
+ * A single value length restriction, as expressed by a length statement, as specified by
+ * <a href="https://tools.ietf.org/html/rfc6020#section-9.4.4">[RFC-6020] The length Statement</a>.
  */
 public interface LengthConstraint extends ConstraintMetaDefinition {
-
-    /**
-     * Returns the length-restricting lower bound value. <br>
-     * The value MUST NOT be negative.
-     *
-     * @return the length-restricting lower bound value.
-     */
-    Number getMin();
-
     /**
-     * Returns the length-restricting upper bound value. <br>
-     * The value MUST NOT be negative.
+     * Return allowed length ranges. Returned RangeSet must not be empty.
      *
-     * @return length-restricting upper bound value.
+     * @return Set of allowed lengths.
      */
-    Number getMax();
+    RangeSet<Integer> getAllowedRanges();
 }
index 4e98e98bed674c5a3c0ad49c743533cd2fe42860..559d5943199e4343c0e894ef3a2af4286644bd9e 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.api.type;
 
-import java.util.List;
+import java.util.Optional;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
 /**
@@ -17,11 +17,11 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
  */
 public interface LengthRestrictedTypeDefinition<T extends TypeDefinition<T>> extends TypeDefinition<T> {
     /**
-     * Returns length constraints. These are the effective constraints, e.g. they include any length constraints
-     * implied by base types.
+     * Returns length constraint of this type, if applicable. This is the effective constraint, e.g. it includes any
+     * length constraints implied by base type hierarchy.
      *
-     * @return list of length constraint which are specified in the <code>length</code> substatement
-     *         of the <code>type</code> statement.
+     * @return length constraint which are specified in the <code>length</code> substatement of the <code>type</code>
+     *         statement.
      */
-    List<LengthConstraint> getLengthConstraints();
+    Optional<LengthConstraint> getLengthConstraint();
 }
index 364e8f7a4e13d1deb256c22da8a5aa14247334e4..1cde06daec0449c01255185d97eca0b76e173865 100644 (file)
@@ -12,6 +12,8 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Predicates;
 import com.google.common.base.Strings;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.Range;
+import com.google.common.collect.RangeSet;
 import com.google.common.primitives.UnsignedInteger;
 import java.net.URI;
 import java.util.Collection;
@@ -1494,7 +1496,7 @@ abstract class SchemaContextEmitter {
             } else if (typeDef instanceof UnionTypeDefinition) {
                 emitUnionSpecification((UnionTypeDefinition) typeDef);
             } else if (typeDef instanceof BinaryTypeDefinition) {
-                emitLength(((BinaryTypeDefinition) typeDef).getLengthConstraints());
+                ((BinaryTypeDefinition) typeDef).getLengthConstraint().ifPresent(this::emitLength);
             } else if (typeDef instanceof BooleanTypeDefinition || typeDef instanceof EmptyTypeDefinition) {
                 // NOOP
             } else {
@@ -1539,34 +1541,24 @@ abstract class SchemaContextEmitter {
         }
 
         private void emitStringRestrictions(final StringTypeDefinition typeDef) {
-
-            // FIXME: BUG-2444: Wrong decomposition in API, should be
-            // LenghtConstraint
-            // which contains ranges.
-            emitLength(typeDef.getLengthConstraints());
+            typeDef.getLengthConstraint().ifPresent(this::emitLength);
 
             for (final PatternConstraint pattern : typeDef.getPatternConstraints()) {
                 emitPatternNode(pattern);
             }
-
         }
 
-        private void emitLength(final List<LengthConstraint> list) {
-            if (!list.isEmpty()) {
-                super.writer.startLengthNode(toLengthString(list));
-                // FIXME: BUG-2444: Workaround for incorrect decomposition in
-                // API
-                final LengthConstraint first = list.iterator().next();
-                emitErrorMessageNode(first.getErrorMessage());
-                emitErrorAppTagNode(first.getErrorAppTag());
-                emitDescriptionNode(first.getDescription());
-                emitReferenceNode(first.getReference());
-                super.writer.endNode();
-            }
+        private void emitLength(final LengthConstraint constraint) {
+            super.writer.startLengthNode(toLengthString(constraint.getAllowedRanges()));
+            emitErrorMessageNode(constraint.getErrorMessage());
+            emitErrorAppTagNode(constraint.getErrorAppTag());
+            emitDescriptionNode(constraint.getDescription());
+            emitReferenceNode(constraint.getReference());
+            super.writer.endNode();
         }
 
-        private static String toLengthString(final List<LengthConstraint> list) {
-            final Iterator<LengthConstraint> it = list.iterator();
+        private static String toLengthString(final RangeSet<Integer> ranges) {
+            final Iterator<Range<Integer>> it = ranges.asRanges().iterator();
             if (!it.hasNext()) {
                 return "";
             }
@@ -1574,9 +1566,9 @@ abstract class SchemaContextEmitter {
             final StringBuilder sb = new StringBuilder();
             boolean haveNext;
             do {
-                final LengthConstraint current = it.next();
+                final Range<Integer> current = it.next();
                 haveNext = it.hasNext();
-                appendRange(sb, current.getMin(), current.getMax(), haveNext);
+                appendRange(sb, current.lowerEndpoint(), current.upperEndpoint(), haveNext);
             } while (haveNext);
 
             return sb.toString();
index bd2ef73882081d0661684ad0332657af3cbc7195..4495cbf92f14cd951f678594e57655f553cb694e 100644 (file)
@@ -10,4 +10,4 @@
     <leaf name="bin-leaf-2">
         <type name="binary" />
     </leaf>
-</module>
\ No newline at end of file
+</module>
index 7b3d71b112208e9400a2b968ea4d3236cf461f78..cda1b56fc929bdd8f4abae3f7f2d24d0b8366fef 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.yangtools.yang.model.util;
 
 import java.util.Optional;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.ModifierKind;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
@@ -19,7 +18,6 @@ import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
  * <p>
  * Provides static factory methods which constructs instances of
  * <ul>
- * <li>{@link LengthConstraint} - {@link #newLengthConstraint(Number, Number, Optional, Optional)}
  * <li>{@link RangeConstraint} - {@link #newRangeConstraint(Number, Number, Optional, Optional)}
  * <li>{@link PatternConstraint} - {@link #newPatternConstraint(String, Optional, Optional)}
  * </ul>
@@ -29,59 +27,6 @@ public final class BaseConstraints {
         throw new UnsupportedOperationException();
     }
 
-    /**
-     * Creates a {@link LengthConstraint}.
-     *
-     * <p>
-     * Creates an instance of Length constraint based on supplied parameters
-     * with additional behaviour:
-     * <ul>
-     * <li>{@link LengthConstraint#getErrorAppTag()} returns <code>length-out-of-specified-bounds</code>
-     * <li>{@link LengthConstraint#getErrorMessage()} returns <code>The argument is out of bounds
-     *     &lt;<i>min</i>, <i>max</i> &gt;</code>
-     * </ul>
-     *
-     * @see LengthConstraint
-     *
-     * @param min  length-restricting lower bound value. The value MUST NOT be negative.
-     * @param max length-restricting upper bound value. The value MUST NOT be negative.
-     * @param description Description associated with constraint. {@link Optional#empty()} if description is undefined.
-     * @param reference Reference associated with constraint. {@link Optional#empty()} if reference is undefined.
-     * @return Instance of {@link LengthConstraint}
-     */
-    public static LengthConstraint newLengthConstraint(final Number min, final Number max,
-            final Optional<String> description, final Optional<String> reference) {
-        return new LengthConstraintImpl(min, max, description, reference);
-    }
-
-    /**
-     * Creates a {@link LengthConstraint}.
-     *
-     * <p>
-     * Creates an instance of Length constraint based on supplied parameters
-     * with additional behaviour:
-     * <ul>
-     * <li>{@link LengthConstraint#getErrorAppTag()} returns <code>length-out-of-specified-bounds</code>
-     * <li>{@link LengthConstraint#getErrorMessage()} returns <code>The argument is out of bounds
-     *     &lt;<i>min</i>, <i>max</i> &gt;</code>
-     * </ul>
-     *
-     * @see LengthConstraint
-     *
-     * @param min  length-restricting lower bound value. The value MUST NOT be negative.
-     * @param max length-restricting upper bound value. The value MUST NOT be negative.
-     * @param description Description associated with constraint. {@link Optional#empty()} if description is undefined.
-     * @param reference Reference associated with constraint. {@link Optional#empty()} if reference is undefined.
-     * @param errorAppTag error-app-tag associated with constraint.
-     * @param errorMessage error message associated with constraint.
-     * @return Instance of {@link LengthConstraint}
-     */
-    public static LengthConstraint newLengthConstraint(final Number min, final Number max,
-            final Optional<String> description, final Optional<String> reference, final String errorAppTag,
-            final String errorMessage) {
-        return new LengthConstraintImpl(min, max, description, reference, errorAppTag, errorMessage);
-    }
-
     /**
      * Creates a {@link RangeConstraint}.
      *
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java
deleted file mode 100644 (file)
index cc8fdb3..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.model.util;
-
-import com.google.common.base.Preconditions;
-import java.util.Objects;
-import java.util.Optional;
-import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
-
-/**
- * {@link Immutable} implementation of {@link LengthConstraint}.
- * Length constraint based on supplied parameters with additional behaviour:
- *
- * <ul>
- * <li>{@link LengthConstraint#getErrorAppTag()} returns
- * <code>length-out-of-specified-bounds</code>
- * <li>{@link LengthConstraint#getErrorMessage()} returns <code>The argument is
- * out of bounds &lt;<i>min</i>, <i>max</i> &gt;</code>
- * </ul>
- */
-final class LengthConstraintImpl implements LengthConstraint, Immutable {
-
-    private final Number min;
-    private final Number max;
-
-    private final String description;
-    private final String reference;
-
-    private final String errorAppTag;
-    private final String errorMessage;
-
-    LengthConstraintImpl(final Number min, final Number max, final Optional<String> description,
-            final Optional<String> reference) {
-        this(min, max, description, reference, "length-out-of-specified-bounds", "The argument is out of bounds <"
-                + min + ", " + max + ">");
-    }
-
-    LengthConstraintImpl(final Number min, final Number max, final Optional<String> description,
-            final Optional<String> reference, final String errorAppTag, final String errorMessage) {
-        this.min = Preconditions.checkNotNull(min, "min must not be null.");
-        this.max = Preconditions.checkNotNull(max, "max must not be null");
-        this.description = description.orElse(null);
-        this.reference = reference.orElse(null);
-        this.errorAppTag = errorAppTag != null ? errorAppTag : "length-out-of-specified-bounds";
-        this.errorMessage = errorMessage != null ? errorMessage : "The argument is out of bounds <" + min + ", " + max
-                + ">";
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
-    public String getErrorAppTag() {
-        return errorAppTag;
-    }
-
-    @Override
-    public String getErrorMessage() {
-        return errorMessage;
-    }
-
-    @Override
-    public String getReference() {
-        return reference;
-    }
-
-    @Override
-    public Number getMin() {
-        return min;
-    }
-
-    @Override
-    public Number getMax() {
-        return max;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + Objects.hashCode(description);
-        result = prime * result + errorAppTag.hashCode();
-        result = prime * result + errorMessage.hashCode();
-        result = prime * result + max.hashCode();
-        result = prime * result + min.hashCode();
-        result = prime * result + Objects.hashCode(reference);
-        return result;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final LengthConstraintImpl other = (LengthConstraintImpl) obj;
-        if (!Objects.equals(description, other.description)) {
-            return false;
-        }
-        if (!Objects.equals(errorAppTag, other.errorAppTag)) {
-            return false;
-        }
-        if (!Objects.equals(errorMessage, other.errorMessage)) {
-            return false;
-        }
-        if (max != other.max) {
-            return false;
-        }
-        if (min != other.min) {
-            return false;
-        }
-        if (!Objects.equals(reference, other.reference)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        return "LengthConstraintImpl [min=" + min
-            + ", max=" + max
-            + ", description=" + description
-            + ", errorAppTag=" + errorAppTag
-            + ", reference=" + reference
-            + ", errorMessage=" + errorMessage
-            + "]";
-    }
-}
index 75bf332e6f44a285b159a9739b90b83c8acea12d..537d56b97ef9f873d06ac236e2d96b63aff176c3 100644 (file)
@@ -7,8 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.util.type;
 
-import com.google.common.collect.ImmutableList;
-import java.util.List;
+import java.util.Optional;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.LengthRestrictedTypeDefinition;
@@ -21,7 +20,7 @@ abstract class AbstractLengthRestrictedBaseType<T extends LengthRestrictedTypeDe
     }
 
     @Override
-    public final List<LengthConstraint> getLengthConstraints() {
-        return ImmutableList.of();
+    public final Optional<LengthConstraint> getLengthConstraint() {
+        return Optional.empty();
     }
 }
index 91b12e9cafdd9ba64d985a34fe4869f1e5566984..e263629f68ae361962bf14781b0265871e7a580d 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.yangtools.yang.model.util.type;
 
 import java.util.Collection;
-import java.util.List;
+import java.util.Optional;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
@@ -27,7 +27,7 @@ abstract class AbstractLengthRestrictedDerivedType<T extends LengthRestrictedTyp
 
     @Nonnull
     @Override
-    public final List<LengthConstraint> getLengthConstraints() {
-        return baseType().getLengthConstraints();
+    public final Optional<LengthConstraint> getLengthConstraint() {
+        return baseType().getLengthConstraint();
     }
 }
index 2776ba3d868ca1a5e26da44bd2a7617428cfbdea..3aaaea1a2f175550428221943ab00769ec072810 100644 (file)
@@ -7,9 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.model.util.type;
 
-import com.google.common.collect.ImmutableList;
 import java.util.Collection;
-import java.util.List;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
@@ -17,16 +17,16 @@ import org.opendaylight.yangtools.yang.model.api.type.LengthRestrictedTypeDefini
 
 abstract class AbstractLengthRestrictedType<T extends LengthRestrictedTypeDefinition<T>>
         extends AbstractRestrictedType<T> implements LengthRestrictedTypeDefinition<T> {
-    private final List<LengthConstraint> lengthConstraints;
+    private final @Nullable LengthConstraint lengthConstraint;
 
     AbstractLengthRestrictedType(final T baseType, final SchemaPath path,
-        final Collection<UnknownSchemaNode> unknownSchemaNodes, final Collection<LengthConstraint> lengthConstraints) {
+        final Collection<UnknownSchemaNode> unknownSchemaNodes, final @Nullable LengthConstraint lengthConstraint) {
         super(baseType, path, unknownSchemaNodes);
-        this.lengthConstraints = ImmutableList.copyOf(lengthConstraints);
+        this.lengthConstraint = lengthConstraint;
     }
 
     @Override
-    public final List<LengthConstraint> getLengthConstraints() {
-        return lengthConstraints;
+    public final Optional<LengthConstraint> getLengthConstraint() {
+        return Optional.ofNullable(lengthConstraint);
     }
 }
index 83af46d85f9e229465c71b57d8c5bbc7670efc28..923a728c2b04bb6a608d24e7e2d3a60b0989d074 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.model.util.type;
 
 import com.google.common.base.Preconditions;
 import java.util.List;
+import java.util.Optional;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
@@ -17,6 +18,7 @@ import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.LengthRestrictedTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
@@ -147,9 +149,8 @@ public final class CompatUtils {
         }
     }
 
-    private static TypeDefinition<?> baseTypeIfNotConstrained(final BinaryTypeDefinition type) {
-        final BinaryTypeDefinition base = type.getBaseType();
-        return baseTypeIfNotConstrained(type, type.getLengthConstraints(), base, base.getLengthConstraints());
+    private static BinaryTypeDefinition baseTypeIfNotConstrained(final BinaryTypeDefinition type) {
+        return baseTypeIfNotConstrained(type, type.getBaseType());
     }
 
     private static TypeDefinition<?> baseTypeIfNotConstrained(final DecimalTypeDefinition type) {
@@ -170,10 +171,10 @@ public final class CompatUtils {
     private static TypeDefinition<?> baseTypeIfNotConstrained(final StringTypeDefinition type) {
         final StringTypeDefinition base = type.getBaseType();
         final List<PatternConstraint> patterns = type.getPatternConstraints();
-        final List<LengthConstraint> lengths = type.getLengthConstraints();
+        final Optional<LengthConstraint> optLengths = type.getLengthConstraint();
 
         if ((patterns.isEmpty() || patterns.equals(base.getPatternConstraints()))
-                && (lengths.isEmpty() || lengths.equals(base.getLengthConstraints()))) {
+                && (!optLengths.isPresent() || optLengths.equals(base.getLengthConstraint()))) {
             return base;
         }
 
@@ -187,9 +188,15 @@ public final class CompatUtils {
 
     private static TypeDefinition<?> baseTypeIfNotConstrained(final TypeDefinition<?> type,
             final List<?> typeConstraints, final TypeDefinition<?> base, final List<?> baseConstraints) {
-        if (typeConstraints.isEmpty() || typeConstraints.equals(baseConstraints)) {
+        return typeConstraints.isEmpty() || typeConstraints.equals(baseConstraints) ? base : type;
+    }
+
+    private static <T extends LengthRestrictedTypeDefinition<T>> T baseTypeIfNotConstrained(final T type,
+            final T base) {
+        final Optional<LengthConstraint> optConstraint = type.getLengthConstraint();
+        if (!optConstraint.isPresent()) {
             return base;
         }
-        return type;
+        return optConstraint.equals(base.getLengthConstraint()) ? base : type;
     }
 }
index 0e8bc99f7832cddbd9ae4067f7b05373ed28d89e..533504a02936f814091dd5ced6060d362d6f6f03 100644 (file)
@@ -8,25 +8,13 @@
 package org.opendaylight.yangtools.yang.model.util.type;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.eclipse.jdt.annotation.NonNull;
 
 @Beta
-public class InvalidLengthConstraintException extends IllegalArgumentException {
+public final class InvalidLengthConstraintException extends Exception {
     private static final long serialVersionUID = 1L;
-    private final LengthConstraint offendingConstraint;
 
-    protected InvalidLengthConstraintException(final LengthConstraint offendingConstraint, final String message) {
-        super(message);
-        this.offendingConstraint = Preconditions.checkNotNull(offendingConstraint);
-    }
-
-    public InvalidLengthConstraintException(final LengthConstraint offendingRange, final String format,
-            final Object... args) {
-        this(offendingRange, String.format(format, args));
-    }
-
-    public LengthConstraint getOffendingConstraint() {
-        return offendingConstraint;
+    public InvalidLengthConstraintException(final @NonNull String format, final Object... args) {
+        super(String.format(format, args));
     }
 }
index 346494db3b0ef53369b492da9479be5c1c3944ef..75227153d2baaf7a51fa8c3320f5e4941b14c273 100644 (file)
@@ -7,17 +7,43 @@
  */
 package org.opendaylight.yangtools.yang.model.util.type;
 
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import java.util.Optional;
+import com.google.common.collect.ImmutableRangeSet;
+import com.google.common.collect.Range;
+import com.google.common.collect.RangeSet;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
-import org.opendaylight.yangtools.yang.model.util.BaseConstraints;
 
 final class JavaLengthConstraints {
     private JavaLengthConstraints() {
         throw new UnsupportedOperationException();
     }
 
-    static final List<LengthConstraint> INTEGER_SIZE_CONSTRAINTS = ImmutableList.of(
-        BaseConstraints.newLengthConstraint(0, Integer.MAX_VALUE, Optional.empty(), Optional.empty()));
+    private static final RangeSet<Integer> INTEGER_ALLOWED_RANGES =
+            ImmutableRangeSet.of(Range.closed(0, Integer.MAX_VALUE));
+
+    static final LengthConstraint INTEGER_SIZE_CONSTRAINTS = new LengthConstraint() {
+        @Override
+        public String getReference() {
+            return null;
+        }
+
+        @Override
+        public String getErrorMessage() {
+            return null;
+        }
+
+        @Override
+        public String getErrorAppTag() {
+            return null;
+        }
+
+        @Override
+        public String getDescription() {
+            return null;
+        }
+
+        @Override
+        public RangeSet<Integer> getAllowedRanges() {
+            return INTEGER_ALLOWED_RANGES;
+        }
+    };
 }
index fbbf77f700540a5ca2b3040d9862831f48db1bcf..7789f5d1d0b34c6117e450a37bd0128e3ea1098d 100644 (file)
  */
 package org.opendaylight.yangtools.yang.model.util.type;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import java.util.Collection;
+import com.google.common.base.Verify;
+import com.google.common.collect.ImmutableRangeSet;
+import com.google.common.collect.ImmutableRangeSet.Builder;
+import com.google.common.collect.Range;
+import com.google.common.collect.RangeSet;
 import java.util.List;
 import java.util.Optional;
-import java.util.function.Function;
-import javax.annotation.Nonnull;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.ConstraintMetaDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnresolvedNumber;
+import org.opendaylight.yangtools.yang.model.api.stmt.ValueRange;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.LengthRestrictedTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.BaseConstraints;
-import org.opendaylight.yangtools.yang.model.util.UnresolvedNumber;
 
 public abstract class LengthRestrictedTypeBuilder<T extends LengthRestrictedTypeDefinition<T>>
         extends AbstractRestrictedTypeBuilder<T> {
-    private List<LengthConstraint> lengthAlternatives;
+    private LengthConstraint lengthConstraint;
 
     LengthRestrictedTypeBuilder(final T baseType, final SchemaPath path) {
-        super(Preconditions.checkNotNull(baseType), path);
+        super(requireNonNull(baseType), path);
     }
 
-    public final void setLengthAlternatives(@Nonnull final Collection<LengthConstraint> lengthAlternatives) {
-        Preconditions.checkState(this.lengthAlternatives == null, "Range alternatives already defined as %s",
-                lengthAlternatives);
-        this.lengthAlternatives = ImmutableList.copyOf(lengthAlternatives);
-        touch();
-    }
-
-    private static List<LengthConstraint> ensureResolvedLengths(final List<LengthConstraint> unresolved,
-            final List<LengthConstraint> baseRangeConstraints) {
-        // First check if we need to resolve anything at all
-        for (LengthConstraint c : unresolved) {
-            if (c.getMax() instanceof UnresolvedNumber || c.getMin() instanceof UnresolvedNumber) {
-                return resolveLengths(unresolved, baseRangeConstraints);
-            }
+    /**
+     * Set a new length constraint.
+     *
+     * @param constraint Constraint metadata
+     * @param ranges Allowed ranges
+     * @throws IllegalStateException if the constraint has already been set
+     * @throws InvalidLengthConstraintException if one of the proposed ranges does not overlap with supertype
+     * @throws NullPointerException if any of the arguments is null
+     */
+    public final void setLengthConstraint(final @NonNull ConstraintMetaDefinition constraint,
+            final @NonNull List<ValueRange> ranges) throws InvalidLengthConstraintException {
+        Preconditions.checkState(lengthConstraint == null, "Length alternatives already defined as %s",
+                lengthConstraint);
+        final LengthConstraint baseLengths = findLenghts();
+        if (ranges.isEmpty()) {
+            lengthConstraint = baseLengths;
+            return;
         }
 
-        // No need, just return the same list
-        return unresolved;
-    }
-
-    private static List<LengthConstraint> resolveLengths(final List<LengthConstraint> unresolved,
-            final List<LengthConstraint> baseLengthConstraints) {
-        final Builder<LengthConstraint> builder = ImmutableList.builder();
-
-        for (LengthConstraint c : unresolved) {
-            final Number max = c.getMax();
-            final Number min = c.getMin();
-
-            if (max instanceof UnresolvedNumber || min instanceof UnresolvedNumber) {
-                final Number rMax = max instanceof UnresolvedNumber
-                    ? ((UnresolvedNumber)max).resolveLength(baseLengthConstraints) : max;
-                final Number rMin = min instanceof UnresolvedNumber
-                    ? ((UnresolvedNumber)min).resolveLength(baseLengthConstraints) : min;
-
-                builder.add(BaseConstraints.newLengthConstraint(rMin, rMax, Optional.ofNullable(c.getDescription()),
-                    Optional.ofNullable(c.getReference()), c.getErrorAppTag(), c.getErrorMessage()));
-            } else {
-                builder.add(c);
-            }
-        }
-
-        return builder.build();
-    }
+        // Run through alternatives and resolve them against the base type
+        requireNonNull(constraint);
+        final Builder<Integer> builder = ImmutableRangeSet.builder();
+        final Range<Integer> span = baseLengths.getAllowedRanges().span();
 
-    private static List<LengthConstraint> ensureTypedLengths(final List<LengthConstraint> lengths,
-            final Class<? extends Number> clazz) {
-        for (LengthConstraint c : lengths) {
-            if (!clazz.isInstance(c.getMin()) || !clazz.isInstance(c.getMax())) {
-                return typedLengths(lengths, clazz);
-            }
+        for (ValueRange c : ranges) {
+            builder.add(Range.closed(resolveLength(c.lowerBound(), span), resolveLength(c.upperBound(), span)));
         }
 
-        return lengths;
-    }
 
-    private static List<LengthConstraint> typedLengths(final List<LengthConstraint> lengths,
-            final Class<? extends Number> clazz) {
-        final Function<Number, Number> function = NumberUtil.converterTo(clazz);
-        Preconditions.checkArgument(function != null, "Unsupported range class %s", clazz);
-
-        final Builder<LengthConstraint> builder = ImmutableList.builder();
-
-        for (LengthConstraint c : lengths) {
-            if (!clazz.isInstance(c.getMin()) || !clazz.isInstance(c.getMax())) {
-                final Number min;
-                final Number max;
-
-                try {
-                    min = function.apply(c.getMin());
-                    max = function.apply(c.getMax());
-                } catch (NumberFormatException e) {
-                    throw new IllegalArgumentException(String.format("Constraint %s does not fit into range of %s",
-                        c, clazz.getSimpleName()), e);
-                }
-                builder.add(BaseConstraints.newLengthConstraint(min, max, Optional.ofNullable(c.getDescription()),
-                    Optional.ofNullable(c.getReference()), c.getErrorAppTag(), c.getErrorMessage()));
-            } else {
-                builder.add(c);
+        // Now verify if new ranges are strict subset of base ranges
+        final RangeSet<Integer> allowed = builder.build();
+        final RangeSet<Integer> baseRanges = baseLengths.getAllowedRanges();
+        for (Range<Integer> range : allowed.asRanges()) {
+            if (!baseRanges.encloses(range)) {
+                throw new InvalidLengthConstraintException("Range %s is not a subset of parent constraint %s", range,
+                    baseRanges);
             }
         }
 
-        return builder.build();
+        lengthConstraint = new ResolvedLengthConstraint(constraint, allowed);
+        touch();
     }
 
-    private static boolean lengthCovered(final List<LengthConstraint> where,
-            final LengthConstraint what) {
-        for (LengthConstraint c : where) {
-            if (NumberUtil.isRangeCovered(what.getMin(), what.getMax(), c.getMin(), c.getMax())) {
-                return true;
-            }
-        }
-
-        return false;
-    }
+    abstract T buildType(LengthConstraint lengthConstraint);
 
     @Override
     final T buildType() {
-        final List<LengthConstraint> baseLengths = findLenghts();
-
-        if (lengthAlternatives == null || lengthAlternatives.isEmpty()) {
-            return buildType(baseLengths);
-        }
-
-        // Run through alternatives and resolve them against the base type
-        final List<LengthConstraint> resolvedLengths = ensureResolvedLengths(lengthAlternatives, baseLengths);
+        return buildType(lengthConstraint != null ? lengthConstraint : findLenghts());
+    }
 
-        // Next up, ensure the of boundaries match base constraints
-        final Class<? extends Number> clazz = baseLengths.get(0).getMin().getClass();
-        final List<LengthConstraint> typedLengths = ensureTypedLengths(resolvedLengths, clazz);
+    abstract LengthConstraint typeLengthConstraints();
 
-        // Now verify if new ranges are strict subset of base ranges
-        for (LengthConstraint c : typedLengths) {
-            if (!lengthCovered(baseLengths, c)) {
-                throw new InvalidLengthConstraintException(c,
-                        "Length constraint %s is not a subset of parent constraints %s", c, baseLengths);
-            }
+    private static Integer resolveLength(final Number unresolved, final Range<Integer> span) {
+        if (unresolved instanceof Integer) {
+            return (Integer) unresolved;
+        }
+        if (unresolved instanceof UnresolvedNumber) {
+            return ((UnresolvedNumber)unresolved).resolveLength(span);
         }
 
-        return buildType(typedLengths);
+        return Verify.verifyNotNull(NumberUtil.converterTo(Integer.class)).apply(unresolved);
     }
 
-    abstract T buildType(List<LengthConstraint> lengthConstraints);
-
-    abstract List<LengthConstraint> typeLengthConstraints();
-
-    private List<LengthConstraint> findLenghts() {
-        List<LengthConstraint> ret = ImmutableList.of();
+    private LengthConstraint findLenghts() {
+        Optional<LengthConstraint> ret = Optional.empty();
         T wlk = getBaseType();
-        while (wlk != null && ret.isEmpty()) {
-            ret = wlk.getLengthConstraints();
+        while (wlk != null && !ret.isPresent()) {
+            ret = wlk.getLengthConstraint();
             wlk = wlk.getBaseType();
         }
 
-        return ret.isEmpty() ? typeLengthConstraints() : ret;
+        return ret.orElse(typeLengthConstraints());
     }
 }
index 0899ed9abad53366689de63505e6a3a9e6a97da4..243aa7f6ceb5050ed835fa49acb0a3f6f84b9dbf 100644 (file)
@@ -105,8 +105,9 @@ final class NumberUtil {
         throw new UnsupportedOperationException();
     }
 
-    static Function<Number, Number> converterTo(final Class<? extends Number> clazz) {
-        return CONVERTERS.get(clazz);
+    @SuppressWarnings("unchecked")
+    static <T extends Number> Function<Number, T> converterTo(final Class<T> clazz) {
+        return (Function<Number, T>) CONVERTERS.get(clazz);
     }
 
     static boolean isRangeCovered(final Number min, final Number max, final Number superMin, final Number superMax) {
index ce7236ab0b7d78383bcdb76477922d045d186693..ba71860a3883348ef1c3993161275665d5447ece 100644 (file)
@@ -17,10 +17,10 @@ import java.util.Optional;
 import java.util.function.Function;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnresolvedNumber;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeRestrictedTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.BaseConstraints;
-import org.opendaylight.yangtools.yang.model.util.UnresolvedNumber;
 
 public abstract class RangeRestrictedTypeBuilder<T extends RangeRestrictedTypeDefinition<T>>
         extends AbstractRestrictedTypeBuilder<T> {
@@ -88,7 +88,7 @@ public abstract class RangeRestrictedTypeBuilder<T extends RangeRestrictedTypeDe
 
     private static List<RangeConstraint> typedRanges(final List<RangeConstraint> ranges,
             final Class<? extends Number> clazz) {
-        final Function<Number, Number> function = NumberUtil.converterTo(clazz);
+        final Function<Number, ? extends Number> function = NumberUtil.converterTo(clazz);
         Preconditions.checkArgument(function != null, "Unsupported range class %s", clazz);
 
         final Builder<RangeConstraint> builder = ImmutableList.builder();
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/ResolvedLengthConstraint.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/ResolvedLengthConstraint.java
new file mode 100644 (file)
index 0000000..53ae1ad
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.model.util.type;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableRangeSet;
+import com.google.common.collect.RangeSet;
+import org.opendaylight.yangtools.yang.model.api.ConstraintMetaDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+
+final class ResolvedLengthConstraint implements LengthConstraint {
+    private final ConstraintMetaDefinition meta;
+    private final RangeSet<Integer> ranges;
+
+    ResolvedLengthConstraint(final ConstraintMetaDefinition meta, final RangeSet<Integer> ranges) {
+        this.meta = requireNonNull(meta);
+        this.ranges = ImmutableRangeSet.copyOf(ranges);
+    }
+
+    @Override
+    public String getDescription() {
+        return meta.getDescription();
+    }
+
+    @Override
+    public String getErrorAppTag() {
+        return meta.getErrorAppTag();
+    }
+
+    @Override
+    public String getErrorMessage() {
+        return meta.getErrorMessage();
+    }
+
+    @Override
+    public String getReference() {
+        return meta.getReference();
+    }
+
+    @Override
+    public RangeSet<Integer> getAllowedRanges() {
+        return ranges;
+    }
+}
index 2e24640fc2c5c3b5f6a22c868e2671f625da903a..f396e4494a6f0be0d544f3cd06907823518191f0 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.model.util.type;
 
 import java.util.Collection;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
@@ -17,8 +18,8 @@ final class RestrictedBinaryType extends AbstractLengthRestrictedType<BinaryType
         implements BinaryTypeDefinition {
     RestrictedBinaryType(final BinaryTypeDefinition baseType, final SchemaPath path,
             final Collection<UnknownSchemaNode> unknownSchemaNodes,
-            final Collection<LengthConstraint> lengthConstraints) {
-        super(baseType, path, unknownSchemaNodes, lengthConstraints);
+            final @Nullable LengthConstraint lengthConstraint) {
+        super(baseType, path, unknownSchemaNodes, lengthConstraint);
     }
 
     @Override
index 0c1aa6aca51a7fc53bd0b663800c219cd2308781..18af66c7aa55cd505f2548dcd83bcb52ee272720 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.model.util.type;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
 import java.util.List;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
@@ -21,7 +22,8 @@ final class RestrictedStringType extends AbstractLengthRestrictedType<StringType
     private final List<PatternConstraint> patternConstraints;
 
     RestrictedStringType(final StringTypeDefinition baseType, final SchemaPath path,
-        final Collection<UnknownSchemaNode> unknownSchemaNodes, final Collection<LengthConstraint> lengthConstraints,
+        final Collection<UnknownSchemaNode> unknownSchemaNodes,
+        final @Nullable LengthConstraint lengthConstraints,
         final List<PatternConstraint> patternConstraints) {
         super(baseType, path, unknownSchemaNodes, lengthConstraints);
         this.patternConstraints = ImmutableList.copyOf(patternConstraints);
index 8de6f1bcf30b9d32d716149fb2a3c127dd953b0d..71fcc36c88ca23d58af743b7c70845804f106a5c 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.model.util.type;
 import com.google.common.annotations.Beta;
 import java.util.List;
 import javax.annotation.Nonnull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
@@ -70,12 +71,12 @@ public final class RestrictedTypes {
             @Nonnull final BinaryTypeDefinition baseType, @Nonnull final SchemaPath path) {
         return new LengthRestrictedTypeBuilder<BinaryTypeDefinition>(baseType, path) {
             @Override
-            BinaryTypeDefinition buildType(final List<LengthConstraint> lengthConstraints) {
-                return new RestrictedBinaryType(getBaseType(), getPath(), getUnknownSchemaNodes(), lengthConstraints);
+            BinaryTypeDefinition buildType(final @Nullable LengthConstraint lengthConstraint) {
+                return new RestrictedBinaryType(getBaseType(), getPath(), getUnknownSchemaNodes(), lengthConstraint);
             }
 
             @Override
-            List<LengthConstraint> typeLengthConstraints() {
+            LengthConstraint typeLengthConstraints() {
                 /**
                  * Length constraint imposed on YANG binary type by our implementation. byte[].length is an integer,
                  * capping our ability to support arbitrary binary data.
index 6f7391ec9a02223262e678ec31faec865347bf7a..fc4b7b7d6031d48d79b471db0cd9b61da4473dd7 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.model.util.type;
 import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.List;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
@@ -29,7 +30,7 @@ public final class StringTypeBuilder extends LengthRestrictedTypeBuilder<StringT
     }
 
     @Override
-    List<LengthConstraint> typeLengthConstraints() {
+    LengthConstraint typeLengthConstraints() {
         /**
          * Length constraint imposed on YANG string type by our implementation. {@link String#length()} is an integer,
          * capping our ability to support strings up to 18446744073709551615 as defined in
@@ -43,7 +44,7 @@ public final class StringTypeBuilder extends LengthRestrictedTypeBuilder<StringT
     }
 
     @Override
-    StringTypeDefinition buildType(final List<LengthConstraint> lengthConstraints) {
+    StringTypeDefinition buildType(final @Nullable LengthConstraint lengthConstraints) {
         return new RestrictedStringType(getBaseType(), getPath(), getUnknownSchemaNodes(),
             lengthConstraints, patternConstraints);
     }
index 8b8ba8d35b034121229d448ffd02ff11534d68eb..44a4ed42e64a481a1551b5f0503499c14d17bcd0 100644 (file)
@@ -62,7 +62,7 @@ final class TypeDefinitions {
 
     static int hashCode(final BinaryTypeDefinition type) {
         return Objects.hash(type.getPath(), type.getUnknownSchemaNodes(), type.getBaseType(), type.getUnits(),
-            type.getDefaultValue(), type.getLengthConstraints());
+            type.getDefaultValue(), type.getLengthConstraint());
     }
 
     static int hashCode(final BitsTypeDefinition type) {
@@ -111,7 +111,7 @@ final class TypeDefinitions {
 
     static int hashCode(final StringTypeDefinition type) {
         return Objects.hash(type.getPath(), type.getUnknownSchemaNodes(), type.getBaseType(), type.getUnits(),
-            type.getDefaultValue(), type.getLengthConstraints(), type.getPatternConstraints());
+            type.getDefaultValue(), type.getLengthConstraint(), type.getPatternConstraints());
     }
 
     static int hashCode(final UnionTypeDefinition type) {
@@ -130,7 +130,7 @@ final class TypeDefinitions {
         }
 
         final BinaryTypeDefinition other = castIfEquals(BinaryTypeDefinition.class, type, obj);
-        return other != null && type.getLengthConstraints().equals(other.getLengthConstraints());
+        return other != null && type.getLengthConstraint().equals(other.getLengthConstraint());
     }
 
     static boolean equals(final BitsTypeDefinition type, final Object obj) {
@@ -211,7 +211,7 @@ final class TypeDefinitions {
         }
 
         final StringTypeDefinition other = castIfEquals(StringTypeDefinition.class, type, obj);
-        return other != null && type.getLengthConstraints().equals(other.getLengthConstraints())
+        return other != null && type.getLengthConstraint().equals(other.getLengthConstraint())
                 && type.getPatternConstraints().equals(other.getPatternConstraints());
     }
 
@@ -234,7 +234,7 @@ final class TypeDefinitions {
     }
 
     static String toString(final BinaryTypeDefinition type) {
-        return toStringHelper(type).add("length", type.getLengthConstraints()).toString();
+        return toStringHelper(type).add("length", type.getLengthConstraint().orElse(null)).toString();
     }
 
     static String toString(final BitsTypeDefinition type) {
@@ -275,7 +275,7 @@ final class TypeDefinitions {
     }
 
     static String toString(final StringTypeDefinition type) {
-        return toStringHelper(type).add("length", type.getLengthConstraints())
+        return toStringHelper(type).add("length", type.getLengthConstraint().orElse(null))
                 .add("patterns", type.getPatternConstraints()).toString();
     }
 
diff --git a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BaseConstraintsTest.java b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BaseConstraintsTest.java
deleted file mode 100644 (file)
index a082d92..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.model.util;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.Optional;
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
-import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
-
-public class BaseConstraintsTest {
-
-    @Test
-    public void canCreateConstraints() {
-        final Number min = 5;
-        final Number max = 99;
-        final String description = "Any description";
-        final String reference = "any_ref";
-
-        LengthConstraint lengthCons = BaseConstraints.newLengthConstraint(min, max, Optional.of(description),
-            Optional.of(reference));
-
-        assertEquals("LengthConstraints Get min", min, lengthCons.getMin());
-        assertEquals("LengthConstraints Get max", max, lengthCons.getMax());
-        assertEquals("LengthConstraints Get description", description, lengthCons.getDescription());
-        assertEquals("LengthConstraints Get reference", reference, lengthCons.getReference());
-
-        final String reg_exp = "x|z";
-        final Optional<String> desc = Optional.of(description);
-        final Optional<String> ref = Optional.of(reference);
-        PatternConstraint patternCons = BaseConstraints.newPatternConstraint(reg_exp, desc, ref);
-
-        assertEquals("PatternConstraints Get regex", reg_exp, patternCons.getRegularExpression());
-        assertEquals("PatternConstraints Get description", description, patternCons.getDescription());
-        assertEquals("PatternConstraints Get reference", reference, patternCons.getReference());
-    }
-}
index 52063b4b88fe7e521a1e5299ef658a45da0457b4..db4e2dd475f2134f5387c575988ae88d102a9234 100644 (file)
@@ -25,7 +25,7 @@ public class BinaryTypeTest {
         final BinaryTypeDefinition binType = binaryType();
         final BinaryTypeDefinition binType1 = binaryType();
 
-        assertEquals(0, binType.getLengthConstraints().size());
+        assertFalse(binType.getLengthConstraint().isPresent());
         assertNull(binType.getDefaultValue());
         assertEquals("CURRENT", Status.CURRENT, binType.getStatus());
         assertEquals("Base type is null", null, binType.getBaseType());
diff --git a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImplTest.java b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImplTest.java
deleted file mode 100644 (file)
index b366ff8..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.yangtools.yang.model.util;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Optional;
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
-
-public class LengthConstraintImplTest {
-
-    @Test
-    public void testLengthConstraint() {
-        LengthConstraint lengthConstraint = new LengthConstraintImpl(3, 5, Optional.of("test description"),
-                Optional.of("test reference"));
-        LengthConstraint lengthConstraint2 = new LengthConstraintImpl(3, 5, Optional.of("test description"),
-                Optional.of("test reference"));
-        assertTrue(lengthConstraint.equals(lengthConstraint2));
-
-        assertFalse(lengthConstraint.equals(null));
-        assertFalse(lengthConstraint.equals(new Object()));
-
-        lengthConstraint2 = new LengthConstraintImpl(3, 5, Optional.of("another test description"),
-                Optional.of("test reference"));
-        assertFalse(lengthConstraint.equals(lengthConstraint2));
-
-        lengthConstraint2 = new LengthConstraintImpl(3, 5, Optional.of("test description"),
-                Optional.of("another test reference"));
-        assertFalse(lengthConstraint.equals(lengthConstraint2));
-
-        lengthConstraint = new LengthConstraintImpl(3, 5, Optional.of("test description"),
-                Optional.of("test reference"), "error app-tag", "error message");
-        lengthConstraint2 = new LengthConstraintImpl(2, 5, Optional.of("test description"),
-                Optional.of("test reference"), "error app-tag", "error message");
-        assertFalse(lengthConstraint.equals(lengthConstraint2));
-
-        lengthConstraint2 = new LengthConstraintImpl(3, 6, Optional.of("test description"),
-                Optional.of("test reference"), "error app-tag", "error message");
-        assertFalse(lengthConstraint.equals(lengthConstraint2));
-
-        lengthConstraint2 = new LengthConstraintImpl(3, 5, Optional.of("test description"),
-                Optional.of("test reference"), "another error app-tag", "error message");
-        assertFalse(lengthConstraint.equals(lengthConstraint2));
-
-        lengthConstraint2 = new LengthConstraintImpl(3, 5, Optional.of("test description"),
-                Optional.of("test reference"), "error app-tag", "another error message");
-        assertFalse(lengthConstraint.equals(lengthConstraint2));
-    }
-}
index c237ec4fbc8786c27733978c3773c53987e9a2bc..38adb1a501ffaefdecc40dbf6b7069652b776857 100644 (file)
@@ -70,8 +70,8 @@ public class NumberUtilTest {
 
     @Test
     public void testConverterToShort() {
-        final short shortNum = 20;
-        final Function<Number, Number> numberFunction = NumberUtil.converterTo(Short.class);
+        final Short shortNum = 20;
+        final Function<Number, Short> numberFunction = NumberUtil.converterTo(Short.class);
         assertEquals(shortNum, numberFunction.apply(shortNum));
 
         final byte byteNum = 20;
@@ -83,16 +83,16 @@ public class NumberUtilTest {
 
     @Test
     public void testConverterToInteger() {
-        final int intNum = 20;
+        final Integer intNum = 20;
         final byte byteNum = 20;
-        final Function<Number, Number> numberFunction = NumberUtil.converterTo(Integer.class);
+        final Function<Number, Integer> numberFunction = NumberUtil.converterTo(Integer.class);
         assertEquals(intNum, numberFunction.apply(byteNum));
     }
 
     @Test
     public void testConverterToLong() {
-        final long longNum = 20L;
-        final Function<Number, Number> numberFunction = NumberUtil.converterTo(Long.class);
+        final Long longNum = 20L;
+        final Function<Number, Long> numberFunction = NumberUtil.converterTo(Long.class);
         assertEquals(longNum, numberFunction.apply(longNum));
 
         final byte byteNum = 20;
@@ -105,7 +105,7 @@ public class NumberUtilTest {
     @Test
     public void testConverterToBigDecimal() {
         BigDecimal bigDecNum = new BigDecimal(20.0);
-        final Function<Number, Number> numberFunction = NumberUtil.converterTo(BigDecimal.class);
+        final Function<Number, BigDecimal> numberFunction = NumberUtil.converterTo(BigDecimal.class);
         assertEquals(bigDecNum, numberFunction.apply(bigDecNum));
 
         int intNum = 20;
@@ -118,7 +118,7 @@ public class NumberUtilTest {
 
     @Test public void testConverterToBigInteger() {
         final BigInteger bigIntNum = new BigInteger("20");
-        final Function<Number, Number> numberFunction = NumberUtil.converterTo(BigInteger.class);
+        final Function<Number, BigInteger> numberFunction = NumberUtil.converterTo(BigInteger.class);
         assertEquals(bigIntNum, numberFunction.apply(bigIntNum));
 
         final int intNum = 20;
index bdab7a070d45abdd98e1c9de9874eae76069c969..38dfc759afc123c38955dd02b364ded8fd018963 100644 (file)
@@ -14,17 +14,22 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 
+import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
 import org.junit.Test;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ConstraintMetaDefinition;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnresolvedNumber;
+import org.opendaylight.yangtools.yang.model.api.stmt.ValueRange;
 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
@@ -32,14 +37,12 @@ import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPai
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.BaseConstraints;
 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
-import org.opendaylight.yangtools.yang.model.util.UnresolvedNumber;
 
 public class TypeTest {
     private static final QName Q_NAME = QName.create("test.namespace", "2016-01-01", "test-name");
@@ -54,7 +57,7 @@ public class TypeTest {
         final BaseBinaryType baseBinaryType1 = BaseBinaryType.INSTANCE;
         final BaseBinaryType baseBinaryType2 = (BaseBinaryType)BaseTypes.binaryType();
         hashCodeEqualsToStringTest(baseBinaryType1, baseBinaryType2);
-        assertEquals(baseBinaryType1.getLengthConstraints(), baseBinaryType2.getLengthConstraints());
+        assertEquals(baseBinaryType1.getLengthConstraint(), baseBinaryType2.getLengthConstraint());
 
         final DerivedBinaryType derivedBinaryType1 = (DerivedBinaryType)DerivedTypes.derivedTypeBuilder(baseBinaryType1,
                 SCHEMA_PATH).build();
@@ -256,7 +259,7 @@ public class TypeTest {
         final BaseStringType baseStringType1 = BaseStringType.INSTANCE;
         final BaseStringType baseStringType2 = (BaseStringType)BaseTypes.stringType();
         hashCodeEqualsToStringTest(baseStringType1, baseStringType2);
-        assertEquals(baseStringType1.getLengthConstraints(), baseStringType2.getLengthConstraints());
+        assertEquals(baseStringType1.getLengthConstraint(), baseStringType2.getLengthConstraint());
         assertEquals(baseStringType1.getPatternConstraints(), baseStringType2.getPatternConstraints());
 
         final DerivedStringType derivedStringType1 = (DerivedStringType)
@@ -405,18 +408,14 @@ public class TypeTest {
     }
 
     @Test
-    public void constraintTypeBuilderTest() {
+    public void constraintTypeBuilderTest() throws InvalidLengthConstraintException {
         final BaseBinaryType baseBinaryType = (BaseBinaryType)BaseTypes.binaryType();
         final LengthRestrictedTypeBuilder<?> lengthRestrictedTypeBuilder = RestrictedTypes
                 .newBinaryBuilder(baseBinaryType, SCHEMA_PATH);
         final Long min = Long.valueOf(0);
         final UnresolvedNumber max = UnresolvedNumber.max();
-        final LengthConstraint lengthConstraint = BaseConstraints.newLengthConstraint(min, max, ABSENT, ABSENT);
-        final ArrayList<LengthConstraint> lengthArrayList = new ArrayList<>(1);
-        assertEquals(lengthConstraint.getErrorAppTag(), "length-out-of-specified-bounds");
-        assertEquals(lengthConstraint.getErrorMessage(), "The argument is out of bounds <0, max>");
-        lengthArrayList.add(lengthConstraint);
-        lengthRestrictedTypeBuilder.setLengthAlternatives(lengthArrayList);
+        final List<ValueRange> lengthArrayList = ImmutableList.of(ValueRange.of(min, max));
+        lengthRestrictedTypeBuilder.setLengthConstraint(mock(ConstraintMetaDefinition.class), lengthArrayList);
         final TypeDefinition<?> typeDefinition = lengthRestrictedTypeBuilder.buildType();
         assertNotNull(typeDefinition);
 
@@ -435,16 +434,12 @@ public class TypeTest {
     public void exceptionTest() {
         final UnresolvedNumber min = UnresolvedNumber.min();
         final UnresolvedNumber max = UnresolvedNumber.max();
-        final LengthConstraint lengthConstraint = BaseConstraints.newLengthConstraint(min, max, ABSENT, ABSENT);
-        final RangeConstraint rangeConstraint = BaseConstraints.newRangeConstraint(min, max, ABSENT, ABSENT);
+        final RangeConstraint rangeConstraint = BaseConstraints.newRangeConstraint(min, max, Optional.empty(),
+            Optional.empty());
 
         final EnumPair enumPair = EnumPairBuilder.create("enum1", 1).setDescription("description")
                 .setReference("reference").setUnknownSchemaNodes(mock(UnknownSchemaNode.class)).build();
 
-        final InvalidLengthConstraintException invalidLengthConstraintException = new InvalidLengthConstraintException(
-                lengthConstraint, "error msg", "other important messages");
-        assertEquals(invalidLengthConstraintException.getOffendingConstraint(), lengthConstraint);
-
         final InvalidRangeConstraintException invalidRangeConstraintException = new InvalidRangeConstraintException(
                 rangeConstraint, "error msg", "other important messages");
         assertEquals(invalidRangeConstraintException.getOffendingConstraint(), rangeConstraint);
index 6ddd0ef2179a1be3296b950f5d955484e27bcb1d..55d58eb7ad12d1ddc0a71e47b250264b3f2ed388 100644 (file)
@@ -15,14 +15,15 @@ import org.opendaylight.yangtools.yang.model.api.stmt.ErrorAppTagStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ErrorMessageStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.LengthStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.stmt.ValueRange;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.LengthEffectiveStatementImpl;
 
-public class LengthStatementImpl extends AbstractDeclaredStatement<List<LengthConstraint>> implements LengthStatement {
+public class LengthStatementImpl extends AbstractDeclaredStatement<List<ValueRange>>
+        implements LengthStatement {
     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
             .LENGTH)
             .addOptional(YangStmtMapping.DESCRIPTION)
@@ -31,30 +32,30 @@ public class LengthStatementImpl extends AbstractDeclaredStatement<List<LengthCo
             .addOptional(YangStmtMapping.REFERENCE)
             .build();
 
-    protected LengthStatementImpl(final StmtContext<List<LengthConstraint>, LengthStatement, ?> context) {
+    protected LengthStatementImpl(final StmtContext<List<ValueRange>, LengthStatement, ?> context) {
         super(context);
     }
 
-    public static class Definition extends AbstractStatementSupport<List<LengthConstraint>, LengthStatement,
-            EffectiveStatement<List<LengthConstraint>, LengthStatement>> {
+    public static class Definition extends AbstractStatementSupport<List<ValueRange>, LengthStatement,
+            EffectiveStatement<List<ValueRange>, LengthStatement>> {
 
         public Definition() {
             super(YangStmtMapping.LENGTH);
         }
 
         @Override
-        public List<LengthConstraint> parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+        public List<ValueRange> parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
             return TypeUtils.parseLengthListFromString(ctx, value);
         }
 
         @Override
-        public LengthStatement createDeclared(final StmtContext<List<LengthConstraint>, LengthStatement, ?> ctx) {
+        public LengthStatement createDeclared(final StmtContext<List<ValueRange>, LengthStatement, ?> ctx) {
             return new LengthStatementImpl(ctx);
         }
 
         @Override
-        public EffectiveStatement<List<LengthConstraint>, LengthStatement> createEffective(
-                final StmtContext<List<LengthConstraint>, LengthStatement, EffectiveStatement<List<LengthConstraint>,
+        public EffectiveStatement<List<ValueRange>, LengthStatement> createEffective(
+                final StmtContext<List<ValueRange>, LengthStatement, EffectiveStatement<List<ValueRange>,
                         LengthStatement>> ctx) {
             return new LengthEffectiveStatementImpl(ctx);
         }
index ad6efa741c9f4998962521ff4e19640e31414d60..30123541b9084d326af4743e0eacd7f0018568db 100644 (file)
@@ -29,17 +29,16 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnresolvedNumber;
+import org.opendaylight.yangtools.yang.model.api.stmt.ValueRange;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.UnresolvedNumber;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.QNameCacheNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.LengthConstraintEffectiveImpl;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.RangeConstraintEffectiveImpl;
 
 /**
@@ -127,8 +126,7 @@ public final class TypeUtils {
         try {
             return new BigInteger(value);
         } catch (final NumberFormatException e) {
-            throw new SourceException(String.format("Value %s is not a valid integer", value),
-                    ctx.getStatementSourceReference(), e);
+            throw new SourceException(ctx.getStatementSourceReference(), e, "Value %s is not a valid integer", value);
         }
     }
 
@@ -186,15 +184,12 @@ public final class TypeUtils {
         return rangeConstraints;
     }
 
-    public static List<LengthConstraint> parseLengthListFromString(final StmtContext<?, ?, ?> ctx,
+    public static List<ValueRange> parseLengthListFromString(final StmtContext<?, ?, ?> ctx,
             final String lengthArgument) {
-        final Optional<String> description = Optional.empty();
-        final Optional<String> reference = Optional.empty();
-
-        final List<LengthConstraint> lengthConstraints = new ArrayList<>();
+        final List<ValueRange> ranges = new ArrayList<>();
 
         for (final String singleRange : PIPE_SPLITTER.split(lengthArgument)) {
-            final Iterator<String> boundaries = TWO_DOTS_SPLITTER.splitToList(singleRange).iterator();
+            final Iterator<String> boundaries = TWO_DOTS_SPLITTER.split(singleRange).iterator();
             final Number min = parseIntegerConstraintValue(ctx, boundaries.next());
 
             final Number max;
@@ -212,15 +207,15 @@ public final class TypeUtils {
             }
 
             // some of intervals overlapping
-            InferenceException.throwIf(lengthConstraints.size() > 1
-                && compareNumbers(min, Iterables.getLast(lengthConstraints).getMax()) != 1,
+            InferenceException.throwIf(ranges.size() > 1
+                && compareNumbers(min, Iterables.getLast(ranges).upperBound()) != 1,
                         ctx.getStatementSourceReference(),  "Some of the length ranges in %s are not disjoint",
                         lengthArgument);
 
-            lengthConstraints.add(new LengthConstraintEffectiveImpl(min, max, description, reference));
+            ranges.add(ValueRange.of(min, max));
         }
 
-        return lengthConstraints;
+        return ranges;
     }
 
     public static boolean isYangTypeBodyStmtString(final String typeName) {
index 984a09ac9436af2712d88a0be2664a9fe29848f8..c97b69809d25168a3dd3e4b42129a8b5b28a63bf 100644 (file)
@@ -13,7 +13,6 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.util.type.InvalidLengthConstraintException;
 import org.opendaylight.yangtools.yang.model.util.type.LengthRestrictedTypeBuilder;
 import org.opendaylight.yangtools.yang.model.util.type.RestrictedTypes;
@@ -37,20 +36,25 @@ public final class BinaryTypeEffectiveStatementImpl extends DeclaredEffectiveSta
 
         for (EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
             if (stmt instanceof LengthEffectiveStatementImpl) {
-                builder.setLengthAlternatives(((LengthEffectiveStatementImpl)stmt).argument());
+                final LengthEffectiveStatementImpl length = (LengthEffectiveStatementImpl)stmt;
+
+                try {
+                    builder.setLengthConstraint(length, length.argument());
+                } catch (IllegalStateException e) {
+                    throw new SourceException(ctx.getStatementSourceReference(), e,
+                        "Multiple length constraints encountered");
+                } catch (InvalidLengthConstraintException e) {
+                    throw new SourceException(ctx.getStatementSourceReference(), e, "Invalid length constraint %s",
+                        length.argument());
+                }
             }
+
             if (stmt instanceof UnknownEffectiveStatementImpl) {
                 builder.addUnknownSchemaNode((UnknownEffectiveStatementImpl)stmt);
             }
         }
 
-        try {
-            typeDefinition = builder.build();
-        } catch (InvalidLengthConstraintException e) {
-            final LengthConstraint c = e.getOffendingConstraint();
-            throw new SourceException(ctx.getStatementSourceReference(), e, "Invalid length constraint: <%s, %s>",
-                c.getMin(), c.getMax());
-        }
+        typeDefinition = builder.build();
     }
 
     @Nonnull
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthConstraintEffectiveImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthConstraintEffectiveImpl.java
deleted file mode 100644 (file)
index 762a6d7..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.Objects;
-import java.util.Optional;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
-
-public class LengthConstraintEffectiveImpl implements LengthConstraint {
-
-    private final Number min;
-    private final Number max;
-
-    private final String description;
-    private final String reference;
-
-    private final String errorAppTag;
-    private final String errorMessage;
-
-    public LengthConstraintEffectiveImpl(final Number min, final Number max, final Optional<String> description,
-            final Optional<String> reference) {
-        this(min, max, description.orElse(null), reference.orElse(null), "length-out-of-specified-bounds",
-            "The argument is out of bounds <" + min + ", " + max + ">");
-    }
-
-    public LengthConstraintEffectiveImpl(final Number min, final Number max, final String description,
-            final String reference, final String errorAppTag, final String errorMessage) {
-        this.min = requireNonNull(min, "min must not be null");
-        this.max = requireNonNull(max, "max must not be null");
-        this.description = description;
-        this.reference = reference;
-        this.errorAppTag = errorAppTag != null ? errorAppTag : "length-out-of-specified-bounds";
-        this.errorMessage = errorMessage != null ? errorMessage : "The argument is out of bounds <" + min + ", " + max
-                + ">";
-    }
-
-    @Override
-    public Number getMin() {
-        return min;
-    }
-
-    @Override
-    public Number getMax() {
-        return max;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
-    public String getErrorAppTag() {
-        return errorAppTag;
-    }
-
-    @Override
-    public String getErrorMessage() {
-        return errorMessage;
-    }
-
-    @Override
-    public String getReference() {
-        return reference;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + Objects.hashCode(description);
-        result = prime * result + errorAppTag.hashCode();
-        result = prime * result + errorMessage.hashCode();
-        result = prime * result + max.hashCode();
-        result = prime * result + min.hashCode();
-        result = prime * result + Objects.hashCode(reference);
-        return result;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final LengthConstraintEffectiveImpl other = (LengthConstraintEffectiveImpl) obj;
-        if (!Objects.equals(description, other.description)) {
-            return false;
-        }
-        if (!Objects.equals(errorAppTag, other.errorAppTag)) {
-            return false;
-        }
-        if (!Objects.equals(errorMessage, other.errorMessage)) {
-            return false;
-        }
-        if (!Objects.equals(max, other.max)) {
-            return false;
-        }
-        if (!Objects.equals(min, other.min)) {
-            return false;
-        }
-        if (!Objects.equals(reference, other.reference)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        return LengthConstraintEffectiveImpl.class.getSimpleName()
-                + " [min=" + min
-                + ", max=" + max
-                + ", description=" + description
-                + ", errorAppTag=" + errorAppTag
-                + ", reference=" + reference
-                + ", errorMessage=" + errorMessage
-                + "]";
-    }
-}
index 4288fcc0a6bfac176710b9a4dfdc38b6908a9e86..35bf0284e5e5328e0d17e770b845b231dae97c3d 100644 (file)
@@ -9,19 +9,18 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type;
 
 import java.util.List;
 import org.opendaylight.yangtools.yang.model.api.stmt.LengthStatement;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.stmt.ValueRange;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
 public class LengthEffectiveStatementImpl extends
-        AbstractListConstraintEffectiveStatement<LengthConstraint, LengthStatement> {
+        AbstractListConstraintEffectiveStatement<ValueRange, LengthStatement> {
 
-    public LengthEffectiveStatementImpl(final StmtContext<List<LengthConstraint>, LengthStatement, ?> ctx) {
+    public LengthEffectiveStatementImpl(final StmtContext<List<ValueRange>, LengthStatement, ?> ctx) {
         super(ctx);
     }
 
     @Override
-    final LengthConstraint createCustomizedConstraint(final LengthConstraint lengthConstraint) {
-        return new LengthConstraintEffectiveImpl(lengthConstraint.getMin(), lengthConstraint.getMax(),
-                getDescription(), getReference(), getErrorAppTag(), getErrorMessage());
+    final ValueRange createCustomizedConstraint(final ValueRange lengthConstraint) {
+        return lengthConstraint;
     }
 }
\ No newline at end of file
index f88aaaee6b14efceb69d972066f10e582c7502af..9292ff75552ac3d13d7e18bd088a8a177a0a58d4 100644 (file)
@@ -12,7 +12,6 @@ import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.type.InvalidLengthConstraintException;
@@ -41,7 +40,17 @@ public final class StringTypeEffectiveStatementImpl extends DeclaredEffectiveSta
 
         for (EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
             if (stmt instanceof LengthEffectiveStatementImpl) {
-                builder.setLengthAlternatives(((LengthEffectiveStatementImpl)stmt).argument());
+                final LengthEffectiveStatementImpl length = (LengthEffectiveStatementImpl)stmt;
+
+                try {
+                    builder.setLengthConstraint(length, length.argument());
+                } catch (IllegalStateException e) {
+                    throw new SourceException(ctx.getStatementSourceReference(), e,
+                            "Multiple length constraints encountered");
+                } catch (InvalidLengthConstraintException e) {
+                    throw new SourceException(ctx.getStatementSourceReference(), e, "Invalid length constraint %s",
+                        length.argument());
+                }
             }
             if (stmt instanceof PatternEffectiveStatementImpl) {
                 final PatternConstraint pattern = ((PatternEffectiveStatementImpl)stmt).argument();
@@ -56,13 +65,7 @@ public final class StringTypeEffectiveStatementImpl extends DeclaredEffectiveSta
             }
         }
 
-        try {
-            typeDefinition = builder.build();
-        } catch (InvalidLengthConstraintException e) {
-            final LengthConstraint c = e.getOffendingConstraint();
-            throw new SourceException(ctx.getStatementSourceReference(), e, "Invalid length constraint: <%s, %s>",
-                c.getMin(), c.getMax());
-        }
+        typeDefinition = builder.build();
     }
 
     @Nonnull
index 04fef165b59c4f7184d4c938d2cbe1706c64b9d2..8b9e3ce08b1dc4a5c98c50ef808dab84086827bd 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.yangtools.yang.stmt;
 
+import com.google.common.collect.Range;
 import java.io.File;
 import java.util.List;
 import org.junit.Assert;
@@ -48,17 +49,17 @@ public class Bug4623Test {
         Assert.assertEquals(unknownSchemaNode.getNodeParameter(), "unknown");
         Assert.assertEquals(unknownSchemaNode.getNodeType().getModule().getNamespace().toString(), "urn:simple.extension.typedefs");
 
-        final List<LengthConstraint> lengthConstraints = ((StringTypeDefinition) type).getLengthConstraints();
+        final LengthConstraint lengthConstraint = ((StringTypeDefinition) type).getLengthConstraint().get();
         final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) type).getPatternConstraints();
 
-        Assert.assertNotNull(lengthConstraints);
+        Assert.assertNotNull(lengthConstraint);
         Assert.assertNotNull(patternConstraints);
-        Assert.assertFalse(lengthConstraints.size() == 0);
-        Assert.assertFalse(patternConstraints.size() == 0);
+        Assert.assertFalse(lengthConstraint.getAllowedRanges().isEmpty());
+        Assert.assertFalse(patternConstraints.isEmpty());
 
-        final LengthConstraint lengthConstraint = lengthConstraints.get(0);
-        Assert.assertEquals(lengthConstraint.getMin(), Integer.valueOf(2));
-        Assert.assertEquals(lengthConstraint.getMax(), Integer.valueOf(10));
+        final Range<Integer> span = lengthConstraint.getAllowedRanges().span();
+        Assert.assertEquals(Integer.valueOf(2), span.lowerEndpoint());
+        Assert.assertEquals(Integer.valueOf(10), span.upperEndpoint());
 
         final PatternConstraint patternConstraint = patternConstraints.get(0);
         Assert.assertEquals(patternConstraint.getRegularExpression(), "^[0-9a-fA-F]$");
@@ -89,17 +90,17 @@ public class Bug4623Test {
         Assert.assertEquals(unknownSchemaNode.getNodeParameter(), "unknown");
         Assert.assertEquals(unknownSchemaNode.getNodeType().getModule().getNamespace().toString(), "urn:simple.extension.typedefs");
 
-        final List<LengthConstraint> lengthConstraints = ((StringTypeDefinition) type).getLengthConstraints();
+        final LengthConstraint lengthConstraints = ((StringTypeDefinition) type).getLengthConstraint().get();
         final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) type).getPatternConstraints();
 
         Assert.assertNotNull(lengthConstraints);
         Assert.assertNotNull(patternConstraints);
-        Assert.assertFalse(lengthConstraints.size() == 0);
-        Assert.assertFalse(patternConstraints.size() == 0);
+        Assert.assertEquals(1, lengthConstraints.getAllowedRanges().asRanges().size());
+        Assert.assertFalse(patternConstraints.isEmpty());
 
-        final LengthConstraint lengthConstraint = lengthConstraints.get(0);
-        Assert.assertEquals(lengthConstraint.getMin(), Integer.valueOf(2));
-        Assert.assertEquals(lengthConstraint.getMax(), Integer.valueOf(10));
+        final Range<Integer> lengthConstraint = lengthConstraints.getAllowedRanges().span();
+        Assert.assertEquals(Integer.valueOf(2), lengthConstraint.lowerEndpoint());
+        Assert.assertEquals(Integer.valueOf(10), lengthConstraint.upperEndpoint());
 
         final PatternConstraint patternConstraint = patternConstraints.get(0);
         Assert.assertEquals(patternConstraint.getRegularExpression(), "^[0-9a-fA-F]$");
@@ -130,17 +131,18 @@ public class Bug4623Test {
         Assert.assertEquals(unknownSchemaNode.getNodeParameter(), "unknown");
         Assert.assertEquals(unknownSchemaNode.getNodeType().getModule().getNamespace().toString(), "urn:simple.extension.typedefs");
 
-        final List<LengthConstraint> lengthConstraints = ((StringTypeDefinition) type).getLengthConstraints();
+        final LengthConstraint lengthConstraints =
+                ((StringTypeDefinition) type).getLengthConstraint().get();
         final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) type).getPatternConstraints();
 
         Assert.assertNotNull(lengthConstraints);
         Assert.assertNotNull(patternConstraints);
-        Assert.assertFalse(lengthConstraints.size() == 0);
+        Assert.assertEquals(1, lengthConstraints.getAllowedRanges().asRanges().size());
         Assert.assertFalse(patternConstraints.size() == 0);
 
-        final LengthConstraint lengthConstraint = lengthConstraints.get(0);
-        Assert.assertEquals(lengthConstraint.getMin(), Integer.valueOf(2));
-        Assert.assertEquals(lengthConstraint.getMax(), Integer.valueOf(10));
+        final Range<Integer> lengthConstraint = lengthConstraints.getAllowedRanges().span();
+        Assert.assertEquals(Integer.valueOf(2), lengthConstraint.lowerEndpoint());
+        Assert.assertEquals(Integer.valueOf(10), lengthConstraint.upperEndpoint());
 
         final PatternConstraint patternConstraint = patternConstraints.get(0);
         Assert.assertEquals(patternConstraint.getRegularExpression(), "^[0-9a-fA-F]$");
index b60f652e0ff898a10868da43d4af14708583dae3..499221c666554ba30998c28168697db3e008a76d 100644 (file)
@@ -15,8 +15,9 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource;
 
+import com.google.common.collect.Range;
 import java.util.List;
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
@@ -54,11 +55,12 @@ public class EffectiveStatementTypeTest {
 
     private static final StatementStreamSource IMPORTED_MODULE = sourceForResource("/type-tests/types.yang");
     private static SchemaContext effectiveSchemaContext;
-    private static LeafSchemaNode currentLeaf;
     private static Module types;
 
-    @Before
-    public void setup() throws ReactorException {
+    private LeafSchemaNode currentLeaf;
+
+    @BeforeClass
+    public static void setup() throws ReactorException {
         final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
         reactor.addSource(IMPORTED_MODULE);
         effectiveSchemaContext = reactor.buildEffective();
@@ -71,14 +73,15 @@ public class EffectiveStatementTypeTest {
         currentLeaf = (LeafSchemaNode) types.getDataChildByName(QName.create(types.getQNameModule(), "leaf-binary"));
         assertNotNull(currentLeaf.getType());
 
-        final BinaryTypeDefinition binaryEff = (BinaryTypeDefinition) ((TypeEffectiveStatement<?>) ((LeafEffectiveStatementImpl) currentLeaf)
+        final BinaryTypeDefinition binaryEff = (BinaryTypeDefinition)
+                ((TypeEffectiveStatement<?>) ((LeafEffectiveStatementImpl) currentLeaf)
                 .effectiveSubstatements().iterator().next()).getTypeDefinition();
 
         assertNull(binaryEff.getBaseType());
         assertNull(binaryEff.getUnits());
         assertNull(binaryEff.getDefaultValue());
         assertEquals("binary", binaryEff.getQName().getLocalName());
-        assertEquals(0, binaryEff.getLengthConstraints().size());
+        assertFalse(binaryEff.getLengthConstraint().isPresent());
         assertEquals("CURRENT", binaryEff.getStatus().toString());
         assertEquals("binary", binaryEff.getPath().getPathFromRoot().iterator().next().getLocalName());
         assertNotNull(binaryEff.getUnknownSchemaNodes());
@@ -383,29 +386,29 @@ public class EffectiveStatementTypeTest {
     public void testLengthConstraint() {
         currentLeaf = (LeafSchemaNode) types.getDataChildByName(QName.create(types.getQNameModule(),
                 "leaf-length-pattern"));
-        assertNotNull(currentLeaf.getType());
-        final LengthConstraint lengthConstraint = ((StringTypeDefinition) currentLeaf.getType())
-                .getLengthConstraints().get(0);
-        final LengthConstraint lengthConstraintThird = ((StringTypeDefinition) currentLeaf.getType())
-                .getLengthConstraints().get(0);
-        currentLeaf = (LeafSchemaNode) types.getDataChildByName(QName.create(types.getQNameModule(),
-                "leaf-length-pattern-second"));
-        assertNotNull(currentLeaf.getType());
-        final LengthConstraint lengthConstraintSecond = ((StringTypeDefinition) currentLeaf.getType())
-                .getLengthConstraints().get(0);
 
-        assertEquals(1, lengthConstraint.getMin().intValue());
-        assertEquals(255, lengthConstraint.getMax().intValue());
+        final StringTypeDefinition leafType = (StringTypeDefinition) currentLeaf.getType();
+        assertNotNull(leafType);
+        final LengthConstraint lengthConstraint = leafType.getLengthConstraint().get();
+
+        final Range<Integer> span = lengthConstraint.getAllowedRanges().span();
+        assertEquals(1, span.lowerEndpoint().intValue());
+        assertEquals(255, span.upperEndpoint().intValue());
         assertNull(lengthConstraint.getReference());
         assertNull(lengthConstraint.getDescription());
-        assertEquals("The argument is out of bounds <1, 255>", lengthConstraint.getErrorMessage());
-        assertEquals("length-out-of-specified-bounds", lengthConstraint.getErrorAppTag());
+        assertNull(lengthConstraint.getErrorMessage());
+        assertNull(lengthConstraint.getErrorAppTag());
         assertNotNull(lengthConstraint.toString());
         assertNotNull(lengthConstraint.hashCode());
         assertFalse(lengthConstraint.equals(null));
         assertFalse(lengthConstraint.equals("test"));
+
+        currentLeaf = (LeafSchemaNode) types.getDataChildByName(QName.create(types.getQNameModule(),
+                "leaf-length-pattern-second"));
+        assertNotNull(currentLeaf.getType());
+        final LengthConstraint lengthConstraintSecond = ((StringTypeDefinition) currentLeaf.getType())
+                .getLengthConstraint().get();
         assertFalse(lengthConstraint.equals(lengthConstraintSecond));
-        assertTrue(lengthConstraint.equals(lengthConstraintThird));
     }
 
     @Test
@@ -457,7 +460,7 @@ public class EffectiveStatementTypeTest {
         assertFalse(stringEff.equals("test"));
         assertTrue(stringEff.equals(stringEff));
         assertEquals("string", stringEff.getPath().getLastComponent().getLocalName());
-        assertEquals(0, stringEff.getLengthConstraints().size());
+        assertFalse(stringEff.getLengthConstraint().isPresent());
         assertNotNull(stringEff.getPatternConstraints());
     }
 }
index ad0f0937bd1bbb3c3023c4930f6b5ebcca3ede9e..e9d2a17356a6e540f9505ce2c74394b6f75e0105 100644 (file)
@@ -16,6 +16,7 @@ import static org.junit.Assert.fail;
 import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource;
 
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Range;
 import java.net.URI;
 import java.util.List;
 import java.util.Set;
@@ -158,11 +159,11 @@ public class TypesResolutionTest {
                 + "([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)" + "|\\.$";
         assertEquals(expectedPattern, patterns.get(0).getRegularExpression());
 
-        List<LengthConstraint> lengths = type.getLengthConstraints();
-        assertEquals(1, lengths.size());
-        LengthConstraint length = type.getLengthConstraints().get(0);
-        assertEquals(Integer.valueOf(1), length.getMin());
-        assertEquals(Integer.valueOf(253), length.getMax());
+        LengthConstraint lengths = type.getLengthConstraint().get();
+        assertEquals(1, lengths.getAllowedRanges().asRanges().size());
+        Range<Integer> length = lengths.getAllowedRanges().span();
+        assertEquals(Integer.valueOf(1), length.lowerEndpoint());
+        assertEquals(Integer.valueOf(253), length.upperEndpoint());
     }
 
     @Test
index dbc00013ddcf7e1349f843fd21faff35461ca9b7..671ed873483dcfa7274ea82d3cbf6d207dd4cac9 100644 (file)
@@ -98,7 +98,9 @@ public class YangParserNegativeTest {
             TestUtils.loadModuleResources(getClass(), "/negative-scenario/testfile5.yang");
             fail("ReactorException should be thrown");
         } catch (final ReactorException e) {
-            assertTrue(e.getCause().getMessage().contains("Invalid length constraint: <4, 10>"));
+            final String message = e.getCause().getMessage();
+
+            assertTrue(message.contains("Invalid length constraint [4..10]"));
         }
     }
 
index f6b0cefbe5f187a9764c25cd159c43f9d44b5627..3c885b074d2366dff5152839bf478c2c3ce3ac6d 100644 (file)
@@ -14,6 +14,8 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource;
 
+import com.google.common.collect.Range;
+import com.google.common.collect.RangeSet;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -53,7 +55,6 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
@@ -222,7 +223,7 @@ public class YangParserTest {
         assertEquals(1, patterns.size());
         PatternConstraint pattern = patterns.iterator().next();
         assertEquals("^[e-z]*$", pattern.getRegularExpression());
-        assertEquals(1, type.getLengthConstraints().size());
+        assertEquals(1, type.getLengthConstraint().get().getAllowedRanges().asRanges().size());
 
         final StringTypeDefinition baseType1 = type.getBaseType();
         final QName baseType1QName = baseType1.getQName();
@@ -234,7 +235,7 @@ public class YangParserTest {
         assertEquals(1, patterns.size());
         pattern = patterns.iterator().next();
         assertEquals("^[b-u]*$", pattern.getRegularExpression());
-        assertEquals(1, baseType1.getLengthConstraints().size());
+        assertEquals(1, baseType1.getLengthConstraint().get().getAllowedRanges().asRanges().size());
 
         final StringTypeDefinition baseType2 = baseType1.getBaseType();
         final QName baseType2QName = baseType2.getQName();
@@ -243,11 +244,11 @@ public class YangParserTest {
         assertNull(baseType2.getUnits());
         assertNull(baseType2.getDefaultValue());
         assertTrue(baseType2.getPatternConstraints().isEmpty());
-        final List<LengthConstraint> baseType2Lengths = baseType2.getLengthConstraints();
-        assertEquals(1, baseType2Lengths.size());
-        LengthConstraint length = baseType2Lengths.get(0);
-        assertEquals(6, length.getMin().intValue());
-        assertEquals(10, length.getMax().intValue());
+        final RangeSet<Integer> baseType2Lengths = baseType2.getLengthConstraint().get().getAllowedRanges();
+        assertEquals(1, baseType2Lengths.asRanges().size());
+        Range<Integer> length = baseType2Lengths.span();
+        assertEquals(6, length.lowerEndpoint().intValue());
+        assertEquals(10, length.upperEndpoint().intValue());
 
         final StringTypeDefinition baseType3 = baseType2.getBaseType();
         assertEquals(QName.create(BAR, "string-ext1"), baseType3.getQName());
@@ -257,11 +258,11 @@ public class YangParserTest {
         assertEquals(1, patterns.size());
         pattern = patterns.iterator().next();
         assertEquals("^[a-k]*$", pattern.getRegularExpression());
-        final List<LengthConstraint> baseType3Lengths = baseType3.getLengthConstraints();
-        assertEquals(1, baseType3Lengths.size());
-        length = baseType3Lengths.get(0);
-        assertEquals(5, length.getMin().intValue());
-        assertEquals(11, length.getMax().intValue());
+        final RangeSet<Integer> baseType3Lengths = baseType3.getLengthConstraint().get().getAllowedRanges();
+        assertEquals(1, baseType3Lengths.asRanges().size());
+        length = baseType3Lengths.span();
+        assertEquals(5, length.lowerEndpoint().intValue());
+        assertEquals(11, length.upperEndpoint().intValue());
 
         assertEquals(BaseTypes.stringType(), baseType3.getBaseType());
     }
@@ -298,7 +299,7 @@ public class YangParserTest {
         assertEquals(1, patterns.size());
         final PatternConstraint pattern = patterns.iterator().next();
         assertEquals("^[e-z]*$", pattern.getRegularExpression());
-        assertEquals(1, type.getLengthConstraints().size());
+        assertEquals(1, type.getLengthConstraint().get().getAllowedRanges().asRanges().size());
 
         final LeafSchemaNode multiplePatternDirectStringDefLeaf = (LeafSchemaNode) foo
                 .getDataChildByName(QName.create(foo.getQNameModule(), "multiple-pattern-direct-string-def-leaf"));
@@ -325,29 +326,30 @@ public class YangParserTest {
 
     @Test
     public void testTypedefLengthsResolving() {
-        final LeafSchemaNode lengthLeaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(), "length-leaf"));
+        final LeafSchemaNode lengthLeaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
+            "length-leaf"));
         final StringTypeDefinition type = (StringTypeDefinition) lengthLeaf.getType();
 
         assertEquals(QName.create(FOO, "string-ext2"), type.getQName());
         assertNull(type.getUnits());
         assertNull(type.getDefaultValue());
         assertTrue(type.getPatternConstraints().isEmpty());
-        final List<LengthConstraint> typeLengths = type.getLengthConstraints();
-        assertEquals(1, typeLengths.size());
-        LengthConstraint length = typeLengths.get(0);
-        assertEquals(7, length.getMin().intValue());
-        assertEquals(10, length.getMax().intValue());
+        final RangeSet<Integer> typeLengths = type.getLengthConstraint().get().getAllowedRanges();
+        assertEquals(1, typeLengths.asRanges().size());
+        Range<Integer> length = typeLengths.span();
+        assertEquals(7, length.lowerEndpoint().intValue());
+        assertEquals(10, length.upperEndpoint().intValue());
 
         final StringTypeDefinition baseType1 = type.getBaseType();
         assertEquals(QName.create(BAR, "string-ext2"), baseType1.getQName());
         assertNull(baseType1.getUnits());
         assertNull(baseType1.getDefaultValue());
         assertTrue(baseType1.getPatternConstraints().isEmpty());
-        final List<LengthConstraint> baseType2Lengths = baseType1.getLengthConstraints();
-        assertEquals(1, baseType2Lengths.size());
-        length = baseType2Lengths.get(0);
-        assertEquals(6, length.getMin().intValue());
-        assertEquals(10, length.getMax().intValue());
+        final RangeSet<Integer> baseType2Lengths = baseType1.getLengthConstraint().get().getAllowedRanges();
+        assertEquals(1, baseType2Lengths.asRanges().size());
+        length = baseType2Lengths.span();
+        assertEquals(6, length.lowerEndpoint().intValue());
+        assertEquals(10, length.upperEndpoint().intValue());
 
         final StringTypeDefinition baseType2 = baseType1.getBaseType();
         assertEquals(QName.create(BAR, "string-ext1"), baseType2.getQName());
@@ -357,11 +359,11 @@ public class YangParserTest {
         assertEquals(1, patterns.size());
         final PatternConstraint pattern = patterns.iterator().next();
         assertEquals("^[a-k]*$", pattern.getRegularExpression());
-        final List<LengthConstraint> baseType3Lengths = baseType2.getLengthConstraints();
-        assertEquals(1, baseType3Lengths.size());
-        length = baseType3Lengths.get(0);
-        assertEquals(5, length.getMin().intValue());
-        assertEquals(11, length.getMax().intValue());
+        final RangeSet<Integer> baseType3Lengths = baseType2.getLengthConstraint().get().getAllowedRanges();
+        assertEquals(1, baseType3Lengths.asRanges().size());
+        length = baseType3Lengths.span();
+        assertEquals(5, length.lowerEndpoint().intValue());
+        assertEquals(11, length.upperEndpoint().intValue());
 
         assertEquals(BaseTypes.stringType(), baseType2.getBaseType());
     }
index f752c70e7c855024a935eed930b80853943bc01b..33db95204366b4a399bf40b5fe76cb8183ababf5 100644 (file)
@@ -52,15 +52,15 @@ public class Bug5200Test {
         assertTrue(myLeafType instanceof StringTypeDefinition);
         assertTrue(myLeaf2Type instanceof IntegerTypeDefinition);
 
-        List<LengthConstraint> lengthConstraints = ((StringTypeDefinition) myLeafType).getLengthConstraints();
-        List<PatternConstraint> patternConstraints = ((StringTypeDefinition) myLeafType).getPatternConstraints();
+        final LengthConstraint lengthConstraint =
+                ((StringTypeDefinition) myLeafType).getLengthConstraint().get();
+        final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) myLeafType).getPatternConstraints();
 
-        assertEquals(1, lengthConstraints.size());
+        assertEquals(1, lengthConstraint.getAllowedRanges().asRanges().size());
         assertEquals(1, patternConstraints.size());
 
-        LengthConstraint lenghtConstraint = lengthConstraints.iterator().next();
-        assertEquals("lenght constraint error-app-tag", lenghtConstraint.getErrorAppTag());
-        assertEquals("lenght constraint error-app-message", lenghtConstraint.getErrorMessage());
+        assertEquals("lenght constraint error-app-tag", lengthConstraint.getErrorAppTag());
+        assertEquals("lenght constraint error-app-message", lengthConstraint.getErrorMessage());
 
         PatternConstraint patternConstraint = patternConstraints.iterator().next();
         assertEquals("pattern constraint error-app-tag", patternConstraint.getErrorAppTag());