View Javadoc
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&lt;String&gt;; 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&lt;T&gt;; 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