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