package com.forter.contracts; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.serializers.FieldSerializer; import com.google.common.base.Optional; import com.google.common.base.Throwables; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; /** * Creates a new object and fills Optional.absent() */ public class ContractFactory<T> { private final Kryo kryo; private final T newInstance; public ContractFactory(Class<T> clazz) { this.kryo = new Kryo(); kryo.register(clazz, new FieldSerializer(kryo, clazz)); newInstance = createAndInitializeInstance(clazz); } public T newInstance() { return kryo.copy(newInstance); } private <T> T createAndInitializeInstance(Class<T> clazz) { T instance = createInstance(clazz); initializeOptionalAsAbsent(instance); return instance; } private static <T> void initializeOptionalAsAbsent(T instance) { Class<?> clazz = instance.getClass(); while (clazz != null && clazz != Object.class) { Field[] fields = instance.getClass().getDeclaredFields(); for (Field field : fields) { Class fieldType = field.getType(); if (Optional.class.isAssignableFrom(fieldType)) { try { field.setAccessible(true); field.set(instance, Optional.absent()); } catch (IllegalAccessException e) { throw Throwables.propagate(e); } } } clazz = clazz.getSuperclass(); } } private static <T> T createInstance(Class<T> clazz) { try { return clazz.getConstructor().newInstance(); } catch (InstantiationException|IllegalAccessException|InvocationTargetException | NoSuchMethodException e) { throw Throwables.propagate(e); } } }