View Javadoc
1   package org.djutils.data.serialization;
2   
3   import java.lang.reflect.InvocationTargetException;
4   import java.lang.reflect.Method;
5   import java.util.LinkedHashMap;
6   import java.util.Map;
7   
8   import org.djunits.unit.Unit;
9   import org.djunits.value.vdouble.scalar.base.AbstractDoubleScalar;
10  
11  /**
12   * DoubleScalarSerializer (de)serializes DJUNITS double scalars.
13   * <p>
14   * Copyright (c) 2020-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15   * BSD-style license. See <a href="https://djutils.org/docs/current/djutils/licenses.html">DJUTILS License</a>.
16   * </p>
17   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
18   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
19   * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
20   * @param <U> the unit type
21   * @param <S> the scalar type
22   */
23  public class DoubleScalarSerializer<U extends Unit<U>, S extends AbstractDoubleScalar<U, S>> implements TextSerializer<S>
24  {
25      /** cache of the retrieved valueOf(String) methods for scalars based on the stored string. */
26      private static Map<String, Method> valueOfMethodCache = new LinkedHashMap<>();
27  
28      /** cache of the retrieved unit instances based on the unit string. */
29      private static Map<String, Unit<?>> unitCache = new LinkedHashMap<>();
30  
31      /**
32       * Serialize an Scalar value to text in such a way that it can be deserialized with the corresponding deserializer.
33       * @param value Object; the scalar to serialize
34       * @return String; a string representation of the value that can later be deserialized
35       */
36      @SuppressWarnings("unchecked")
37      @Override
38      public String serialize(final S value, final String unitString)
39      {
40          if (value == null)
41          {
42              return null;
43          }
44  
45          String key = value.getClass().getSimpleName() + "_" + unitString;
46          Unit<?> unit = unitCache.get(key);
47          if (unit == null)
48          {
49              unit = value.getDisplayUnit().getQuantity().of(unitString);
50              unitCache.put(key, unit);
51          }
52          return String.valueOf(value.getInUnit((U) unit));
53      }
54  
55      /**
56       * Deserialize a String to the correct Scalar value. The method caches the valueOf(String) method for repeated use.
57       * @param text String; the text to deserialize
58       * @return S; the reconstructed scalar
59       */
60      @SuppressWarnings("unchecked")
61      @Override
62      public S deserialize(final Class<S> type, final String text, final String unit)
63      {
64          if (text == null || text.isEmpty())
65          {
66              return null;
67          }
68          try
69          {
70              Method valueOfMethod = valueOfMethodCache.get(type.getName());
71              if (valueOfMethod == null)
72              {
73                  valueOfMethod = type.getDeclaredMethod("valueOf", String.class);
74                  valueOfMethodCache.put(type.getName(), valueOfMethod);
75              }
76              return (S) valueOfMethod.invoke(null, text + unit);
77          }
78          catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
79                  | SecurityException exception)
80          {
81              throw new RuntimeException(exception);
82          }
83      }
84  
85  }