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 }