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