1 package org.opentrafficsim.core.gtu.behavioralcharacteristics;
2
3 import java.io.Serializable;
4 import java.lang.reflect.Field;
5 import java.util.HashMap;
6 import java.util.Map;
7 import java.util.Set;
8
9 import org.djunits.unit.DimensionlessUnit;
10 import org.djunits.value.vdouble.scalar.Dimensionless;
11 import org.djunits.value.vdouble.scalar.DoubleScalarInterface;
12
13 import nl.tudelft.simulation.language.Throw;
14 import nl.tudelft.simulation.language.reflection.ClassUtil;
15
16
17
18
19
20
21
22
23
24
25
26 public class BehavioralCharacteristics implements Serializable
27 {
28
29
30 private static final long serialVersionUID = 20160400L;
31
32
33
34
35 private static final Empty EMPTY = new Empty();
36
37
38 private boolean copyOnWrite = false;
39
40
41 private Map<AbstractParameterType<?>, DoubleScalarInterface> parameters;
42
43
44 private Map<AbstractParameterType<?>, DoubleScalarInterface> previous;
45
46
47
48
49 public BehavioralCharacteristics()
50 {
51 this.parameters = new HashMap<>();
52 this.previous = new HashMap<>();
53 }
54
55
56
57
58
59 public BehavioralCharacteristics(final BehavioralCharacteristics behavioralCharacteristics)
60 {
61 this.parameters = behavioralCharacteristics.parameters;
62 this.previous = behavioralCharacteristics.previous;
63 this.copyOnWrite = true;
64 behavioralCharacteristics.copyOnWrite = true;
65 }
66
67
68
69
70
71
72
73
74 public final <T extends DoubleScalarInterface> void setParameter(final ParameterType<T> parameterType, final T value)
75 throws ParameterException
76 {
77 Throw.when(value == null, ParameterException.class,
78 "Parameter of type '%s' was assigned a null value, this is not allowed.", parameterType.getId());
79 parameterType.check(value, this);
80 saveSetParameter(parameterType, value);
81 }
82
83
84
85
86
87
88 public final void setParameter(final ParameterTypeBoolean parameterType, final boolean value)
89 {
90 try
91 {
92 saveSetParameter(parameterType, new Dimensionless(value ? 1.0 : 0.0, DimensionlessUnit.SI));
93 }
94 catch (ParameterException pe)
95 {
96
97 throw new RuntimeException("ParameterTypeBoolean default check throws a ParameterException.", pe);
98 }
99 }
100
101
102
103
104
105
106
107 public final void setParameter(final ParameterTypeDouble parameterType, final double value) throws ParameterException
108 {
109 parameterType.check(value, this);
110 saveSetParameter(parameterType, new Dimensionless(value, DimensionlessUnit.SI));
111 }
112
113
114
115
116
117
118
119 public final void setParameter(final ParameterTypeInteger parameterType, final int value) throws ParameterException
120 {
121 parameterType.check(value, this);
122 saveSetParameter(parameterType, new Dimensionless(value, DimensionlessUnit.SI));
123 }
124
125
126
127
128
129
130
131
132 private <T extends DoubleScalarInterface> void saveSetParameter(final AbstractParameterType<T> parameterType, final T value)
133 throws ParameterException
134 {
135 parameterType.checkCheck(value);
136 checkCopyOnWrite();
137 if (this.parameters.containsKey(parameterType))
138 {
139 this.previous.put(parameterType, this.parameters.get(parameterType));
140 }
141 else
142 {
143
144 this.previous.put(parameterType, EMPTY);
145 }
146 this.parameters.put(parameterType, value);
147 }
148
149
150
151
152
153
154 public final void resetParameter(final AbstractParameterType<?> parameterType) throws ParameterException
155 {
156 Throw.when(!this.previous.containsKey(parameterType), ParameterException.class,
157 "Reset on parameter of type '%s' could not be performed, it was not set.", parameterType.getId());
158 checkCopyOnWrite();
159 if (this.previous.get(parameterType) instanceof Empty)
160 {
161
162 this.parameters.remove(parameterType);
163 }
164 else
165 {
166 this.parameters.put(parameterType, this.previous.get(parameterType));
167 }
168 this.previous.remove(parameterType);
169 }
170
171
172
173
174 private void checkCopyOnWrite()
175 {
176 if (this.copyOnWrite)
177 {
178 this.parameters = new HashMap<>(this.parameters);
179 this.previous = new HashMap<>(this.previous);
180 this.copyOnWrite = false;
181 }
182 }
183
184
185
186
187
188
189
190
191 @SuppressWarnings("checkstyle:designforextension")
192 public <T extends DoubleScalarInterface> T getParameter(final ParameterType<T> parameterType) throws ParameterException
193 {
194 checkContains(parameterType);
195 @SuppressWarnings("unchecked")
196
197 T result = (T) this.parameters.get(parameterType);
198 return result;
199 }
200
201
202
203
204
205
206
207 public final boolean getParameter(final ParameterTypeBoolean parameterType) throws ParameterException
208 {
209 checkContains(parameterType);
210 return this.parameters.get(parameterType).getSI() != 0.0;
211 }
212
213
214
215
216
217
218
219 public final int getParameter(final ParameterTypeInteger parameterType) throws ParameterException
220 {
221 checkContains(parameterType);
222 return (int) this.parameters.get(parameterType).getSI();
223 }
224
225
226
227
228
229
230
231 public final double getParameter(final ParameterTypeDouble parameterType) throws ParameterException
232 {
233 checkContains(parameterType);
234 return this.parameters.get(parameterType).getSI();
235 }
236
237
238
239
240
241
242 private void checkContains(final AbstractParameterType<?> parameterType) throws ParameterException
243 {
244 Throw.when(!contains(parameterType), ParameterException.class,
245 "Could not get parameter of type '%s' as it was not set.", parameterType.getId());
246 }
247
248
249
250
251
252
253 public final boolean contains(final AbstractParameterType<?> parameterType)
254 {
255 return this.parameters.containsKey(parameterType);
256 }
257
258
259
260
261
262 public final Map<AbstractParameterType<?>, DoubleScalarInterface> getParameters()
263 {
264 return new HashMap<>(this.parameters);
265 }
266
267
268
269
270
271
272
273
274 @SuppressWarnings("unchecked")
275 public final <T extends DoubleScalarInterface> BehavioralCharacteristics setDefaultParameter(
276 final AbstractParameterType<T> parameter) throws ParameterException
277 {
278 T defaultValue;
279 if (parameter.getDefaultValue() instanceof DoubleScalarInterface)
280 {
281
282 defaultValue = (T) parameter.getDefaultValue();
283 }
284 else if (parameter.getDefaultValue() instanceof Boolean)
285 {
286
287 defaultValue = (T) new Dimensionless((boolean) parameter.getDefaultValue() ? 1.0 : 0.0, DimensionlessUnit.SI);
288 }
289 else
290 {
291
292 defaultValue = (T) new Dimensionless(((Number) parameter.getDefaultValue()).doubleValue(), DimensionlessUnit.SI);
293 }
294 try
295 {
296 saveSetParameter(parameter, defaultValue);
297 }
298 catch (ParameterException pe)
299 {
300
301 throw new RuntimeException(pe);
302 }
303 return this;
304 }
305
306
307
308
309
310
311 public final BehavioralCharacteristics setDefaultParameters(final Class<?> clazz)
312 {
313 return setDefaultParametersLocal(clazz);
314 }
315
316
317
318
319
320
321
322 @SuppressWarnings("unchecked")
323 private <T extends DoubleScalarInterface> BehavioralCharacteristics setDefaultParametersLocal(final Class<?> clazz)
324 {
325
326 Set<Field> fields = ClassUtil.getAllFields(clazz);
327
328 for (Field field : fields)
329 {
330 if (AbstractParameterType.class.isAssignableFrom(field.getType()))
331 {
332 try
333 {
334 field.setAccessible(true);
335 AbstractParameterType<T> p = (AbstractParameterType<T>) field.get(clazz);
336 T defaultValue;
337 if (p.getDefaultValue() instanceof DoubleScalarInterface)
338 {
339
340 defaultValue = (T) p.getDefaultValue();
341 }
342 else if (p.getDefaultValue() instanceof Boolean)
343 {
344
345 defaultValue = (T) new Dimensionless((boolean) p.getDefaultValue() ? 1.0 : 0.0, DimensionlessUnit.SI);
346 }
347 else
348 {
349
350 defaultValue =
351 (T) new Dimensionless(((Number) p.getDefaultValue()).doubleValue(), DimensionlessUnit.SI);
352 }
353 saveSetParameter(p, defaultValue);
354 }
355 catch (IllegalArgumentException iare)
356 {
357
358 throw new RuntimeException(iare);
359 }
360 catch (IllegalAccessException iace)
361 {
362
363 }
364 catch (ParameterException pe)
365 {
366
367 }
368 }
369 }
370
371 return this;
372 }
373
374
375
376
377
378 public final void setAll(final BehavioralCharacteristics behavioralCharacteristics)
379 {
380 for (AbstractParameterType<?> key : behavioralCharacteristics.parameters.keySet())
381 {
382 this.parameters.put(key, behavioralCharacteristics.parameters.get(key));
383 }
384 }
385
386
387 public final String toString()
388 {
389 StringBuilder out = new StringBuilder("BehavioralCharacteristics [");
390 String sep = "";
391 for (AbstractParameterType<?> apt : this.parameters.keySet())
392 {
393 try
394 {
395 out.append(sep).append(apt.getId()).append("=").append(apt.printValue(this));
396 sep = ", ";
397 }
398 catch (ParameterException pe)
399 {
400
401 }
402 }
403 out.append("]");
404 return out.toString();
405 }
406
407
408
409
410
411
412
413
414
415
416
417
418 private static class Empty extends Dimensionless
419 {
420
421 private static final long serialVersionUID = 20160414L;
422
423
424
425
426 Empty()
427 {
428 super(Double.NaN, DimensionlessUnit.SI);
429 }
430 }
431
432 }