package org.gbif.occurrence.common.json;
import org.gbif.dwc.terms.Term;
import org.gbif.dwc.terms.jackson.TermKeyDeserializer;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.base.Throwables;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.SerializationConfig.Feature;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.ser.std.SerializerBase;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.type.JavaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class for common operations while persisting and retrieving extension objects.
*/
public class ExtensionSerDeserUtils {
private static final Logger LOG = LoggerFactory.getLogger(ExtensionSerDeserUtils.class);
private static final String DEFAULT_ERROR_MSG = "Error serializing extensions values";
private static final JavaType LIST_MAP_TERMS_TYPE;
private static final ObjectMapper MAPPER = new ObjectMapper();
static {
MAPPER.enable(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
MAPPER.enable(SerializationConfig.Feature.INDENT_OUTPUT);
MAPPER.setSerializationConfig(MAPPER.getSerializationConfig().withSerializationInclusion(Inclusion.ALWAYS));
TypeFactory typeFactory = MAPPER.getTypeFactory();
LIST_MAP_TERMS_TYPE =
typeFactory.constructCollectionType(List.class,
typeFactory.constructMapType(Map.class, Term.class, String.class));
SimpleModule extensionsModule = new SimpleModule("Verbatim", Version.unknownVersion());
extensionsModule.addSerializer(new InnerTermMapListSerializer());
extensionsModule.addKeyDeserializer(Term.class, new TermKeyDeserializer());
MAPPER.registerModule(extensionsModule);
}
/**
* Inner class that serializes List<Map<Term, String>> objects.
*/
private static class InnerTermMapListSerializer extends SerializerBase<List<Map<Term, String>>> {
protected InnerTermMapListSerializer() {
super(LIST_MAP_TERMS_TYPE);
}
@Override
public void serialize(List<Map<Term, String>> value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
if ((value == null || value.isEmpty()) && provider.getConfig().isEnabled(Feature.WRITE_EMPTY_JSON_ARRAYS)) {
jgen.writeStartArray();
jgen.writeEndArray();
} else {
jgen.writeStartArray();
for (Map<Term, String> extension : value) {
jgen.writeStartObject();
for (Entry<Term, String> entry : extension.entrySet()) {
jgen.writeStringField(entry.getKey().qualifiedName(), entry.getValue());
}
jgen.writeEndObject();
}
jgen.writeEndArray();
}
}
}
private ExtensionSerDeserUtils() {
// private constructor
}
/**
* Serializes a List<Map<Term, String>> to a Json String.
*/
public static String toJson(List<Map<Term, String>> extensionValues) {
try {
return MAPPER.writeValueAsString(extensionValues);
} catch (IOException e) {
LOG.error(DEFAULT_ERROR_MSG, e);
Throwables.propagate(e);
}
return null;
}
/**
* Deserializes a List<Map<Term, String>> from a Json String.
*/
public static List<Map<Term, String>> fromJson(String json) {
try (StringReader stringReader = new StringReader(json)) {
return MAPPER.readValue(stringReader, LIST_MAP_TERMS_TYPE);
} catch (IOException e) {
LOG.error(DEFAULT_ERROR_MSG, e);
Throwables.propagate(e);
}
return null;
}
}