SingleBound.java

  1. package org.opentrafficsim.base.parameters.constraint;

  2. import org.djunits.value.vdouble.scalar.base.AbstractDoubleScalar;
  3. import org.djutils.exceptions.Throw;

  4. /**
  5.  * Continuous constraints with a single bound. To allow both {@code Double} and {@code AbstractDoubleScalar<?, ?>} constraints,
  6.  * the generic type is restricted to {@code Number}. However, that also allows other subclasses of {@code Number}, e.g.
  7.  * {@code Integer}. Due to rounding and value limits from the type (e.g. {@code Integer.MAX_VALEU}), bounds may not function
  8.  * correctly after a call to {@code Number.doubleValue()}. To restrict the usage, the constructor is private and static factory
  9.  * methods for {@code Double} and {@code AbstractDoubleScalar<?, ?>} are supplied.
  10.  * <p>
  11.  * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  12.  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  13.  * <p>
  14.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version Aug 14, 2017 <br>
  15.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  16.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  17.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  18.  * @param <T> value type
  19.  */
  20. public class SingleBound<T extends Number> implements Constraint<T>
  21. {

  22.     /** The bound. */
  23.     private final Bound bound;

  24.     /** Message about values that do not comply with the bound. */
  25.     private final String failMessage;

  26.     /**
  27.      * Creates a lower inclusive bound; {@code value >= bound}.
  28.      * @param bound double; bound value
  29.      * @return lower inclusive bound
  30.      */
  31.     public static final SingleBound<Double> lowerInclusive(final double bound)
  32.     {
  33.         return createLowerInclusive(bound);
  34.     }

  35.     /**
  36.      * Creates a lower inclusive bound; {@code value >= bound}.
  37.      * @param bound T; bound value
  38.      * @param <T> value type
  39.      * @return lower inclusive bound
  40.      */
  41.     public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> lowerInclusive(final T bound)
  42.     {
  43.         return createLowerInclusive(bound);
  44.     }

  45.     /**
  46.      * Creates a lower inclusive bound; {@code value >= bound}.
  47.      * @param bound T; bound value
  48.      * @param <T> value type
  49.      * @return lower inclusive bound
  50.      */
  51.     private static <T extends Number> SingleBound<T> createLowerInclusive(final T bound)
  52.     {
  53.         return new SingleBound<>(new LowerBoundInclusive<>(bound),
  54.                 String.format("Value is not greater than or equal to %s", bound));
  55.     }

  56.     /**
  57.      * Creates a lower exclusive bound; {@code value > bound}.
  58.      * @param bound double; bound value
  59.      * @return lower exclusive bound
  60.      */
  61.     public static final SingleBound<Double> lowerExclusive(final double bound)
  62.     {
  63.         return createLowerExclusive(bound);
  64.     }

  65.     /**
  66.      * Creates a lower exclusive bound; {@code value > bound}.
  67.      * @param bound T; bound value
  68.      * @param <T> value type
  69.      * @return lower exclusive bound
  70.      */
  71.     public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> lowerExclusive(final T bound)
  72.     {
  73.         return createLowerExclusive(bound);
  74.     }

  75.     /**
  76.      * Creates a lower exclusive bound; {@code value > bound}.
  77.      * @param bound T; bound value
  78.      * @param <T> value type
  79.      * @return lower exclusive bound
  80.      */
  81.     private static <T extends Number> SingleBound<T> createLowerExclusive(final T bound)
  82.     {
  83.         return new SingleBound<>(new LowerBoundExclusive<>(bound), String.format("Value is not greater than %s", bound));
  84.     }

  85.     /**
  86.      * Creates an upper inclusive bound; {@code value <= bound}.
  87.      * @param bound double; bound value
  88.      * @return upper inclusive bound
  89.      */
  90.     public static final SingleBound<Double> upperInclusive(final double bound)
  91.     {
  92.         return createUpperInclusive(bound);
  93.     }

  94.     /**
  95.      * Creates an upper inclusive bound; {@code value <= bound}.
  96.      * @param bound T; bound value
  97.      * @return upper inclusive bound
  98.      * @param <T> value type
  99.      */
  100.     public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> upperInclusive(final T bound)
  101.     {
  102.         return createUpperInclusive(bound);
  103.     }

  104.     /**
  105.      * Creates an upper inclusive bound; {@code value <= bound}.
  106.      * @param bound T; bound value
  107.      * @param <T> value type
  108.      * @return upper inclusive bound
  109.      */
  110.     private static <T extends Number> SingleBound<T> createUpperInclusive(final T bound)
  111.     {
  112.         return new SingleBound<>(new UpperBoundInclusive<>(bound),
  113.                 String.format("Value is not smaller than or equal to %s", bound));
  114.     }

  115.     /**
  116.      * Creates an upper exclusive bound; {@code value < bound}.
  117.      * @param bound double; bound value
  118.      * @return upper exclusive bound
  119.      */
  120.     public static final SingleBound<Double> upperExclusive(final double bound)
  121.     {
  122.         return createUpperExclusive(bound);
  123.     }

  124.     /**
  125.      * Creates an upper exclusive bound; {@code value < bound}.
  126.      * @param bound T; bound value
  127.      * @param <T> value type
  128.      * @return upper exclusive bound
  129.      */
  130.     public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> upperExclusive(final T bound)
  131.     {
  132.         return createUpperExclusive(bound);
  133.     }

  134.     /**
  135.      * Creates an upper exclusive bound; {@code value < bound}.
  136.      * @param bound T; bound value
  137.      * @param <T> value type
  138.      * @return upper exclusive bound
  139.      */
  140.     private static <T extends Number> SingleBound<T> createUpperExclusive(final T bound)
  141.     {
  142.         return new SingleBound<>(new UpperBoundExclusive<>(bound), String.format("Value is not smaller than %s", bound));
  143.     }

  144.     /**
  145.      * Constructor.
  146.      * @param bound Bound; bound
  147.      * @param failMessage String; message about values that do not comply with the bound
  148.      */
  149.     SingleBound(final Bound bound, final String failMessage)
  150.     {
  151.         this.bound = bound;
  152.         this.failMessage = failMessage;
  153.     }

  154.     /** {@inheritDoc} */
  155.     @Override
  156.     public boolean accept(final T value)
  157.     {
  158.         return this.bound.accept(value);
  159.     }

  160.     /** {@inheritDoc} */
  161.     @Override
  162.     public String failMessage()
  163.     {
  164.         return this.failMessage;
  165.     }

  166.     /**
  167.      * @return bound.
  168.      */
  169.     public Bound getBound()
  170.     {
  171.         return this.bound;
  172.     }

  173.     /**
  174.      * Super class for classes that implement a specific numeric check.
  175.      * <p>
  176.      * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  177.      * <br>
  178.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  179.      * <p>
  180.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
  181.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  182.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  183.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  184.      */
  185.     abstract static class Bound
  186.     {

  187.         /** Value of the bound. */
  188.         @SuppressWarnings("checkstyle:visibilitymodifier")
  189.         final Number bound;

  190.         /** Hashcode of the value class. */
  191.         @SuppressWarnings("checkstyle:visibilitymodifier")
  192.         final int classHashcode;

  193.         /** String representation of this bound with %s for the value. */
  194.         private final String stringFormat;

  195.         /**
  196.          * Constructor.
  197.          * @param bound Number; value of the bound
  198.          * @param stringFormat String; string representation of this bound with %s for the value
  199.          */
  200.         Bound(final Number bound, final String stringFormat)
  201.         {
  202.             Throw.whenNull(bound, "Bound may not be null.");
  203.             Throw.whenNull(bound, "String format may not be null.");
  204.             Throw.when(Double.isNaN(bound.doubleValue()), IllegalArgumentException.class, "Bound value may not be NaN.");
  205.             this.bound = bound;
  206.             this.classHashcode = bound.getClass().hashCode();
  207.             this.stringFormat = stringFormat;
  208.         }

  209.         /**
  210.          * Returns true if the bound accepts the value.
  211.          * @param value Number; the value to check
  212.          * @return true if the bound accepts the value
  213.          */
  214.         abstract boolean accept(Number value);

  215.         /** {@inheritDoc} */
  216.         @Override
  217.         public final String toString()
  218.         {
  219.             return String.format(this.stringFormat, this.bound);
  220.         }
  221.     }

  222.     /**
  223.      * Class implementing a lower inclusive bound; {@code value >= bound}.
  224.      * <p>
  225.      * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  226.      * <br>
  227.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  228.      * <p>
  229.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
  230.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  231.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  232.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  233.      * @param <T> value type
  234.      */
  235.     static class LowerBoundInclusive<T extends Number> extends Bound
  236.     {

  237.         /**
  238.          * Constructor.
  239.          * @param bound T; bound
  240.          */
  241.         LowerBoundInclusive(final T bound)
  242.         {
  243.             super(bound, "%s <= value");
  244.         }

  245.         /** {@inheritDoc} */
  246.         @Override
  247.         protected boolean accept(final Number value)
  248.         {
  249.             return this.bound.doubleValue() <= value.doubleValue();
  250.         }

  251.     }

  252.     /**
  253.      * Class implementing a lower exclusive bound; {@code value > bound}.
  254.      * <p>
  255.      * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  256.      * <br>
  257.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  258.      * <p>
  259.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
  260.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  261.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  262.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  263.      * @param <T> value type
  264.      */
  265.     static class LowerBoundExclusive<T extends Number> extends Bound
  266.     {

  267.         /**
  268.          * Constructor.
  269.          * @param bound T; bound
  270.          */
  271.         LowerBoundExclusive(final T bound)
  272.         {
  273.             super(bound, "%s < value");
  274.         }

  275.         /** {@inheritDoc} */
  276.         @Override
  277.         protected boolean accept(final Number value)
  278.         {
  279.             return this.bound.doubleValue() < value.doubleValue();
  280.         }

  281.     }

  282.     /**
  283.      * Class implementing an upper inclusive bound; {@code value <= bound}.
  284.      * <p>
  285.      * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  286.      * <br>
  287.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  288.      * <p>
  289.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
  290.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  291.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  292.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  293.      * @param <T> value type
  294.      */
  295.     static class UpperBoundInclusive<T extends Number> extends Bound
  296.     {

  297.         /**
  298.          * Constructor.
  299.          * @param bound T; bound
  300.          */
  301.         UpperBoundInclusive(final T bound)
  302.         {
  303.             super(bound, "value <= %s");
  304.         }

  305.         /** {@inheritDoc} */
  306.         @Override
  307.         protected boolean accept(final Number value)
  308.         {
  309.             return this.bound.doubleValue() >= value.doubleValue();
  310.         }

  311.     }

  312.     /**
  313.      * Class implementing an upper exclusive bound; {@code value < bound}.
  314.      * <p>
  315.      * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  316.      * <br>
  317.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  318.      * <p>
  319.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
  320.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  321.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  322.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  323.      * @param <T> value type
  324.      */
  325.     static class UpperBoundExclusive<T extends Number> extends Bound
  326.     {

  327.         /**
  328.          * Constructor.
  329.          * @param bound T; bound
  330.          */
  331.         UpperBoundExclusive(final T bound)
  332.         {
  333.             super(bound, "value < %s");
  334.         }

  335.         /** {@inheritDoc} */
  336.         @Override
  337.         protected boolean accept(final Number value)
  338.         {
  339.             return this.bound.doubleValue() > value.doubleValue();
  340.         }

  341.     }

  342.     /** {@inheritDoc} */
  343.     @Override
  344.     public String toString()
  345.     {
  346.         return "SingleBound [" + this.bound + "]";
  347.     }

  348. }