CompoundProperty.java

  1. package org.opentrafficsim.simulationengine.properties;

  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.Comparator;
  5. import java.util.Iterator;

  6. /**
  7.  * Compound property.
  8.  * <p>
  9.  * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  10.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  11.  * <p>
  12.  * $LastChangedDate: 2016-04-05 01:45:04 +0200 (Tue, 05 Apr 2016) $, @version $Revision: 1874 $, by $Author: pknoppers $,
  13.  * initial version 30 dec. 2014 <br>
  14.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  15.  */
  16. public class CompoundProperty extends AbstractProperty<ArrayList<AbstractProperty<?>>>
  17. {
  18.     /** Properties contained in this one. */
  19.     private ArrayList<AbstractProperty<?>> value;

  20.     /** The shortName of the property. */
  21.     private String shortName;

  22.     /** The description of the property. */
  23.     private String description;

  24.     /** The property is read-only. */
  25.     private final Boolean readOnly;

  26.     /**
  27.      * Construct a CompoundProperty.
  28.      * @param shortName String; the short name of the new CompoundProperty
  29.      * @param description String; description of the new CompoundProperty (may use HTML mark up)
  30.      * @param initialValue Integer; the initial value of the new CompoundProperty
  31.      * @param readOnly boolean; if true this CompoundProperty can not be altered
  32.      * @param displayPriority int; the display priority of the new CompoundProperty
  33.      */
  34.     public CompoundProperty(final String shortName, final String description,
  35.         final ArrayList<AbstractProperty<?>> initialValue, final boolean readOnly, final int displayPriority)
  36.     {
  37.         super(displayPriority);
  38.         this.shortName = shortName;
  39.         this.description = description;
  40.         this.value = null == initialValue ? new ArrayList<AbstractProperty<?>>() : initialValue;
  41.         this.readOnly = readOnly;
  42.     }

  43.     /** {@inheritDoc} */
  44.     @Override
  45.     public final ArrayList<AbstractProperty<?>> getValue()
  46.     {
  47.         return new ArrayList<AbstractProperty<?>>(this.value);
  48.     }

  49.     /** {@inheritDoc} */
  50.     @Override
  51.     public final String getShortName()
  52.     {
  53.         return this.shortName;
  54.     }

  55.     /** {@inheritDoc} */
  56.     @Override
  57.     public final String getDescription()
  58.     {
  59.         return this.description;
  60.     }

  61.     /** {@inheritDoc} */
  62.     @Override
  63.     public final void setValue(final ArrayList<AbstractProperty<?>> newValue) throws PropertyException
  64.     {
  65.         if (this.readOnly)
  66.         {
  67.             throw new PropertyException("Cannot modify a read-only CompoundProperty");
  68.         }
  69.         this.value = newValue;
  70.     }

  71.     /** {@inheritDoc} */
  72.     @Override
  73.     public final boolean isReadOnly()
  74.     {
  75.         return this.readOnly;
  76.     }

  77.     /**
  78.      * Find an embedded AbstractProperty that has a specified shortName. <br>
  79.      * Return the first matching one, or null if none of the embedded AbstractProperties has the specified name.
  80.      * @param name String; the name of the sought embedded AbstractProperty
  81.      * @return AbstractProperty&lt;?&gt;; the first matching embedded AbstractProperty or null if there is no embedded
  82.      *         AbstractProperty with the specified name
  83.      */
  84.     public final AbstractProperty<?> findByShortName(final String name)
  85.     {
  86.         // System.out.println("Searching property " + name);
  87.         Iterator<AbstractProperty<ArrayList<AbstractProperty<?>>>> i = this.iterator();
  88.         while (i.hasNext())
  89.         {
  90.             AbstractProperty<?> ap = i.next();
  91.             // System.out.println("Inspecting " + ap.getShortName());
  92.             if (ap.getShortName().equals(name))
  93.             {
  94.                 return ap;
  95.             }
  96.         }
  97.         return null;
  98.     }

  99.     /**
  100.      * Add an AbstractProperty at a specified position.
  101.      * @param index int; the position where the AbstractProperty must be added
  102.      * @param ap AbstractProperty; the property to add
  103.      * @throws PropertyException when this CompoundProperty is read-only, or index is out of range
  104.      */
  105.     public final void add(final int index, final AbstractProperty<?> ap) throws PropertyException
  106.     {
  107.         if (this.readOnly)
  108.         {
  109.             throw new PropertyException("Cannot modify a read-only CompoundProperty");
  110.         }
  111.         if (index < 0 || index > this.value.size())
  112.         {
  113.             throw new PropertyException("index is out of range");
  114.         }
  115.         this.value.add(index, ap);
  116.     }

  117.     /**
  118.      * Add an AbstractProperty at the end of the list.
  119.      * @param ap AbstractProperty; the property to add
  120.      * @throws PropertyException when this CompoundProperty is read-only
  121.      */
  122.     public final void add(final AbstractProperty<?> ap) throws PropertyException
  123.     {
  124.         add(this.value.size(), ap);
  125.     }

  126.     /**
  127.      * Remove a sub property from this CompoundProperty.
  128.      * @param index int; the position of the sub property to remove
  129.      * @throws PropertyException when this CompoundProperty is read-only, or index is out of range
  130.      */
  131.     public final void remove(final int index) throws PropertyException
  132.     {
  133.         if (this.readOnly)
  134.         {
  135.             throw new PropertyException("Cannot modify a read-only CompoundProperty");
  136.         }
  137.         if (index < 0 || index >= this.value.size())
  138.         {
  139.             throw new PropertyException("index is out of range");
  140.         }
  141.         this.value.remove(index);
  142.     }

  143.     /**
  144.      * Return the number of sub properties of this CompoundProperty.
  145.      * @return int; the number of sub properties of this CompoundProperty
  146.      */
  147.     public final int size()
  148.     {
  149.         return this.value.size();
  150.     }

  151.     /**
  152.      * Return the sub property at a specified index.
  153.      * @param index int; the index of the property to retrieve
  154.      * @return AbstractProperty; the sub property at the specified index
  155.      * @throws PropertyException when index is out of range
  156.      */
  157.     public final AbstractProperty<?> get(final int index) throws PropertyException
  158.     {
  159.         if (index < 0 || index >= this.value.size())
  160.         {
  161.             throw new PropertyException("index is out of range");
  162.         }
  163.         return this.value.get(index);
  164.     }

  165.     /**
  166.      * Return the sub-items in display order.
  167.      * @return ArrayList&lt;AbstractProperty&lt;?&gt;&gt;; the sub-items in display order
  168.      */
  169.     public final ArrayList<AbstractProperty<?>> displayOrderedValue()
  170.     {
  171.         ArrayList<AbstractProperty<?>> result = new ArrayList<AbstractProperty<?>>(this.value);
  172.         final ArrayList<AbstractProperty<?>> list = this.value;
  173.         Collections.sort(result, new Comparator<AbstractProperty<?>>()
  174.         {

  175.             @Override
  176.             public int compare(final AbstractProperty<?> arg0, final AbstractProperty<?> arg1)
  177.             {
  178.                 int dp0 = arg0.getDisplayPriority();
  179.                 int dp1 = arg1.getDisplayPriority();
  180.                 if (dp0 < dp1)
  181.                 {
  182.                     return -1;
  183.                 }
  184.                 else if (dp0 > dp1)
  185.                 {
  186.                     return 1;
  187.                 }
  188.                 int i0 = list.indexOf(arg0);
  189.                 int i1 = list.indexOf(arg1);
  190.                 if (i0 < i1)
  191.                 {
  192.                     return -1;
  193.                 }
  194.                 else if (i0 > i1)
  195.                 {
  196.                     return 1;
  197.                 }
  198.                 return 0;
  199.             }

  200.         });
  201.         /*-
  202.         System.out.println("Sorted " + getShortName());
  203.         int pos = 0;
  204.         for (AbstractProperty<?> ap : result)
  205.         {
  206.             System.out.println(++pos + " - " + ap.getDisplayPriority() + ": " + ap.getShortName());
  207.         }
  208.          */
  209.         return result;
  210.     }

  211.     /** {@inheritDoc} */
  212.     @Override
  213.     public final String htmlStateDescription()
  214.     {
  215.         StringBuilder result = new StringBuilder();
  216.         result.append("<table border=\"1\">");
  217.         result.append("<tr><th align=\"left\">" + getShortName() + "</th></tr>\n");
  218.         for (AbstractProperty<?> ap : displayOrderedValue())
  219.         {
  220.             result.append("<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;" + ap.htmlStateDescription() + "</td></tr>\n");
  221.         }
  222.         result.append("</table>\n");
  223.         return result.toString();
  224.     }

  225.     /**
  226.      * Remove a property from this CompoundProperty.
  227.      * @param removeMe AbstractProperty the property that must be removed
  228.      * @throws PropertyException when the supplied property cannot be removed (probably because it is not part of this
  229.      *             CompoundProperty)
  230.      */
  231.     public final void remove(final AbstractProperty<?> removeMe) throws PropertyException
  232.     {
  233.         if (!this.value.remove(removeMe))
  234.         {
  235.             throw new PropertyException("Cannot remove property " + removeMe);
  236.         }
  237.     }

  238.     /** {@inheritDoc} */
  239.     @Override
  240.     public final AbstractProperty<ArrayList<AbstractProperty<?>>> deepCopy()
  241.     {
  242.         ArrayList<AbstractProperty<?>> copyOfValue = new ArrayList<AbstractProperty<?>>();
  243.         for (AbstractProperty<?> ap : this.value)
  244.         {
  245.             copyOfValue.add(ap.deepCopy());
  246.         }
  247.         return new CompoundProperty(this.shortName, this.description, copyOfValue, this.readOnly, getDisplayPriority());
  248.     }

  249. }