ParameterType.java

  1. package org.opentrafficsim.base.parameters;

  2. import java.io.Serializable;

  3. import org.djutils.base.Identifiable;
  4. import org.djutils.exceptions.Throw;
  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-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  11.  * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  12.  * </p>
  13.  * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
  14.  * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
  15.  * @param <T> Type of the value.
  16.  */
  17. public class ParameterType<T> implements Serializable, Identifiable, Type<ParameterType<T>>
  18. {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  264.     @Override
  265.     public String toString()
  266.     {
  267.         return "ParameterType [id=" + this.id + ", description=" + this.description + ", valueClass=" + this.valueClass + "]";
  268.     }

  269. }