ExpressionAdapter.java

  1. package org.opentrafficsim.xml.bindings;

  2. import java.util.function.Function;

  3. import javax.xml.bind.annotation.adapters.XmlAdapter;

  4. import org.djutils.exceptions.Throw;
  5. import org.opentrafficsim.xml.bindings.types.ExpressionType;

  6. /**
  7.  * Super class for adapters of expression types. This class performs default marshaling by using the expression, or
  8.  * {@code toString()} on the value (or an empty {@code String} if its {@code null}). Sub-classes may overwrite the
  9.  * {@code marshal(E value)} method, calling {@code marshal(E value, Function stringFunction)} to use a different form of
  10.  * representing the value as a {@code String} and/or to implement value checks.
  11.  * <p>
  12.  * Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  13.  * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  14.  * </p>
  15.  * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
  16.  * @param <T> value type wrapped in ExpressionType
  17.  * @param <E> ExpressionType
  18.  */
  19. public abstract class ExpressionAdapter<T, E extends ExpressionType<T>> extends XmlAdapter<String, E>
  20. {

  21.     /** {@inheritDoc} */
  22.     @Override
  23.     public String marshal(final E value)
  24.     {
  25.         return marshal(value, (t) -> t == null ? "" : t.toString());
  26.     }

  27.     /**
  28.      * Marshaling of {@code ExpressionType}. If the {@code ExpressionType} contains an expression, it is returned with brackets.
  29.      * Otherwise a {@code String} representation of the contained value is returned using the supplied function.
  30.      * @param value ExpressionType&lt;?&gt;; value.
  31.      * @param stringFunction Function&lt;T, String&gt;; function to get a {@code String} representation of a contained value.
  32.      * @return Marshaled {@code String} of an {@code ExpressionType}.
  33.      */
  34.     protected final String marshal(final E value, final Function<T, String> stringFunction)
  35.     {
  36.         if (value.isExpression())
  37.         {
  38.             return value.getBracedExpression();
  39.         }
  40.         return stringFunction.apply(value.getValue());
  41.     }
  42.    
  43.     /** {@inheritDoc} */
  44.     @Override
  45.     public abstract E unmarshal(String v); // removes throws Exception

  46.     /**
  47.      * Checks whether field value is a bracketed expression.
  48.      * @param field String; field value.
  49.      * @return boolean; whether field value is a bracketed expression.
  50.      * @throws IllegalArgumentException when the fields starts with { but does not end with }
  51.      */
  52.     protected static boolean isExpression(final String field) throws IllegalArgumentException
  53.     {
  54.         if (field.startsWith("{"))
  55.         {
  56.             Throw.when(!field.endsWith("}"), IllegalArgumentException.class,
  57.                     "Field %s starts with { but does not end with }, i.e. it is not a valid expression.", field);
  58.             return true;
  59.         }
  60.         return false;
  61.     }

  62.     /**
  63.      * Trims the brackets from an expression.
  64.      * @param field String; expression with brackets.
  65.      * @return String; expression trimmed from brackets.
  66.      * @throws IllegalArgumentException when the field is not a valid expression between brackets
  67.      */
  68.     protected static String trimBrackets(final String field) throws IllegalArgumentException
  69.     {
  70.         Throw.when(!isExpression(field), IllegalArgumentException.class,
  71.                 "Field %s is not a valid expression, cannot trim brackets.", field);
  72.         return field.substring(1, field.length() - 1);
  73.     }

  74. }