Skip to content

Commit 25d6256

Browse files
committed
work on SerializationSpecWriter and XMLSpecWriter + tests
1 parent 9f3624e commit 25d6256

File tree

8 files changed

+340
-117
lines changed

8 files changed

+340
-117
lines changed

net.lecousin.core/src/main/java/net/lecousin/framework/io/serialization/AbstractSerializationSpecWriter.java

Lines changed: 105 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package net.lecousin.framework.io.serialization;
22

3+
import java.io.InputStream;
4+
import java.util.ArrayList;
5+
import java.util.Collection;
36
import java.util.List;
7+
import java.util.Map;
48

59
import net.lecousin.framework.concurrent.Task;
610
import net.lecousin.framework.concurrent.synch.ISynchronizationPoint;
@@ -9,7 +13,9 @@
913
import net.lecousin.framework.io.IO;
1014
import net.lecousin.framework.io.serialization.SerializationClass.Attribute;
1115
import net.lecousin.framework.io.serialization.SerializationContext.AttributeContext;
16+
import net.lecousin.framework.io.serialization.SerializationContext.CollectionContext;
1217
import net.lecousin.framework.io.serialization.SerializationContext.ObjectContext;
18+
import net.lecousin.framework.io.serialization.SerializationUtil.MapEntry;
1319
import net.lecousin.framework.io.serialization.annotations.AttributeAnnotationToRuleOnAttribute;
1420
import net.lecousin.framework.io.serialization.annotations.AttributeAnnotationToRuleOnType;
1521
import net.lecousin.framework.io.serialization.annotations.TypeAnnotationToRule;
@@ -73,43 +79,129 @@ protected List<SerializationRule> addRulesForAttribute(Attribute a, List<Seriali
7379
protected ISynchronizationPoint<? extends Exception> specifyValue(
7480
SerializationContext context, TypeDefinition typeDef, List<SerializationRule> rules
7581
) {
82+
for (SerializationRule rule : rules)
83+
typeDef = rule.getDeserializationType(typeDef, context);
84+
7685
Class<?> type = typeDef.getBase();
7786

87+
if (type.isArray()) {
88+
Class<?> elementType = type.getComponentType();
89+
CollectionContext ctx = new CollectionContext(context, null, typeDef, new TypeDefinition(elementType));
90+
return specifyCollectionValue(ctx, rules);
91+
}
92+
7893
if (boolean.class.equals(type))
79-
return specifyBooleanValue(false);
94+
return specifyBooleanValue(context, false);
8095
if (Boolean.class.equals(type))
81-
return specifyBooleanValue(true);
96+
return specifyBooleanValue(context, true);
8297

8398
if (byte.class.equals(type))
84-
return specifyNumericValue(Byte.class, false, Byte.valueOf(Byte.MIN_VALUE), Byte.valueOf(Byte.MAX_VALUE));
99+
return specifyNumericValue(context, Byte.class, false, Byte.valueOf(Byte.MIN_VALUE), Byte.valueOf(Byte.MAX_VALUE));
85100
if (Byte.class.equals(type))
86-
return specifyNumericValue(Byte.class, true, Byte.valueOf(Byte.MIN_VALUE), Byte.valueOf(Byte.MAX_VALUE));
101+
return specifyNumericValue(context, Byte.class, true, Byte.valueOf(Byte.MIN_VALUE), Byte.valueOf(Byte.MAX_VALUE));
87102
if (short.class.equals(type))
88-
return specifyNumericValue(Short.class, false, Short.valueOf(Short.MIN_VALUE), Short.valueOf(Short.MAX_VALUE));
103+
return specifyNumericValue(context, Short.class, false, Short.valueOf(Short.MIN_VALUE), Short.valueOf(Short.MAX_VALUE));
89104
if (Short.class.equals(type))
90-
return specifyNumericValue(Short.class, true, Short.valueOf(Short.MIN_VALUE), Short.valueOf(Short.MAX_VALUE));
105+
return specifyNumericValue(context, Short.class, true, Short.valueOf(Short.MIN_VALUE), Short.valueOf(Short.MAX_VALUE));
91106
if (int.class.equals(type))
92-
return specifyNumericValue(Integer.class, false, Integer.valueOf(Integer.MIN_VALUE), Integer.valueOf(Integer.MAX_VALUE));
107+
return specifyNumericValue(context, Integer.class, false,
108+
Integer.valueOf(Integer.MIN_VALUE), Integer.valueOf(Integer.MAX_VALUE));
93109
if (Integer.class.equals(type))
94-
return specifyNumericValue(Integer.class, true, Integer.valueOf(Integer.MIN_VALUE), Integer.valueOf(Integer.MAX_VALUE));
110+
return specifyNumericValue(context, Integer.class, true,
111+
Integer.valueOf(Integer.MIN_VALUE), Integer.valueOf(Integer.MAX_VALUE));
95112
if (long.class.equals(type))
96-
return specifyNumericValue(Long.class, false, Long.valueOf(Long.MIN_VALUE), Long.valueOf(Long.MAX_VALUE));
113+
return specifyNumericValue(context, Long.class, false, Long.valueOf(Long.MIN_VALUE), Long.valueOf(Long.MAX_VALUE));
97114
if (Long.class.equals(type))
98-
return specifyNumericValue(Long.class, true, Long.valueOf(Long.MIN_VALUE), Long.valueOf(Long.MAX_VALUE));
115+
return specifyNumericValue(context, Long.class, true, Long.valueOf(Long.MIN_VALUE), Long.valueOf(Long.MAX_VALUE));
116+
if (float.class.equals(type) ||
117+
double.class.equals(type) ||
118+
Number.class.isAssignableFrom(type))
119+
return specifyNumericValue(context, type, !type.isPrimitive(), null, null);
120+
121+
if (char.class.equals(type))
122+
return specifyCharacterValue(context, false);
123+
if (Character.class.equals(type))
124+
return specifyCharacterValue(context, true);
99125

100126
if (CharSequence.class.isAssignableFrom(type))
101127
return specifyStringValue(context, typeDef);
128+
129+
if (type.isEnum())
130+
return specifyEnumValue(context, typeDef);
131+
132+
if (Collection.class.isAssignableFrom(type)) {
133+
TypeDefinition elementType;
134+
if (typeDef.getParameters().isEmpty())
135+
elementType = null;
136+
else
137+
elementType = typeDef.getParameters().get(0);
138+
CollectionContext ctx = new CollectionContext(context, null, typeDef, elementType);
139+
return specifyCollectionValue(ctx, rules);
140+
}
102141

103-
// TODO
142+
if (Map.class.isAssignableFrom(type))
143+
return specifyMapValue(context, typeDef, rules);
144+
145+
if (InputStream.class.isAssignableFrom(type))
146+
return specifyInputStreamValue(context, rules);
147+
148+
if (IO.Readable.class.isAssignableFrom(type))
149+
return specifyIOReadableValue(context, rules);
104150

105151
return specifyObjectValue(context, typeDef, rules);
106152
}
107153

108-
protected abstract ISynchronizationPoint<? extends Exception> specifyBooleanValue(boolean nullable);
154+
// *** boolean ***
155+
156+
protected abstract ISynchronizationPoint<? extends Exception> specifyBooleanValue(SerializationContext context, boolean nullable);
157+
158+
// *** number ***
109159

110-
protected abstract ISynchronizationPoint<? extends Exception> specifyNumericValue(Class<?> type, boolean nullable, Number min, Number max);
160+
protected abstract ISynchronizationPoint<? extends Exception> specifyNumericValue(
161+
SerializationContext context, Class<?> type, boolean nullable, Number min, Number max);
162+
163+
// *** character ***
164+
165+
protected abstract ISynchronizationPoint<? extends Exception> specifyCharacterValue(SerializationContext context, boolean nullable);
166+
167+
// *** string ***
111168

112169
protected abstract ISynchronizationPoint<? extends Exception> specifyStringValue(SerializationContext context, TypeDefinition type);
170+
171+
// *** enum ***
172+
173+
protected abstract ISynchronizationPoint<? extends Exception> specifyEnumValue(SerializationContext context, TypeDefinition type);
174+
175+
// *** collection ***
176+
177+
protected abstract ISynchronizationPoint<? extends Exception> specifyCollectionValue(
178+
CollectionContext context, List<SerializationRule> rules);
179+
180+
// *** map ***
181+
182+
protected ISynchronizationPoint<? extends Exception> specifyMapValue(
183+
SerializationContext context, TypeDefinition type, List<SerializationRule> rules
184+
) {
185+
TypeDefinition elementType = new TypeDefinition(MapEntry.class, type.getParameters());
186+
TypeDefinition colType = new TypeDefinition(ArrayList.class, elementType);
187+
CollectionContext ctx = new CollectionContext(context, null, colType, elementType);
188+
return specifyCollectionValue(ctx, rules);
189+
}
190+
191+
// *** InputStream ***
192+
193+
protected ISynchronizationPoint<? extends Exception> specifyInputStreamValue(
194+
SerializationContext context, List<SerializationRule> rules
195+
) {
196+
return specifyIOReadableValue(context, rules);
197+
}
198+
199+
// *** IO.Readable ***
200+
201+
protected abstract ISynchronizationPoint<? extends Exception> specifyIOReadableValue(
202+
SerializationContext context, List<SerializationRule> rules);
203+
204+
// *** object ***
113205

114206
protected ISynchronizationPoint<? extends Exception> specifyObjectValue(
115207
SerializationContext context, TypeDefinition typeDef, List<SerializationRule> rules

net.lecousin.core/src/main/java/net/lecousin/framework/io/serialization/rules/MergeTypeAttributes.java

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,29 @@ public boolean apply(
4646
if (serializing) {
4747
// we need to change the instance
4848
Object containerObject = octx.getInstance();
49-
Object targetInstance;
50-
Method getter = ClassUtil.getGetter(containerObject.getClass(), targetAttributeName);
51-
if (getter != null)
52-
targetInstance = getter.invoke(containerObject);
53-
else {
54-
Field f = ClassUtil.getField(containerObject.getClass(), targetAttributeName);
55-
if (f != null)
56-
targetInstance = f.get(containerObject);
57-
else
58-
throw new Exception("Cannot find attribute " + targetAttributeName
59-
+ " on class " + containerObject.getClass().getName());
49+
TypeDefinition targetType;
50+
if (containerObject != null) {
51+
Object targetInstance;
52+
Method getter = ClassUtil.getGetter(containerObject.getClass(), targetAttributeName);
53+
if (getter != null)
54+
targetInstance = getter.invoke(containerObject);
55+
else {
56+
Field f = ClassUtil.getField(containerObject.getClass(), targetAttributeName);
57+
if (f != null)
58+
targetInstance = f.get(containerObject);
59+
else
60+
throw new Exception("Cannot find attribute " + targetAttributeName
61+
+ " on class " + containerObject.getClass().getName());
62+
}
63+
octx.setInstance(targetInstance);
64+
targetType = TypeDefinition.from(targetInstance.getClass(), ma.targetType);
65+
} else {
66+
Attribute a = octx.getSerializationClass().getAttributeByOriginalName(targetAttributeName);
67+
targetType = a.getOriginalType();
6068
}
61-
octx.setInstance(targetInstance);
6269
// we need to change the type
6370
SerializationClass containerClass = octx.getSerializationClass();
64-
SerializationClass sc =
65-
new SerializationClass(TypeDefinition.from(targetInstance.getClass(), ma.targetType));
71+
SerializationClass sc = new SerializationClass(targetType);
6672
octx.setSerializationClass(sc);
6773
octx.setOriginalType(ma.targetType);
6874
// we need to add other attributes
@@ -116,28 +122,34 @@ public boolean apply(
116122
if (serializing) {
117123
// we need to change the instance
118124
Object containerObject = octx.getInstance();
119-
Object targetInstance;
120-
Method getter =
125+
TypeDefinition newType;
126+
if (containerObject != null) {
127+
Object targetInstance;
128+
Method getter =
121129
ClassUtil.getGetter(containerObject.getClass(), targetAttributeName);
122-
if (getter != null)
123-
targetInstance = getter.invoke(containerObject);
124-
else {
125-
Field f = ClassUtil.getField(
126-
containerObject.getClass(), targetAttributeName);
127-
if (f != null)
128-
targetInstance = f.get(containerObject);
129-
else
130-
throw new Exception("Cannot find attribute "
131-
+ targetAttributeName
132-
+ " on class "
133-
+ containerObject.getClass().getName());
130+
if (getter != null)
131+
targetInstance = getter.invoke(containerObject);
132+
else {
133+
Field f = ClassUtil.getField(
134+
containerObject.getClass(), targetAttributeName);
135+
if (f != null)
136+
targetInstance = f.get(containerObject);
137+
else
138+
throw new Exception("Cannot find attribute "
139+
+ targetAttributeName
140+
+ " on class "
141+
+ containerObject.getClass().getName());
142+
}
143+
octx.setInstance(targetInstance);
144+
newType = TypeDefinition.from(targetInstance.getClass(), targetType);
145+
} else {
146+
Attribute a = octx.getSerializationClass()
147+
.getAttributeByOriginalName(targetAttributeName);
148+
newType = a.getOriginalType();
134149
}
135-
octx.setInstance(targetInstance);
136150
// we need to change the type
137151
SerializationClass containerClass = octx.getSerializationClass();
138-
SerializationClass sc =
139-
new SerializationClass(
140-
TypeDefinition.from(targetInstance.getClass(), targetType));
152+
SerializationClass sc = new SerializationClass(newType);
141153
octx.setSerializationClass(sc);
142154
octx.setOriginalType(targetType);
143155
// we need to add other attributes

net.lecousin.core/src/main/java/net/lecousin/framework/io/serialization/rules/SerializationRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ default Object convertSerializationValue(Object value, TypeDefinition type, Seri
2424
}
2525

2626
/** Can be used to change a type during deserialization, in a similar way as the method
27-
* convertSerializationValue during serialization.
27+
* convertSerializationValue during serialization. This is also used for writing
28+
* serialization specification.
2829
*/
2930
default TypeDefinition getDeserializationType(TypeDefinition type, SerializationContext context) {
3031
return type;

net.lecousin.core/src/main/java/net/lecousin/framework/memory/MemoryManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ public static void logMemory(Level level) {
228228
logger.log(level, s.toString());
229229
}
230230

231+
/** Log memory status into the given StringBuilder. */
231232
public static void logMemory(StringBuilder s) {
232233
long total = Runtime.getRuntime().totalMemory();
233234
long free = Runtime.getRuntime().freeMemory();

net.lecousin.core/src/main/java/net/lecousin/framework/xml/serialization/XMLSerializer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,14 @@ public int compare(Attribute o1, Attribute o2) {
162162
if (c.isPrimitive()) return -1;
163163
if (Boolean.class.equals(c)) return -1;
164164
if (Number.class.isAssignableFrom(c)) return -1;
165-
if (String.class.equals(c)) return -1;
165+
if (CharSequence.class.isAssignableFrom(c)) return -1;
166166
if (Character.class.equals(c)) return -1;
167167
if (c.isEnum()) return -1;
168168
c = o2.getType().getBase();
169169
if (c.isPrimitive()) return 1;
170170
if (Boolean.class.equals(c)) return 1;
171171
if (Number.class.isAssignableFrom(c)) return 1;
172-
if (String.class.equals(c)) return 1;
172+
if (CharSequence.class.isAssignableFrom(c)) return 1;
173173
if (Character.class.equals(c)) return 1;
174174
if (c.isEnum()) return 1;
175175
return 0;
@@ -218,7 +218,7 @@ protected ISynchronizationPoint<IOException> serializeNullAttribute(AttributeCon
218218
if (c.isPrimitive() ||
219219
Boolean.class.equals(c) ||
220220
Number.class.isAssignableFrom(c) ||
221-
String.class.equals(c) ||
221+
CharSequence.class.isAssignableFrom(c) ||
222222
Character.class.equals(c) ||
223223
c.isEnum())
224224
return new SynchronizationPoint<>(true);

0 commit comments

Comments
 (0)