import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
+import com.google.common.annotations.Beta;
import java.util.Optional;
-abstract class AbstractYangXPathMathSupport<N extends YangNumberExpr<N, ?>> implements YangXPathMathSupport<N> {
+/**
+ * Type-safe shim to ensure concrete {@link YangXPathMathSupport} implementations get handed properly-typed
+ * YangNumberExprs.
+ *
+ * @param <N> Type of YangNumberExpr
+ * @author Robert Varga
+ */
+@Beta
+public abstract class AbstractYangXPathMathSupport<N extends YangNumberExpr> implements YangXPathMathSupport {
private final Class<N> numberClass;
- AbstractYangXPathMathSupport(final Class<N> numberClass) {
+ protected AbstractYangXPathMathSupport(final Class<N> numberClass) {
this.numberClass = requireNonNull(numberClass);
}
@Override
- public final N negateNumber(final YangNumberExpr<?, ?> number) {
+ public final N negateNumber(final YangNumberExpr number) {
checkArgument(numberClass.isInstance(requireNonNull(number)), "Expected %s have %s", numberClass, number);
- return doNegate(numberClass.cast(number));
+ return doNegateNumber(numberClass.cast(number));
}
-
@Override
- public final Optional<YangExpr> tryEvaluate(final YangBinaryOperator operator,
- final YangNumberExpr<?, ?> left, final YangNumberExpr<?, ?> right) {
+ public final Optional<YangExpr> tryEvaluate(final YangBinaryOperator operator, final YangNumberExpr left,
+ final YangNumberExpr right) {
if (!numberClass.isInstance(left) || !numberClass.isInstance(right)) {
requireNonNull(operator);
requireNonNull(left);
return Optional.empty();
}
- return Optional.of(evaluate(requireNonNull(operator), numberClass.cast(left), numberClass.cast(right)));
+ return Optional.of(doEvaluate(requireNonNull(operator), numberClass.cast(left), numberClass.cast(right)));
}
- abstract N doNegate(N number);
+ /**
+ * Create a {@link YangNumberExpr} representing the negated value of a number.
+ *
+ * @param number input number
+ * @return negated number expression
+ */
+ protected abstract N doNegateNumber(N number);
/**
* Evaluate an operator and its left- and right-handside.
* @param right Right hand-side
* @return Evaluation result
*/
- abstract YangExpr evaluate(YangBinaryOperator operator, N left, N right);
+ protected abstract YangExpr doEvaluate(YangBinaryOperator operator, N left, N right);
}
import java.math.BigDecimal;
import org.eclipse.jdt.annotation.Nullable;
-final class BigDecimalNumberExpr extends YangNumberExpr<BigDecimalNumberExpr, BigDecimal> {
+final class BigDecimalNumberExpr extends YangNumberExpr {
private static final long serialVersionUID = 1L;
private final BigDecimal number;
@Override
public BigDecimalXPathMathSupport getSupport() {
- return BigDecimalXPathMathSupport.getInstance();
+ return BigDecimalXPathMathSupport.INSTANCE;
}
@Override
import java.math.BigDecimal;
final class BigDecimalXPathMathSupport extends AbstractYangXPathMathSupport<BigDecimalNumberExpr> {
- private static final BigDecimalXPathMathSupport INSTANCE = new BigDecimalXPathMathSupport();
+ static final BigDecimalXPathMathSupport INSTANCE = new BigDecimalXPathMathSupport();
+
private static final BigDecimalNumberExpr ZERO = BigDecimalNumberExpr.of(BigDecimal.ZERO);
private static final BigDecimalNumberExpr ONE = BigDecimalNumberExpr.of(BigDecimal.ONE);
private static final BigDecimalNumberExpr TEN = BigDecimalNumberExpr.of(BigDecimal.TEN);
super(BigDecimalNumberExpr.class);
}
- static BigDecimalXPathMathSupport getInstance() {
- return INSTANCE;
- }
-
@Override
public BigDecimalNumberExpr createNumber(final String str) {
switch (str) {
}
@Override
- BigDecimalNumberExpr doNegate(final BigDecimalNumberExpr number) {
+ protected BigDecimalNumberExpr doNegateNumber(final BigDecimalNumberExpr number) {
return BigDecimalNumberExpr.of(number.getNumber().negate());
}
@Override
- YangExpr evaluate(final YangBinaryOperator operator, final BigDecimalNumberExpr left,
+ protected YangExpr doEvaluate(final YangBinaryOperator operator, final BigDecimalNumberExpr left,
final BigDecimalNumberExpr right) {
final BigDecimal l = left.getNumber();
final BigDecimal r = right.getNumber();
*/
package org.opendaylight.yangtools.yang.xpath.api;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.eclipse.jdt.annotation.Nullable;
-final class DoubleNumberExpr extends YangNumberExpr<DoubleNumberExpr, Double> {
+final class DoubleNumberExpr extends YangNumberExpr {
private static final long serialVersionUID = 1L;
private final double value;
@Override
public DoubleXPathMathSupport getSupport() {
- return DoubleXPathMathSupport.getInstance();
+ return DoubleXPathMathSupport.INSTANCE;
}
@Override
}
@Override
- @SuppressFBWarnings(value = "FE_FLOATING_POINT_EQUALITY", justification = "")
public boolean equals(final @Nullable Object obj) {
return this == obj || obj instanceof DoubleNumberExpr && bitEqual(((DoubleNumberExpr) obj).value);
}
public String toString() {
return String.valueOf(value);
}
-
-}
\ No newline at end of file
+}
package org.opendaylight.yangtools.yang.xpath.api;
final class DoubleXPathMathSupport extends AbstractYangXPathMathSupport<DoubleNumberExpr> {
- private static final DoubleXPathMathSupport INSTANCE = new DoubleXPathMathSupport();
+ static final DoubleXPathMathSupport INSTANCE = new DoubleXPathMathSupport();
private DoubleXPathMathSupport() {
super(DoubleNumberExpr.class);
}
- static DoubleXPathMathSupport getInstance() {
- return INSTANCE;
- }
-
@Override
public DoubleNumberExpr createNumber(final String str) {
return DoubleNumberExpr.of(Double.parseDouble(str));
}
@Override
- DoubleNumberExpr doNegate(final DoubleNumberExpr number) {
+ protected DoubleNumberExpr doNegateNumber(final DoubleNumberExpr number) {
return DoubleNumberExpr.of(-number.getValue());
}
@Override
- YangExpr evaluate(final YangBinaryOperator operator, final DoubleNumberExpr left, final DoubleNumberExpr right) {
+ protected YangExpr doEvaluate(final YangBinaryOperator operator, final DoubleNumberExpr left,
+ final DoubleNumberExpr right) {
final double l = left.getValue();
final double r = right.getValue();
package org.opendaylight.yangtools.yang.xpath.api;
import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.Nullable;
/**
* A number-bearing expression.
*/
@Beta
-public abstract class YangNumberExpr<T extends YangNumberExpr<T, N>, N extends Number> implements YangExpr {
+public abstract class YangNumberExpr implements YangExpr {
private static final long serialVersionUID = 1L;
YangNumberExpr() {
// Hidden to prevent external subclassing
}
- public abstract N getNumber();
+ public abstract Number getNumber();
- public abstract YangXPathMathSupport<T> getSupport();
+ public abstract YangXPathMathSupport getSupport();
+
+ @Override
+ public abstract int hashCode();
+
+ @Override
+ public abstract boolean equals(@Nullable Object obj);
}
* All number expressions are treated as {@code double}. This in spirit of XPath 1.0 -- any number expression
* starts its life as a double, making all operations subject to IEEE754 rounding and range rules.
*/
- IEEE754(DoubleXPathMathSupport.getInstance()),
+ IEEE754(DoubleXPathMathSupport.INSTANCE),
/**
* All number expressions are treated as infinite-precision numbers. This follows the spirit of YANG 1.1 --
* where mostly have integral types and decimal64 mapped to BigDecimal. Non-decimal numbers are mapped either to
* {@code int}, {@code long} or {@code BigInteger}.
*/
- EXACT(BigDecimalXPathMathSupport.getInstance());
+ EXACT(BigDecimalXPathMathSupport.INSTANCE);
/*
* FIXME: 3.0.0: specify and implement this:
*/
// ODL_COMMON;
- private YangXPathMathSupport<?> support;
+ private YangXPathMathSupport support;
- YangXPathMathMode(final YangXPathMathSupport<?> support) {
+ YangXPathMathMode(final YangXPathMathSupport support) {
this.support = requireNonNull(support);
}
*
* @return YangXPathMathSupport supporting this mode.
*/
- public YangXPathMathSupport<?> getSupport() {
+ public YangXPathMathSupport getSupport() {
return support;
}
}
import com.google.common.annotations.Beta;
import java.util.Optional;
+/**
+ * Interface supporting mathematical operations. This interface should be implemented by subclassing
+ * {@link AbstractYangXPathMathSupport}, which provides type safety guards.
+ *
+ * @author Robert Varga
+ */
@Beta
-public interface YangXPathMathSupport<N extends YangNumberExpr<N, ?>> {
+public interface YangXPathMathSupport {
/**
* Create a {@link YangNumberExpr} backed by specified string.
*
* @throws NullPointerException if {@code str} is null
* @throws NumberFormatException if the string does not represent a valid number
*/
- N createNumber(String str);
+ YangNumberExpr createNumber(String str);
/**
* Create a {@link YangNumberExpr} for specified integer.
* @param value integer value
* @return number expression
*/
- N createNumber(int value);
+ YangNumberExpr createNumber(int value);
/**
* Create a {@link YangNumberExpr} representing the negated value of a number.
* @throws NullPointerException if {@code number} is null
* @throws IllegalArgumentException if {@code number} has unrecognized type
*/
- N negateNumber(YangNumberExpr<?, ?> number);
+ YangNumberExpr negateNumber(YangNumberExpr number);
/**
* Attempt to evaluate an operator and its left- and right-handside.
* @return Evaluation result, if evaluation succeeded
* @throws NullPointerException if any of the arguments is null
*/
- Optional<YangExpr> tryEvaluate(YangBinaryOperator operator, YangNumberExpr<?, ?> left, YangNumberExpr<?, ?> right);
+ Optional<YangExpr> tryEvaluate(YangBinaryOperator operator, YangNumberExpr left, YangNumberExpr right);
}
private static final AxisStep SELF_STEP = YangXPathAxis.SELF.asStep();
private final YangXPathMathMode mathMode;
- private final YangXPathMathSupport<?> mathSupport;
+ private final YangXPathMathSupport mathSupport;
private final YangNamespaceContext namespaceContext;
private final FunctionSupport functionSupport;
// Even number of '-' tokens cancel out
return ret;
}
-
- return ret instanceof YangNumberExpr ? mathSupport.negateNumber((YangNumberExpr<?, ?>) ret)
- : YangNegateExpr.of(ret);
+ return ret instanceof YangNumberExpr ? mathSupport.negateNumber((YangNumberExpr) ret) : YangNegateExpr.of(ret);
}
private YangExpr parseUnion(final UnionExprNoRootContext expr) {
final YangExpr right) {
if (left instanceof YangNumberExpr && right instanceof YangNumberExpr) {
// Constant folding on numbers -- precision plays a role here
- return mathSupport.tryEvaluate(operator, (YangNumberExpr<?, ?>)left, (YangNumberExpr<?, ?>)right);
+ return mathSupport.tryEvaluate(operator, (YangNumberExpr)left, (YangNumberExpr)right);
}
return Optional.empty();
}
private static final YangFunctionCallExpr STRING_LENGTH = YangFunctionCallExpr.of(
YangFunction.STRING_LENGTH.getIdentifier());
- private final YangXPathMathSupport<?> mathSupport;
+ private final YangXPathMathSupport mathSupport;
private final YangNamespaceContext namespaceContext;
- FunctionSupport(final YangNamespaceContext namespaceContext, final YangXPathMathSupport<?> mathSupport) {
+ FunctionSupport(final YangNamespaceContext namespaceContext, final YangXPathMathSupport mathSupport) {
this.namespaceContext = requireNonNull(namespaceContext);
this.mathSupport = requireNonNull(mathSupport);
}
import org.opendaylight.yangtools.yang.xpath.impl.instanceIdentifierParser.QuotedStringContext;
final class InstanceIdentifierParser {
-
private final YangNamespaceContext namespaceContext;
- private final YangXPathMathSupport<?> mathSupport;
+ private final YangXPathMathSupport mathSupport;
InstanceIdentifierParser(final YangNamespaceContext namespaceContext, final YangXPathMathMode mathMode) {
this.namespaceContext = requireNonNull(namespaceContext);