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