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-2018 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 boolean; the new value for the readonly flag
59       */
60      // XXX Made this method public to allow changes in e.g., tests; it should really be private
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     @Override
110     public final String getKey()
111     {
112         return this.key;
113     }
114 
115     /** {@inheritDoc} */
116     @Override
117     public final Property<?> findByKey(final String propertyKey)
118     {
119         if (this.key.equals(propertyKey))
120         {
121             return this;
122         }
123         if (this instanceof CompoundProperty)
124         {
125             return ((CompoundProperty) this).getPropertyGroup().get(propertyKey);
126         }
127         if (null == getParent())
128         {
129             return null;
130         }
131         return getParent().getPropertyGroup().get(propertyKey);
132     }
133 
134     /**
135      * Set the parent of this AbstractProperty.
136      * @param newParent AbstractProperty&lt;?&gt;; the new parent of this AbstractProperty
137      */
138     protected final void setParent(final CompoundProperty newParent)
139     {
140         this.parentProperty = newParent;
141     }
142 
143     /** {@inheritDoc} */
144     @Override
145     public final CompoundProperty getParent()
146     {
147         return this.parentProperty;
148     }
149 
150     /** {@inheritDoc} */
151     @Override
152     public final String toString()
153     {
154         return this.getShortName();
155     }
156 
157     /**
158      * Really simple iterator for properties.
159      * <p>
160      * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
161      * <br>
162      * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
163      * <p>
164      * $LastChangedDate: 2016-05-28 11:33:31 +0200 (Sat, 28 May 2016) $, @version $Revision: 2051 $, by $Author: averbraeck $,
165      * initial version jan. 2015 <br>
166      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
167      */
168     class PropertyIterator implements Iterator<Property<?>>, Serializable
169     {
170         /** */
171         private static final long serialVersionUID = 20150000L;
172 
173         /** Next in line in the main CompoundProperty. */
174         private int currentIndex;
175 
176         /** Full list of Properties. */
177         private final ArrayList<Property<?>> list;
178 
179         /**
180          * Construct a new PropertyIterator.
181          * @param ap AbstractProperty; root of the tree to iterate over
182          */
183         PropertyIterator(final Property<T> ap)
184         {
185             this.currentIndex = 0;
186             this.list = new ArrayList<Property<?>>();
187             addToList(ap);
188         }
189 
190         /**
191          * Recursively add all properties to the list. <br>
192          * Compound properties are included <b>right before</b> their contents.
193          * @param cp AbstractProperty&lt;T&gt;; the property to add (if compound it and all it's children are added)
194          */
195         private void addToList(final Property<?> cp)
196         {
197             this.list.add(cp);
198             if (cp instanceof CompoundProperty)
199             {
200                 for (Property<?> ap : ((CompoundProperty) cp).getValue())
201                 {
202                     addToList(ap);
203                 }
204             }
205         }
206 
207         /** {@inheritDoc} */
208         @Override
209         public boolean hasNext()
210         {
211             return this.currentIndex < this.list.size();
212         }
213 
214         /** {@inheritDoc} */
215         @Override
216         public Property<?> next()
217         {
218             return this.list.get(this.currentIndex++);
219         }
220 
221         /** {@inheritDoc} */
222         @Override
223         public void remove()
224         {
225             throw new UnsupportedOperationException();
226         }
227 
228         /** {@inheritDoc} */
229         @Override
230         public String toString()
231         {
232             return "PropertyIterator [currentIndex=" + this.currentIndex + ", list=" + this.list + "]";
233         }
234 
235     }
236 
237 }