Improves Json util class: ability to add TypeAdapterFactory on the fly.

This commit is contained in:
Marc Baloup 2023-03-09 18:57:09 +01:00
parent a6bde9e191
commit df46026457
3 changed files with 57 additions and 15 deletions

View File

@ -1,12 +1,8 @@
package fr.pandacube.lib.bungee.backup; package fr.pandacube.lib.bungee.backup;
import fr.pandacube.lib.core.backup.BackupProcess; import fr.pandacube.lib.core.backup.BackupProcess;
import fr.pandacube.lib.util.Log;
import net.md_5.bungee.api.ChatColor;
import java.io.File; import java.io.File;
import java.text.DateFormat;
import java.util.Date;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
public class BungeeWorkdirProcess extends BackupProcess { public class BungeeWorkdirProcess extends BackupProcess {
@ -22,7 +18,7 @@ public class BungeeWorkdirProcess extends BackupProcess {
public BiPredicate<File, String> getFilenameFilter() { public BiPredicate<File, String> getFilenameFilter() {
return new BiPredicate<File, String>() { return new BiPredicate<>() {
@Override @Override
public boolean test(File file, String path) { public boolean test(File file, String path) {
if (new File(getSourceDir(), "logs").equals(file)) if (new File(getSourceDir(), "logs").equals(file))

View File

@ -1,6 +1,5 @@
package fr.pandacube.lib.bungee.commands; package fr.pandacube.lib.bungee.commands;
import fr.pandacube.lib.bungee.PandaLibBungee;
import fr.pandacube.lib.chat.Chat; import fr.pandacube.lib.chat.Chat;
import fr.pandacube.lib.commands.BrigadierDispatcher; import fr.pandacube.lib.commands.BrigadierDispatcher;
import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.ComponentLike;
@ -21,6 +20,10 @@ public class BungeeBrigadierDispatcher extends BrigadierDispatcher<CommandSender
private static BungeeBrigadierDispatcher instance = null; private static BungeeBrigadierDispatcher instance = null;
/**
* Gets the instance of {@link BungeeBrigadierDispatcher}.
* @return the instance of {@link BungeeBrigadierDispatcher}.
*/
public static synchronized BungeeBrigadierDispatcher getInstance() { public static synchronized BungeeBrigadierDispatcher getInstance() {
return instance; return instance;
} }

View File

@ -4,7 +4,9 @@ import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.RecordComponent; import java.lang.reflect.RecordComponent;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -18,30 +20,35 @@ import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
/** /**
* Provides pre-instanciated {@link Gson} instances, all with support for Java records. * Provides pre-instanciated {@link Gson} instances, all with support for Java records and additionnal
* {@link TypeAdapterFactory} provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public class Json { public class Json {
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()} and support for Java records. * {@link Gson} instance with {@link GsonBuilder#setLenient()} and support for Java records and additionnal
* {@link TypeAdapterFactory} provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gson = build(Function.identity()); public static final Gson gson = build(Function.identity());
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#setPrettyPrinting()} * {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#setPrettyPrinting()} and support
* and support for Java records. * for Java records and additionnal {@link TypeAdapterFactory} provided with
* {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gsonPrettyPrinting = build(GsonBuilder::setPrettyPrinting); public static final Gson gsonPrettyPrinting = build(GsonBuilder::setPrettyPrinting);
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()} * {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()} and support for
* and support for Java records. * Java records and additionnal {@link TypeAdapterFactory} provided with
* {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gsonSerializeNulls = build(GsonBuilder::serializeNulls); public static final Gson gsonSerializeNulls = build(GsonBuilder::serializeNulls);
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()}, * {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()},
* {@link GsonBuilder#setPrettyPrinting()} and support for Java records. * {@link GsonBuilder#setPrettyPrinting()} and support for Java records and additionnal {@link TypeAdapterFactory}
* provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gsonSerializeNullsPrettyPrinting = build(b -> b.serializeNulls().setPrettyPrinting()); public static final Gson gsonSerializeNullsPrettyPrinting = build(b -> b.serializeNulls().setPrettyPrinting());
@ -52,8 +59,41 @@ public class Json {
private static Gson build(Function<GsonBuilder, GsonBuilder> builderModifier) { private static Gson build(Function<GsonBuilder, GsonBuilder> builderModifier) {
return builderModifier GsonBuilder base = new GsonBuilder()
.apply(new GsonBuilder().registerTypeAdapterFactory(new RecordAdapterFactory()).setLenient()).create(); .registerTypeAdapterFactory(new CustomAdapterFactory())
.setLenient();
return builderModifier.apply(base).create();
}
/**
* Adds the provided {@link TypeAdapterFactory} to all the static Gson instances of this class.
* @param factory the factory to add to the
*/
public static void registerTypeAdapterFactory(TypeAdapterFactory factory) {
synchronized (customTypeAdapterFactories) {
customTypeAdapterFactories.add(factory);
}
}
private static final List<TypeAdapterFactory> customTypeAdapterFactories = new ArrayList<>();
private static class CustomAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
synchronized (customTypeAdapterFactories) {
for (TypeAdapterFactory actualFactory : customTypeAdapterFactories) {
TypeAdapter<T> adapter = actualFactory.create(gson, type);
if (adapter != null)
return adapter;
}
}
return null;
}
} }
@ -62,6 +102,9 @@ public class Json {
static {
registerTypeAdapterFactory(new RecordAdapterFactory());
}
// from https://github.com/google/gson/issues/1794#issuecomment-812964421 // from https://github.com/google/gson/issues/1794#issuecomment-812964421
private static class RecordAdapterFactory implements TypeAdapterFactory { private static class RecordAdapterFactory implements TypeAdapterFactory {