![JAR search and dependency download from the Maven repository](/logo.png)
net.lecousin.framework.serialization.AbstractSerializationSpecWriter Maven / Gradle / Ivy
The newest version!
package net.lecousin.framework.serialization;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.lecousin.framework.concurrent.async.Async;
import net.lecousin.framework.concurrent.async.IAsync;
import net.lecousin.framework.concurrent.threads.Task;
import net.lecousin.framework.concurrent.threads.Task.Priority;
import net.lecousin.framework.exception.NoException;
import net.lecousin.framework.io.IO;
import net.lecousin.framework.serialization.SerializationClass.Attribute;
import net.lecousin.framework.serialization.SerializationContext.AttributeContext;
import net.lecousin.framework.serialization.SerializationContext.CollectionContext;
import net.lecousin.framework.serialization.SerializationContext.ObjectContext;
import net.lecousin.framework.serialization.SerializationUtil.MapEntry;
import net.lecousin.framework.serialization.annotations.AttributeAnnotationToRuleOnAttribute;
import net.lecousin.framework.serialization.annotations.AttributeAnnotationToRuleOnType;
import net.lecousin.framework.serialization.annotations.TypeAnnotationToRule;
import net.lecousin.framework.serialization.rules.SerializationRule;
/** Generate serialization specification. */
public abstract class AbstractSerializationSpecWriter implements SerializationSpecWriter {
protected Priority priority;
protected final String taskDescription = "Write specification using " + getClass().getName();
protected abstract IAsync initializeSpecWriter(IO.Writable output);
protected abstract IAsync finalizeSpecWriter();
@Override
public IAsync writeSpecification(Class> type, IO.Writable output, List rules) {
priority = output.getPriority();
IAsync init = initializeSpecWriter(output);
Async result = new Async<>();
init.thenStart(taskDescription, priority, (Task t) -> {
IAsync sp;
if (type != null)
sp = specifyValue(null, new TypeDefinition(type), rules);
else
sp = specifyAnyValue(null);
sp.onDone(() -> finalizeSpecWriter().onDone(result), result);
return null;
}, result);
return result;
}
protected List addRulesForType(SerializationClass type, List currentList) {
currentList = TypeAnnotationToRule.addRules(type.getType().getBase(), currentList);
currentList = AttributeAnnotationToRuleOnType.addRules(type, true, currentList);
return currentList;
}
protected List addRulesForAttribute(Attribute a, List currentList) {
return AttributeAnnotationToRuleOnAttribute.addRules(a, true, currentList);
}
protected abstract IAsync specifyAnyValue(SerializationContext context);
/** Can be used when already initialized. */
@SuppressWarnings("squid:S3776") // complexity
public IAsync specifyValue(
SerializationContext context, TypeDefinition typeDef, List rules
) {
for (SerializationRule rule : rules)
typeDef = rule.getDeserializationType(typeDef, context);
Class> type = typeDef.getBase();
if (type.isArray()) {
if (byte[].class.equals(type))
return specifyByteArrayValue(context, rules);
Class> elementType = type.getComponentType();
CollectionContext ctx = new CollectionContext(context, null, typeDef, new TypeDefinition(elementType));
return specifyCollectionValue(ctx, rules);
}
if (boolean.class.equals(type))
return specifyBooleanValue(context, false);
if (Boolean.class.equals(type))
return specifyBooleanValue(context, true);
if (byte.class.equals(type))
return specifyNumericValue(context, Byte.class, false, Byte.valueOf(Byte.MIN_VALUE), Byte.valueOf(Byte.MAX_VALUE));
if (Byte.class.equals(type))
return specifyNumericValue(context, Byte.class, true, Byte.valueOf(Byte.MIN_VALUE), Byte.valueOf(Byte.MAX_VALUE));
if (short.class.equals(type))
return specifyNumericValue(context, Short.class, false, Short.valueOf(Short.MIN_VALUE), Short.valueOf(Short.MAX_VALUE));
if (Short.class.equals(type))
return specifyNumericValue(context, Short.class, true, Short.valueOf(Short.MIN_VALUE), Short.valueOf(Short.MAX_VALUE));
if (int.class.equals(type))
return specifyNumericValue(context, Integer.class, false,
Integer.valueOf(Integer.MIN_VALUE), Integer.valueOf(Integer.MAX_VALUE));
if (Integer.class.equals(type))
return specifyNumericValue(context, Integer.class, true,
Integer.valueOf(Integer.MIN_VALUE), Integer.valueOf(Integer.MAX_VALUE));
if (long.class.equals(type))
return specifyNumericValue(context, Long.class, false, Long.valueOf(Long.MIN_VALUE), Long.valueOf(Long.MAX_VALUE));
if (Long.class.equals(type))
return specifyNumericValue(context, Long.class, true, Long.valueOf(Long.MIN_VALUE), Long.valueOf(Long.MAX_VALUE));
if (float.class.equals(type) ||
double.class.equals(type) ||
Number.class.isAssignableFrom(type))
return specifyNumericValue(context, type, !type.isPrimitive(), null, null);
if (char.class.equals(type))
return specifyCharacterValue(context, false);
if (Character.class.equals(type))
return specifyCharacterValue(context, true);
if (CharSequence.class.isAssignableFrom(type))
return specifyStringValue(context, typeDef);
if (type.isEnum())
return specifyEnumValue(context, typeDef);
if (Collection.class.isAssignableFrom(type)) {
TypeDefinition elementType;
if (typeDef.getParameters().isEmpty())
elementType = null;
else
elementType = typeDef.getParameters().get(0);
CollectionContext ctx = new CollectionContext(context, null, typeDef, elementType);
return specifyCollectionValue(ctx, rules);
}
if (Map.class.isAssignableFrom(type))
return specifyMapValue(context, typeDef, rules);
if (InputStream.class.isAssignableFrom(type))
return specifyInputStreamValue(context, rules);
if (IO.Readable.class.isAssignableFrom(type))
return specifyIOReadableValue(context, rules);
return specifyObjectValue(context, typeDef, rules);
}
// *** boolean ***
protected abstract IAsync specifyBooleanValue(SerializationContext context, boolean nullable);
// *** number ***
protected abstract IAsync specifyNumericValue(
SerializationContext context, Class> type, boolean nullable, Number min, Number max);
// *** character ***
protected abstract IAsync specifyCharacterValue(SerializationContext context, boolean nullable);
// *** string ***
protected abstract IAsync specifyStringValue(SerializationContext context, TypeDefinition type);
// *** enum ***
protected abstract IAsync specifyEnumValue(SerializationContext context, TypeDefinition type);
// *** collection ***
protected abstract IAsync specifyCollectionValue(
CollectionContext context, List rules);
// *** map ***
protected IAsync specifyMapValue(
SerializationContext context, TypeDefinition type, List rules
) {
TypeDefinition elementType = new TypeDefinition(MapEntry.class, type.getParameters());
TypeDefinition colType = new TypeDefinition(ArrayList.class, elementType);
CollectionContext ctx = new CollectionContext(context, null, colType, elementType);
return specifyCollectionValue(ctx, rules);
}
// *** InputStream ***
protected IAsync specifyInputStreamValue(
SerializationContext context, List rules
) {
return specifyIOReadableValue(context, rules);
}
// *** IO.Readable ***
protected abstract IAsync specifyIOReadableValue(
SerializationContext context, List rules);
// *** byte[] ***
protected IAsync specifyByteArrayValue(
SerializationContext context, List rules
) {
return specifyIOReadableValue(context, rules);
}
// *** object ***
protected IAsync specifyObjectValue(
SerializationContext context, TypeDefinition typeDef, List rules
) {
ObjectContext ctx;
try {
Class> type = typeDef.getBase();
SerializationClass sc = new SerializationClass(TypeDefinition.from(type, typeDef));
ctx = new ObjectContext(context, null, sc, typeDef);
rules = addRulesForType(sc, rules);
sc.apply(rules, ctx, true);
} catch (SerializationException e) {
return new Async<>(e);
}
return specifyTypedValue(ctx, rules);
}
protected abstract IAsync specifyTypedValue(ObjectContext context, List rules);
protected IAsync specifyTypeContent(ObjectContext context, List rules) {
List attributes = sortAttributes(context.getSerializationClass().getAttributes());
Async sp = new Async<>();
specifyTypeAttribute(context, attributes, 0, rules, sp);
return sp;
}
protected List sortAttributes(List attributes) {
return attributes;
}
protected void specifyTypeAttribute(
ObjectContext context, List attributes, int index, List rules,
Async sp
) {
if (index == attributes.size()) {
sp.unblock();
return;
}
Attribute attr = attributes.get(index);
AttributeContext ctx = new AttributeContext(context, attr);
IAsync s = specifyTypeAttribute(ctx, rules);
if (s.isDone()) {
if (s.hasError()) sp.error(s.getError());
else specifyTypeAttribute(context, attributes, index + 1, rules, sp);
return;
}
s.thenStart(taskDescription, priority, () -> specifyTypeAttribute(context, attributes, index + 1, rules, sp), sp);
}
protected abstract IAsync specifyTypeAttribute(
AttributeContext context, List rules);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy