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 }