View Javadoc
1   package org.opentrafficsim.base.modelproperties;
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-2017 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>, 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      // XXX Made this method public to allow changes in e.g., tests
61      public final void setReadOnly(final boolean readOnlyValue)
62      {
63          this.readOnly = readOnlyValue;
64      }
65  
66      /** {@inheritDoc} */
67      @Override
68      public final int getDisplayPriority()
69      {
70          return this.displayPriority;
71      }
72  
73      /** {@inheritDoc} */
74      @Override
75      public abstract String htmlStateDescription();
76  
77      /** {@inheritDoc} */
78      @Override
79      public final Iterator<Property<?>> iterator()
80      {
81          return new PropertyIterator(this);
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public final String getShortName()
87      {
88          return this.shortName;
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public final String getDescription()
94      {
95          return this.description;
96      }
97  
98      /** {@inheritDoc} */
99      @Override
100     public final boolean isReadOnly()
101     {
102         return null != this.readOnly && this.readOnly;
103     }
104 
105     /**
106      * Retrieve the key of this AbstractProperty.
107      * @return String; the key of this AbstractProperty
108      */
109     public final String getKey()
110     {
111         return this.key;
112     }
113 
114     /** {@inheritDoc} */
115     @Override
116     public final Property<?> findByKey(final String propertyKey)
117     {
118         if (this.key.equals(propertyKey))
119         {
120             return this;
121         }
122         if (this instanceof CompoundProperty)
123         {
124             return ((CompoundProperty) this).getPropertyGroup().get(propertyKey);
125         }
126         if (null == getParent())
127         {
128             return null;
129         }
130         return getParent().getPropertyGroup().get(propertyKey);
131     }
132 
133     /**
134      * Set the parent of this AbstractProperty.
135      * @param newParent AbstractProperty&lt;?&gt;; the new parent of this AbstractProperty
136      */
137     protected final void setParent(final CompoundProperty newParent)
138     {
139         this.parentProperty = newParent;
140     }
141 
142     /** {@inheritDoc} */
143     @Override
144     public final CompoundProperty getParent()
145     {
146         return this.parentProperty;
147     }
148 
149     /** {@inheritDoc} */
150     @Override
151     public final String toString()
152     {
153         return this.getShortName();
154     }
155 
156     /**
157      * Really simple iterator for properties.
158      * <p>
159      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
160      * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
161      * <p>
162      * $LastChangedDate: 2016-05-28 11:33:31 +0200 (Sat, 28 May 2016) $, @version $Revision: 2051 $, by $Author: averbraeck $,
163      * initial version jan. 2015 <br>
164      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
165      */
166     class PropertyIterator implements Iterator<Property<?>>, Serializable
167     {
168         /** */
169         private static final long serialVersionUID = 20150000L;
170 
171         /** Next in line in the main CompoundProperty. */
172         private int currentIndex;
173 
174         /** Full list of AbstractProperties. */
175         private final ArrayList<Property<?>> list;
176 
177         /**
178          * Construct a new PropertyIterator.
179          * @param ap AbstractProperty; root of the tree to iterate over
180          */
181         PropertyIterator(final Property<T> ap)
182         {
183             this.currentIndex = 0;
184             this.list = new ArrayList<Property<?>>();
185             addToList(ap);
186         }
187 
188         /**
189          * Recursively add all properties to the list. <br>
190          * Compound properties are included <b>before</b> their contents.
191          * @param cp AbstractProperty&lt;T&gt;; the property to add (if compound it and all it's children are added)
192          */
193         private void addToList(final Property<?> cp)
194         {
195             this.list.add(cp);
196             if (cp instanceof CompoundProperty)
197             {
198                 for (Property<?> ap : ((CompoundProperty) cp).getValue())
199                 {
200                     addToList(ap);
201                 }
202             }
203         }
204 
205         /** {@inheritDoc} */
206         @Override
207         public boolean hasNext()
208         {
209             return this.currentIndex < this.list.size();
210         }
211 
212         /** {@inheritDoc} */
213         @Override
214         public Property<?> next()
215         {
216             return this.list.get(this.currentIndex++);
217         }
218 
219         /** {@inheritDoc} */
220         @Override
221         public void remove()
222         {
223             throw new UnsupportedOperationException();
224         }
225 
226         /** {@inheritDoc} */
227         @Override
228         public String toString()
229         {
230             return "PropertyIterator [currentIndex=" + this.currentIndex + ", list=" + this.list + "]";
231         }
232 
233     }
234 
235 }