View Javadoc
1   package org.djutils.serialization.serializers;
2   
3   import java.lang.reflect.Constructor;
4   import java.lang.reflect.InvocationTargetException;
5   import java.util.HashMap;
6   import java.util.Map;
7   
8   import org.djunits.unit.SIUnit;
9   import org.djunits.unit.Unit;
10  import org.djunits.unit.scale.IdentityScale;
11  import org.djunits.unit.util.UnitRuntimeException;
12  import org.djunits.value.storage.StorageType;
13  import org.djunits.value.vdouble.scalar.base.DoubleScalar;
14  import org.djunits.value.vdouble.vector.SIVector;
15  import org.djunits.value.vdouble.vector.base.DoubleVector;
16  import org.djunits.value.vdouble.vector.data.DoubleVectorData;
17  import org.djutils.serialization.EndianUtil;
18  import org.djutils.serialization.FieldTypes;
19  import org.djutils.serialization.SerializationException;
20  
21  /**
22   * (De)serializes a DJUNITS DoubleVector.
23   * <p>
24   * Copyright (c) 2019-2025 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
25   * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>.
26   * </p>
27   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
28   * @param <U> the unit type
29   * @param <S> the scalar type
30   * @param <V> the vector type
31   */
32  public class DoubleVectorSerializer<U extends Unit<U>, S extends DoubleScalar<U, S>, V extends DoubleVector<U, S, V>>
33          extends ArrayOrMatrixWithUnitSerializer<U, V>
34  {
35      /** The cache to make the lookup of the constructor for a Vevtor belonging to a unit faster. */
36      private static final Map<Unit<?>, Constructor<? extends DoubleVector<?, ?, ?>>> CACHE = new HashMap<>();
37  
38      /** */
39      public DoubleVectorSerializer()
40      {
41          super(FieldTypes.DOUBLE_64_UNIT_ARRAY, "Djunits_DoubleVector", 1);
42      }
43  
44      @Override
45      public int size(final V adv)
46      {
47          return 4 + 2 + 8 * adv.size();
48      }
49  
50      @Override
51      public int getElementSize()
52      {
53          return 8;
54      }
55  
56      @Override
57      public void serialize(final V adv, final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil)
58              throws SerializationException
59      {
60          endianUtil.encodeInt(adv.size(), buffer, pointer.getAndIncrement(4));
61          encodeUnit(adv.getDisplayUnit(), buffer, pointer, endianUtil);
62          for (int i = 0; i < adv.size(); i++)
63          {
64              endianUtil.encodeDouble(adv.get(i).getSI(), buffer, pointer.getAndIncrement(8));
65          }
66      }
67  
68      @Override
69      public V deSerialize(final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil) throws SerializationException
70      {
71          int size = endianUtil.decodeInt(buffer, pointer.getAndIncrement(4));
72          Unit<? extends Unit<?>> unit = getUnit(buffer, pointer, endianUtil);
73          double[] array = new double[size];
74          for (int i = 0; i < size; i++)
75          {
76              array[i] = endianUtil.decodeDouble(buffer, pointer.getAndIncrement(8));
77          }
78          try
79          {
80              DoubleVectorData fvd = DoubleVectorData.instantiate(array, IdentityScale.SCALE, StorageType.DENSE);
81              return instantiateAnonymous(fvd, unit);
82          }
83          catch (UnitRuntimeException exception)
84          {
85              throw new SerializationException(exception);
86          }
87      }
88  
89      /**
90       * Instantiate the DoubleVector based on its unit. Loose check for types on the compiler. This allows the unit to be
91       * specified as a Unit&lt;?&gt; type.<br>
92       * <b>Note</b> that it is possible to make mistakes with anonymous units.
93       * @param data the values
94       * @param unit the unit in which the value is expressed
95       * @return an instantiated DoubleVector with the provided displayUunit
96       * @param <U> the unit type
97       * @param <S> the scalar type
98       * @param <V> the vector type
99       */
100     @SuppressWarnings("unchecked")
101     public static <U extends Unit<U>, S extends DoubleScalar<U, S>,
102             V extends DoubleVector<U, S, V>> V instantiateAnonymous(final DoubleVectorData data, final Unit<?> unit)
103     {
104         try
105         {
106             Constructor<? extends DoubleVector<?, ?, ?>> vectorConstructor = CACHE.get(unit);
107             if (vectorConstructor == null)
108             {
109                 if (!unit.getClass().getSimpleName().endsWith("Unit"))
110                 {
111                     throw new ClassNotFoundException("Unit " + unit.getClass().getSimpleName()
112                             + " name does noet end with 'Unit'. Cannot find corresponding scalar");
113                 }
114                 Class<? extends DoubleVector<?, ?, ?>> vectorClass;
115                 if (unit instanceof SIUnit)
116                 {
117                     vectorClass = SIVector.class;
118                 }
119                 else
120                 {
121                     vectorClass = (Class<DoubleVector<?, ?, ?>>) Class.forName("org.djunits.value.vdouble.vector."
122                             + unit.getClass().getSimpleName().replace("Unit", "") + "Vector");
123                 }
124                 vectorConstructor = vectorClass.getDeclaredConstructor(DoubleVectorData.class, unit.getClass());
125                 CACHE.put(unit, vectorConstructor);
126             }
127             return (V) vectorConstructor.newInstance(data, unit);
128         }
129         catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
130                 | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception)
131         {
132             throw new UnitRuntimeException(
133                     "Cannot instantiate DoubleVector of unit " + unit.toString() + ". Reason: " + exception.getMessage());
134         }
135     }
136 }