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.ValueRuntimeException;
13 import org.djunits.value.storage.StorageType;
14 import org.djunits.value.vfloat.matrix.FloatSIMatrix;
15 import org.djunits.value.vfloat.matrix.base.FloatMatrix;
16 import org.djunits.value.vfloat.matrix.data.FloatMatrixData;
17 import org.djunits.value.vfloat.scalar.base.FloatScalar;
18 import org.djunits.value.vfloat.vector.base.FloatVector;
19 import org.djutils.serialization.EndianUtil;
20 import org.djutils.serialization.FieldTypes;
21 import org.djutils.serialization.SerializationException;
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public class FloatMatrixSerializer<U extends Unit<U>, S extends FloatScalar<U, S>, V extends FloatVector<U, S, V>,
36 M extends FloatMatrix<U, S, V, M>> extends ArrayOrMatrixWithUnitSerializer<U, M>
37 {
38
39 private static final Map<Unit<?>, Constructor<? extends FloatMatrix<?, ?, ?, ?>>> CACHE = new HashMap<>();
40
41
42 public FloatMatrixSerializer()
43 {
44 super(FieldTypes.FLOAT_32_UNIT_MATRIX, "Djunits_FloatMatrix", 2);
45 }
46
47 @Override
48 public int size(final M afm) throws SerializationException
49 {
50 try
51 {
52 return 4 + 4 + 2 + 4 * afm.rows() * afm.cols();
53 }
54 catch (ValueRuntimeException e)
55 {
56 throw new SerializationException(e);
57 }
58 }
59
60 @Override
61 public void serialize(final M afm, final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil)
62 throws SerializationException
63 {
64 try
65 {
66 endianUtil.encodeInt(afm.rows(), buffer, pointer.getAndIncrement(4));
67 endianUtil.encodeInt(afm.cols(), buffer, pointer.getAndIncrement(4));
68 encodeUnit(afm.getDisplayUnit(), buffer, pointer, endianUtil);
69 for (int i = 0; i < afm.rows(); i++)
70 {
71 for (int j = 0; j < afm.cols(); j++)
72 {
73 endianUtil.encodeFloat(afm.get(i, j).getSI(), buffer, pointer.getAndIncrement(4));
74 }
75 }
76 }
77 catch (ValueRuntimeException e)
78 {
79 throw new SerializationException(e);
80 }
81 }
82
83 @Override
84 public M deSerialize(final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil) throws SerializationException
85 {
86 int height = endianUtil.decodeInt(buffer, pointer.getAndIncrement(4));
87 int width = endianUtil.decodeInt(buffer, pointer.getAndIncrement(4));
88 Unit<? extends Unit<?>> unit = getUnit(buffer, pointer, endianUtil);
89 float[][] array = new float[height][width];
90 for (int i = 0; i < height; i++)
91 {
92 for (int j = 0; j < width; j++)
93 {
94 array[i][j] = endianUtil.decodeFloat(buffer, pointer.getAndIncrement(4));
95 }
96 }
97 try
98 {
99 FloatMatrixData fvd = FloatMatrixData.instantiate(array, IdentityScale.SCALE, StorageType.DENSE);
100 return instantiateAnonymous(fvd, unit);
101 }
102 catch (ValueRuntimeException exception)
103 {
104 throw new SerializationException(exception);
105 }
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120 @SuppressWarnings("unchecked")
121 public static <U extends Unit<U>, S extends FloatScalar<U, S>, V extends FloatVector<U, S, V>,
122 M extends FloatMatrix<U, S, V, M>> M instantiateAnonymous(final FloatMatrixData data, final Unit<?> unit)
123 {
124 try
125 {
126 Constructor<? extends FloatMatrix<?, ?, ?, ?>> matrixConstructor = CACHE.get(unit);
127 if (matrixConstructor == null)
128 {
129 if (!unit.getClass().getSimpleName().endsWith("Unit"))
130 {
131 throw new ClassNotFoundException("Unit " + unit.getClass().getSimpleName()
132 + " name does noet end with 'Unit'. Cannot find corresponding scalar");
133 }
134 Class<? extends FloatMatrix<?, ?, ?, ?>> matrixClass;
135 if (unit instanceof SIUnit)
136 {
137 matrixClass = FloatSIMatrix.class;
138 }
139 else
140 {
141 matrixClass = (Class<FloatMatrix<?, ?, ?, ?>>) Class.forName("org.djunits.value.vfloat.matrix.Float"
142 + unit.getClass().getSimpleName().replace("Unit", "") + "Matrix");
143 }
144 matrixConstructor = matrixClass.getDeclaredConstructor(FloatMatrixData.class, unit.getClass());
145 CACHE.put(unit, matrixConstructor);
146 }
147 return (M) matrixConstructor.newInstance(data, unit);
148 }
149 catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
150 | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception)
151 {
152 throw new UnitRuntimeException(
153 "Cannot instantiate FloatMatrix of unit " + unit.toString() + ". Reason: " + exception.getMessage());
154 }
155 }
156
157 }