Propagate namespaceContext/mathSupport to FunctionSupport 23/80623/5
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 27 Feb 2019 12:50:00 +0000 (13:50 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 27 Feb 2019 15:29:16 +0000 (16:29 +0100)
A number of operations in Functions requires either mathSupport
or namespaceContext to work correctly. This patch makes sure it
is available.

Change-Id: Icdbf6eda25017f9c921d2009b52e1fa012d08033
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-xpath-api/src/main/java/org/opendaylight/yangtools/yang/xpath/api/BigDecimalXPathMathSupport.java
yang/yang-xpath-api/src/main/java/org/opendaylight/yangtools/yang/xpath/api/DoubleXPathMathSupport.java
yang/yang-xpath-api/src/main/java/org/opendaylight/yangtools/yang/xpath/api/YangBooleanConstantExpr.java
yang/yang-xpath-api/src/main/java/org/opendaylight/yangtools/yang/xpath/api/YangXPathMathSupport.java
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/AntlrXPathParser.java
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/FunctionSupport.java [moved from yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/Functions.java with 86% similarity]
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/InstanceIdentifierParser.java

index 34d4829675a9879250ae00c1cab14facdfd2d24e..5c3c117c83091ff0d5fb490d33d552d95018cd3d 100644 (file)
@@ -37,6 +37,20 @@ final class BigDecimalXPathMathSupport extends AbstractYangXPathMathSupport<BigD
         }
     }
 
+    @Override
+    public BigDecimalNumberExpr createNumber(final int value) {
+        switch (value) {
+            case 0:
+                return ZERO;
+            case 1:
+                return ONE;
+            case 10:
+                return TEN;
+            default:
+                return BigDecimalNumberExpr.of(BigDecimal.valueOf(value));
+        }
+    }
+
     @Override
     BigDecimalNumberExpr doNegate(final BigDecimalNumberExpr number) {
         return BigDecimalNumberExpr.of(number.getNumber().negate());
index fb396efd2598b1b85bbc30a81232f1e0695aa104..97e76474ebc01b366d3a8a9a0468b2bc3bfcf35c 100644 (file)
@@ -23,6 +23,11 @@ final class DoubleXPathMathSupport extends AbstractYangXPathMathSupport<DoubleNu
         return DoubleNumberExpr.of(Double.parseDouble(str));
     }
 
