ParameterType.java

  1. package org.opentrafficsim.base.parameters;

  2. import java.io.Serializable;

  3. import org.djutils.exceptions.Throw;
  4. import org.opentrafficsim.base.Identifiable;
  5. import org.opentrafficsim.base.Type;
  6. import org.opentrafficsim.base.parameters.constraint.Constraint;

  7. /**
  8.  * Defines meta-information of a parameter, defining the parameter uniquely.
  9.  * <p>
  10.  * Copyright (c) 2013-2020 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/current/license.html">OpenTrafficSim License</a>.
  12.  * <p>
  13.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
  14.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  15.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  16.  * @param <T> Type of the value.
  17.  */
  18. public class ParameterType<T> extends Type<ParameterType<T>> implements Serializable, Identifiable
  19. {

  20.     /** */
  21.     private static final long serialVersionUID = 20160400L;

  22.     /** Short name of parameter. */
  23.     private final String id;

  24.     /** Parameter description or full name. */
  25.     private final String description;

  26.     /** Default constraint. */
  27.     private final Constraint<? super T> constraint;

  28.     /** Class of the value. */
  29.     private final Class<T> valueClass;

  30.     /** Default value. */
  31.     @SuppressWarnings("checkstyle:visibilitymodifier")
  32.     protected final T defaultValue;

  33.     /**
  34.      * Construct a new AbstractParameterType without default value and constraint.
  35.      * @param id String; short name of the new AbstractParameterType
  36.      * @param description String; description or full name of the new AbstractParameterType
  37.      * @param valueClass Class&lt;T&gt;; class of the value of the new AbstractParameterType
  38.      */
  39.     public ParameterType(final String id, final String description, final Class<T> valueClass)
  40.     {
  41.         this(id, description, valueClass, null, null, false);
  42.     }

  43.     /**
  44.      * Construct a new AbstractParameterType without default value and with constraint.
  45.      * @param id String; short name of the new AbstractParameterType
  46.      * @param description String; description or full name of the new AbstractParameterType
  47.      * @param valueClass Class&lt;T&gt;; class of the value of the new AbstractParameterType
  48.      * @param constraint Constraint&lt;? super T&gt;; constraint that applies to the value of the new AbstractParameterType
  49.      */
  50.     public ParameterType(final String id, final String description, final Class<T> valueClass,
  51.             final Constraint<? super T> constraint)
  52.     {
  53.         this(id, description, valueClass, null, constraint, false);
  54.     }

  55.     /**
  56.      * Construct a new AbstractParameterType with default value, without constraint.
  57.      * @param id String; short name of the new AbstractParameterType
  58.      * @param description String; description or full name of the new AbstractParameterType
  59.      * @param valueClass Class&lt;T&gt;; class of the value of the new AbstractParameterType
  60.      * @param defaultValue T; default value of the new AbstractParameterType
  61.      */
  62.     public ParameterType(final String id, final String description, final Class<T> valueClass, final T defaultValue)
  63.     {
  64.         this(id, description, valueClass, defaultValue, null, true);
  65.     }

  66.     /**
  67.      * Construct a new AbstractParameterType with default value and constraint.
  68.      * @param id String; short name of the new AbstractParameterType
  69.      * @param description String; description or full name of the new AbstractParameterType
  70.      * @param valueClass Class&lt;T&gt;; class of the value of the new AbstractParameterType
  71.      * @param defaultValue T; default value of the new AbstractParameterType
  72.      * @param constraint Constraint&lt;? super T&gt;; constraint that applies to the value of the new AbstractParameterType
  73.      */
  74.     public ParameterType(final String id, final String description, final Class<T> valueClass, final T defaultValue,
  75.             final Constraint<? super T> constraint)
  76.     {
  77.         this(id, description, valueClass, defaultValue, constraint, true);
  78.     }

  79.     /**
  80.      * Protected constructor with default value and constraint, which may check the default value.
  81.      * @param id String; short name of the new AbstractParameterType
  82.      * @param description String; description or full name of the new AbstractParameterType
  83.      * @param valueClass Class&lt;T&gt;; class of the value of the new AbstractParameterType
  84.      * @param defaultValue T; default value of the new AbstractParameterType
  85.      * @param constraint Constraint&lt;? super T&gt;; constraint that applies to the value of the new AbstractParameterType
  86.      * @param hasDefaultValue boolean; if true a check is performed to ensure that the default value is not null and does not
  87.      *            violate the constraint
  88.      */
  89.     private ParameterType(final String id, final String description, final Class<T> valueClass, final T defaultValue,
  90.             final Constraint<? super T> constraint, final boolean hasDefaultValue)
  91.     {
  92.         Throw.whenNull(id, "Id may not be null.");
  93.         Throw.whenNull(description, "Description may not be null.");
  94.         Throw.whenNull(valueClass, "Value class may not be null.");
  95.         if (hasDefaultValue)
  96.         {
  97.             Throw.whenNull(defaultValue, "Default values of parameter types may not be null.");
  98.         }
  99.         this.id = id;
  100.         this.description = description;
  101.         this.valueClass = valueClass;
  102.         this.defaultValue = defaultValue;
  103.         this.constraint = constraint;
  104.         if (this.defaultValue != null)
  105.         {
  106.             try
  107.             {
  108.                 checkConstraint(this.defaultValue);
  109.             }
  110.             catch (ParameterException pe)
  111.             {
  112.                 throw new RuntimeException(
  113.                         "Default value of parameter '" + this.id + "' does not comply with default constraints.", pe);
  114.             }
  115.             try
  116.             {
  117.                 // Forward empty set of parameters. At creation time of parameter types, values cannot be checked with values of
  118.                 // other parameter types.
  119.                 check(defaultValue, new ParameterSet());
  120.             }
  121.             catch (ParameterException pe)
  122.             {
  123.                 throw new RuntimeException(
  124.                         "Default value of parameter '" + getId() + "' does not comply with custom constraints.", pe);
  125.             }
  126.         }
  127.     }

  128.     /**
  129.      * Retrieve the id of this AbstractParameterType.
  130.      * @return String; the id of this AbstractParameterType
  131.      */
  132.     @Override
  133.     public final String getId()
  134.     {
  135.         return this.id;
  136.     }

  137.     /**
  138.      * Retrieve the description of this AbstractParameterType.
  139.      * @return String; the description of this AbstractParameterType
  140.      */
  141.     public final String getDescription()
  142.     {
  143.         return this.description;
  144.     }

  145.     /**
  146.      * Retrieve the class of the value of this AbstractParameterType.
  147.      * @return valueClass Class&lt;T&gt;; the class of the value of this AbstractParameterType
  148.      */
  149.     public final Class<T> getValueClass()
  150.     {
  151.         return this.valueClass;
  152.     }

  153.     /**
  154.      * Returns whether this parameter type has a default value.
  155.      * @return boolean; true if this AbstractParameterType type has a default value; false if it does not have a default value
  156.      */
  157.     public final boolean hasDefaultValue()
  158.     {
  159.         return this.defaultValue != null;
  160.     }

  161.     /**
  162.      * Retrieve the the default value of this AbstractParameterType.
  163.      * @return T; the default value of this AbstractParameterType
  164.      * @throws ParameterException if this AbstractParameterType does not have a default value
  165.      */
  166.     public final T getDefaultValue() throws ParameterException
  167.     {
  168.         Throw.when(null == this.defaultValue, ParameterException.class, "No default value was set for '%s'.", getId());
  169.         return this.defaultValue;
  170.     }

  171.     /**
  172.      * Check that a value complies with the constraint of this AbstractParameterType.
  173.      * @param value T; the value to check
  174.      * @throws ParameterException if the value does not comply with constraints
  175.      */
  176.     public final void checkConstraint(final T value) throws ParameterException
  177.     {
  178.         if (this.constraint == null)
  179.         {
  180.             return;
  181.         }
  182.         Throw.when(!this.constraint.accept(value), ParameterException.class, this.constraint.failMessage(), this.getId());
  183.     }

  184.     /**
  185.      * Default implementation of check method. This default implementation will never throw any Exception.
  186.      * @param value T; the value to check
  187.      * @param params Parameters; Set of parameters to check
  188.      * @throws ParameterException If the value does not comply with constraints.
  189.      */
  190.     public void check(final T value, final Parameters params) throws ParameterException
  191.     {
  192.         // Default implementation does nothing
  193.     }

  194.     /**
  195.      * Print the given value from the map in Parameters in a presentable format. The default implementation simply returns the
  196.      * output of toString().
  197.      * @param parameters Parameters; Parameters to get the value from
  198.      * @return String; readable representation of the value
  199.      * @throws ParameterException If the parameter is not present
  200.      */
  201.     public String printValue(final Parameters parameters) throws ParameterException
  202.     {
  203.         return parameters.getParameter(this).toString();
  204.     }

  205.     /** {@inheritDoc} */
  206.     @Override
  207.     public final int hashCode()
  208.     {
  209.         final int prime = 31;
  210.         int result = 1;
  211.         result = prime * result + ((this.defaultValue == null) ? 0 : this.defaultValue.hashCode());
  212.         result = prime * result + this.description.hashCode();
  213.         result = prime * result + this.id.hashCode();
  214.         result = prime * result + this.valueClass.hashCode();
  215.         return result;
  216.     }

  217.     /** {@inheritDoc} */
  218.     @Override
  219.     public final boolean equals(final Object obj)
  220.     {
  221.         if (this == obj)
  222.         {
  223.             return true;
  224.         }
  225.         if (obj == null)
  226.         {
  227.             return false;
  228.         }
  229.         if (getClass() != obj.getClass())
  230.         {
  231.             return false;
  232.         }
  233.         ParameterType<?> other = (ParameterType<?>) obj;
  234.         if (!this.id.equals(other.id))
  235.         {
  236.             return false;
  237.         }
  238.         if (!this.description.equals(other.description))
  239.         {
  240.             return false;
  241.         }
  242.         if (!this.valueClass.equals(other.valueClass))
  243.         {
  244.             return false;
  245.         }
  246.         if (this.defaultValue == null)
  247.         {
  248.             if (other.defaultValue != null)
  249.             {
  250.                 return false;
  251.             }
  252.         }
  253.         else if (!this.defaultValue.equals(other.defaultValue))
  254.         {
  255.             return false;
  256.         }
  257.         return true;
  258.     }

  259.     /**
  260.      * Retrieve the constraint.
  261.      * @return Constraint; the constraint of this AbstractParameterType
  262.      */
  263.     public final Constraint<? super T> getConstraint()
  264.     {
  265.         return this.constraint;
  266.     }

  267.     /** {@inheritDoc} */
  268.     @SuppressWarnings("checkstyle:designforextension")
  269.     @Override
  270.     public String toString()
  271.     {
  272.         return "ParameterType [id=" + this.id + ", description=" + this.description + ", valueClass=" + this.valueClass + "]";
  273.     }

  274. }