1 package nl.tno.imb.mc;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 import java.util.List;
7
8 import org.opentrafficsim.base.modelproperties.CompoundProperty;
9 import org.opentrafficsim.base.modelproperties.Property;
10 import org.opentrafficsim.imb.IMBException;
11
12 import nl.tno.imb.TByteBuffer;
13
14 /**
15 * IMB model control parameter.
16 * <p>
17 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
18 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
19 * <p>
20 * @version $Revision$, $LastChangedDate$, by $Author$,
21 * initial version Oct 14, 2016 <br>
22 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
23 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
24 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
25 */
26 public class Parameter
27 {
28 /** Name of this parameter. */
29 private final String name;
30
31 /** Type of this Parameter. */
32 private final Object value;
33
34 /** Type of this parameter. */
35 private final ParameterType type;
36
37 /** List of possible values. */
38 private List<String> valueList = null;
39
40 /**
41 * Construct a new float parameter.
42 * @param name String; name of the new float parameter
43 * @param value double; value of the new float parameter
44 */
45 public Parameter(final String name, final double value)
46 {
47 this.name = name;
48 this.type = ParameterType.FLOAT;
49 this.value = value;
50 }
51
52 /**
53 * Construct a Boolean parameter.
54 * @param name String; the name of the new Boolean parameter
55 * @param value String; the value of the new Boolean parameter
56 */
57 public Parameter(final String name, final Boolean value)
58 {
59 this.name = name;
60 this.type = ParameterType.BOOLEAN;
61 this.value = value;
62 }
63
64 /**
65 * Construct a new integer parameter.
66 * @param name String; name of the new integer parameter
67 * @param value double; value of the new integer parameter
68 */
69 public Parameter(final String name, final int value)
70 {
71 this.name = name;
72 this.type = ParameterType.INTEGER;
73 this.value = value;
74 }
75
76 /**
77 * Construct a String parameter.
78 * @param name String; the name of the new String parameter
79 * @param value String; the value of the new String parameter
80 */
81 public Parameter(final String name, final String value)
82 {
83 this.name = name;
84 this.type = ParameterType.STRING;
85 this.value = value;
86 }
87
88 /**
89 * Construct a new Parameter from the next object in a TByteBuffer.
90 * @param payload TByteBuffer; the received IMB data
91 * @throws IMBException when the received type cannot be converted to a Parameter sub-type
92 */
93 public Parameter (final TByteBuffer payload) throws IMBException
94 {
95 this.name = payload.readString();
96 int valueCode = payload.readInt32();
97 if (ParameterType.BOOLEAN.value == valueCode)
98 {
99 this.type = ParameterType.BOOLEAN;
100 this.value = payload.readBoolean();
101 }
102 else if (ParameterType.FLOAT.value == valueCode)
103 {
104 this.type = ParameterType.FLOAT;
105 this.value = payload.readDouble();
106 }
107 else if (ParameterType.INTEGER.value == valueCode)
108 {
109 this.type = ParameterType.INTEGER;
110 this.value = payload.readInt32();
111 }
112 else if (ParameterType.STRING.value == valueCode)
113 {
114 this.type = ParameterType.STRING;
115 this.value = payload.readString();
116 }
117 else
118 {
119 throw new IMBException("Inhandled type: " + valueCode);
120 }
121 int optionCount = payload.readInt32();
122 if (optionCount > 0)
123 {
124 this.valueList = new ArrayList<String>(optionCount);
125 for (int optionIndex = 0; optionIndex < optionCount; optionIndex++)
126 {
127 this.valueList.add(payload.readString());
128 }
129 }
130 }
131
132 /**
133 * Prepare this parameter for transmission over IMB.
134 * @param payload TByteBuffer; the transmission buffer
135 */
136 public void prepare (final TByteBuffer payload)
137 {
138 payload.prepare(this.name);
139 payload.prepare(this.type.value);
140 switch (this.type)
141 {
142 case BOOLEAN:
143 payload.prepare((boolean) this.value);
144 break;
145
146 case FLOAT:
147 payload.prepare((double) this.value);
148 break;
149
150 case INTEGER:
151 payload.prepare((int) this.value);
152 break;
153
154 case STRING:
155 payload.prepare((String) this.value);
156 break;
157 }
158 if (null != this.valueList && this.valueList.size() > 0)
159 {
160 payload.prepare(this.valueList.size());
161 for (String option : this.valueList)
162 {
163 payload.prepare(option);
164 }
165 }
166 else
167 {
168 payload.prepare(0);
169 }
170 }
171
172 /**
173 * Prepare this parameter for transmission over IMB.
174 * @param payload TByteBuffer; the transmission buffer
175 */
176 public void qWrite (final TByteBuffer payload)
177 {
178 payload.qWrite(this.name);
179 payload.qWrite(this.type.value);
180 switch (this.type)
181 {
182 case BOOLEAN:
183 payload.qWrite((boolean) this.value);
184 break;
185
186 case FLOAT:
187 payload.qWrite((double) this.value);
188 break;
189
190 case INTEGER:
191 payload.qWrite((int) this.value);
192 break;
193
194 case STRING:
195 payload.qWrite((String) this.value);
196 break;
197 }
198 if (null != this.valueList && this.valueList.size() > 0)
199 {
200 payload.qWrite(this.valueList.size());
201 for (String option : this.valueList)
202 {
203 payload.qWrite(option);
204 }
205 }
206 else
207 {
208 payload.qWrite(0);
209 }
210 }
211
212 /**
213 * Set the list of pre-defined options that the user may choose from.
214 * @param list List<String>; the list of options
215 */
216 public void setValueList(final List<String> list)
217 {
218 this.valueList = new ArrayList<String>(list);
219 }
220
221 /** {@inheritDoc} */
222 @Override
223 public final String toString()
224 {
225 return "Parameter [name=" + this.name + ", value=" + this.value + ", type=" + this.type + "]";
226 }
227
228 /**
229 * @return name.
230 */
231 public String getName()
232 {
233 return this.name;
234 }
235
236 /**
237 * @return value.
238 */
239 public Object getValue()
240 {
241 return this.value;
242 }
243
244 /**
245 * @return type.
246 */
247 public ParameterType getType()
248 {
249 return this.type;
250 }
251
252 /**
253 * @return valueList.
254 */
255 public List<String> getValueList()
256 {
257 return this.valueList;
258 }
259
260 /**
261 * IMB integer numbers and our corresponding enum values.
262 */
263 public enum ParameterType
264 {
265 /** Float parameter. */
266 FLOAT(0),
267 /** Boolean parameter. */
268 BOOLEAN(1),
269 /** Integer parameter. */
270 INTEGER(2),
271 /** String parameter. */
272 STRING(3);
273
274 /** The IMB integer value used for this ParameterType. */
275 public final int value;
276
277 /**
278 * Construct a new ParameterType.
279 * @param value int; the IMB integer value for the new ParameterType
280 */
281 ParameterType(final int value)
282 {
283 this.value = value;
284 }
285
286 };
287
288 /**
289 * Really simple iterator for properties.
290 * <p>
291 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
292 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
293 * <p>
294 * $LastChangedDate: 2016-05-28 11:33:31 +0200 (Sat, 28 May 2016) $, @version $Revision: 2051 $, by $Author: averbraeck $,
295 * initial version jan. 2015 <br>
296 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
297 */
298 class PropertyIterator implements Iterator<Property<?>>, Serializable
299 {
300 /** */
301 private static final long serialVersionUID = 20150000L;
302
303 /** Next in line in the main CompoundProperty. */
304 private int currentIndex;
305
306 /** Full list of AbstractProperties. */
307 private final ArrayList<Property<?>> list;
308
309 /**
310 * Construct a new PropertyIterator.
311 * @param ap Property; root of the tree to iterate over
312 */
313 PropertyIterator(final Property<?> ap)
314 {
315 this.currentIndex = 0;
316 this.list = new ArrayList<Property<?>>();
317 addToList(ap);
318 }
319
320 /**
321 * Recursively add all properties to the list. <br>
322 * Compound properties are included <b>before</b> their contents.
323 * @param cp Property<T>; the property to add (if compound it and all it's children are added)
324 */
325 private void addToList(final Property<?> cp)
326 {
327 this.list.add(cp);
328 if (cp instanceof CompoundProperty)
329 {
330 for (Property<?> ap : ((CompoundProperty) cp).getValue())
331 {
332 addToList(ap);
333 }
334 }
335 }
336
337 /** {@inheritDoc} */
338 @Override
339 public boolean hasNext()
340 {
341 return this.currentIndex < this.list.size();
342 }
343
344 /** {@inheritDoc} */
345 @Override
346 public Property<?> next()
347 {
348 return this.list.get(this.currentIndex++);
349 }
350
351 /** {@inheritDoc} */
352 @Override
353 public void remove()
354 {
355 throw new UnsupportedOperationException();
356 }
357
358 /** {@inheritDoc} */
359 @Override
360 public String toString()
361 {
362 return "PropertyIterator [currentIndex=" + this.currentIndex + ", list=" + this.list + "]";
363 }
364
365 }
366
367
368 }
369