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.vfloat.scalar.base.FloatScalar;
14  import org.djunits.value.vfloat.vector.FloatSIVector;
15  import org.djunits.value.vfloat.vector.base.FloatVector;
16  import org.djunits.value.vfloat.vector.data.FloatVectorData;
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 FloatVector.
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 FloatVectorSerializer<U extends Unit<U>, S extends FloatScalar<U, S>, V extends FloatVector<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 FloatVector<?, ?, ?>>> CACHE = new HashMap<>();
37  
38      /** */
39      public FloatVectorSerializer()
40      {
41          super(FieldTypes.FLOAT_32_UNIT_ARRAY, "Djunits_FloatVector", 1);
42      }
43  
44      @Override
45      public int size(final V afv)
46      {
47          return 4 + 2 + 4 * afv.size();
48      }
49  
50      @Override
51      public int getElementSize()
52      {
53          return 4;
54      }
55  
56      @Override
57      public void serialize(final V afv, final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil)
58      {
59          endianUtil.encodeInt(afv.size(), buffer, pointer.getAndIncrement(4));
60          encodeUnit(afv.getDisplayUnit(), buffer, pointer, endianUtil);
61          for (int i = 0; i < afv.size(); i++)
62          {
63              endianUtil.encodeFloat(afv.get(i).getSI(), buffer, pointer.getAndIncrement(4));
64          }
65      }
66  
67      @Override
68      public V deSerialize(final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil) throws SerializationException
69      {
70          int size = endianUtil.decodeInt(buffer, pointer.getAndIncrement(4));
71          Unit<?> unit = getUnit(buffer, pointer, endianUtil);
72          float[] array = new float[size];
73          for (int i = 0; i < size; i++)
74          {
75              array[i] = endianUtil.decodeFloat(buffer, pointer.getAndIncrement(4));
76          }
77          try
78          {
79              FloatVectorData fvd = FloatVectorData.instantiate(array, IdentityScale.SCALE, StorageType.DENSE);
80              return instantiateAnonymous(fvd, unit);
81          }
82          catch (UnitRuntimeException exception)
83          {
84              throw new SerializationException(exception);
85          }
86      }
87  
88      /**
89       * Instantiate the FloatVector based on its unit. Loose check for types on the compiler. This allows the unit to be
90       * specified as a Unit&lt;?&gt; type.<br>
91       * <b>Note</b> that it is possible to make mistakes with anonymous units.
92       * @param data the values
93       * @param unit the unit in which the value is expressed
94       * @return an instantiated FloatVector with the provided displayUunit
95       * @param <U> the unit type
96       * @param <S> the scalar type
97       * @param <V> the vector type
98       */
99      @SuppressWarnings("unchecked")
100     public static <U extends Unit<U>, S extends FloatScalar<U, S>,
101             V extends FloatVector<U, S, V>> V instantiateAnonymous(final FloatVectorData data, final Unit<?> unit)
102     {
103         try
104         {
105             Constructor<? extends FloatVector<?, ?, ?>> vectorConstructor = CACHE.get(unit);
106             if (vectorConstructor == null)
107             {
108                 if (!unit.getClass().getSimpleName().endsWith("Unit"))
109                 {
110                     throw new ClassNotFoundException("Unit " + unit.getClass().getSimpleName()
111                             + " name does noet end with 'Unit'. Cannot find corresponding scalar");
112                 }
113                 Class<? extends FloatVector<?, ?, ?>> vectorClass;
114                 if (unit instanceof SIUnit)
115                 {
116                     vectorClass = FloatSIVector.class;
117                 }
118                 else
119                 {
120                     vectorClass = (Class<FloatVector<?, ?, ?>>) Class.forName("org.djunits.value.vfloat.vector.Float"
121                             + unit.getClass().getSimpleName().replace("Unit", "") + "Vector");
122                 }
123                 vectorConstructor = vectorClass.getDeclaredConstructor(FloatVectorData.class, unit.getClass());
124                 CACHE.put(unit, vectorConstructor);
125             }
126             return (V) vectorConstructor.newInstance(data, unit);
127         }
128         catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
129                 | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception)
130         {
131             throw new UnitRuntimeException(
132                     "Cannot instantiate FloatVector of unit " + unit.toString() + ". Reason: " + exception.getMessage());
133         }
134     }
135 
136 }