+    @Override
+    public DoubleNumberExpr createNumber(final int value) {
+        return DoubleNumberExpr.of(value);
+    }
+
     @Override
     DoubleNumberExpr doNegate(final DoubleNumberExpr number) {
         return DoubleNumberExpr.of(-number.getValue());
index cd7f8d77faf5a07a1b6e5708931412d700f2012d..85c4327dcec6c56def8f7925c54202db899dd7c1 100644 (file)
@@ -29,19 +29,21 @@ public enum YangBooleanConstantExpr implements YangConstantExpr<Boolean> {
     /**
      * A constant {@code false} expression.
      */
-    FALSE(Boolean.FALSE, YangFunction.FALSE),
+    FALSE(Boolean.FALSE, YangFunction.FALSE, "false"),
     /**
      * A constant {@code true} expression.
      */
-    TRUE(Boolean.TRUE, YangFunction.TRUE);
+    TRUE(Boolean.TRUE, YangFunction.TRUE, "true");
 
     private final YangFunctionCallExpr function;
+    private final YangLiteralExpr literal;
     private final Boolean value;
 
     @SuppressWarnings("null")
-    YangBooleanConstantExpr(final @Nullable Boolean value, final YangFunction function) {
+    YangBooleanConstantExpr(final @Nullable Boolean value, final YangFunction function, final String literal) {
         this.value = requireNonNull(value);
         this.function = YangFunctionCallExpr.of(function.getIdentifier());
+        this.literal = YangLiteralExpr.of(literal);
     }
 
     @Override
@@ -63,6 +65,16 @@ public enum YangBooleanConstantExpr implements YangConstantExpr<Boolean> {
         return function;
     }
 
+    /**
+     * Convert this constant into a string literal, i.e. the result of calling {@code string(boolean)} function on this
+     * constant.
+     *
+     * @return Literal expression.
+     */
+    public YangLiteralExpr asStringLiteral() {
+        return literal;
+    }
+
     public static YangBooleanConstantExpr of(final boolean bool) {
         return bool ? TRUE : FALSE;
     }
index 20ee96b31bb6b818d515453dea6f8d0dad4e068d..9dd1f8c98504568f7dd6861c6a9beb2a4e3af526 100644 (file)
@@ -22,6 +22,14 @@ public interface YangXPathMathSupport<N extends YangNumberExpr<N, ?>> {
      */
     N createNumber(String str);
 
+    /**
+     * Create a {@link YangNumberExpr} for specified integer.
+     *
+     * @param value integer value
+     * @return number expression
+     */
+    N createNumber(int value);
+
     /**
      * Create a {@link YangNumberExpr} representing the negated value of a number.
      *
index 2b53a3b2f9f769bedee01d387d639f32b3dc1b5d..f3e9a0998ee428412200120093a9ffb84e2173c4 100644 (file)
@@ -118,11 +118,13 @@ final class AntlrXPathParser implements YangXPathParser {
     private final YangXPathMathMode mathMode;
     private final YangXPathMathSupport<?> mathSupport;
     private final YangNamespaceContext namespaceContext;
+    private final FunctionSupport functionSupport;
 
     AntlrXPathParser(final YangXPathMathMode mathMode, final YangNamespaceContext namespaceContext) {
         this.mathMode = requireNonNull(mathMode);
         this.mathSupport = mathMode.getSupport();
         this.namespaceContext = requireNonNull(namespaceContext);
+        this.functionSupport = new FunctionSupport(namespaceContext, mathSupport);
     }
 
     @Override
@@ -232,7 +234,7 @@ final class AntlrXPathParser implements YangXPathParser {
         final List<YangExpr> args = ImmutableList.copyOf(Lists.transform(expr.expr(), this::parseExpr));
         final YangFunction func = YANG_FUNCTIONS.get(parsed);
         if (func != null) {
-            return Functions.functionToExpr(func, args);
+            return functionSupport.functionToExpr(func, args);
         }
 
         checkArgument(!YangConstants.RFC6020_YIN_MODULE.equals(parsed.getModule()), "Unknown default function %s",
similarity index 86%
rename from yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/Functions.java
rename to yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/FunctionSupport.java
index dc673978c90d3b154428b9d3dee16cb5ae8f3b37..b12ba65835c9be32fdaba2a58435bce51fb99a92 100644 (file)
@@ -8,16 +8,24 @@
 package org.opendaylight.yangtools.yang.xpath.impl;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
 
 import java.util.List;
+import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
 import org.opendaylight.yangtools.yang.xpath.api.YangBooleanConstantExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangFunction;
 import org.opendaylight.yangtools.yang.xpath.api.YangFunctionCallExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangLiteralExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangNumberExpr;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathMathSupport;
+
+/**
+ * This class provides support for validating function call arguments as well as compile-time evaluation.
+ */
+final class FunctionSupport {
+    static final YangFunctionCallExpr POSITION = YangFunctionCallExpr.of(YangFunction.POSITION.getIdentifier());
 
-final class Functions {
     private static final YangFunctionCallExpr CURRENT = YangFunctionCallExpr.of(YangFunction.CURRENT.getIdentifier());
     private static final YangFunctionCallExpr LAST = YangFunctionCallExpr.of(YangFunction.LAST.getIdentifier());
     private static final YangFunctionCallExpr LOCAL_NAME = YangFunctionCallExpr.of(
@@ -28,16 +36,19 @@ final class Functions {
     private static final YangFunctionCallExpr NORMALIZE_SPACE = YangFunctionCallExpr.of(
         YangFunction.NORMALIZE_SPACE.getIdentifier());
     private static final YangFunctionCallExpr NUMBER = YangFunctionCallExpr.of(YangFunction.NUMBER.getIdentifier());
-    static final YangFunctionCallExpr POSITION = YangFunctionCallExpr.of(YangFunction.POSITION.getIdentifier());
     private static final YangFunctionCallExpr STRING = YangFunctionCallExpr.of(YangFunction.STRING.getIdentifier());
     private static final YangFunctionCallExpr STRING_LENGTH = YangFunctionCallExpr.of(
         YangFunction.STRING_LENGTH.getIdentifier());
 
-    private Functions() {
+    private final YangXPathMathSupport<?> mathSupport;
+    private final YangNamespaceContext namespaceContext;
 
+    FunctionSupport(final YangNamespaceContext namespaceContext, final YangXPathMathSupport<?> mathSupport) {
+        this.namespaceContext = requireNonNull(namespaceContext);
+        this.mathSupport = requireNonNull(mathSupport);
     }
 
-    static YangExpr functionToExpr(final YangFunction func, final List<YangExpr> args) {
+    YangExpr functionToExpr(final YangFunction func, final List<YangExpr> args) {
         switch (func) {
             case BIT_IS_SET:
                 checkArgument(args.size() == 2, "bit-is-set(node-set, string) takes two arguments");
@@ -158,9 +169,11 @@ final class Functions {
             return arg;
         }
         if (arg instanceof YangLiteralExpr) {
-            return YangBooleanConstantExpr.of(((YangLiteralExpr) arg).getLiteral().isEmpty());
+            return YangBooleanConstantExpr.of(!((YangLiteralExpr) arg).getLiteral().isEmpty());
         }
+
         // TODO: handling YangNumberExpr requires math support
+
         return YangFunctionCallExpr.of(YangFunction.BOOLEAN.getIdentifier(), args);
     }
 
@@ -210,7 +223,7 @@ final class Functions {
     }
 
     private static YangExpr normalizeSpaceExpr(final List<YangExpr> args) {
-        checkArgument(args.size() <= 1, "number(object?) takes at most one argument");
+        checkArgument(args.size() <= 1, "normalize-space(object?) takes at most one argument");
         if (args.isEmpty()) {
             return NORMALIZE_SPACE;
         }
@@ -222,7 +235,7 @@ final class Functions {
         return YangFunctionCallExpr.of(YangFunction.NORMALIZE_SPACE.getIdentifier(), args);
     }
 
-    private static YangExpr numberExpr(final List<YangExpr> args) {
+    private YangExpr numberExpr(final List<YangExpr> args) {
         checkArgument(args.size() <= 1, "number(object?) takes at most one argument");
         if (args.isEmpty()) {
             return NUMBER;
@@ -232,8 +245,14 @@ final class Functions {
         if (arg instanceof YangNumberExpr) {
             return arg;
         }
+        if (arg instanceof YangLiteralExpr) {
+            return mathSupport.createNumber(((YangLiteralExpr) arg).getLiteral());
+        }
+        if (arg instanceof YangBooleanConstantExpr) {
+            final boolean value = ((YangBooleanConstantExpr) arg).getValue();
+            return mathSupport.createNumber(value ? 1 : 0);
+        }
 
-        // TODO: constant literal folding requires math support
         return YangFunctionCallExpr.of(YangFunction.NUMBER.getIdentifier(), args);
     }
 
@@ -280,18 +299,27 @@ final class Functions {
         if (arg instanceof YangLiteralExpr) {
             return arg;
         }
+        if (arg instanceof YangBooleanConstantExpr) {
+            return ((YangBooleanConstantExpr) arg).asStringLiteral();
+        }
 
         // TODO: handling YangNumberExpr requires math support
         return YangFunctionCallExpr.of(YangFunction.STRING.getIdentifier(), args);
     }
 
-    private static YangExpr stringLengthExpr(final List<YangExpr> args) {
-        checkArgument(args.size() <= 1, "string(object?) takes at most one argument");
+    private YangExpr stringLengthExpr(final List<YangExpr> args) {
+        checkArgument(args.size() <= 1, "string-length(object?) takes at most one argument");
         if (args.isEmpty()) {
             return STRING_LENGTH;
         }
 
-        // TODO: constant literal requires math support
+        YangExpr first = args.get(0);
+        if (first instanceof YangBooleanConstantExpr) {
+            first = ((YangBooleanConstantExpr) first).asStringLiteral();
+        }
+        if (first instanceof YangLiteralExpr) {
+            return mathSupport.createNumber(((YangLiteralExpr) first).getLiteral().length());
+        }
 
         return YangFunctionCallExpr.of(YangFunction.STRING_LENGTH.getIdentifier(), args);
     }
index cc6b3d8d0536867b5447f519dd9a46d51e795b7e..edc5653d22ddb8625fe8d2354720b27877225790 100644 (file)
@@ -90,8 +90,9 @@ final class InstanceIdentifierParser {
                 parseEqStringValue(getChild(((LeafListPredicateContext) first)
                     .getChild(LeafListPredicateExprContext.class, 0), EqQuotedStringContext.class, 1))));
         } else if (first instanceof PosContext) {
-            return ImmutableSet.of(YangBinaryOperator.EQUALS.exprWith(Functions.POSITION, mathSupport.createNumber(
-                ((PosContext) first).getToken(instanceIdentifierParser.PositiveIntegerValue, 0).getText())));
+            return ImmutableSet.of(YangBinaryOperator.EQUALS.exprWith(FunctionSupport.POSITION,
+                mathSupport.createNumber(((PosContext) first).getToken(instanceIdentifierParser.PositiveIntegerValue, 0)
+                    .getText())));
         }
 
         final int length = expr.getChildCount();