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.vfloat.scalar.base.FloatScalarInterface;
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 FloatScalarSerializer<U extends Unit<U>, S extends FloatScalarInterface<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 FloatScalar 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 S; 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 Object value)
39 {
40 return value.getClass().getName() + "#" + ((S) value).toTextualString();
41 }
42
43 /**
44 * Deserialize a String to the correct FloatScalar value in line with the FloatScalarSerializer.serialize method. In this
45 * case, it assumes a string with the class name of the Scalar, followed by a hash sign, followed by the printed value of
46 * the scalar including the unit. So, the String "org.djunits.value.vdouble.scalar.Length#12.5 km" will be deserialized into
47 * a Length of 12500 m with LengthUnit.KILOMETER as the display unit. The method caches the valueOf(String) method for
48 * repeated use.
49 * @param text text; the text to deserialize
50 * @return S; the reconstructed scalar
51 */
52 @SuppressWarnings("unchecked")
53 @Override
54 public S deserialize(final String text)
55 {
56 String[] parts = text.split("#");
57 try
58 {
59 Method valueOfMethod = valueOfMethodCache.get(parts[0]);
60 if (valueOfMethod == null)
61 {
62 Class<?> scalarClass = Class.forName(parts[0]);
63 valueOfMethod = scalarClass.getDeclaredMethod("valueOf", String.class);
64 valueOfMethodCache.put(parts[0], valueOfMethod);
65 }
66 return (S) valueOfMethodCache.get(parts[0]).invoke(null, parts[1]);
67 }
68 catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
69 | NoSuchMethodException | SecurityException exception)
70 {
71 throw new RuntimeException(exception);
72 }
73 }
74
75 }