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 }