Improve Decimal64 range support 14/100114/1
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 13 Mar 2022 23:55:26 +0000 (00:55 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 14 Mar 2022 00:00:49 +0000 (01:00 +0100)
We have classImporter available during generation, hence we can neatly
import Decimal64, reducing boiler plate in range and value declarations.

Decimal64 also exposes a fast instantiation type with scale and unscaled
value -- use those instead of parsing strings.

Change-Id: Ieba07af36fa3d03e20fda0c65754ec2dbfeee451
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractBigRangeGenerator.java [deleted file]
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractPrimitiveRangeGenerator.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractRangeGenerator.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/Decimal64RangeGenerator.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/LongRangeGenerator.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/Decimal64RangeGeneratorTest.java

diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractBigRangeGenerator.java b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractBigRangeGenerator.java
deleted file mode 100644 (file)
index 4a47616..0000000
+++ /dev/null
@@ -1,86 +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.mdsal.binding.java.api.generator;
-
-import com.google.common.collect.Range;
-import java.lang.reflect.Array;
-import java.util.Locale;
-import java.util.Set;
-import java.util.function.Function;
-import org.opendaylight.yangtools.yang.binding.CodeHelpers;
-import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
-
-/**
- * Abstract base for generators which require instantiation of boundary values to check. These are implemented
- * by generating an array constant within the class, which contains {@link Range} instances, which hold pre-instantiated
- * boundary values.
- *
- * @param <T> type of the class
- */
-abstract class AbstractBigRangeGenerator<T extends Number & Comparable<T>> extends AbstractRangeGenerator<T> {
-    protected AbstractBigRangeGenerator(final Class<T> typeClass) {
-        super(typeClass);
-    }
-
-    private static String range(final Function<Class<?>, String> classImporter) {
-        return classImporter.apply(Range.class);
-    }
-
-    private String itemType(final Function<Class<?>, String> classImporter) {
-        return range(classImporter) + '<' + getTypeName() + '>';
-    }
-
-    private String arrayType(final Function<Class<?>, String> classImporter) {
-        return itemType(classImporter) + "[]";
-    }
-
-    @Override
-    protected final String generateRangeCheckerImplementation(final String checkerName,
-            final RangeConstraint<?> constraint, final Function<Class<?>, String> classImporter) {
-        final Set<? extends Range<? extends Number>> constraints = constraint.getAllowedRanges().asRanges();
-        final String fieldName = checkerName.toUpperCase(Locale.ENGLISH) + "_RANGES";
-        final StringBuilder sb = new StringBuilder();
-
-        // Field to hold the Range objects in an array
-        sb.append("private static final ").append(arrayType(classImporter)).append(' ').append(fieldName).append(";\n");
-
-        // Static initializer block for the array
-        sb.append("static {\n");
-        sb.append("    @SuppressWarnings(\"unchecked\")\n");
-        sb.append("    final ").append(arrayType(classImporter)).append(" a = (").append(arrayType(classImporter))
-            .append(") ").append(classImporter.apply(Array.class)).append(".newInstance(").append(range(classImporter))
-            .append(".class, ").append(constraints.size()).append(");\n");
-
-        int offset = 0;
-        for (Range<? extends Number> r : constraints) {
-            final String min = format(getValue(r.lowerEndpoint()));
-            final String max = format(getValue(r.upperEndpoint()));
-
-            sb.append("    a[").append(offset++).append("] = ").append(range(classImporter)).append(".closed(")
-                .append(min).append(", ").append(max).append(");\n");
-        }
-
-        sb.append("    ").append(fieldName).append(" = a;\n");
-        sb.append("}\n");
-
-        // Static enforcement method
-        sb.append("private static void ").append(checkerName).append("(final ").append(getTypeName())
-            .append(" value) {\n");
-        sb.append("    for (").append(itemType(classImporter)).append(" r : ").append(fieldName).append(") {\n");
-        sb.append("        if (r.contains(value)) {\n");
-        sb.append("            return;\n");
-        sb.append("        }\n");
-        sb.append("    }\n");
-
-        sb.append("    ").append(classImporter.apply(CodeHelpers.class)).append(".throwInvalidRange(").append(fieldName)
-            .append(", value);\n");
-        sb.append("}\n");
-
-        return sb.toString();
-    }
-}
index 0c8fe8e9e4f617638fbcbb2845b07f1f7cf3c9aa..e29a9a16be980e86470d01288cd015e586d8cc01 100644 (file)
@@ -27,7 +27,7 @@ abstract class AbstractPrimitiveRangeGenerator<T extends Number & Comparable<T>>
     private final @NonNull T minValue;
     private final @NonNull T maxValue;
 
-    protected AbstractPrimitiveRangeGenerator(final Class<T> typeClass, final String primitiveName, final T minValue,
+    AbstractPrimitiveRangeGenerator(final Class<T> typeClass, final String primitiveName, final T minValue,
             final T maxValue) {
         super(typeClass);
         this.primitiveName = requireNonNull(primitiveName);
@@ -94,6 +94,15 @@ abstract class AbstractPrimitiveRangeGenerator<T extends Number & Comparable<T>>
         sb.append("value >= ").append(format(min));
     }
 
+    /**
+     * Format a value into a Java-compilable expression which results in the appropriate
+     * type.
+     *
+     * @param value Number value
+     * @return Java language string representation
+     */
+    protected abstract @NonNull String format(T value);
+
     String codeHelpersThrow() {
         return "throwInvalidRange";
     }
index 27c580f9af18f29306e8c8c1a6d111bb7f925863..50e9798df83bff52d216f32320b35ec0169c9736 100644 (file)
@@ -105,15 +105,6 @@ abstract class AbstractRangeGenerator<T extends Number & Comparable<T>> {
     @Deprecated
     protected abstract T convert(Number value);
 
-    /**
-     * Format a value into a Java-compilable expression which results in the appropriate
-     * type.
-     *
-     * @param value Number value
-     * @return Java language string representation
-     */
-    protected abstract @NonNull String format(T value);
-
     /**
      * Generate the checker method source code.
      * @param checkerName Name of the checker method.
index dcb6497a1e72f39f8c302049ef537b3e9a72ff4e..93342e7096e65431dcf63992bc1de3e8f0444dee 100644 (file)
@@ -7,18 +7,41 @@
  */
 package org.opendaylight.mdsal.binding.java.api.generator;
 
+import com.google.common.collect.Range;
+import java.lang.reflect.Array;
+import java.util.Locale;
+import java.util.Set;
+import java.util.function.Function;
+import org.opendaylight.yangtools.yang.binding.CodeHelpers;
 import org.opendaylight.yangtools.yang.common.Decimal64;
 import org.opendaylight.yangtools.yang.common.Uint16;
 import org.opendaylight.yangtools.yang.common.Uint8;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 
-final class Decimal64RangeGenerator extends AbstractBigRangeGenerator<Decimal64> {
+/**
+ * Decimal64 boundary check generator. It requires instantiation of boundary values -- these are implemented by
+ * generating an array constant within the class, which contains {@link Range} instances, which hold pre-instantiated
+ * boundary values.
+ */
+final class Decimal64RangeGenerator extends AbstractRangeGenerator<Decimal64> {
     Decimal64RangeGenerator() {
         super(Decimal64.class);
     }
 
-    @Override
-    protected String format(final Decimal64 value) {
-        return "org.opendaylight.yangtools.yang.common.Decimal64.valueOf(\"" + value + "\")";
+    private static String range(final Function<Class<?>, String> classImporter) {
+        return classImporter.apply(Range.class);
+    }
+
+    private static String itemType(final Function<Class<?>, String> classImporter) {
+        return range(classImporter) + '<' + classImporter.apply(Decimal64.class) + '>';
+    }
+
+    private static String arrayType(final Function<Class<?>, String> classImporter) {
+        return itemType(classImporter) + "[]";
+    }
+
+    private static String format(final Function<Class<?>, String> classImporter, final Decimal64 value) {
+        return classImporter.apply(Decimal64.class) +  ".of(" + value.scale() + ", " + value.unscaledValue() + "L)";
     }
 
     @Override
@@ -33,4 +56,49 @@ final class Decimal64RangeGenerator extends AbstractBigRangeGenerator<Decimal64>
             return Decimal64.valueOf(1, value.longValue());
         }
     }
+
+    @Override
+    protected String generateRangeCheckerImplementation(final String checkerName,
+            final RangeConstraint<?> constraint, final Function<Class<?>, String> classImporter) {
+        final Set<? extends Range<? extends Number>> constraints = constraint.getAllowedRanges().asRanges();
+        final String fieldName = checkerName.toUpperCase(Locale.ENGLISH) + "_RANGES";
+        final StringBuilder sb = new StringBuilder();
+
+        // Field to hold the Range objects in an array
+        sb.append("private static final ").append(arrayType(classImporter)).append(' ').append(fieldName).append(";\n");
+
+        // Static initializer block for the array
+        sb.append("static {\n");
+        sb.append("    @SuppressWarnings(\"unchecked\")\n");
+        sb.append("    final ").append(arrayType(classImporter)).append(" a = (").append(arrayType(classImporter))
+            .append(") ").append(classImporter.apply(Array.class)).append(".newInstance(").append(range(classImporter))
+            .append(".class, ").append(constraints.size()).append(");\n");
+
+        int offset = 0;
+        for (Range<? extends Number> r : constraints) {
+            final String min = format(classImporter, getValue(r.lowerEndpoint()));
+            final String max = format(classImporter, getValue(r.upperEndpoint()));
+
+            sb.append("    a[").append(offset++).append("] = ").append(range(classImporter)).append(".closed(")
+                .append(min).append(", ").append(max).append(");\n");
+        }
+
+        sb.append("    ").append(fieldName).append(" = a;\n");
+        sb.append("}\n");
+
+        // Static enforcement method
+        sb.append("private static void ").append(checkerName).append("(final ").append(getTypeName())
+            .append(" value) {\n");
+        sb.append("    for (").append(itemType(classImporter)).append(" r : ").append(fieldName).append(") {\n");
+        sb.append("        if (r.contains(value)) {\n");
+        sb.append("            return;\n");
+        sb.append("        }\n");
+        sb.append("    }\n");
+
+        sb.append("    ").append(classImporter.apply(CodeHelpers.class)).append(".throwInvalidRange(").append(fieldName)
+            .append(", value);\n");
+        sb.append("}\n");
+
+        return sb.toString();
+    }
 }
index a1c78c89bb11f1fa859ca9d3ac3eca8a1c39aae1..736e052da7b01c747e78fbd786b8612744da94cc 100644 (file)
@@ -8,8 +8,7 @@
 package org.opendaylight.mdsal.binding.java.api.generator;
 
 final class LongRangeGenerator extends AbstractPrimitiveRangeGenerator<Long> {
-
-    protected LongRangeGenerator() {
+    LongRangeGenerator() {
         super(Long.class, long.class.getName(), Long.MIN_VALUE, Long.MAX_VALUE);
     }
 
index 5f96b3ddf52eaaa32a9226b79cb7096aee5c07ba..4fcde3a4a9ca11c38391b2d5e70819ec9c8f8cc6 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.mdsal.binding.java.api.generator;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
 
 import java.math.BigInteger;
 import org.junit.Test;
@@ -25,6 +24,5 @@ public class Decimal64RangeGeneratorTest {
         assertEquals(one, generator.convert(Byte.valueOf("1")));
         assertEquals(one, generator.convert(Short.valueOf("1")));
         assertEquals(one, generator.convert(Integer.valueOf("1")));
-        assertNotNull(generator.format(Decimal64.valueOf("10")));
     }
 }