View Javadoc
1   package org.opentrafficsim.base.parameters.constraint;
2   
3   import org.djunits.value.vdouble.scalar.AbstractDoubleScalar;
4   import org.djutils.exceptions.Throw;
5   
6   /**
7    * Continuous constraints with a single bound. To allow both {@code Double} and {@code AbstractDoubleScalar<?, ?>} constraints,
8    * the generic type is restricted to {@code Number}. However, that also allows other subclasses of {@code Number}, e.g.
9    * {@code Integer}. Due to rounding and value limits from the type (e.g. {@code Integer.MAX_VALEU}), bounds may not function
10   * correctly after a call to {@code Number.doubleValue()}. To restrict the usage, the constructor is private and static factory
11   * methods for {@code Double} and {@code AbstractDoubleScalar<?, ?>} are supplied.
12   * <p>
13   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
15   * <p>
16   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Aug 14, 2017 <br>
17   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
18   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
19   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
20   * @param <T> value type
21   */
22  public class SingleBound<T extends Number> implements Constraint<T>
23  {
24  
25      /** The bound. */
26      private final Bound bound;
27  
28      /** Message about values that do not comply with the bound. */
29      private final String failMessage;
30  
31      /**
32       * Creates a lower inclusive bound; {@code value >= bound}.
33       * @param bound double; bound value
34       * @return lower inclusive bound
35       */
36      public static final SingleBound<Double> lowerInclusive(final double bound)
37      {
38          return createLowerInclusive(bound);
39      }
40  
41      /**
42       * Creates a lower inclusive bound; {@code value >= bound}.
43       * @param bound T; bound value
44       * @param <T> value type
45       * @return lower inclusive bound
46       */
47      public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> lowerInclusive(final T bound)
48      {
49          return createLowerInclusive(bound);
50      }
51  
52      /**
53       * Creates a lower inclusive bound; {@code value >= bound}.
54       * @param bound T; bound value
55       * @param <T> value type
56       * @return lower inclusive bound
57       */
58      private static <T extends Number> SingleBound<T> createLowerInclusive(final T bound)
59      {
60          return new SingleBound<>(new LowerBoundInclusive<>(bound),
61                  String.format("Value is not greater than or equal to %s", bound));
62      }
63  
64      /**
65       * Creates a lower exclusive bound; {@code value > bound}.
66       * @param bound double; bound value
67       * @return lower exclusive bound
68       */
69      public static final SingleBound<Double> lowerExclusive(final double bound)
70      {
71          return createLowerExclusive(bound);
72      }
73  
74      /**
75       * Creates a lower exclusive bound; {@code value > bound}.
76       * @param bound T; bound value
77       * @param <T> value type
78       * @return lower exclusive bound
79       */
80      public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> lowerExclusive(final T bound)
81      {
82          return createLowerExclusive(bound);
83      }
84  
85      /**
86       * Creates a lower exclusive bound; {@code value > bound}.
87       * @param bound T; bound value
88       * @param <T> value type
89       * @return lower exclusive bound
90       */
91      private static <T extends Number> SingleBound<T> createLowerExclusive(final T bound)
92      {
93          return new SingleBound<>(new LowerBoundExclusive<>(bound), String.format("Value is not greater than %s", bound));
94      }
95  
96      /**
97       * Creates an upper inclusive bound; {@code value <= bound}.
98       * @param bound double; bound value
99       * @return upper inclusive bound
100      */
101     public static final SingleBound<Double> upperInclusive(final double bound)
102     {
103         return createUpperInclusive(bound);
104     }
105 
106     /**
107      * Creates an upper inclusive bound; {@code value <= bound}.
108      * @param bound T; bound value
109      * @return upper inclusive bound
110      * @param <T> value type
111      */
112     public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> upperInclusive(final T bound)
113     {
114         return createUpperInclusive(bound);
115     }
116 
117     /**
118      * Creates an upper inclusive bound; {@code value <= bound}.
119      * @param bound T; bound value
120      * @param <T> value type
121      * @return upper inclusive bound
122      */
123     private static <T extends Number> SingleBound<T> createUpperInclusive(final T bound)
124     {
125         return new SingleBound<>(new UpperBoundInclusive<>(bound),
126                 String.format("Value is not smaller than or equal to %s", bound));
127     }
128 
129     /**
130      * Creates an upper exclusive bound; {@code value < bound}.
131      * @param bound double; bound value
132      * @return upper exclusive bound
133      */
134     public static final SingleBound<Double> upperExclusive(final double bound)
135     {
136         return createUpperExclusive(bound);
137     }
138 
139     /**
140      * Creates an upper exclusive bound; {@code value < bound}.
141      * @param bound T; bound value
142      * @param <T> value type
143      * @return upper exclusive bound
144      */
145     public static final <T extends AbstractDoubleScalar<?, ?>> SingleBound<T> upperExclusive(final T bound)
146     {
147         return createUpperExclusive(bound);
148     }
149 
150     /**
151      * Creates an upper exclusive bound; {@code value < bound}.
152      * @param bound T; bound value
153      * @param <T> value type
154      * @return upper exclusive bound
155      */
156     private static <T extends Number> SingleBound<T> createUpperExclusive(final T bound)
157     {
158         return new SingleBound<>(new UpperBoundExclusive<>(bound), String.format("Value is not smaller than %s", bound));
159     }
160 
161     /**
162      * Constructor.
163      * @param bound Bound; bound
164      * @param failMessage String; message about values that do not comply with the bound
165      */
166     SingleBound(final Bound bound, final String failMessage)
167     {
168         this.bound = bound;
169         this.failMessage = failMessage;
170     }
171 
172     /** {@inheritDoc} */
173     @Override
174     public boolean accept(final T value)
175     {
176         return this.bound.accept(value);
177     }
178 
179     /** {@inheritDoc} */
180     @Override
181     public String failMessage()
182     {
183         return this.failMessage;
184     }
185 
186     /**
187      * @return bound.
188      */
189     public Bound getBound()
190     {
191         return this.bound;
192     }
193 
194     /**
195      * Super class for classes that implement a specific numeric check.
196      * <p>
197      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
198      * <br>
199      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
200      * <p>
201      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
202      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
203      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
204      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
205      */
206     abstract static class Bound
207     {
208 
209         /** Value of the bound. */
210         @SuppressWarnings("checkstyle:visibilitymodifier")
211         final Number bound;
212 
213         /** Hashcode of the value class. */
214         @SuppressWarnings("checkstyle:visibilitymodifier")
215         final int classHashcode;
216 
217         /** String representation of this bound with %s for the value. */
218         private final String stringFormat;
219 
220         /**
221          * Constructor.
222          * @param bound Number; value of the bound
223          * @param stringFormat String; string representation of this bound with %s for the value
224          */
225         Bound(final Number bound, final String stringFormat)
226         {
227             Throw.whenNull(bound, "Bound may not be null.");
228             Throw.whenNull(bound, "String format may not be null.");
229             Throw.when(Double.isNaN(bound.doubleValue()), IllegalArgumentException.class, "Bound value may not be NaN.");
230             this.bound = bound;
231             this.classHashcode = bound.getClass().hashCode();
232             this.stringFormat = stringFormat;
233         }
234 
235         /**
236          * Returns true if the bound accepts the value.
237          * @param value Number; the value to check
238          * @return true if the bound accepts the value
239          */
240         abstract boolean accept(Number value);
241 
242         /** {@inheritDoc} */
243         @Override
244         public final String toString()
245         {
246             return String.format(this.stringFormat, this.bound);
247         }
248     }
249 
250     /**
251      * Class implementing a lower inclusive bound; {@code value >= bound}.
252      * <p>
253      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
254      * <br>
255      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
256      * <p>
257      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
258      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
259      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
260      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
261      * @param <T> value type
262      */
263     static class LowerBoundInclusive<T extends Number> extends Bound
264     {
265 
266         /**
267          * Constructor.
268          * @param bound T; bound
269          */
270         LowerBoundInclusive(final T bound)
271         {
272             super(bound, "%s <= value");
273         }
274 
275         /** {@inheritDoc} */
276         protected boolean accept(final Number value)
277         {
278             return this.bound.doubleValue() <= value.doubleValue();
279         }
280 
281     }
282 
283     /**
284      * Class implementing a lower exclusive bound; {@code value > bound}.
285      * <p>
286      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
287      * <br>
288      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
289      * <p>
290      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
291      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
292      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
293      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
294      * @param <T> value type
295      */
296     static class LowerBoundExclusive<T extends Number> extends Bound
297     {
298 
299         /**
300          * Constructor.
301          * @param bound T; bound
302          */
303         LowerBoundExclusive(final T bound)
304         {
305             super(bound, "%s < value");
306         }
307 
308         /** {@inheritDoc} */
309         protected boolean accept(final Number value)
310         {
311             return this.bound.doubleValue() < value.doubleValue();
312         }
313 
314     }
315 
316     /**
317      * Class implementing an upper inclusive bound; {@code value <= bound}.
318      * <p>
319      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
320      * <br>
321      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
322      * <p>
323      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
324      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
325      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
326      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
327      * @param <T> value type
328      */
329     static class UpperBoundInclusive<T extends Number> extends Bound
330     {
331 
332         /**
333          * Constructor.
334          * @param bound T; bound
335          */
336         UpperBoundInclusive(final T bound)
337         {
338             super(bound, "value <= %s");
339         }
340 
341         /** {@inheritDoc} */
342         protected boolean accept(final Number value)
343         {
344             return this.bound.doubleValue() >= value.doubleValue();
345         }
346 
347     }
348 
349     /**
350      * Class implementing an upper exclusive bound; {@code value < bound}.
351      * <p>
352      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
353      * <br>
354      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
355      * <p>
356      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 sep. 2017 <br>
357      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
358      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
359      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
360      * @param <T> value type
361      */
362     static class UpperBoundExclusive<T extends Number> extends Bound
363     {
364 
365         /**
366          * Constructor.
367          * @param bound T; bound
368          */
369         UpperBoundExclusive(final T bound)
370         {
371             super(bound, "value < %s");
372         }
373 
374         /** {@inheritDoc} */
375         protected boolean accept(final Number value)
376         {
377             return this.bound.doubleValue() > value.doubleValue();
378         }
379 
380     }
381 
382     /** {@inheritDoc} */
383     @Override
384     public String toString()
385     {
386         return "SingleBound [" + this.bound + "]";
387     }
388 
389 }