feat(serialize-databind): split into databind and databind-api

This commit is contained in:
Johannes Frohnmeyer 2024-04-13 13:48:34 +02:00
parent 98fae535e7
commit 9fa795f18e
Signed by: Johannes
GPG Key ID: E76429612C2929F4
27 changed files with 121 additions and 42 deletions

View File

@ -0,0 +1,29 @@
import io.gitlab.jfronny.scripts.*
plugins {
commons.library
}
dependencies {
implementation(projects.commons)
api(projects.commonsSerialize)
testImplementation(libs.junit.jupiter.api)
testRuntimeOnly(libs.junit.jupiter.engine)
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "io.gitlab.jfronny"
artifactId = "commons-serialize-databind-api"
from(components["java"])
}
}
}
tasks.javadoc {
linksOffline("https://maven.frohnmeyer-wds.de/javadoc/artifacts/io/gitlab/jfronny/commons/$version/raw", projects.commons)
linksOffline("https://maven.frohnmeyer-wds.de/javadoc/artifacts/io/gitlab/jfronny/commons-serialize/$version/raw", projects.commonsSerialize)
}

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.commons.serialize.databind;
package io.gitlab.jfronny.commons.serialize.databind.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -12,7 +12,7 @@ import java.lang.annotation.Target;
@Target(ElementType.TYPE)
public @interface SerializeWithAdapter {
/**
* Either a {@link TypeAdapter} or {@link TypeAdapterFactory}.
* Either a {@link TypeAdapter} or {@code TypeAdapterFactory} (in commons-serialize-databind).
*/
Class<?> adapter();

View File

@ -1,10 +1,14 @@
package io.gitlab.jfronny.commons.serialize.databind;
package io.gitlab.jfronny.commons.serialize.databind.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotate a TypeAdapter with this to specify the type it handles.
* Required for the ServiceLoader-based registration of TypeAdapters.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SerializerFor {

View File

@ -1,9 +1,14 @@
package io.gitlab.jfronny.commons.serialize.databind;
package io.gitlab.jfronny.commons.serialize.databind.api;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
/**
* A type adapter for serializing and deserializing objects of a specific type.
*
* @param <T> The type of the object to serialize/deserialize
*/
public abstract class TypeAdapter<T> {
public abstract <TEx extends Throwable, Writer extends SerializeWriter<TEx, Writer>> void serialize(T value, Writer writer) throws TEx, MalformedDataException;
public abstract <TEx extends Throwable, Reader extends SerializeReader<TEx, Reader>> T deserialize(Reader reader) throws TEx, MalformedDataException;

View File

@ -1,12 +1,14 @@
package io.gitlab.jfronny.commons.serialize.databind;
import io.gitlab.jfronny.commons.serialize.databind.impl.TypeUtils;
package io.gitlab.jfronny.commons.serialize.databind.api;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* Represents a generic type {@code T}. Based on the Gson TypeToken implementation.
* @param <T> the type that this token represents.
*/
public class TypeToken<T> {
private final Class<? super T> rawType;
private final Type type;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.commons.serialize.databind.impl;
package io.gitlab.jfronny.commons.serialize.databind.api;
import java.io.Serializable;
import java.lang.reflect.*;
@ -6,6 +6,9 @@ import java.util.*;
import static java.util.Objects.requireNonNull;
/**
* Utility methods for working with types.
*/
public class TypeUtils {
static final Type[] EMPTY_TYPE_ARRAY = new Type[] {};

View File

@ -0,0 +1,6 @@
module io.gitlab.jfronny.commons.serialize.databind.api {
requires io.gitlab.jfronny.commons;
requires io.gitlab.jfronny.commons.serialize;
requires static org.jetbrains.annotations;
exports io.gitlab.jfronny.commons.serialize.databind.api;
}

View File

@ -16,10 +16,11 @@
package io.gitlab.jfronny.commons.serialize.databind.sql;
import io.gitlab.jfronny.commons.serialize.databind.*;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import java.text.DateFormat;
import java.text.ParseException;

View File

@ -17,8 +17,8 @@
package io.gitlab.jfronny.commons.serialize.databind.sql;
import io.gitlab.jfronny.commons.serialize.databind.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;

View File

@ -17,9 +17,9 @@
package io.gitlab.jfronny.commons.serialize.databind.sql;
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapterFactory;
import io.gitlab.jfronny.commons.serialize.databind.TypeToken;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;

View File

@ -2,6 +2,7 @@ module io.gitlab.jfronny.commons.serialize.databind.sql {
requires io.gitlab.jfronny.commons;
requires io.gitlab.jfronny.commons.serialize;
requires io.gitlab.jfronny.commons.serialize.databind;
requires io.gitlab.jfronny.commons.serialize.databind.api;
requires java.sql;
requires static org.jetbrains.annotations;
}

View File

@ -7,6 +7,7 @@ plugins {
dependencies {
implementation(projects.commons)
api(projects.commonsSerialize)
api(projects.commonsSerializeDatabindApi)
testImplementation(libs.junit.jupiter.api)
testRuntimeOnly(libs.junit.jupiter.engine)
@ -26,4 +27,5 @@ publishing {
tasks.javadoc {
linksOffline("https://maven.frohnmeyer-wds.de/javadoc/artifacts/io/gitlab/jfronny/commons/$version/raw", projects.commons)
linksOffline("https://maven.frohnmeyer-wds.de/javadoc/artifacts/io/gitlab/jfronny/commons-serialize/$version/raw", projects.commonsSerialize)
linksOffline("https://maven.frohnmeyer-wds.de/javadoc/artifacts/io/gitlab/jfronny/commons-serialize-databind-api/$version/raw", projects.commonsSerializeDatabindApi)
}

View File

@ -4,6 +4,7 @@ import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.commons.serialize.Transport;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;

View File

@ -1,6 +1,10 @@
package io.gitlab.jfronny.commons.serialize.databind;
import io.gitlab.jfronny.commons.serialize.databind.impl.adapter.SerializationDelegatingTypeAdapter;
import io.gitlab.jfronny.commons.concurrent.ScopedValue;
import io.gitlab.jfronny.commons.concurrent.WithScopedValue;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
@ -10,7 +14,8 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class ObjectMapper {
public class ObjectMapper implements WithScopedValue<ObjectMapper> {
public static final ScopedValue<ObjectMapper> CURRENT = new ScopedValue<>();
private final ThreadLocal<Map<TypeToken<?>, TypeAdapter<?>>> threadLocalAdapterResults = new ThreadLocal<>();
private final ConcurrentMap<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<>();
private final List<TypeAdapterFactory> factories = new ArrayList<>();
@ -45,11 +50,11 @@ public class ObjectMapper {
}
public <TEx extends Throwable, Reader extends SerializeReader<TEx, Reader>, T> T deserialize(Class<T> type, Reader reader) throws TEx, MalformedDataException {
return getAdapter(type).deserialize(reader);
return this.<T, TEx, MalformedDataException>withContext(() -> getAdapter(type).deserialize(reader));
}
public <TEx extends Throwable, Writer extends SerializeWriter<TEx, Writer>, T> void serialize(T value, Writer writer) throws TEx, MalformedDataException {
getAdapter((Class<T>) value.getClass()).serialize(value, writer);
this.<TEx, MalformedDataException>withContext(() -> getAdapter((Class<T>) value.getClass()).serialize(value, writer));
}
public <T> TypeAdapter<T> getAdapter(Class<T> type) {
@ -121,6 +126,16 @@ public class ObjectMapper {
return candidate;
}
@Override
public ScopedValue<ObjectMapper> getAttached() {
return CURRENT;
}
@Override
public ObjectMapper self() {
return this;
}
static class FutureTypeAdapter<T> extends SerializationDelegatingTypeAdapter<T> {
private TypeAdapter<T> delegate = null;

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
package io.gitlab.jfronny.commons.serialize.databind;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
public abstract class SerializationDelegatingTypeAdapter<T> extends TypeAdapter<T> {
public abstract TypeAdapter<T> getSerializationDelegate();

View File

@ -1,5 +1,8 @@
package io.gitlab.jfronny.commons.serialize.databind;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
public interface TypeAdapterFactory {
<T> TypeAdapter<T> create(ObjectMapper mapper, TypeToken<T> type);
}

View File

@ -1,10 +1,10 @@
package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapterFactory;
import io.gitlab.jfronny.commons.serialize.databind.TypeToken;
import io.gitlab.jfronny.commons.serialize.databind.impl.TypeUtils;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeUtils;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
import io.gitlab.jfronny.commons.serialize.databind.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.impl.ISO8601Utils;
import io.gitlab.jfronny.commons.serialize.databind.impl.PreJava9DateFormatProvider;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;

View File

@ -2,9 +2,9 @@ package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
import io.gitlab.jfronny.commons.serialize.annotations.SerializedName;
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapterFactory;
import io.gitlab.jfronny.commons.serialize.databind.TypeToken;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;

View File

@ -1,12 +1,12 @@
package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapterFactory;
import io.gitlab.jfronny.commons.serialize.databind.TypeToken;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.serialize.databind.impl.MapKeyReader;
import io.gitlab.jfronny.commons.serialize.databind.impl.MapKeyWriter;
import io.gitlab.jfronny.commons.serialize.databind.impl.TypeUtils;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeUtils;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
import io.gitlab.jfronny.commons.serialize.databind.*;
import io.gitlab.jfronny.commons.serialize.databind.impl.TypeUtils;
import io.gitlab.jfronny.commons.serialize.databind.api.*;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;

View File

@ -2,8 +2,8 @@ package io.gitlab.jfronny.commons.serialize.databind.impl.adapter;
import io.gitlab.jfronny.commons.data.LazilyParsedNumber;
import io.gitlab.jfronny.commons.data.NumberLimits;
import io.gitlab.jfronny.commons.serialize.databind.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;

View File

@ -1,8 +1,12 @@
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.databind.TypeAdapterFactory;
module io.gitlab.jfronny.commons.serialize.databind {
uses io.gitlab.jfronny.commons.serialize.databind.TypeAdapterFactory;
uses io.gitlab.jfronny.commons.serialize.databind.TypeAdapter;
uses TypeAdapterFactory;
uses TypeAdapter;
requires io.gitlab.jfronny.commons;
requires io.gitlab.jfronny.commons.serialize;
requires io.gitlab.jfronny.commons.serialize.databind.api;
requires static org.jetbrains.annotations;
exports io.gitlab.jfronny.commons.serialize.databind;
}

View File

@ -1,18 +1,16 @@
rootProject.name = "JfCommons"
include("commons")
include("commons-io")
include("commons-http-client")
include("commons-http-server")
// serialization
include("commons-serialize")
include("commons-serialize-gson-dsl")
include("commons-serialize-json")
include("commons-serialize-databind")
include("commons-serialize-databind-api")
include("commons-serialize-databind-sql")
include("commons-io")
include("commons-logger")
include("commons-http-client")
include("commons-http-server")
include("commons-manifold")
include("commons-gson")
include("commons-unsafe")
// new muscript
include("muscript-core")
include("muscript-ast")
@ -23,5 +21,10 @@ include("muscript-serialize")
include("muscript-optimizer")
include("muscript-runtime")
include("muscript-json")
// interop
include("commons-logger")
include("commons-manifold")
include("commons-gson")
include("commons-unsafe")
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")