All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.codecamp.messages.shared.model.AbstractPersistableData Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
package de.codecamp.messages.shared.model;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;


public abstract class AbstractPersistableData
{

  private static final Gson GSON;
  static
  {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setPrettyPrinting();
    gsonBuilder.registerTypeAdapter(SortedSetMultimap.class, new SortedSetMultimapSerializer());
    gsonBuilder.registerTypeAdapter(SetMultimap.class, new SetMultimapSerializer());
    gsonBuilder.registerTypeAdapter(Instant.class, new InstantSerializer());
    gsonBuilder.registerTypeAdapter(Locale.class, new LocaleSerializer());
    GSON = gsonBuilder.create();
  }


  public void writeTo(OutputStream outputStream)
    throws PersistableDataException
  {
    try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))
    {
      GSON.toJson(this, writer);
      writer.flush();
    }
    catch (IOException ex)
    {
      throw new PersistableDataException(ex);
    }
  }

  public void writeTo(Path path)
    throws PersistableDataException
  {
    try
    {
      Files.createDirectories(path.getParent());
      try (OutputStream out = Files.newOutputStream(path, StandardOpenOption.CREATE,
          StandardOpenOption.TRUNCATE_EXISTING))
      {
        writeTo(out);
      }
    }
    catch (IOException ex)
    {
      throw new PersistableDataException(ex);
    }
  }

  protected static  T readFrom(InputStream inputStream, Class type)
    throws PersistableDataException
  {
    try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8))
    {
      return GSON.fromJson(reader, type);
    }
    catch (IOException | JsonIOException | JsonSyntaxException ex)
    {
      throw new PersistableDataException(ex);
    }
  }

  protected static  T readFrom(Path path, Class type)
    throws PersistableDataException
  {
    try (InputStream in = Files.newInputStream(path))
    {
      return readFrom(in, type);
    }
    catch (IOException | JsonIOException | JsonSyntaxException ex)
    {
      throw new PersistableDataException(ex);
    }
  }


  private static class LocaleSerializer
    implements
      JsonSerializer,
      JsonDeserializer
  {

    @Override
    public JsonElement serialize(Locale src, Type typeOfSrc, JsonSerializationContext context)
    {
      return context.serialize(src.toLanguageTag());
    }

    @Override
    public Locale deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException
    {
      String languageTag = context.deserialize(json, String.class);
      return Locale.forLanguageTag(languageTag);
    }

  }

  private static class InstantSerializer
    implements
      JsonSerializer,
      JsonDeserializer
  {

    @Override
    public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context)
    {
      return context.serialize(DateTimeFormatter.ISO_INSTANT.format(src));
    }

    @Override
    public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException
    {
      String instantString = context.deserialize(json, String.class);
      return DateTimeFormatter.ISO_INSTANT.parse(instantString, Instant::from);
    }

  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private static class SortedSetMultimapSerializer
    implements
      JsonSerializer,
      JsonDeserializer
  {

    @Override
    public JsonElement serialize(SortedSetMultimap src, Type typeOfSrc,
        JsonSerializationContext context)
    {
      return context.serialize(src.asMap(), Map.class);
    }

    @Override
    public SortedSetMultimap deserialize(JsonElement json, Type typeOfT,
        JsonDeserializationContext context)
      throws JsonParseException
    {
      ParameterizedType multimapTypeParams = (ParameterizedType) typeOfT;

      Type keyType = multimapTypeParams.getActualTypeArguments()[0];
      Type valueSetType = TypeToken
          .getParameterized(Set.class, multimapTypeParams.getActualTypeArguments()[1]).getType();
      Type serMapType = TypeToken.getParameterized(Map.class, keyType, valueSetType).getType();

      Map> map = context.deserialize(json, serMapType);

      SortedSetMultimap multimap = TreeMultimap.create();
      map.forEach(multimap::putAll);

      return multimap;
    }

  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private static class SetMultimapSerializer
    implements
      JsonSerializer,
      JsonDeserializer
  {

    @Override
    public JsonElement serialize(SetMultimap src, Type typeOfSrc, JsonSerializationContext context)
    {
      return context.serialize(src.asMap(), Map.class);
    }

    @Override
    public SetMultimap deserialize(JsonElement json, Type typeOfT,
        JsonDeserializationContext context)
      throws JsonParseException
    {
      ParameterizedType multimapTypeParams = (ParameterizedType) typeOfT;

      Type keyType = multimapTypeParams.getActualTypeArguments()[0];
      Type valueSetType = TypeToken
          .getParameterized(Set.class, multimapTypeParams.getActualTypeArguments()[1]).getType();
      Type serMapType = TypeToken.getParameterized(Map.class, keyType, valueSetType).getType();

      Map> map = context.deserialize(json, serMapType);

      SetMultimap multimap = HashMultimap.create();
      map.forEach(multimap::putAll);

      return multimap;
    }

  }


  public static class PersistableDataException
    extends
      Exception
  {

    public PersistableDataException(String message)
    {
      super(message);
    }

    public PersistableDataException(Throwable cause)
    {
      super(cause);
    }

    public PersistableDataException(String message, Throwable cause)
    {
      super(message, cause);
    }

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy