001package org.conqat.engine.commons.util;
002
003import java.io.IOException;
004import java.io.Serializable;
005import java.util.Arrays;
006import java.util.Collection;
007
008import org.conqat.lib.commons.collections.ListMap;
009import org.conqat.lib.commons.collections.UnmodifiableSet;
010
011import com.fasterxml.jackson.annotation.JsonCreator;
012import com.fasterxml.jackson.annotation.JsonProperty;
013import com.fasterxml.jackson.core.JsonGenerator;
014import com.fasterxml.jackson.core.JsonParser;
015import com.fasterxml.jackson.databind.DeserializationContext;
016import com.fasterxml.jackson.databind.JsonDeserializer;
017import com.fasterxml.jackson.databind.JsonSerializer;
018import com.fasterxml.jackson.databind.SerializerProvider;
019import com.fasterxml.jackson.databind.module.SimpleModule;
020
021/**
022 * Jackson module which supports serialization and deserialization of
023 * {@link ListMap} object and back.
024 */
025public class ListMapSerializationModule extends SimpleModule {
026
027        ListMapSerializationModule() {
028                addSerializer(ListMap.class, new ListMapSerializer());
029                addDeserializer(ListMap.class, new ListMapDeserializer());
030        }
031
032        /** Serializer for {@link ListMap} objects. */
033        private static class ListMapSerializer extends JsonSerializer<ListMap> {
034
035                @Override
036                public void serialize(ListMap value, JsonGenerator generator, SerializerProvider serializers)
037                                throws IOException {
038                        UnmodifiableSet keys = value.getKeys();
039                        SerializableListMapEntry[] entries = new SerializableListMapEntry[keys.size()];
040                        int i = 0;
041                        for (Object key : keys) {
042                                entries[i++] = new SerializableListMapEntry(key, value.getCollection(key));
043                        }
044                        generator.writeObject(entries);
045                }
046        }
047
048        /** Deserializer for {@link ListMap} objects. */
049        private static class ListMapDeserializer extends JsonDeserializer<ListMap> {
050
051                @Override
052                public ListMap deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
053                        SerializableListMapEntry[] root = parser.getCodec().readValue(parser, SerializableListMapEntry[].class);
054                        ListMap<Object, Serializable> listMap = new ListMap<>();
055                        for (SerializableListMapEntry serializableListMapEntry : root) {
056                                listMap.addAll(serializableListMapEntry.key, Arrays.asList(serializableListMapEntry.values));
057                        }
058                        return listMap;
059                }
060        }
061
062        private static class SerializableListMapEntry {
063
064                /** The name of the JSON property name for {@link #key}. */
065                private static final String KEY_PROPERTY = "key";
066
067                /** The name of the JSON property name for {@link #values}. */
068                private static final String VALUES_PROPERTY = "values";
069
070                @JsonProperty(KEY_PROPERTY)
071                private final Object key;
072
073                @JsonProperty(VALUES_PROPERTY)
074                private final Serializable[] values;
075
076                @JsonCreator
077                private SerializableListMapEntry(@JsonProperty(KEY_PROPERTY) Object key,
078                                @JsonProperty(VALUES_PROPERTY) Collection<Serializable> values) {
079                        this.key = key;
080                        this.values = values.toArray(new Serializable[0]);
081                }
082        }
083
084}