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 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 FloatScalar value in line with the FloatScalarSerializer.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
52 * @return S; the reconstructed scalar
53 */
54 @SuppressWarnings("unchecked")
55 @Override
56 public S deserialize(final String text)
57 {
58 String[] parts = text.split("#");
59 try
60 {
61 Method valueOfMethod = valueOfMethodCache.get(parts[0]);
62 if (valueOfMethod == null)
63 {
64 Class<?> scalarClass = Class.forName(parts[0]);
65 valueOfMethod = scalarClass.getDeclaredMethod("valueOf", String.class);
66 valueOfMethodCache.put(parts[0], valueOfMethod);
67 }
68 return (S) valueOfMethodCache.get(parts[0]).invoke(null, parts[1]);
69 }
70 catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
71 | NoSuchMethodException | SecurityException exception)
72 {
73 throw new RuntimeException(exception);
74 }
75 }
76
77 }