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-2022 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 * @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 String; 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 }