1 package org.opentrafficsim.simulationengine.properties;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6
7 /**
8 * Abstract property.
9 * <p>
10 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
11 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
12 * <p>
13 * $LastChangedDate: 2016-05-28 11:33:31 +0200 (Sat, 28 May 2016) $, @version $Revision: 2051 $, by $Author: averbraeck $,
14 * initial version 18 dec. 2014 <br>
15 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
16 * @param <T> type of the property
17 */
18 public abstract class AbstractProperty<T> implements Property<T>, Iterable<AbstractProperty<T>>, Serializable
19 {
20 /** */
21 private static final long serialVersionUID = 20150000L;
22
23 /** Key of this property. */
24 private final String key;
25
26 /** Determines sorting order when properties are displayed to the user. */
27 private final int displayPriority;
28
29 /** The shortName of the property. */
30 private String shortName;
31
32 /** The description of the property. */
33 private String description;
34
35 /** The property is read-only. */
36 private Boolean readOnly = null;
37
38 /** Parent of this AbstractProperty. */
39 private CompoundProperty parentProperty = null;
40
41 /**
42 * Construct a new AbstractProperty.
43 * @param key String; unique (within this property tree) name of the new AbstractProperty
44 * @param displayPriority sorting order when properties are displayed to the user
45 * @param shortName String; concise description of the property
46 * @param description String; long description of the property (may use HTML markup)
47 */
48 public AbstractProperty(final String key, final int displayPriority, final String shortName, final String description)
49 {
50 this.key = key;
51 this.displayPriority = displayPriority;
52 this.shortName = shortName;
53 this.description = description;
54 }
55
56 /**
57 * Finalize the readOnly flag.
58 * @param readOnlyValue the readonly property value to set
59 */
60 protected final void setReadOnly(final boolean readOnlyValue)
61 {
62 this.readOnly = readOnlyValue;
63 }
64
65 /** {@inheritDoc} */
66 @Override
67 public final int getDisplayPriority()
68 {
69 return this.displayPriority;
70 }
71
72 /** {@inheritDoc} */
73 @Override
74 public abstract String htmlStateDescription();
75
76 /** {@inheritDoc} */
77 @Override
78 public final Iterator<AbstractProperty<T>> iterator()
79 {
80 return new PropertyIterator(this);
81 }
82
83 /** {@inheritDoc} */
84 @Override
85 public final String getShortName()
86 {
87 return this.shortName;
88 }
89
90 /** {@inheritDoc} */
91 @Override
92 public final String getDescription()
93 {
94 return this.description;
95 }
96
97 /** {@inheritDoc} */
98 @Override
99 public final boolean isReadOnly()
100 {
101 return null != this.readOnly && this.readOnly;
102 }
103
104 /**
105 * Retrieve the key of this AbstractProperty.
106 * @return String; the key of this AbstractProperty
107 */
108 public final String getKey()
109 {
110 return this.key;
111 }
112
113 /**
114 * Retrieve an AbstractProperty anywhere in this group that has the specified key.
115 * @param propertyKey String; the key
116 * @return AbstractProperty; the matching AbstractProperty, or null if no property with the specified key exists in the
117 * group.
118 */
119 public final AbstractProperty<?> findByKey(final String propertyKey)
120 {
121 if (this.key.equals(propertyKey))
122 {
123 return this;
124 }
125 if (this instanceof CompoundProperty)
126 {
127 return ((CompoundProperty) this).getPropertyGroup().get(propertyKey);
128 }
129 if (null == getParent())
130 {
131 return null;
132 }
133 return getParent().getPropertyGroup().get(propertyKey);
134 }
135
136 /**
137 * Set the parent of this AbstractProperty.
138 * @param newParent AbstractProperty<?>; the new parent of this AbstractProperty
139 */
140 protected final void setParent(final CompoundProperty newParent)
141 {
142 this.parentProperty = newParent;
143 }
144
145 /**
146 * Retrieve the parent property.
147 * @return AbstractProperty<?>; the CompoundProperty that is the parent of this AbstractProperty (result is null if this property is not contained in a CompoundProperty)
148 */
149 protected final CompoundProperty getParent()
150 {
151 return this.parentProperty;
152 }
153
154 /** {@inheritDoc} */
155 public final String toString()
156 {
157 return this.getShortName();
158 }
159
160 /**
161 * Really simple iterator for properties.
162 * <p>
163 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
164 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
165 * <p>
166 * $LastChangedDate: 2016-05-28 11:33:31 +0200 (Sat, 28 May 2016) $, @version $Revision: 2051 $, by $Author: averbraeck $,
167 * initial version jan. 2015 <br>
168 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
169 */
170 class PropertyIterator implements Iterator<AbstractProperty<T>>, Serializable
171 {
172 /** */
173 private static final long serialVersionUID = 20150000L;
174
175 /** Next in line in the main CompoundProperty. */
176 private int currentIndex;
177
178 /** Full list of AbstractProperties. */
179 private final ArrayList<AbstractProperty<T>> list;
180
181 /**
182 * Construct a new PropertyIterator.
183 * @param ap AbstractProperty; root of the tree to iterate over
184 */
185 PropertyIterator(final AbstractProperty<T> ap)
186 {
187 this.currentIndex = 0;
188 this.list = new ArrayList<AbstractProperty<T>>();
189 addToList(ap);
190 }
191
192 /**
193 * Recursively add all properties to the list. <br>
194 * Compound properties are included <b>before</b> their contents.
195 * @param cp AbstractProperty<T>; the property to add (if compound it and all it's children are added)
196 */
197 @SuppressWarnings("unchecked")
198 private void addToList(final AbstractProperty<T> cp)
199 {
200 this.list.add(cp);
201 if (cp instanceof CompoundProperty)
202 {
203 for (AbstractProperty<?> ap : ((CompoundProperty) cp).getValue())
204 {
205 addToList((AbstractProperty<T>) ap);
206 }
207 }
208 }
209
210 /** {@inheritDoc} */
211 @Override
212 public boolean hasNext()
213 {
214 return this.currentIndex < this.list.size();
215 }
216
217 /** {@inheritDoc} */
218 @Override
219 public AbstractProperty<T> next()
220 {
221 return this.list.get(this.currentIndex++);
222 }
223
224 /** {@inheritDoc} */
225 @Override
226 public void remove()
227 {
228 throw new UnsupportedOperationException();
229 }
230
231 /** {@inheritDoc} */
232 @Override
233 public String toString()
234 {
235 return "PropertyIterator [currentIndex=" + this.currentIndex + ", list=" + this.list + "]";
236 }
237
238 }
239
240 }