BUG-8043: correct RangeConstraint definition
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / codec / AbstractIntegerStringCodec.java
index 5ff364828dd598df46a1679dadc04d8cb843e266..159a28f3b4f871b11ed551273f9970c3bf0a15e1 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.codec;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT16_QNAME;
 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT32_QNAME;
 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT64_QNAME;
@@ -15,20 +16,23 @@ import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT16_QNAME;
 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT32_QNAME;
 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT64_QNAME;
 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT8_QNAME;
+
+import com.google.common.annotations.Beta;
 import com.google.common.base.CharMatcher;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Range;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import com.google.common.collect.RangeSet;
+import java.util.Optional;
 import java.util.regex.Pattern;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
 
-abstract class AbstractIntegerStringCodec<N extends Number & Comparable<N>, T extends TypeDefinition<T>> extends TypeDefinitionAwareCodec<N, T>{
+/**
+ * Do not use this class outside of yangtools, its presence does not fall into the API stability contract.
+ */
+@Beta
+public abstract class AbstractIntegerStringCodec<N extends Number & Comparable<N>, T extends TypeDefinition<T>>
+        extends TypeDefinitionAwareCodec<N, T> {
 
     private static final Pattern INT_PATTERN = Pattern.compile("[+-]?[1-9][0-9]*$");
     private static final Pattern HEX_PATTERN = Pattern.compile("[+-]?0[xX][0-9a-fA-F]+");
@@ -37,29 +41,22 @@ abstract class AbstractIntegerStringCodec<N extends Number & Comparable<N>, T ex
     // For up to two characters, this is very fast
     private static final CharMatcher X_MATCHER = CharMatcher.anyOf("xX");
 
-    private static final String INCORRECT_LEXICAL_REPRESENTATION = "Incorrect lexical representation of integer value: %s."
-            + "\nAn integer value can be defined as: "
-            + "\n  - a decimal number,"
-            + "\n  - a hexadecimal number (prefix 0x)," + "%n  - an octal number (prefix 0)."
-            + "\nSigned values are allowed. Spaces between digits are NOT allowed.";
-
+    private static final String INCORRECT_LEXICAL_REPRESENTATION =
+            "Incorrect lexical representation of integer value: %s."
+                    + "\nAn integer value can be defined as: "
+                    + "\n  - a decimal number,"
+                    + "\n  - a hexadecimal number (prefix 0x)," + "%n  - an octal number (prefix 0)."
+                    + "\nSigned values are allowed. Spaces between digits are NOT allowed.";
 
-    private final List<Range<N>> rangeConstraints;
+    private final RangeSet<N> rangeConstraints;
 
-    protected AbstractIntegerStringCodec(final Optional<T> typeDefinition, final List<RangeConstraint> constraints , final Class<N> outputClass) {
+    AbstractIntegerStringCodec(final Optional<T> typeDefinition, final Optional<RangeConstraint<?>> constraint,
+        final Class<N> outputClass) {
         super(typeDefinition, outputClass);
-        if (constraints.isEmpty()) {
-            rangeConstraints = Collections.emptyList();
-        } else {
-            final List<Range<N>> builder = new ArrayList<>(constraints.size());
-            for (final RangeConstraint yangConstraint : constraints) {
-                builder.add(createRange(yangConstraint.getMin(), yangConstraint.getMax()));
-            }
-            rangeConstraints = builder;
-        }
+        rangeConstraints = (RangeSet<N>) constraint.map(RangeConstraint::getAllowedRanges).orElse(null);
     }
 
-    static TypeDefinitionAwareCodec<?, IntegerTypeDefinition> from(final IntegerTypeDefinition type) {
+    public static AbstractIntegerStringCodec<?, IntegerTypeDefinition> from(final IntegerTypeDefinition type) {
         // FIXME: this is not necessary with yang.model.util.type
         IntegerTypeDefinition baseType = type;
         while (baseType.getBaseType() != null) {
@@ -82,7 +79,8 @@ abstract class AbstractIntegerStringCodec<N extends Number & Comparable<N>, T ex
         }
     }
 
-    static TypeDefinitionAwareCodec<?, UnsignedIntegerTypeDefinition> from(final UnsignedIntegerTypeDefinition type) {
+    public static AbstractIntegerStringCodec<?, UnsignedIntegerTypeDefinition> from(
+            final UnsignedIntegerTypeDefinition type) {
         // FIXME: this is not necessary with yang.model.util.type
         UnsignedIntegerTypeDefinition baseType = type;
         while (baseType.getBaseType() != null) {
@@ -105,12 +103,6 @@ abstract class AbstractIntegerStringCodec<N extends Number & Comparable<N>, T ex
         }
     }
 
-    private Range<N> createRange(final Number yangMin, final Number yangMax) {
-        final N min = convertValue(yangMin);
-        final N max = convertValue(yangMax);
-        return Range.closed(min, max);
-    }
-
     @Override
     public final N deserialize(final String stringRepresentation) {
         final int base = provideBase(stringRepresentation);
@@ -124,51 +116,33 @@ abstract class AbstractIntegerStringCodec<N extends Number & Comparable<N>, T ex
         return deserialized;
     }
 
-
-    private void validate(final N value) {
-        if (rangeConstraints.isEmpty()) {
-            return;
-        }
-        for (final Range<N> constraint : rangeConstraints) {
-            if (constraint.contains(value)) {
-                return;
-            }
-        }
-        throw new IllegalArgumentException("Value '" + value + "'  is not in required range " + rangeConstraints);
-    }
-
     /**
-     * Deserializes value from supplied string representation
-     * is supplied radix.
-     *
-     * See {@link Integer#parseInt(String, int)} for in-depth
-     * description about string and radix relationship.
+     * Deserializes value from supplied string representation is supplied radix. See
+     * {@link Integer#parseInt(String, int)} for in-depth description about string and radix relationship.
      *
      * @param stringRepresentation String representation
      * @param radix numeric base.
      * @return Deserialized value.
      */
-    protected abstract N deserialize(String stringRepresentation, int radix);
-
-    protected abstract N convertValue(Number value);
-
+    abstract N deserialize(String stringRepresentation, int radix);
 
-    protected static List<RangeConstraint> extractRange(final IntegerTypeDefinition type) {
-        if (type == null) {
-            return Collections.emptyList();
+    private void validate(final N value) {
+        if (rangeConstraints != null) {
+            checkArgument(rangeConstraints.contains(value), "Value '%s'  is not in required ranges %s",
+                value, rangeConstraints);
         }
-        return type.getRangeConstraints();
     }
 
-    protected static List<RangeConstraint> extractRange(final UnsignedIntegerTypeDefinition type) {
-        if (type == null) {
-            return Collections.emptyList();
-        }
-        return type.getRangeConstraints();
+    protected static Optional<RangeConstraint<?>> extractRange(final IntegerTypeDefinition type) {
+        return type == null ? Optional.empty() : type.getRangeConstraint();
+    }
+
+    protected static Optional<RangeConstraint<?>> extractRange(final UnsignedIntegerTypeDefinition type) {
+        return type == null ? Optional.empty() : type.getRangeConstraint();
     }
 
     private static int provideBase(final String integer) {
-        Preconditions.checkArgument(integer != null, "String representing integer number cannot be NULL");
+        checkArgument(integer != null, "String representing integer number cannot be NULL");
 
         if (integer.length() == 1 && integer.charAt(0) == '0') {
             return 10;
@@ -184,9 +158,7 @@ abstract class AbstractIntegerStringCodec<N extends Number & Comparable<N>, T ex
     }
 
     private static String normalizeHexadecimal(final String hexInt) {
-        Preconditions.checkArgument(hexInt != null,
-                "String representing integer number in Hexadecimal format cannot be NULL!");
-
+        checkArgument(hexInt != null, "String representing integer number in Hexadecimal format cannot be NULL!");
         return X_MATCHER.removeFrom(hexInt);
     }
 }