/*
* (c) Copyright Reserved EVRYTHNG Limited 2016. All rights reserved.
* Use of this material is subject to license.
* Copying and unauthorised use of this material strictly prohibited.
*/
package com.evrythng.java.wrapper.mapping;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Base class for deserializers with a type map.
*
**/
public abstract class TypeMapDeserializer<T> extends Deserializer<T> {
private static final long serialVersionUID = 1L;
private Map<String, Class<? extends T>> registry = new HashMap<>();
private Map<Class<? extends T>, String> reverseRegistry = new HashMap<>();
private String typeFieldName;
protected TypeMapDeserializer(final Class<?> cls, final String fieldName) {
super(cls);
this.typeFieldName = fieldName;
}
public void registerType(final String type, final Class<? extends T> objectClass) {
registry.put(type, objectClass);
reverseRegistry.put(objectClass, type);
}
@Override
public T deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
ObjectCodec codec = jp.getCodec();
ObjectMapper mapper = (ObjectMapper) codec;
ObjectNode root = mapper.readTree(jp);
JsonNode type = root.get(typeFieldName);
final String sType = type == null ? null : type.textValue();
Class<? extends T> clazz = resolveClass(sType);
return codec.treeToValue(root, clazz);
}
protected Class<? extends T> resolveClass(final String type) {
Class<? extends T> clazz = registry.get(type);
if (clazz == null) {
throw new IllegalArgumentException(this.getValueClass().getSimpleName() + " type '" + type + "' is not recognized.");
}
return clazz;
}
public <U extends T> String getObjectType(final Class<U> objectClass) {
return reverseRegistry.get(objectClass);
}
public String getTypeFieldName() {
return typeFieldName;
}
}