Newer
Older
wicketspringdata / src / main / java / ru / simplex_software / wicket_springdata / kryo / PersistableSerializer.java
package ru.simplex_software.wicket_springdata.kryo;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.springframework.data.domain.Persistable;

import java.io.Serializable;
import java.util.Optional;
import java.util.function.Function;

/**
 * Чтение и запись хранимых сущностей.
 */
public class PersistableSerializer<P extends Persistable<ID>, ID extends Serializable> extends Serializer<P> {

    private final Function<ID, Optional<P>> findByIdFunction;
    private final Class<ID> idClass;

    /**
     * Созания сериализатора для хранимых сущностей.
     *
     * @param findByIdFunction функция поиска сущности по первичному ключу.
     * @param idClass          класс первичного ключа сущности.
     */
    public PersistableSerializer(Function<ID, Optional<P>> findByIdFunction, Class<ID> idClass) {
        this.findByIdFunction = findByIdFunction;
        this.idClass = idClass;
    }

    @Override
    public void write(Kryo kryo, Output output, P entity) {
        output.writeBoolean(entity.isNew());
        if (entity.isNew()) {
            Serializer<P> defaultSerializer = kryo.getDefaultSerializer(entity.getClass());
            defaultSerializer.write(kryo, output, entity);
        } else {
            Serializer<Serializable> idSerializer = kryo.getSerializer(idClass);
            idSerializer.write(kryo, output, entity.getId());
        }
    }

    @Override
    public P read(Kryo kryo, Input input, Class<? extends P> type) {
        if (input.readBoolean()) {
            Serializer<P> defaultSerializer = kryo.getDefaultSerializer(type);
            return defaultSerializer.read(kryo, input, type);
        } else {
            Serializer<ID> idSerializer = kryo.getSerializer(idClass);
            ID id = idSerializer.read(kryo, input, idClass);
            return findByIdFunction.apply(id)
                    .orElseThrow(() -> new IllegalArgumentException("Cannot load entity of type " + type + " with id " + id));
        }
    }
}