package decoder;
import api.Decoder;
import api.MessageDecoder;
import api.annotations.Constructor;
import api.annotations.Size;
import api.exceptions.DecodingException;
import decoder.primitive.IntDecoder;
import decoder.primitive.NumberDecoder;
import org.apache.commons.beanutils.BeanUtils;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
/**
* If you see it, than I've forgotten javadoc
*
* @author Denis Golovachev
* @author $Author$ (current maintainer)
* @since 1.0
*/
public class ContentMessageDecoder implements MessageDecoder {
private Map<Class, Decoder> decodersMap = DefaultDecoderConfig.decodersMap();
private Decoder<Integer> integerDecoder = new IntDecoder();
@Override
public <T> T decode(InputStream data, Class<T> objClass) throws DecodingException {
try {
return tryDecode(data, objClass);
} catch (InstantiationException e) {
throw new DecodingException("Construct failed", e);
} catch (IllegalAccessException e) {
throw new DecodingException("Construct failed", e);
} catch (InvocationTargetException e) {
throw new DecodingException("Decoding went wrong", e);
}
}
private <T> T tryDecode(InputStream data, Class<T> objClass) throws InstantiationException, IllegalAccessException, InvocationTargetException, DecodingException {
int constructorCode = objClass.getAnnotation(Constructor.class).value();
if(constructorCode != integerDecoder.decode(data)) {
throw new DecodingException("Another object was received");
}
T obj = objClass.newInstance();
Field[] fields = objClass.getDeclaredFields();
for(Field field: fields) {
Decoder decoder = lookupDecoder(field);
BeanUtils.setProperty(obj, field.getName(), decoder.decode(data));
}
return obj;
}
private Decoder lookupDecoder(Field field) {
Decoder decoder = decodersMap.get(field.getType());
if(field.getType() == Number.class) {
decoder = new NumberDecoder(field.getAnnotation(Size.class).value());
}
return decoder;
}
public void setDecodersMap(Map<Class, Decoder> decodersMap) {
this.decodersMap = decodersMap;
}
}