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

org.babyfish.jimmer.sql.cache.ValueSerializer Maven / Gradle / Ivy

There is a newer version: 0.9.19
Show newest version
package org.babyfish.jimmer.sql.cache;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.SimpleType;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.babyfish.jimmer.jackson.ImmutableModule;
import org.babyfish.jimmer.meta.ImmutableProp;
import org.babyfish.jimmer.meta.ImmutableType;
import org.babyfish.jimmer.meta.TargetLevel;
import org.babyfish.jimmer.runtime.DraftContext;
import org.babyfish.jimmer.runtime.Internal;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;

public class ValueSerializer {

    private static final byte[] NULL_BYTES = "".getBytes(StandardCharsets.UTF_8);

    private final ObjectMapper mapper;

    private final JavaType valueType;

    public ValueSerializer(@NotNull ImmutableType type) {
        this(type, null, null);
    }

    public ValueSerializer(@NotNull ImmutableProp prop) {
        this(null, prop, null);
    }

    public ValueSerializer(@NotNull ImmutableType type, ObjectMapper mapper) {
        this(type, null, mapper);
    }

    public ValueSerializer(@NotNull ImmutableProp prop, ObjectMapper mapper) {
        this(null, prop, mapper);
    }

    private ValueSerializer(ImmutableType type, ImmutableProp prop, ObjectMapper mapper) {
        if ((type == null) == (prop == null)) {
            throw new IllegalArgumentException("Internal bug: nullity of type and prop must be different");
        }
        ObjectMapper clonedMapper = mapper != null?
            new ObjectMapper(mapper) {} :
            new ObjectMapper().registerModule(new JavaTimeModule());
        clonedMapper.registerModule(new ImmutableModule());
        this.mapper = clonedMapper;
        if (prop == null) {
            this.valueType = SimpleType.constructUnsafe(type.getJavaClass());
        } else if (prop.isAssociation(TargetLevel.ENTITY)) {
            ImmutableProp targetIdProp = prop.getTargetType().getIdProp();
            JavaType targetIdType = SimpleType.constructUnsafe(
                    targetIdProp.getElementClass()
            );
            if (prop.isReferenceList(TargetLevel.OBJECT)) {
                this.valueType = CollectionType.construct(
                        List.class,
                        null,
                        null,
                        null,
                        targetIdType
                );
            } else {
                this.valueType = targetIdType;
            }
        } else {
            this.valueType = SimpleType.constructUnsafe(prop.getElementClass());
        }
    }

    @NotNull
    public byte[] serialize(T value) {
        if (value == null) {
            return NULL_BYTES.clone();
        }
        try {
            return mapper.writeValueAsBytes(value);
        } catch (JsonProcessingException ex) {
            throw new SerializationException(ex);
        }
    }

    @NotNull
    public  Map serialize(@NotNull Map map) {
        Map serializedMap = new LinkedHashMap<>((map.size() * 4 + 2) / 3);
        for (Map.Entry e : map.entrySet()) {
            serializedMap.put(e.getKey(), serialize(e.getValue()));
        }
        return serializedMap;
    }

    @NotNull
    public  Map serialize(@NotNull Map map, @NotNull Function keyMapper) {
        Map serializedMap = new LinkedHashMap<>((map.size() * 4 + 2) / 3);
        for (Map.Entry e : map.entrySet()) {
            serializedMap.put(keyMapper.apply(e.getKey()), serialize(e.getValue()));
        }
        return serializedMap;
    }

    public T deserialize(byte[] value) {
        if (value == null || value.length == 0 || Arrays.equals(value, NULL_BYTES)) {
            return null;
        }
        try {
            return mapper.readValue(value, valueType);
        } catch (IOException ex) {
            throw new SerializationException(ex);
        }
    }

    @NotNull
    public  Map deserialize(@NotNull Map map) {
        Map deserializedMap = new LinkedHashMap<>((map.size() * 4 + 2) / 3);
        for (Map.Entry e : map.entrySet()) {
            deserializedMap.put(e.getKey(), deserialize(e.getValue()));
        }
        return deserializedMap;
    }

    @NotNull
    public  Map deserialize(@NotNull Map map, @NotNull Function keyMapper) {
        Map deserializedMap = new LinkedHashMap<>((map.size() * 4 + 2) / 3);
        for (Map.Entry e : map.entrySet()) {
            deserializedMap.put(keyMapper.apply(e.getKey()), deserialize(e.getValue()));
        }
        return deserializedMap;
    }

    @NotNull
    public  Map deserialize(@NotNull Collection keys, @NotNull Collection values) {
        Map deserializedMap = new LinkedHashMap<>((keys.size() * 4 + 2) / 3);
        Iterator keyItr = keys.iterator();
        Iterator byteArrItr = values.iterator();
        while (keyItr.hasNext() && byteArrItr.hasNext()) {
            K key = keyItr.next();
            byte[] byteArr = byteArrItr.next();
            if (byteArr != null) {
                deserializedMap.put(key, deserialize(byteArr));
            }
        }
        return deserializedMap;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy