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