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.DoubleScalarInterface;
10  
11  /**
12   * ScalarSerializer (de)serializes DJUNITS scalars. <br>
13   * <br>
14   * Copyright (c) 2020-2020 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
15   * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
16   * distributed under a three-clause BSD-style license, which can be found at
17   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>. <br>
18   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19   * @author <a href="https://www.tudelft.nl/pknoppers">Peter Knoppers</a>
20   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
21   * @param <U> the unit type
22   * @param <S> the scalar type
23   */
24  public class DoubleScalarSerializer<U extends Unit<U>, S extends DoubleScalarInterface<U, S>> implements TextSerializer<S>
25  {
26      /** cache of the retrieved valueOf(String) methods for scalars based on the stored string. */
27      private static Map<String, Method> valueOfMethodCache = new LinkedHashMap<>();
28  
29      /**
30       * Serialize a DoubleScalar value to text in such a way that it can be deserialized with the corresponding deserializer. In
31       * this case, it serializes the class name of the Scalar, followed by a hash sign, followed by the printed value of the
32       * scalar including the unit. So a Length of 12.5 kilometer will return "org.djunits.value.vdouble.scalar.Length#12.5 km".
33   * @param value Object; the scalar to serialize
34  
35       * @return String; a string representation of the value that can later be deserialized
36       */
37      @SuppressWarnings("unchecked")
38      @Override
39      public String serialize(final Object value)
40      {
41          return value.getClass().getName() + "#" + ((S) value).toTextualString();
42      }
43  
44      /**
45       * Deserialize a String to the correct DoubleScalar value in line with the DoubleScalarSerializer.serialize method. In this
46       * case, it assumes a string with the class name of the Scalar, followed by a hash sign, followed by the printed value of
47       * the scalar including the unit. So, the String "org.djunits.value.vdouble.scalar.Length#12.5 km" will be deserialized into
48       * a Length of 12500 m with LengthUnit.KILOMETER as the display unit. The method caches the valueOf(String) method for
49       * repeated use.
50       * @param text String; the text to deserialize
51       * @return S; the reconstructed scalar
52       */
53      @SuppressWarnings("unchecked")
54      @Override
55      public S deserialize(final String text)
56      {
57          String[] parts = text.split("#");
58          try
59          {
60              Method valueOfMethod = valueOfMethodCache.get(parts[0]);
61              if (valueOfMethod == null)
62              {
63                  Class<?> scalarClass = Class.forName(parts[0]);
64                  valueOfMethod = scalarClass.getDeclaredMethod("valueOf", String.class);
65                  valueOfMethodCache.put(parts[0], valueOfMethod);
66              }
67              return (S) valueOfMethodCache.get(parts[0]).invoke(null, parts[1]);
68          }
69          catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
70                  | NoSuchMethodException | SecurityException exception)
71          {
72              throw new RuntimeException(exception);
73          }
74      }
75  
76  }