From e4e04843c84f255b6c223ba48b582019ed91dee6 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 29 Aug 2017 09:19:57 +0200 Subject: [PATCH] BUG-8043: correct LengthConstraint definition 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 --- .../data/impl/codec/BinaryStringCodec.java | 25 +-- .../data/impl/codec/StringStringCodec.java | 25 +-- .../yang/model/api/package-info.java | 2 +- .../yang/model/api/stmt/LengthStatement.java | 5 +- .../model/api/stmt}/UnresolvedNumber.java | 16 +- .../yang/model/api/stmt/ValueRange.java | 100 ++++++++++ .../yang/model/api/type/LengthConstraint.java | 38 +--- .../type/LengthRestrictedTypeDefinition.java | 12 +- .../model/export/SchemaContextEmitter.java | 38 ++-- .../bug2444/yin/binary-spec@1970-01-01.yin | 2 +- .../yang/model/util/BaseConstraints.java | 55 ------ .../yang/model/util/LengthConstraintImpl.java | 141 -------------- .../AbstractLengthRestrictedBaseType.java | 7 +- .../AbstractLengthRestrictedDerivedType.java | 6 +- .../type/AbstractLengthRestrictedType.java | 14 +- .../yang/model/util/type/CompatUtils.java | 21 +- .../InvalidLengthConstraintException.java | 20 +- .../util/type/JavaLengthConstraints.java | 38 +++- .../type/LengthRestrictedTypeBuilder.java | 180 ++++++------------ .../yang/model/util/type/NumberUtil.java | 5 +- .../util/type/RangeRestrictedTypeBuilder.java | 4 +- .../util/type/ResolvedLengthConstraint.java | 50 +++++ .../model/util/type/RestrictedBinaryType.java | 5 +- .../model/util/type/RestrictedStringType.java | 4 +- .../yang/model/util/type/RestrictedTypes.java | 7 +- .../model/util/type/StringTypeBuilder.java | 5 +- .../yang/model/util/type/TypeDefinitions.java | 12 +- .../yang/model/util/BaseConstraintsTest.java | 43 ----- .../yang/model/util/BinaryTypeTest.java | 2 +- .../model/util/LengthConstraintImplTest.java | 57 ------ .../yang/model/util/type/NumberUtilTest.java | 16 +- .../yang/model/util/type/TypeTest.java | 29 ++- .../stmt/rfc6020/LengthStatementImpl.java | 19 +- .../yang/parser/stmt/rfc6020/TypeUtils.java | 25 +-- .../BinaryTypeEffectiveStatementImpl.java | 22 ++- .../type/LengthConstraintEffectiveImpl.java | 131 ------------- .../type/LengthEffectiveStatementImpl.java | 11 +- .../StringTypeEffectiveStatementImpl.java | 21 +- .../yangtools/yang/stmt/Bug4623Test.java | 38 ++-- .../yang/stmt/EffectiveStatementTypeTest.java | 47 ++--- .../yang/stmt/TypesResolutionTest.java | 11 +- .../yang/stmt/YangParserNegativeTest.java | 4 +- .../yangtools/yang/stmt/YangParserTest.java | 62 +++--- .../yangtools/yang/stmt/test/Bug5200Test.java | 12 +- 44 files changed, 514 insertions(+), 873 deletions(-) rename yang/{yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util => yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt}/UnresolvedNumber.java (82%) create mode 100644 yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ValueRange.java delete mode 100644 yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java create mode 100644 yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/ResolvedLengthConstraint.java delete mode 100644 yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BaseConstraintsTest.java delete mode 100644 yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImplTest.java delete mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthConstraintEffectiveImpl.java diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/BinaryStringCodec.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/BinaryStringCodec.java index 7d30edfa3b..912283c2ee 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/BinaryStringCodec.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/BinaryStringCodec.java @@ -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 implements BinaryCodec { private static final class Restricted extends BinaryStringCodec { - private final RangeSet ranges; + private final LengthConstraint lengthConstraint; - Restricted(final BinaryTypeDefinition typeDef) { + Restricted(final BinaryTypeDefinition typeDef, final LengthConstraint lengthConstraint) { super(typeDef); - - final RangeSet 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 optConstraint = type.getLengthConstraint(); + return optConstraint.isPresent() ? new Restricted(type, optConstraint.get()) : new Unrestricted(type); } @Override diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/StringStringCodec.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/StringStringCodec.java index d05f57c5b9..b905305b01 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/StringStringCodec.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/StringStringCodec.java @@ -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 implements StringCodec { - private final RangeSet lengths; + private final LengthConstraint lengthConstraint; StringStringCodec(final StringTypeDefinition typeDef) { super(Optional.of(typeDef), String.class); - - final Collection constraints = typeDef.getLengthConstraints(); - if (!constraints.isEmpty()) { - final RangeSet 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 TypeDefinitionAwareCodeclength *
{@link org.opendaylight.yangtools.yang.model.api.type.LengthConstraint} - *
{@link org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition#getLengthConstraints()} + *
{@link org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition#getLengthConstraint()} * *
list *
{@link org.opendaylight.yangtools.yang.model.api.ListSchemaNode} diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/LengthStatement.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/LengthStatement.java index 6585a48a6e..c5dcdcf1f2 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/LengthStatement.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/LengthStatement.java @@ -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>, DocumentedConstraintGroup { +public interface LengthStatement extends DeclaredStatement>, DocumentedConstraintGroup { @Nonnull @Override - List argument(); + List argument(); } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnresolvedNumber.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/UnresolvedNumber.java 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 3cdb7df9f6..987a6466a8 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnresolvedNumber.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/UnresolvedNumber.java @@ -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 constraints) { - return resolve(constraints.get(constraints.size() - 1).getMax()); + public > T resolveLength(final Range 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 constraints) { - return resolve(constraints.get(0).getMin()); + public > T resolveLength(final Range 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 resolve(final T number) { checkArgument(!(number instanceof UnresolvedNumber)); return number; } - public abstract Number resolveLength(List constraints); + public abstract > T resolveLength(Range span); public abstract Number resolveRange(List 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 index 0000000000..e124a5c38a --- /dev/null +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/ValueRange.java @@ -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()); + } +} diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthConstraint.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthConstraint.java index b7d64aa8e2..e3f59ab437 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthConstraint.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthConstraint.java @@ -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()}.
- *
- * Length-restricting values MUST NOT be negative. A length value is a - * non-negative integer, or one of the special values min or - * max. The defined min and max mean the - * minimum and maximum length accepted for the type being restricted, - * respectively.
- * An implementation is not required to support a length value larger than - * {@link Long#MAX_VALUE}
- *
- * The interface extends definitions from {@link ConstraintMetaDefinition}
- *
- * This interface was modeled according to definition in [RFC-6020] The - * length Statement. - * - * @see ConstraintMetaDefinition + * A single value length restriction, as expressed by a length statement, as specified by + * [RFC-6020] The length Statement. */ public interface LengthConstraint extends ConstraintMetaDefinition { - - /** - * Returns the length-restricting lower bound value.
- * The value MUST NOT be negative. - * - * @return the length-restricting lower bound value. - */ - Number getMin(); - /** - * Returns the length-restricting upper bound value.
- * 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 getAllowedRanges(); } diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthRestrictedTypeDefinition.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthRestrictedTypeDefinition.java index 4e98e98bed..559d594319 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthRestrictedTypeDefinition.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/type/LengthRestrictedTypeDefinition.java @@ -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> extends TypeDefinition { /** - * 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 length substatement - * of the type statement. + * @return length constraint which are specified in the length substatement of the type + * statement. */ - List getLengthConstraints(); + Optional getLengthConstraint(); } diff --git a/yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/SchemaContextEmitter.java b/yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/SchemaContextEmitter.java index 364e8f7a4e..1cde06daec 100644 --- a/yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/SchemaContextEmitter.java +++ b/yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/SchemaContextEmitter.java @@ -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 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 list) { - final Iterator it = list.iterator(); + private static String toLengthString(final RangeSet ranges) { + final Iterator> 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 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(); diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin index bd2ef73882..4495cbf92f 100644 --- a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin +++ b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BaseConstraints.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BaseConstraints.java index 7b3d71b112..cda1b56fc9 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BaseConstraints.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BaseConstraints.java @@ -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; *

* Provides static factory methods which constructs instances of *

    - *
  • {@link LengthConstraint} - {@link #newLengthConstraint(Number, Number, Optional, Optional)} *
  • {@link RangeConstraint} - {@link #newRangeConstraint(Number, Number, Optional, Optional)} *
  • {@link PatternConstraint} - {@link #newPatternConstraint(String, Optional, Optional)} *
@@ -29,59 +27,6 @@ public final class BaseConstraints { throw new UnsupportedOperationException(); } - /** - * Creates a {@link LengthConstraint}. - * - *

- * Creates an instance of Length constraint based on supplied parameters - * with additional behaviour: - *

    - *
  • {@link LengthConstraint#getErrorAppTag()} returns length-out-of-specified-bounds - *
  • {@link LengthConstraint#getErrorMessage()} returns The argument is out of bounds - * <min, max > - *
- * - * @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 description, final Optional reference) { - return new LengthConstraintImpl(min, max, description, reference); - } - - /** - * Creates a {@link LengthConstraint}. - * - *

- * Creates an instance of Length constraint based on supplied parameters - * with additional behaviour: - *

    - *
  • {@link LengthConstraint#getErrorAppTag()} returns length-out-of-specified-bounds - *
  • {@link LengthConstraint#getErrorMessage()} returns The argument is out of bounds - * <min, max > - *
- * - * @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 description, final Optional 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 index cc8fdb3a48..0000000000 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java +++ /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: - * - *
    - *
  • {@link LengthConstraint#getErrorAppTag()} returns - * length-out-of-specified-bounds - *
  • {@link LengthConstraint#getErrorMessage()} returns The argument is - * out of bounds <min, max > - *
- */ -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 description, - final Optional 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 description, - final Optional 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 - + "]"; - } -} diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedBaseType.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedBaseType.java index 75bf332e6f..537d56b97e 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedBaseType.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedBaseType.java @@ -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 getLengthConstraints() { - return ImmutableList.of(); + public final Optional getLengthConstraint() { + return Optional.empty(); } } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedDerivedType.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedDerivedType.java index 91b12e9caf..e263629f68 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedDerivedType.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedDerivedType.java @@ -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 getLengthConstraints() { - return baseType().getLengthConstraints(); + public final Optional getLengthConstraint() { + return baseType().getLengthConstraint(); } } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedType.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedType.java index 2776ba3d86..3aaaea1a2f 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedType.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/AbstractLengthRestrictedType.java @@ -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> extends AbstractRestrictedType implements LengthRestrictedTypeDefinition { - private final List lengthConstraints; + private final @Nullable LengthConstraint lengthConstraint; AbstractLengthRestrictedType(final T baseType, final SchemaPath path, - final Collection unknownSchemaNodes, final Collection lengthConstraints) { + final Collection unknownSchemaNodes, final @Nullable LengthConstraint lengthConstraint) { super(baseType, path, unknownSchemaNodes); - this.lengthConstraints = ImmutableList.copyOf(lengthConstraints); + this.lengthConstraint = lengthConstraint; } @Override - public final List getLengthConstraints() { - return lengthConstraints; + public final Optional getLengthConstraint() { + return Optional.ofNullable(lengthConstraint); } } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java index 83af46d85f..923a728c2b 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java @@ -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 patterns = type.getPatternConstraints(); - final List lengths = type.getLengthConstraints(); + final Optional 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 baseTypeIfNotConstrained(final T type, + final T base) { + final Optional optConstraint = type.getLengthConstraint(); + if (!optConstraint.isPresent()) { return base; } - return type; + return optConstraint.equals(base.getLengthConstraint()) ? base : type; } } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/InvalidLengthConstraintException.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/InvalidLengthConstraintException.java index 0e8bc99f78..533504a029 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/InvalidLengthConstraintException.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/InvalidLengthConstraintException.java @@ -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)); } } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/JavaLengthConstraints.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/JavaLengthConstraints.java index 346494db3b..75227153d2 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/JavaLengthConstraints.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/JavaLengthConstraints.java @@ -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 INTEGER_SIZE_CONSTRAINTS = ImmutableList.of( - BaseConstraints.newLengthConstraint(0, Integer.MAX_VALUE, Optional.empty(), Optional.empty())); + private static final RangeSet 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 getAllowedRanges() { + return INTEGER_ALLOWED_RANGES; + } + }; } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/LengthRestrictedTypeBuilder.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/LengthRestrictedTypeBuilder.java index fbbf77f700..7789f5d1d0 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/LengthRestrictedTypeBuilder.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/LengthRestrictedTypeBuilder.java @@ -7,161 +7,103 @@ */ 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> extends AbstractRestrictedTypeBuilder { - private List 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 lengthAlternatives) { - Preconditions.checkState(this.lengthAlternatives == null, "Range alternatives already defined as %s", - lengthAlternatives); - this.lengthAlternatives = ImmutableList.copyOf(lengthAlternatives); - touch(); - } - - private static List ensureResolvedLengths(final List unresolved, - final List 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 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 resolveLengths(final List unresolved, - final List baseLengthConstraints) { - final Builder 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 builder = ImmutableRangeSet.builder(); + final Range span = baseLengths.getAllowedRanges().span(); - private static List ensureTypedLengths(final List lengths, - final Class 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 typedLengths(final List lengths, - final Class clazz) { - final Function function = NumberUtil.converterTo(clazz); - Preconditions.checkArgument(function != null, "Unsupported range class %s", clazz); - - final Builder 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 allowed = builder.build(); + final RangeSet baseRanges = baseLengths.getAllowedRanges(); + for (Range 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 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 baseLengths = findLenghts(); - - if (lengthAlternatives == null || lengthAlternatives.isEmpty()) { - return buildType(baseLengths); - } - - // Run through alternatives and resolve them against the base type - final List resolvedLengths = ensureResolvedLengths(lengthAlternatives, baseLengths); + return buildType(lengthConstraint != null ? lengthConstraint : findLenghts()); + } - // Next up, ensure the of boundaries match base constraints - final Class clazz = baseLengths.get(0).getMin().getClass(); - final List 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 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 lengthConstraints); - - abstract List typeLengthConstraints(); - - private List findLenghts() { - List ret = ImmutableList.of(); + private LengthConstraint findLenghts() { + Optional 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()); } } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtil.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtil.java index 0899ed9aba..243aa7f6ce 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtil.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtil.java @@ -105,8 +105,9 @@ final class NumberUtil { throw new UnsupportedOperationException(); } - static Function converterTo(final Class clazz) { - return CONVERTERS.get(clazz); + @SuppressWarnings("unchecked") + static Function converterTo(final Class clazz) { + return (Function) CONVERTERS.get(clazz); } static boolean isRangeCovered(final Number min, final Number max, final Number superMin, final Number superMax) { diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RangeRestrictedTypeBuilder.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RangeRestrictedTypeBuilder.java index ce7236ab0b..ba71860a38 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RangeRestrictedTypeBuilder.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RangeRestrictedTypeBuilder.java @@ -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> extends AbstractRestrictedTypeBuilder { @@ -88,7 +88,7 @@ public abstract class RangeRestrictedTypeBuilder typedRanges(final List ranges, final Class clazz) { - final Function function = NumberUtil.converterTo(clazz); + final Function function = NumberUtil.converterTo(clazz); Preconditions.checkArgument(function != null, "Unsupported range class %s", clazz); final Builder 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 index 0000000000..53ae1ada96 --- /dev/null +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/ResolvedLengthConstraint.java @@ -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 ranges; + + ResolvedLengthConstraint(final ConstraintMetaDefinition meta, final RangeSet 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 getAllowedRanges() { + return ranges; + } +} diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedBinaryType.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedBinaryType.java index 2e24640fc2..f396e4494a 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedBinaryType.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedBinaryType.java @@ -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 unknownSchemaNodes, - final Collection lengthConstraints) { - super(baseType, path, unknownSchemaNodes, lengthConstraints); + final @Nullable LengthConstraint lengthConstraint) { + super(baseType, path, unknownSchemaNodes, lengthConstraint); } @Override diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedStringType.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedStringType.java index 0c1aa6aca5..18af66c7aa 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedStringType.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedStringType.java @@ -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 patternConstraints; RestrictedStringType(final StringTypeDefinition baseType, final SchemaPath path, - final Collection unknownSchemaNodes, final Collection lengthConstraints, + final Collection unknownSchemaNodes, + final @Nullable LengthConstraint lengthConstraints, final List patternConstraints) { super(baseType, path, unknownSchemaNodes, lengthConstraints); this.patternConstraints = ImmutableList.copyOf(patternConstraints); diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedTypes.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedTypes.java index 8de6f1bcf3..71fcc36c88 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedTypes.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/RestrictedTypes.java @@ -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(baseType, path) { @Override - BinaryTypeDefinition buildType(final List lengthConstraints) { - return new RestrictedBinaryType(getBaseType(), getPath(), getUnknownSchemaNodes(), lengthConstraints); + BinaryTypeDefinition buildType(final @Nullable LengthConstraint lengthConstraint) { + return new RestrictedBinaryType(getBaseType(), getPath(), getUnknownSchemaNodes(), lengthConstraint); } @Override - List 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. diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/StringTypeBuilder.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/StringTypeBuilder.java index 6f7391ec9a..fc4b7b7d60 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/StringTypeBuilder.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/StringTypeBuilder.java @@ -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 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 lengthConstraints) { + StringTypeDefinition buildType(final @Nullable LengthConstraint lengthConstraints) { return new RestrictedStringType(getBaseType(), getPath(), getUnknownSchemaNodes(), lengthConstraints, patternConstraints); } diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/TypeDefinitions.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/TypeDefinitions.java index 8b8ba8d35b..44a4ed42e6 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/TypeDefinitions.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/TypeDefinitions.java @@ -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 index a082d92f95..0000000000 --- a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BaseConstraintsTest.java +++ /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 desc = Optional.of(description); - final Optional 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()); - } -} diff --git a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BinaryTypeTest.java b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BinaryTypeTest.java index 52063b4b88..db4e2dd475 100644 --- a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BinaryTypeTest.java +++ b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/BinaryTypeTest.java @@ -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 index b366ff84ff..0000000000 --- a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImplTest.java +++ /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)); - } -} diff --git a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtilTest.java b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtilTest.java index c237ec4fbc..38adb1a501 100644 --- a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtilTest.java +++ b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/NumberUtilTest.java @@ -70,8 +70,8 @@ public class NumberUtilTest { @Test public void testConverterToShort() { - final short shortNum = 20; - final Function numberFunction = NumberUtil.converterTo(Short.class); + final Short shortNum = 20; + final Function 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 numberFunction = NumberUtil.converterTo(Integer.class); + final Function numberFunction = NumberUtil.converterTo(Integer.class); assertEquals(intNum, numberFunction.apply(byteNum)); } @Test public void testConverterToLong() { - final long longNum = 20L; - final Function numberFunction = NumberUtil.converterTo(Long.class); + final Long longNum = 20L; + final Function 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 numberFunction = NumberUtil.converterTo(BigDecimal.class); + final Function 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 numberFunction = NumberUtil.converterTo(BigInteger.class); + final Function numberFunction = NumberUtil.converterTo(BigInteger.class); assertEquals(bigIntNum, numberFunction.apply(bigIntNum)); final int intNum = 20; diff --git a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/TypeTest.java b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/TypeTest.java index bdab7a070d..38dfc759af 100644 --- a/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/TypeTest.java +++ b/yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/type/TypeTest.java @@ -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 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 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); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LengthStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LengthStatementImpl.java index 6ddd0ef217..55d58eb7ad 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LengthStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/LengthStatementImpl.java @@ -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> implements LengthStatement { +public class LengthStatementImpl extends AbstractDeclaredStatement> + implements LengthStatement { private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping .LENGTH) .addOptional(YangStmtMapping.DESCRIPTION) @@ -31,30 +32,30 @@ public class LengthStatementImpl extends AbstractDeclaredStatement, LengthStatement, ?> context) { + protected LengthStatementImpl(final StmtContext, LengthStatement, ?> context) { super(context); } - public static class Definition extends AbstractStatementSupport, LengthStatement, - EffectiveStatement, LengthStatement>> { + public static class Definition extends AbstractStatementSupport, LengthStatement, + EffectiveStatement, LengthStatement>> { public Definition() { super(YangStmtMapping.LENGTH); } @Override - public List parseArgumentValue(final StmtContext ctx, final String value) { + public List parseArgumentValue(final StmtContext ctx, final String value) { return TypeUtils.parseLengthListFromString(ctx, value); } @Override - public LengthStatement createDeclared(final StmtContext, LengthStatement, ?> ctx) { + public LengthStatement createDeclared(final StmtContext, LengthStatement, ?> ctx) { return new LengthStatementImpl(ctx); } @Override - public EffectiveStatement, LengthStatement> createEffective( - final StmtContext, LengthStatement, EffectiveStatement, + public EffectiveStatement, LengthStatement> createEffective( + final StmtContext, LengthStatement, EffectiveStatement, LengthStatement>> ctx) { return new LengthEffectiveStatementImpl(ctx); } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/TypeUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/TypeUtils.java index ad6efa741c..30123541b9 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/TypeUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/TypeUtils.java @@ -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 parseLengthListFromString(final StmtContext ctx, + public static List parseLengthListFromString(final StmtContext ctx, final String lengthArgument) { - final Optional description = Optional.empty(); - final Optional reference = Optional.empty(); - - final List lengthConstraints = new ArrayList<>(); + final List ranges = new ArrayList<>(); for (final String singleRange : PIPE_SPLITTER.split(lengthArgument)) { - final Iterator boundaries = TWO_DOTS_SPLITTER.splitToList(singleRange).iterator(); + final Iterator 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) { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/BinaryTypeEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/BinaryTypeEffectiveStatementImpl.java index 984a09ac94..c97b69809d 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/BinaryTypeEffectiveStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/BinaryTypeEffectiveStatementImpl.java @@ -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 index 762a6d7691..0000000000 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthConstraintEffectiveImpl.java +++ /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 description, - final Optional 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 - + "]"; - } -} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthEffectiveStatementImpl.java index 4288fcc0a6..35bf0284e5 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthEffectiveStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/LengthEffectiveStatementImpl.java @@ -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 { + AbstractListConstraintEffectiveStatement { - public LengthEffectiveStatementImpl(final StmtContext, LengthStatement, ?> ctx) { + public LengthEffectiveStatementImpl(final StmtContext, 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 diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/StringTypeEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/StringTypeEffectiveStatementImpl.java index f88aaaee6b..9292ff7555 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/StringTypeEffectiveStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/type/StringTypeEffectiveStatementImpl.java @@ -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 diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug4623Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug4623Test.java index 04fef165b5..8b9e3ce08b 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug4623Test.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug4623Test.java @@ -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 lengthConstraints = ((StringTypeDefinition) type).getLengthConstraints(); + final LengthConstraint lengthConstraint = ((StringTypeDefinition) type).getLengthConstraint().get(); final List 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 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 lengthConstraints = ((StringTypeDefinition) type).getLengthConstraints(); + final LengthConstraint lengthConstraints = ((StringTypeDefinition) type).getLengthConstraint().get(); final List 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 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 lengthConstraints = ((StringTypeDefinition) type).getLengthConstraints(); + final LengthConstraint lengthConstraints = + ((StringTypeDefinition) type).getLengthConstraint().get(); final List 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 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]$"); diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/EffectiveStatementTypeTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/EffectiveStatementTypeTest.java index b60f652e0f..499221c666 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/EffectiveStatementTypeTest.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/EffectiveStatementTypeTest.java @@ -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 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()); } } diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/TypesResolutionTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/TypesResolutionTest.java index ad0f0937bd..e9d2a17356 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/TypesResolutionTest.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/TypesResolutionTest.java @@ -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 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 length = lengths.getAllowedRanges().span(); + assertEquals(Integer.valueOf(1), length.lowerEndpoint()); + assertEquals(Integer.valueOf(253), length.upperEndpoint()); } @Test diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java index dbc00013dd..671ed87348 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java @@ -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]")); } } diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserTest.java index f6b0cefbe5..3c885b074d 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserTest.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserTest.java @@ -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 baseType2Lengths = baseType2.getLengthConstraints(); - assertEquals(1, baseType2Lengths.size()); - LengthConstraint length = baseType2Lengths.get(0); - assertEquals(6, length.getMin().intValue()); - assertEquals(10, length.getMax().intValue()); + final RangeSet baseType2Lengths = baseType2.getLengthConstraint().get().getAllowedRanges(); + assertEquals(1, baseType2Lengths.asRanges().size()); + Range 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 baseType3Lengths = baseType3.getLengthConstraints(); - assertEquals(1, baseType3Lengths.size()); - length = baseType3Lengths.get(0); - assertEquals(5, length.getMin().intValue()); - assertEquals(11, length.getMax().intValue()); + final RangeSet 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 typeLengths = type.getLengthConstraints(); - assertEquals(1, typeLengths.size()); - LengthConstraint length = typeLengths.get(0); - assertEquals(7, length.getMin().intValue()); - assertEquals(10, length.getMax().intValue()); + final RangeSet typeLengths = type.getLengthConstraint().get().getAllowedRanges(); + assertEquals(1, typeLengths.asRanges().size()); + Range 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 baseType2Lengths = baseType1.getLengthConstraints(); - assertEquals(1, baseType2Lengths.size()); - length = baseType2Lengths.get(0); - assertEquals(6, length.getMin().intValue()); - assertEquals(10, length.getMax().intValue()); + final RangeSet 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 baseType3Lengths = baseType2.getLengthConstraints(); - assertEquals(1, baseType3Lengths.size()); - length = baseType3Lengths.get(0); - assertEquals(5, length.getMin().intValue()); - assertEquals(11, length.getMax().intValue()); + final RangeSet 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()); } diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5200Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5200Test.java index f752c70e7c..33db952043 100644 --- a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5200Test.java +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5200Test.java @@ -52,15 +52,15 @@ public class Bug5200Test { assertTrue(myLeafType instanceof StringTypeDefinition); assertTrue(myLeaf2Type instanceof IntegerTypeDefinition); - List lengthConstraints = ((StringTypeDefinition) myLeafType).getLengthConstraints(); - List patternConstraints = ((StringTypeDefinition) myLeafType).getPatternConstraints(); + final LengthConstraint lengthConstraint = + ((StringTypeDefinition) myLeafType).getLengthConstraint().get(); + final List 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()); -- 2.36.6