[*] Migrate to jspecify annotations
This commit is contained in:
@@ -35,7 +35,10 @@ dependencies {
|
|||||||
testCompileOnly(libs.autoservice.annotations)
|
testCompileOnly(libs.autoservice.annotations)
|
||||||
testAnnotationProcessor(libs.autoservice.processor)
|
testAnnotationProcessor(libs.autoservice.processor)
|
||||||
|
|
||||||
implementation(libs.jetbrains.annotations)
|
compileOnly(libs.jetbrains.annotations)
|
||||||
|
testImplementation(libs.jetbrains.annotations)
|
||||||
|
compileOnly(libs.jspecify.annotations)
|
||||||
|
testImplementation(libs.jspecify.annotations)
|
||||||
|
|
||||||
implementation(libs.slf4j.api)
|
implementation(libs.slf4j.api)
|
||||||
"localRuntimeOnly"(libs.slf4j.rt)
|
"localRuntimeOnly"(libs.slf4j.rt)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ asm = "9.7"
|
|||||||
autoservice = "1.1.1"
|
autoservice = "1.1.1"
|
||||||
java = "8"
|
java = "8"
|
||||||
jetbrains-annotations = "26.0.1"
|
jetbrains-annotations = "26.0.1"
|
||||||
|
jspecify = "1.0.0"
|
||||||
junit = "5.12.0"
|
junit = "5.12.0"
|
||||||
lombok = "1.18.34"
|
lombok = "1.18.34"
|
||||||
mockito = "5.14.2"
|
mockito = "5.14.2"
|
||||||
@@ -19,6 +20,7 @@ asm-core = { group = "org.ow2.asm", name = "asm", version.ref = "asm" }
|
|||||||
autoservice-annotations = { group = "com.google.auto.service", name = "auto-service-annotations", version.ref = "autoservice" }
|
autoservice-annotations = { group = "com.google.auto.service", name = "auto-service-annotations", version.ref = "autoservice" }
|
||||||
autoservice-processor = { group = "com.google.auto.service", name = "auto-service", version.ref = "autoservice" }
|
autoservice-processor = { group = "com.google.auto.service", name = "auto-service", version.ref = "autoservice" }
|
||||||
jetbrains-annotations = { group = "org.jetbrains", name = "annotations", version.ref = "jetbrains-annotations" }
|
jetbrains-annotations = { group = "org.jetbrains", name = "annotations", version.ref = "jetbrains-annotations" }
|
||||||
|
jspecify-annotations = { group = "org.jspecify", name = "jspecify", version.ref = "jspecify" }
|
||||||
junit-platform = { group = "org.junit", name = "junit-bom", version.ref = "junit" }
|
junit-platform = { group = "org.junit", name = "junit-bom", version.ref = "junit" }
|
||||||
junit-core = { group = "org.junit.jupiter", name = "junit-jupiter" }
|
junit-core = { group = "org.junit.jupiter", name = "junit-jupiter" }
|
||||||
junit-launcher = { group = "org.junit.platform", name = "junit-platform-launcher" }
|
junit-launcher = { group = "org.junit.platform", name = "junit-platform-launcher" }
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ package de.siphalor.tweed5.construct.api;
|
|||||||
import de.siphalor.tweed5.construct.impl.TweedConstructFactoryImpl;
|
import de.siphalor.tweed5.construct.impl.TweedConstructFactoryImpl;
|
||||||
import org.jetbrains.annotations.CheckReturnValue;
|
import org.jetbrains.annotations.CheckReturnValue;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory that allows to construct instances of subclasses of a specific type.
|
* A factory that allows to construct instances of subclasses of a specific type.
|
||||||
@@ -20,7 +19,7 @@ public interface TweedConstructFactory<T> {
|
|||||||
/**
|
/**
|
||||||
* Starts building a new factory for the given base class.
|
* Starts building a new factory for the given base class.
|
||||||
*/
|
*/
|
||||||
static <T> TweedConstructFactory.@NotNull FactoryBuilder<T> builder(Class<T> baseClass) {
|
static <T> TweedConstructFactory.FactoryBuilder<T> builder(Class<T> baseClass) {
|
||||||
return TweedConstructFactoryImpl.builder(baseClass);
|
return TweedConstructFactoryImpl.builder(baseClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ public interface TweedConstructFactory<T> {
|
|||||||
*/
|
*/
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
<C extends T> @NotNull Construct<C> construct(@NotNull Class<C> subClass);
|
<C extends T> Construct<C> construct(Class<C> subClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for the factory.
|
* Builder for the factory.
|
||||||
@@ -40,19 +39,19 @@ public interface TweedConstructFactory<T> {
|
|||||||
* Defines a new typed argument of the given type.
|
* Defines a new typed argument of the given type.
|
||||||
*/
|
*/
|
||||||
@Contract(mutates = "this", value = "_ -> this")
|
@Contract(mutates = "this", value = "_ -> this")
|
||||||
<A> @NotNull FactoryBuilder<T> typedArg(@NotNull Class<A> argType);
|
<A> FactoryBuilder<T> typedArg(Class<A> argType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a new named argument with the given name and value type.
|
* Defines a new named argument with the given name and value type.
|
||||||
*/
|
*/
|
||||||
@Contract(mutates = "this", value = "_, _ -> this")
|
@Contract(mutates = "this", value = "_, _ -> this")
|
||||||
<A> @NotNull FactoryBuilder<T> namedArg(@NotNull String name, @NotNull Class<A> argType);
|
<A> FactoryBuilder<T> namedArg(String name, Class<A> argType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the factory.
|
* Builds the factory.
|
||||||
*/
|
*/
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
@NotNull TweedConstructFactory<T> build();
|
TweedConstructFactory<T> build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +70,7 @@ public interface TweedConstructFactory<T> {
|
|||||||
* @see #namedArg(String, Object)
|
* @see #namedArg(String, Object)
|
||||||
*/
|
*/
|
||||||
@Contract(mutates = "this", value = "_ -> this")
|
@Contract(mutates = "this", value = "_ -> this")
|
||||||
<A> @NotNull Construct<C> typedArg(@NotNull A value);
|
<A> Construct<C> typedArg(A value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds a value to a typed argument of the given type.
|
* Binds a value to a typed argument of the given type.
|
||||||
@@ -81,19 +80,19 @@ public interface TweedConstructFactory<T> {
|
|||||||
* @see #namedArg(String, Object)
|
* @see #namedArg(String, Object)
|
||||||
*/
|
*/
|
||||||
@Contract(mutates = "this", value = "_, _ -> this")
|
@Contract(mutates = "this", value = "_, _ -> this")
|
||||||
<A> @NotNull Construct<C> typedArg(@NotNull Class<? super A> argType, @Nullable A value);
|
<A> Construct<C> typedArg(Class<? super A> argType, @Nullable A value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds a value to a named argument.
|
* Binds a value to a named argument.
|
||||||
* @see #typedArg(Object)
|
* @see #typedArg(Object)
|
||||||
*/
|
*/
|
||||||
@Contract(mutates = "this", value = "_, _ -> this")
|
@Contract(mutates = "this", value = "_, _ -> this")
|
||||||
<A> @NotNull Construct<C> namedArg(@NotNull String name, @Nullable A value);
|
<A> Construct<C> namedArg(String name, @Nullable A value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finishes the binding and actually constructs the class.
|
* Finishes the binding and actually constructs the class.
|
||||||
*/
|
*/
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
@NotNull C finish();
|
C finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.construct.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -4,8 +4,7 @@ import de.siphalor.tweed5.construct.api.ConstructParameter;
|
|||||||
import de.siphalor.tweed5.construct.api.TweedConstruct;
|
import de.siphalor.tweed5.construct.api.TweedConstruct;
|
||||||
import de.siphalor.tweed5.construct.api.TweedConstructFactory;
|
import de.siphalor.tweed5.construct.api.TweedConstructFactory;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@@ -37,11 +36,11 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C extends T> TweedConstructFactory.@NotNull Construct<C> construct(@NotNull Class<C> subClass) {
|
public <C extends T> TweedConstructFactory.Construct<C> construct(Class<C> subClass) {
|
||||||
return new Construct<>(getConstructTarget(subClass));
|
return new Construct<>(getConstructTarget(subClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <C extends T> @NotNull ConstructTarget<C> getConstructTarget(Class<C> type) {
|
private <C extends T> ConstructTarget<C> getConstructTarget(Class<C> type) {
|
||||||
ConstructTarget<C> cachedConstructTarget = readConstructTargetFromCache(type);
|
ConstructTarget<C> cachedConstructTarget = readConstructTargetFromCache(type);
|
||||||
if (cachedConstructTarget != null) {
|
if (cachedConstructTarget != null) {
|
||||||
return cachedConstructTarget;
|
return cachedConstructTarget;
|
||||||
@@ -164,7 +163,7 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
return new ConstructTarget<>(type, argOrder, createInvokerFromCandidate(type, executable));
|
return new ConstructTarget<>(type, argOrder, createInvokerFromCandidate(type, executable));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <C> Function<Object[], C> createInvokerFromCandidate(Class<C> type, Executable executable) {
|
private <C> Function<@Nullable Object[], C> createInvokerFromCandidate(Class<C> type, Executable executable) {
|
||||||
MethodHandle handle;
|
MethodHandle handle;
|
||||||
try {
|
try {
|
||||||
if (executable instanceof Method) {
|
if (executable instanceof Method) {
|
||||||
@@ -263,7 +262,7 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
private final Map<String, Class<?>> namedArgs = new HashMap<>();
|
private final Map<String, Class<?>> namedArgs = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A> TweedConstructFactory.@NotNull FactoryBuilder<T> typedArg(@NotNull Class<A> argType) {
|
public <A> TweedConstructFactory.FactoryBuilder<T> typedArg(Class<A> argType) {
|
||||||
argType = boxClass(argType);
|
argType = boxClass(argType);
|
||||||
if (typedArgs.contains(argType)) {
|
if (typedArgs.contains(argType)) {
|
||||||
throw new IllegalArgumentException("Argument for type " + argType + " has already been registered");
|
throw new IllegalArgumentException("Argument for type " + argType + " has already been registered");
|
||||||
@@ -273,10 +272,7 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A> TweedConstructFactory.@NotNull FactoryBuilder<T> namedArg(
|
public <A> TweedConstructFactory.FactoryBuilder<T> namedArg(String name, Class<A> argType) {
|
||||||
@NotNull String name,
|
|
||||||
@NotNull Class<A> argType
|
|
||||||
) {
|
|
||||||
Class<?> existingArgType = namedArgs.get(name);
|
Class<?> existingArgType = namedArgs.get(name);
|
||||||
if (existingArgType != null) {
|
if (existingArgType != null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@@ -290,7 +286,7 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull TweedConstructFactory<T> build() {
|
public TweedConstructFactory<T> build() {
|
||||||
return new TweedConstructFactoryImpl<>(
|
return new TweedConstructFactoryImpl<>(
|
||||||
constructBaseClass,
|
constructBaseClass,
|
||||||
typedArgs,
|
typedArgs,
|
||||||
@@ -302,18 +298,18 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
private class Construct<C> implements TweedConstructFactory.Construct<C> {
|
private class Construct<C> implements TweedConstructFactory.Construct<C> {
|
||||||
private final ConstructTarget<C> target;
|
private final ConstructTarget<C> target;
|
||||||
private final Map<Class<?>, Object> typedArgValues = new HashMap<>();
|
private final Map<Class<?>, @Nullable Object> typedArgValues = new HashMap<>();
|
||||||
private final Map<String, Object> namedArgValues = new HashMap<>();
|
private final Map<String, @Nullable Object> namedArgValues = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A> TweedConstructFactory.@NotNull Construct<C> typedArg(@NotNull A value) {
|
public <A> TweedConstructFactory.Construct<C> typedArg(A value) {
|
||||||
requireTypedArgExists(value.getClass(), value);
|
requireTypedArgExists(value.getClass(), value);
|
||||||
typedArgValues.put(value.getClass(), value);
|
typedArgValues.put(value.getClass(), value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A> TweedConstructFactory.@NotNull Construct<C> typedArg(@NotNull Class<? super A> argType, @Nullable A value) {
|
public <A> TweedConstructFactory.Construct<C> typedArg(Class<? super A> argType, @Nullable A value) {
|
||||||
argType = boxClass(argType);
|
argType = boxClass(argType);
|
||||||
if (value != null && !argType.isAssignableFrom(value.getClass())) {
|
if (value != null && !argType.isAssignableFrom(value.getClass())) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@@ -327,7 +323,7 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <A> void requireTypedArgExists(@NotNull Class<?> type, @Nullable A value) {
|
private <A> void requireTypedArgExists(Class<?> type, @Nullable A value) {
|
||||||
if (!typedArgs.contains(type)) {
|
if (!typedArgs.contains(type)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Typed argument for type " + type.getName() + " does not exist, value: " + value
|
"Typed argument for type " + type.getName() + " does not exist, value: " + value
|
||||||
@@ -336,7 +332,7 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A> TweedConstructFactory.@NotNull Construct<C> namedArg(@NotNull String name, @Nullable A value) {
|
public <A> TweedConstructFactory.Construct<C> namedArg(String name, @Nullable A value) {
|
||||||
Class<?> argType = namedArgs.get(name);
|
Class<?> argType = namedArgs.get(name);
|
||||||
if (argType == null) {
|
if (argType == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@@ -353,10 +349,10 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull C finish() {
|
public C finish() {
|
||||||
checkAllArgsFilled();
|
checkAllArgsFilled();
|
||||||
|
|
||||||
Object[] argValues = new Object[target.argOrder.length];
|
@Nullable Object[] argValues = new Object[target.argOrder.length];
|
||||||
for (int i = 0; i < target.argOrder.length; i++) {
|
for (int i = 0; i < target.argOrder.length; i++) {
|
||||||
Object arg = target.argOrder[i];
|
Object arg = target.argOrder[i];
|
||||||
if (arg instanceof Class<?>) {
|
if (arg instanceof Class<?>) {
|
||||||
@@ -459,6 +455,6 @@ public class TweedConstructFactoryImpl<T> implements TweedConstructFactory<T> {
|
|||||||
private static class ConstructTarget<C> {
|
private static class ConstructTarget<C> {
|
||||||
Class<?> type;
|
Class<?> type;
|
||||||
Object[] argOrder;
|
Object[] argOrder;
|
||||||
Function<Object[], C> invoker;
|
Function<@Nullable Object[], C> invoker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
package de.siphalor.tweed5.construct.impl;
|
package de.siphalor.tweed5.construct.impl;
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
|
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
|
||||||
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|||||||
@@ -4,13 +4,11 @@ import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
|||||||
import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
|
import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
public abstract class BaseConfigEntry<T> implements ConfigEntry<T> {
|
public abstract class BaseConfigEntry<T> implements ConfigEntry<T> {
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final Class<T> valueClass;
|
private final Class<T> valueClass;
|
||||||
private ConfigContainer<?> container;
|
private ConfigContainer<?> container;
|
||||||
private EntryExtensionsData extensionsData;
|
private EntryExtensionsData extensionsData;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package de.siphalor.tweed5.core.api.entry;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
|
import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
|
||||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public interface ConfigEntry<T> {
|
public interface ConfigEntry<T> {
|
||||||
Class<T> valueClass();
|
Class<T> valueClass();
|
||||||
@@ -15,6 +14,5 @@ public interface ConfigEntry<T> {
|
|||||||
void visitInOrder(ConfigEntryVisitor visitor);
|
void visitInOrder(ConfigEntryVisitor visitor);
|
||||||
void visitInOrder(ConfigEntryValueVisitor visitor, T value);
|
void visitInOrder(ConfigEntryValueVisitor visitor, T value);
|
||||||
|
|
||||||
@NotNull
|
T deepCopy(T value);
|
||||||
T deepCopy(@NotNull T value);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.core.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -12,11 +12,13 @@ import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
|
|||||||
import de.siphalor.tweed5.utils.api.collection.InheritanceMap;
|
import de.siphalor.tweed5.utils.api.collection.InheritanceMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@NullUnmarked
|
||||||
public class DefaultConfigContainer<T> implements ConfigContainer<T> {
|
public class DefaultConfigContainer<T> implements ConfigContainer<T> {
|
||||||
@Getter
|
@Getter
|
||||||
private ConfigContainerSetupPhase setupPhase = ConfigContainerSetupPhase.EXTENSIONS_SETUP;
|
private ConfigContainerSetupPhase setupPhase = ConfigContainerSetupPhase.EXTENSIONS_SETUP;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package de.siphalor.tweed5.core.impl.entry;
|
package de.siphalor.tweed5.core.impl.entry;
|
||||||
|
|
||||||
import de.siphalor.tweed5.core.api.entry.*;
|
import de.siphalor.tweed5.core.api.entry.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
@@ -52,7 +51,7 @@ public class CollectionConfigEntryImpl<E, T extends Collection<E>> extends BaseC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull T deepCopy(@NotNull T value) {
|
public T deepCopy(T value) {
|
||||||
T copy = collectionConstructor.apply(value.size());
|
T copy = collectionConstructor.apply(value.size());
|
||||||
for (E element : value) {
|
for (E element : value) {
|
||||||
copy.add(elementEntry().deepCopy(element));
|
copy.add(elementEntry().deepCopy(element));
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import de.siphalor.tweed5.core.api.entry.BaseConfigEntry;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntryValueVisitor;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntryValueVisitor;
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntryVisitor;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntryVisitor;
|
||||||
import de.siphalor.tweed5.core.api.entry.SimpleConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.SimpleConfigEntry;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class SimpleConfigEntryImpl<T> extends BaseConfigEntry<T> implements SimpleConfigEntry<T> {
|
public class SimpleConfigEntryImpl<T> extends BaseConfigEntry<T> implements SimpleConfigEntry<T> {
|
||||||
public SimpleConfigEntryImpl(Class<T> valueClass) {
|
public SimpleConfigEntryImpl(Class<T> valueClass) {
|
||||||
@@ -22,8 +21,7 @@ public class SimpleConfigEntryImpl<T> extends BaseConfigEntry<T> implements Simp
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
public T deepCopy(T value) {
|
||||||
public T deepCopy(@NotNull T value) {
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package de.siphalor.tweed5.core.impl.entry;
|
package de.siphalor.tweed5.core.impl.entry;
|
||||||
|
|
||||||
import de.siphalor.tweed5.core.api.entry.*;
|
import de.siphalor.tweed5.core.api.entry.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -11,7 +10,7 @@ public class StaticMapCompoundConfigEntryImpl<T extends Map<String, Object>> ext
|
|||||||
private final IntFunction<T> mapConstructor;
|
private final IntFunction<T> mapConstructor;
|
||||||
private final Map<String, ConfigEntry<?>> compoundEntries = new LinkedHashMap<>();
|
private final Map<String, ConfigEntry<?>> compoundEntries = new LinkedHashMap<>();
|
||||||
|
|
||||||
public StaticMapCompoundConfigEntryImpl(@NotNull Class<T> valueClass, IntFunction<T> mapConstructor) {
|
public StaticMapCompoundConfigEntryImpl(Class<T> valueClass, IntFunction<T> mapConstructor) {
|
||||||
super(valueClass);
|
super(valueClass);
|
||||||
this.mapConstructor = mapConstructor;
|
this.mapConstructor = mapConstructor;
|
||||||
}
|
}
|
||||||
@@ -80,7 +79,7 @@ public class StaticMapCompoundConfigEntryImpl<T extends Map<String, Object>> ext
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull T deepCopy(@NotNull T value) {
|
public T deepCopy(T value) {
|
||||||
T copy = instantiateCompoundValue();
|
T copy = instantiateCompoundValue();
|
||||||
value.forEach((String key, Object element) -> {
|
value.forEach((String key, Object element) -> {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
|||||||
@@ -1 +1,4 @@
|
|||||||
package de.siphalor.tweed5.core.impl;
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.core.impl;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package de.siphalor.tweed5.defaultextensions.comment.api;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface CommentExtension extends TweedExtension {
|
public interface CommentExtension extends TweedExtension {
|
||||||
@Nullable String getFullComment(ConfigEntry<?> configEntry);
|
@Nullable String getFullComment(ConfigEntry<?> configEntry);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.comment.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -13,9 +13,12 @@ import de.siphalor.tweed5.data.extension.api.extension.ReadWriteRelatedExtension
|
|||||||
import de.siphalor.tweed5.defaultextensions.comment.api.*;
|
import de.siphalor.tweed5.defaultextensions.comment.api.*;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.NonNull;
|
||||||
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@AutoService(CommentExtension.class)
|
@AutoService(CommentExtension.class)
|
||||||
|
@NullUnmarked
|
||||||
public class CommentExtensionImpl implements ReadWriteRelatedExtension, CommentExtension {
|
public class CommentExtensionImpl implements ReadWriteRelatedExtension, CommentExtension {
|
||||||
@Getter
|
@Getter
|
||||||
private RegisteredExtensionData<EntryExtensionsData, InternalCommentEntryData> internalEntryDataExtension;
|
private RegisteredExtensionData<EntryExtensionsData, InternalCommentEntryData> internalEntryDataExtension;
|
||||||
@@ -62,8 +65,7 @@ public class CommentExtensionImpl implements ReadWriteRelatedExtension, CommentE
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
public @Nullable String getFullComment(@NonNull ConfigEntry<?> configEntry) {
|
||||||
public String getFullComment(ConfigEntry<?> configEntry) {
|
|
||||||
String comment = ((InternalCommentEntryData) configEntry.extensionsData()).commentProducer().createComment(configEntry);
|
String comment = ((InternalCommentEntryData) configEntry.extensionsData()).commentProducer().createComment(configEntry);
|
||||||
return comment.isEmpty() ? null : comment;
|
return comment.isEmpty() ? null : comment;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import de.siphalor.tweed5.core.api.middleware.Middleware;
|
|||||||
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.NonNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?, ?>> {
|
class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?, ?>> {
|
||||||
public static final TweedEntryWriterCommentMiddleware INSTANCE = new TweedEntryWriterCommentMiddleware();
|
public static final TweedEntryWriterCommentMiddleware INSTANCE = new TweedEntryWriterCommentMiddleware();
|
||||||
@@ -20,8 +20,8 @@ class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?
|
|||||||
@Override
|
@Override
|
||||||
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) {
|
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
TweedEntryWriter<Object, ConfigEntry<Object>> innerCasted = (TweedEntryWriter<Object, ConfigEntry<Object>>) inner;
|
TweedEntryWriter<Object, ConfigEntry<Object>> innerCasted = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner;
|
||||||
return (TweedEntryWriter<Object, ConfigEntry<Object>>) (writer, value, entry, context) -> {
|
return (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) (writer, value, entry, context) -> {
|
||||||
if (writer instanceof CompoundDataVisitor) {
|
if (writer instanceof CompoundDataVisitor) {
|
||||||
// Comment is already written in front of the key by the CompoundDataWriter,
|
// Comment is already written in front of the key by the CompoundDataWriter,
|
||||||
// so we don't have to write it here.
|
// so we don't have to write it here.
|
||||||
@@ -94,7 +94,7 @@ class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitString(@NotNull String value) {
|
public void visitString(String value) {
|
||||||
delegate.visitString(value);
|
delegate.visitString(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
package de.siphalor.tweed5.defaultextensions.comment.impl;
|
package de.siphalor.tweed5.defaultextensions.comment.impl;
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package de.siphalor.tweed5.defaultextensions.pather.api;
|
package de.siphalor.tweed5.defaultextensions.pather.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
|
|
||||||
@@ -9,7 +11,7 @@ public class PathTracking implements PatherData {
|
|||||||
private final Deque<String> pathParts = new ArrayDeque<>(50);
|
private final Deque<String> pathParts = new ArrayDeque<>(50);
|
||||||
private final Deque<Integer> listIndexes = new ArrayDeque<>(10);
|
private final Deque<Integer> listIndexes = new ArrayDeque<>(10);
|
||||||
|
|
||||||
public Context currentContext() {
|
public @Nullable Context currentContext() {
|
||||||
return contextStack.peek();
|
return contextStack.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package de.siphalor.tweed5.defaultextensions.pather.api;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PathTrackingDataVisitor implements TweedDataVisitor {
|
public class PathTrackingDataVisitor implements TweedDataVisitor {
|
||||||
@@ -58,7 +57,7 @@ public class PathTrackingDataVisitor implements TweedDataVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitString(@NotNull String value) {
|
public void visitString(String value) {
|
||||||
delegate.visitString(value);
|
delegate.visitString(value);
|
||||||
valueVisited();
|
valueVisited();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.pather.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -15,10 +15,13 @@ import de.siphalor.tweed5.defaultextensions.pather.api.PathTracking;
|
|||||||
import de.siphalor.tweed5.defaultextensions.pather.api.PathTrackingDataReader;
|
import de.siphalor.tweed5.defaultextensions.pather.api.PathTrackingDataReader;
|
||||||
import de.siphalor.tweed5.defaultextensions.pather.api.PathTrackingDataVisitor;
|
import de.siphalor.tweed5.defaultextensions.pather.api.PathTrackingDataVisitor;
|
||||||
import de.siphalor.tweed5.defaultextensions.pather.api.PatherExtension;
|
import de.siphalor.tweed5.defaultextensions.pather.api.PatherExtension;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import lombok.val;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.NonNull;
|
||||||
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@AutoService(PatherExtension.class)
|
@AutoService(PatherExtension.class)
|
||||||
|
@NullUnmarked
|
||||||
public class PatherExtensionImpl implements PatherExtension, TweedExtension, ReadWriteRelatedExtension {
|
public class PatherExtensionImpl implements PatherExtension, TweedExtension, ReadWriteRelatedExtension {
|
||||||
private static final String PATHER_ID = "pather";
|
private static final String PATHER_ID = "pather";
|
||||||
|
|
||||||
@@ -39,7 +42,7 @@ public class PatherExtensionImpl implements PatherExtension, TweedExtension, Rea
|
|||||||
entryWriterMiddleware = createEntryWriterMiddleware();
|
entryWriterMiddleware = createEntryWriterMiddleware();
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull Middleware<TweedEntryReader<?, ?>> createEntryReaderMiddleware() {
|
private @NonNull Middleware<TweedEntryReader<?, ?>> createEntryReaderMiddleware() {
|
||||||
return new Middleware<TweedEntryReader<?, ?>>() {
|
return new Middleware<TweedEntryReader<?, ?>>() {
|
||||||
@Override
|
@Override
|
||||||
public String id() {
|
public String id() {
|
||||||
@@ -49,7 +52,7 @@ public class PatherExtensionImpl implements PatherExtension, TweedExtension, Rea
|
|||||||
@Override
|
@Override
|
||||||
public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner) {
|
public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
TweedEntryReader<Object, ConfigEntry<Object>> castedInner = (TweedEntryReader<Object, ConfigEntry<Object>>) inner;
|
val castedInner = (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner;
|
||||||
|
|
||||||
return (TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext context) -> {
|
return (TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext context) -> {
|
||||||
if (context.extensionsData().isPatchworkPartSet(PathTracking.class)) {
|
if (context.extensionsData().isPatchworkPartSet(PathTracking.class)) {
|
||||||
@@ -74,7 +77,7 @@ public class PatherExtensionImpl implements PatherExtension, TweedExtension, Rea
|
|||||||
@Override
|
@Override
|
||||||
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) {
|
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
TweedEntryWriter<Object, ConfigEntry<Object>> castedInner = (TweedEntryWriter<Object, ConfigEntry<Object>>) inner;
|
val castedInner = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner;
|
||||||
|
|
||||||
return (TweedDataVisitor writer, Object value, ConfigEntry<Object> entry, TweedWriteContext context) -> {
|
return (TweedDataVisitor writer, Object value, ConfigEntry<Object> entry, TweedWriteContext context) -> {
|
||||||
if (context.extensionsData().isPatchworkPartSet(PathTracking.class)) {
|
if (context.extensionsData().isPatchworkPartSet(PathTracking.class)) {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.pather.impl;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -2,11 +2,10 @@ package de.siphalor.tweed5.defaultextensions.validation.api;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface ConfigEntryValidator {
|
public interface ConfigEntryValidator {
|
||||||
<T> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value);
|
<T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value);
|
||||||
|
|
||||||
@NotNull
|
|
||||||
<T> String description(ConfigEntry<T> configEntry);
|
<T> String description(ConfigEntry<T> configEntry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package de.siphalor.tweed5.defaultextensions.validation.api;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssues;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssues;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface ValidationExtension extends TweedExtension {
|
public interface ValidationExtension extends TweedExtension {
|
||||||
<T> ValidationIssues validate(ConfigEntry<T> entry, T value);
|
<T extends @Nullable Object> ValidationIssues validate(ConfigEntry<T> entry, T value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.validation.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -3,7 +3,6 @@ package de.siphalor.tweed5.defaultextensions.validation.api.result;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -14,7 +13,6 @@ import java.util.function.Function;
|
|||||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class ValidationResult<T> {
|
public class ValidationResult<T> {
|
||||||
private final T value;
|
private final T value;
|
||||||
@NotNull
|
|
||||||
private final Collection<ValidationIssue> issues;
|
private final Collection<ValidationIssue> issues;
|
||||||
private final boolean hasError;
|
private final boolean hasError;
|
||||||
|
|
||||||
@@ -22,7 +20,7 @@ public class ValidationResult<T> {
|
|||||||
return new ValidationResult<>(value, Collections.emptyList(), false);
|
return new ValidationResult<>(value, Collections.emptyList(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ValidationResult<T> withIssues(T value, @NotNull Collection<ValidationIssue> issues) {
|
public static <T> ValidationResult<T> withIssues(T value, Collection<ValidationIssue> issues) {
|
||||||
return new ValidationResult<>(value, issues, issuesContainError(issues));
|
return new ValidationResult<>(value, issues, issuesContainError(issues));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator;
|
|||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssue;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssue;
|
||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssueLevel;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssueLevel;
|
||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
public class NonNullValidator implements ConfigEntryValidator {
|
public class NonNullValidator implements ConfigEntryValidator {
|
||||||
@Override
|
@Override
|
||||||
public <T> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return ValidationResult.withIssues(null, Collections.singleton(
|
return ValidationResult.withIssues(null, Collections.singleton(
|
||||||
new ValidationIssue("Value must not be null", ValidationIssueLevel.ERROR)
|
new ValidationIssue("Value must not be null", ValidationIssueLevel.ERROR)
|
||||||
@@ -21,7 +21,7 @@ public class NonNullValidator implements ConfigEntryValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull <T> String description(ConfigEntry<T> configEntry) {
|
public <T> String description(ConfigEntry<T> configEntry) {
|
||||||
return "Must be set (not null).";
|
return "Must be set (not null).";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,23 +7,20 @@ import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssu
|
|||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.NonNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class NumberRangeValidator<N extends Number> implements ConfigEntryValidator {
|
public class NumberRangeValidator<N extends @NonNull Number> implements ConfigEntryValidator {
|
||||||
@NotNull
|
|
||||||
Class<N> numberClass;
|
Class<N> numberClass;
|
||||||
@Nullable
|
@Nullable N minimum;
|
||||||
N minimum;
|
@Nullable N maximum;
|
||||||
@Nullable
|
|
||||||
N maximum;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
||||||
if (!(value instanceof Number)) {
|
if (!(value instanceof Number)) {
|
||||||
return ValidationResult.withIssues(value, Collections.singleton(
|
return ValidationResult.withIssues(value, Collections.singleton(
|
||||||
new ValidationIssue("Value must be numeric", ValidationIssueLevel.ERROR)
|
new ValidationIssue("Value must be numeric", ValidationIssueLevel.ERROR)
|
||||||
@@ -56,7 +53,7 @@ public class NumberRangeValidator<N extends Number> implements ConfigEntryValida
|
|||||||
return ValidationResult.ok(value);
|
return ValidationResult.ok(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int compare(@NotNull Number a, @NotNull Number b) {
|
private int compare(Number a, Number b) {
|
||||||
if (numberClass == Byte.class) {
|
if (numberClass == Byte.class) {
|
||||||
return Byte.compare(a.byteValue(), b.byteValue());
|
return Byte.compare(a.byteValue(), b.byteValue());
|
||||||
} else if (numberClass == Short.class) {
|
} else if (numberClass == Short.class) {
|
||||||
@@ -73,7 +70,7 @@ public class NumberRangeValidator<N extends Number> implements ConfigEntryValida
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull <T> String description(ConfigEntry<T> configEntry) {
|
public <T> String description(ConfigEntry<T> configEntry) {
|
||||||
if (minimum == null) {
|
if (minimum == null) {
|
||||||
if (maximum == null) {
|
if (maximum == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator;
|
|||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@@ -18,12 +18,12 @@ public class SimpleValidatorMiddleware implements Middleware<ConfigEntryValidato
|
|||||||
public ConfigEntryValidator process(ConfigEntryValidator inner) {
|
public ConfigEntryValidator process(ConfigEntryValidator inner) {
|
||||||
return new ConfigEntryValidator() {
|
return new ConfigEntryValidator() {
|
||||||
@Override
|
@Override
|
||||||
public <T> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
||||||
return inner.validate(configEntry, value).andThen(v -> validator.validate(configEntry, v));
|
return inner.validate(configEntry, value).andThen(v -> validator.validate(configEntry, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull <T> String description(ConfigEntry<T> configEntry) {
|
public <T extends @Nullable Object> String description(ConfigEntry<T> configEntry) {
|
||||||
String description = validator.description(configEntry);
|
String description = validator.description(configEntry);
|
||||||
if (description.isEmpty()) {
|
if (description.isEmpty()) {
|
||||||
return inner.description(configEntry);
|
return inner.description(configEntry);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.validation.api.validators;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -35,11 +35,13 @@ import lombok.Getter;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@AutoService(ValidationExtension.class)
|
@AutoService(ValidationExtension.class)
|
||||||
|
@NullUnmarked
|
||||||
public class ValidationExtensionImpl implements ReadWriteRelatedExtension, ValidationExtension, CommentModifyingExtension {
|
public class ValidationExtensionImpl implements ReadWriteRelatedExtension, ValidationExtension, CommentModifyingExtension {
|
||||||
private static final ValidationResult<?> PRIMITIVE_IS_NULL_RESULT = ValidationResult.withIssues(
|
private static final ValidationResult<?> PRIMITIVE_IS_NULL_RESULT = ValidationResult.withIssues(
|
||||||
null,
|
null,
|
||||||
@@ -47,7 +49,7 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
|
|||||||
);
|
);
|
||||||
private static final ConfigEntryValidator PRIMITIVE_VALIDATOR = new ConfigEntryValidator() {
|
private static final ConfigEntryValidator PRIMITIVE_VALIDATOR = new ConfigEntryValidator() {
|
||||||
@Override
|
@Override
|
||||||
public <T> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
public <T> ValidationResult<T> validate(@NotNull ConfigEntry<T> configEntry, @Nullable T value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (ValidationResult<T>) PRIMITIVE_IS_NULL_RESULT;
|
return (ValidationResult<T>) PRIMITIVE_IS_NULL_RESULT;
|
||||||
@@ -56,18 +58,18 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull <T> String description(ConfigEntry<T> configEntry) {
|
public <T> String description(@NotNull ConfigEntry<T> configEntry) {
|
||||||
return "Value must not be null.";
|
return "Value must not be null.";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private static final ConfigEntryValidator NOOP_VALIDATOR = new ConfigEntryValidator() {
|
private static final ConfigEntryValidator NOOP_VALIDATOR = new ConfigEntryValidator() {
|
||||||
@Override
|
@Override
|
||||||
public <T> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
public <T> ValidationResult<T> validate(@NotNull ConfigEntry<T> configEntry, @Nullable T value) {
|
||||||
return ValidationResult.ok(value);
|
return ValidationResult.ok(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull <T> String description(ConfigEntry<T> configEntry) {
|
public <T> String description(@NotNull ConfigEntry<T> configEntry) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -166,7 +168,7 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ValidationIssues validate(ConfigEntry<T> entry, T value) {
|
public <T> ValidationIssues validate(@NotNull ConfigEntry<T> entry, @Nullable T value) {
|
||||||
PathTracking pathTracking = new PathTracking();
|
PathTracking pathTracking = new PathTracking();
|
||||||
ValidatingConfigEntryVisitor validatingVisitor = new ValidatingConfigEntryVisitor(pathTracking);
|
ValidatingConfigEntryVisitor validatingVisitor = new ValidatingConfigEntryVisitor(pathTracking);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.validation.impl;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package de.siphalor.tweed5.defaultextensions.validationfallback.api;
|
package de.siphalor.tweed5.defaultextensions.validationfallback.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface ValidationFallbackValue {
|
public interface ValidationFallbackValue {
|
||||||
Object validationFallbackValue();
|
@Nullable Object validationFallbackValue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.validationfallback.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -11,7 +11,7 @@ import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssu
|
|||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
|
||||||
import de.siphalor.tweed5.defaultextensions.validationfallback.api.ValidationFallbackExtension;
|
import de.siphalor.tweed5.defaultextensions.validationfallback.api.ValidationFallbackExtension;
|
||||||
import de.siphalor.tweed5.defaultextensions.validationfallback.api.ValidationFallbackValue;
|
import de.siphalor.tweed5.defaultextensions.validationfallback.api.ValidationFallbackValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -55,7 +55,7 @@ public class ValidationFallbackExtensionImpl implements ValidationFallbackExtens
|
|||||||
public ConfigEntryValidator process(ConfigEntryValidator inner) {
|
public ConfigEntryValidator process(ConfigEntryValidator inner) {
|
||||||
return new ConfigEntryValidator() {
|
return new ConfigEntryValidator() {
|
||||||
@Override
|
@Override
|
||||||
public <T> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {
|
||||||
ValidationResult<T> result = inner.validate(configEntry, value);
|
ValidationResult<T> result = inner.validate(configEntry, value);
|
||||||
if (!result.hasError()) {
|
if (!result.hasError()) {
|
||||||
return result;
|
return result;
|
||||||
@@ -90,7 +90,7 @@ public class ValidationFallbackExtensionImpl implements ValidationFallbackExtens
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull <T> String description(ConfigEntry<T> configEntry) {
|
public <T> String description(ConfigEntry<T> configEntry) {
|
||||||
if (!configEntry.extensionsData().isPatchworkPartSet(ValidationFallbackValue.class)) {
|
if (!configEntry.extensionsData().isPatchworkPartSet(ValidationFallbackValue.class)) {
|
||||||
return inner.description(configEntry);
|
return inner.description(configEntry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.defaultextensions.validationfallback.impl;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.namingformat.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
package de.siphalor.tweed5.namingformat.impl;
|
package de.siphalor.tweed5.namingformat.impl;
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import de.siphalor.tweed5.patchwork.impl.ByteArrayClassLoader;
|
|||||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClass;
|
import de.siphalor.tweed5.patchwork.impl.PatchworkClass;
|
||||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClassGenerator;
|
import de.siphalor.tweed5.patchwork.impl.PatchworkClassGenerator;
|
||||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
|
import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
|
||||||
import lombok.*;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@@ -16,17 +19,18 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
@Value
|
@Value
|
||||||
public class PatchworkClassCreator<P extends Patchwork<P>> {
|
public class PatchworkClassCreator<P extends Patchwork<P>> {
|
||||||
@NonNull
|
|
||||||
Class<P> patchworkInterface;
|
Class<P> patchworkInterface;
|
||||||
@NonNull
|
|
||||||
PatchworkClassGenerator.Config generatorConfig;
|
PatchworkClassGenerator.Config generatorConfig;
|
||||||
|
|
||||||
public static <P extends Patchwork<P>> Builder<P> builder() {
|
public static <P extends Patchwork<P>> Builder<P> builder() {
|
||||||
return new Builder<>();
|
return new Builder<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PatchworkClass<P> createClass(Collection<Class<?>> partInterfaces) throws PatchworkClassGenerator.GenerationException {
|
public PatchworkClass<P> createClass(Collection<Class<?>> partInterfaces) throws
|
||||||
List<PatchworkClassPart> parts = partInterfaces.stream().map(PatchworkClassPart::new).collect(Collectors.toList());
|
PatchworkClassGenerator.GenerationException {
|
||||||
|
List<PatchworkClassPart> parts = partInterfaces.stream()
|
||||||
|
.map(PatchworkClassPart::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
PatchworkClassGenerator generator = new PatchworkClassGenerator(generatorConfig, parts);
|
PatchworkClassGenerator generator = new PatchworkClassGenerator(generatorConfig, parts);
|
||||||
try {
|
try {
|
||||||
@@ -45,7 +49,10 @@ public class PatchworkClassCreator<P extends Patchwork<P>> {
|
|||||||
MethodHandle setterHandle = lookup.findSetter(patchworkClass, part.fieldName(), part.partInterface());
|
MethodHandle setterHandle = lookup.findSetter(patchworkClass, part.fieldName(), part.partInterface());
|
||||||
part.fieldSetter(setterHandle);
|
part.fieldSetter(setterHandle);
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
throw new IllegalStateException("Failed to access setter for patchwork part " + part.partInterface().getName(), e);
|
throw new IllegalStateException(
|
||||||
|
"Failed to access setter for patchwork part " + part.partInterface().getName(),
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -67,9 +74,7 @@ public class PatchworkClassCreator<P extends Patchwork<P>> {
|
|||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public static class Builder<P extends Patchwork<P>> {
|
public static class Builder<P extends Patchwork<P>> {
|
||||||
@NonNull
|
|
||||||
private Class<P> patchworkInterface;
|
private Class<P> patchworkInterface;
|
||||||
@NonNull
|
|
||||||
private String classPackage;
|
private String classPackage;
|
||||||
private String classPrefix = "";
|
private String classPrefix = "";
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.patchwork.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package de.siphalor.tweed5.patchwork.impl;
|
package de.siphalor.tweed5.patchwork.impl;
|
||||||
|
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public class ByteArrayClassLoader extends ClassLoader {
|
public class ByteArrayClassLoader extends ClassLoader {
|
||||||
public static Class<?> loadClass(String binaryClassName, byte[] byteCode) {
|
public static Class<?> loadClass(@Nullable String binaryClassName, byte[] byteCode) {
|
||||||
return new ByteArrayClassLoader(ByteArrayClassLoader.class.getClassLoader())
|
return new ByteArrayClassLoader(ByteArrayClassLoader.class.getClassLoader())
|
||||||
.createClass(binaryClassName, byteCode);
|
.createClass(binaryClassName, byteCode);
|
||||||
}
|
}
|
||||||
@@ -11,7 +13,7 @@ public class ByteArrayClassLoader extends ClassLoader {
|
|||||||
super(parent);
|
super(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> createClass(String binaryClassName, byte[] byteCode) {
|
public Class<?> createClass(@Nullable String binaryClassName, byte[] byteCode) {
|
||||||
Class<?> clazz = defineClass(binaryClassName, byteCode, 0, byteCode.length);
|
Class<?> clazz = defineClass(binaryClassName, byteCode, 0, byteCode.length);
|
||||||
resolveClass(clazz);
|
resolveClass(clazz);
|
||||||
return clazz;
|
return clazz;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import de.siphalor.tweed5.patchwork.api.Patchwork;
|
|||||||
import de.siphalor.tweed5.patchwork.api.PatchworkPartIsNullException;
|
import de.siphalor.tweed5.patchwork.api.PatchworkPartIsNullException;
|
||||||
import de.siphalor.tweed5.patchwork.impl.util.StreamUtils;
|
import de.siphalor.tweed5.patchwork.impl.util.StreamUtils;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
import org.objectweb.asm.commons.GeneratorAdapter;
|
||||||
|
|
||||||
@@ -21,7 +23,8 @@ public class PatchworkClassGenerator {
|
|||||||
*/
|
*/
|
||||||
private static final int CLASS_VERSION = Opcodes.V1_8;
|
private static final int CLASS_VERSION = Opcodes.V1_8;
|
||||||
private static final String TARGET_PACKAGE = "de.siphalor.tweed5.core.generated.contextextensions";
|
private static final String TARGET_PACKAGE = "de.siphalor.tweed5.core.generated.contextextensions";
|
||||||
private static final List<Type> DEFAULT_PATHWORK_INTERFACES = Collections.singletonList(Type.getType(Patchwork.class));
|
private static final List<Type> DEFAULT_PATHWORK_INTERFACES
|
||||||
|
= Collections.singletonList(Type.getType(Patchwork.class));
|
||||||
|
|
||||||
private static final String INNER_EQUALS_METHOD_NAME = "patchwork$innerEquals";
|
private static final String INNER_EQUALS_METHOD_NAME = "patchwork$innerEquals";
|
||||||
|
|
||||||
@@ -458,7 +461,13 @@ public class PatchworkClassGenerator {
|
|||||||
}
|
}
|
||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
|
|
||||||
private GeneratorAdapter createMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
private GeneratorAdapter createMethod(
|
||||||
|
int access,
|
||||||
|
String name,
|
||||||
|
String desc,
|
||||||
|
@Nullable String signature,
|
||||||
|
String @Nullable [] exceptions
|
||||||
|
) {
|
||||||
MethodVisitor methodVisitor = classWriter.visitMethod(access, name, desc, signature, exceptions);
|
MethodVisitor methodVisitor = classWriter.visitMethod(access, name, desc, signature, exceptions);
|
||||||
return new GeneratorAdapter(methodVisitor, access, name, desc);
|
return new GeneratorAdapter(methodVisitor, access, name, desc);
|
||||||
}
|
}
|
||||||
@@ -502,7 +511,13 @@ public class PatchworkClassGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
public MethodVisitor visitMethod(
|
||||||
|
int access,
|
||||||
|
String name,
|
||||||
|
String descriptor,
|
||||||
|
String signature,
|
||||||
|
String[] exceptions
|
||||||
|
) {
|
||||||
GeneratorAdapter methodWriter = createMethod(Opcodes.ACC_PUBLIC, name, descriptor, signature, exceptions);
|
GeneratorAdapter methodWriter = createMethod(Opcodes.ACC_PUBLIC, name, descriptor, signature, exceptions);
|
||||||
return new PartMethodVisitor(api, methodWriter, descriptor, extensionClass);
|
return new PartMethodVisitor(api, methodWriter, descriptor, extensionClass);
|
||||||
}
|
}
|
||||||
@@ -513,7 +528,12 @@ public class PatchworkClassGenerator {
|
|||||||
private final String methodDescriptor;
|
private final String methodDescriptor;
|
||||||
private final PatchworkClassPart patchworkPart;
|
private final PatchworkClassPart patchworkPart;
|
||||||
|
|
||||||
protected PartMethodVisitor(int api, GeneratorAdapter methodWriter, String methodDescriptor, PatchworkClassPart patchworkPart) {
|
protected PartMethodVisitor(
|
||||||
|
int api,
|
||||||
|
GeneratorAdapter methodWriter,
|
||||||
|
String methodDescriptor,
|
||||||
|
PatchworkClassPart patchworkPart
|
||||||
|
) {
|
||||||
super(api);
|
super(api);
|
||||||
this.methodWriter = methodWriter;
|
this.methodWriter = methodWriter;
|
||||||
this.patchworkPart = patchworkPart;
|
this.patchworkPart = patchworkPart;
|
||||||
@@ -531,7 +551,12 @@ public class PatchworkClassGenerator {
|
|||||||
|
|
||||||
methodWriter.visitCode();
|
methodWriter.visitCode();
|
||||||
methodWriter.visitVarInsn(Opcodes.ALOAD, 0);
|
methodWriter.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
methodWriter.visitFieldInsn(Opcodes.GETFIELD, internalClassName(), patchworkPart.fieldName(), Type.getDescriptor(patchworkPart.partInterface()));
|
methodWriter.visitFieldInsn(
|
||||||
|
Opcodes.GETFIELD,
|
||||||
|
internalClassName(),
|
||||||
|
patchworkPart.fieldName(),
|
||||||
|
Type.getDescriptor(patchworkPart.partInterface())
|
||||||
|
);
|
||||||
methodWriter.dup();
|
methodWriter.dup();
|
||||||
methodWriter.ifNull(nullLabel);
|
methodWriter.ifNull(nullLabel);
|
||||||
methodWriter.loadArgs();
|
methodWriter.loadArgs();
|
||||||
@@ -563,11 +588,9 @@ public class PatchworkClassGenerator {
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class Config {
|
public static class Config {
|
||||||
@NonNull
|
@lombok.NonNull
|
||||||
private String classPackage;
|
private @NonNull String classPackage;
|
||||||
@NonNull
|
|
||||||
private String classPrefix = "";
|
private String classPrefix = "";
|
||||||
@NonNull
|
|
||||||
private Collection<Class<?>> markerInterfaces = Collections.emptyList();
|
private Collection<Class<?>> markerInterfaces = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,12 +617,16 @@ public class PatchworkClassGenerator {
|
|||||||
transient Collection<Method> signatures;
|
transient Collection<Method> signatures;
|
||||||
|
|
||||||
private DuplicateMethodsException(Collection<Method> methods) {
|
private DuplicateMethodsException(Collection<Method> methods) {
|
||||||
super("Duplicate method signatures:\n" + methods.stream().map(DuplicateMethodsException::getMethodMessage).collect(Collectors.joining("\n")));
|
super("Duplicate method signatures:\n" + methods.stream()
|
||||||
|
.map(DuplicateMethodsException::getMethodMessage)
|
||||||
|
.collect(Collectors.joining("\n")));
|
||||||
this.signatures = methods;
|
this.signatures = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getMethodMessage(Method method) {
|
private static String getMethodMessage(Method method) {
|
||||||
StringBuilder stringBuilder = new StringBuilder("\t- " + method.getDeclaringClass().getCanonicalName() + "#(");
|
StringBuilder stringBuilder = new StringBuilder("\t- "
|
||||||
|
+ method.getDeclaringClass().getCanonicalName()
|
||||||
|
+ "#(");
|
||||||
for (Class<?> parameterType : method.getParameterTypes()) {
|
for (Class<?> parameterType : method.getParameterTypes()) {
|
||||||
stringBuilder.append(parameterType.getCanonicalName());
|
stringBuilder.append(parameterType.getCanonicalName());
|
||||||
stringBuilder.append(", ");
|
stringBuilder.append(", ");
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.patchwork.impl;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -3,7 +3,7 @@ package de.siphalor.tweed5.dataapi.api;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class TweedDataReadException extends RuntimeException {
|
public class TweedDataReadException extends RuntimeException {
|
||||||
@@ -28,8 +28,7 @@ public class TweedDataReadException extends RuntimeException {
|
|||||||
private String message;
|
private String message;
|
||||||
private Throwable cause;
|
private Throwable cause;
|
||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
@Nullable
|
private @Nullable TweedDataReaderRecoverMode recoverMode;
|
||||||
private TweedDataReaderRecoverMode recoverMode;
|
|
||||||
|
|
||||||
public TweedDataReadException build() {
|
public TweedDataReadException build() {
|
||||||
return new TweedDataReadException(message, cause, recoverMode);
|
return new TweedDataReadException(message, cause, recoverMode);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package de.siphalor.tweed5.dataapi.api;
|
package de.siphalor.tweed5.dataapi.api;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public interface TweedDataVisitor {
|
public interface TweedDataVisitor {
|
||||||
void visitNull();
|
void visitNull();
|
||||||
void visitBoolean(boolean value);
|
void visitBoolean(boolean value);
|
||||||
@@ -11,7 +9,7 @@ public interface TweedDataVisitor {
|
|||||||
void visitLong(long value);
|
void visitLong(long value);
|
||||||
void visitFloat(float value);
|
void visitFloat(float value);
|
||||||
void visitDouble(double value);
|
void visitDouble(double value);
|
||||||
void visitString(@NotNull String value);
|
void visitString(String value);
|
||||||
|
|
||||||
default void visitEmptyList() {
|
default void visitEmptyList() {
|
||||||
visitListStart();
|
visitListStart();
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.dataapi.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -5,13 +5,23 @@ import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
|||||||
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteContextExtensionsData;
|
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteContextExtensionsData;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataReader;
|
import de.siphalor.tweed5.dataapi.api.TweedDataReader;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface ReadWriteExtension extends TweedExtension {
|
public interface ReadWriteExtension extends TweedExtension {
|
||||||
void setEntryReaderWriterDefinition(ConfigEntry<?> entry, EntryReaderWriterDefinition readerWriterDefinition);
|
void setEntryReaderWriterDefinition(ConfigEntry<?> entry, EntryReaderWriterDefinition readerWriterDefinition);
|
||||||
|
|
||||||
ReadWriteContextExtensionsData createReadWriteContextExtensionsData();
|
ReadWriteContextExtensionsData createReadWriteContextExtensionsData();
|
||||||
|
|
||||||
<T> T read(TweedDataReader reader, ConfigEntry<T> entry, ReadWriteContextExtensionsData contextExtensionsData) throws TweedEntryReadException;
|
<T extends @Nullable Object> T read(
|
||||||
|
TweedDataReader reader,
|
||||||
|
ConfigEntry<T> entry,
|
||||||
|
ReadWriteContextExtensionsData contextExtensionsData
|
||||||
|
) throws TweedEntryReadException;
|
||||||
|
|
||||||
<T> void write(TweedDataVisitor writer, T value, ConfigEntry<T> entry, ReadWriteContextExtensionsData contextExtensionsData) throws TweedEntryWriteException;
|
<T extends @Nullable Object> void write(
|
||||||
|
TweedDataVisitor writer,
|
||||||
|
T value,
|
||||||
|
ConfigEntry<T> entry,
|
||||||
|
ReadWriteContextExtensionsData contextExtensionsData
|
||||||
|
) throws TweedEntryWriteException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ package de.siphalor.tweed5.data.extension.api;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataReadException;
|
import de.siphalor.tweed5.dataapi.api.TweedDataReadException;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataReader;
|
import de.siphalor.tweed5.dataapi.api.TweedDataReader;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface TweedEntryReader<T, C extends ConfigEntry<T>> {
|
public interface TweedEntryReader<T extends @Nullable Object, C extends ConfigEntry<T>> {
|
||||||
T read(TweedDataReader reader, C entry, TweedReadContext context) throws TweedEntryReadException, TweedDataReadException;
|
T read(TweedDataReader reader, C entry, TweedReadContext context) throws
|
||||||
|
TweedEntryReadException,
|
||||||
|
TweedDataReadException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package de.siphalor.tweed5.data.extension.api;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
|
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface TweedEntryWriter<T, C extends ConfigEntry<T>> {
|
public interface TweedEntryWriter<T extends @Nullable Object, C extends ConfigEntry<T>> {
|
||||||
void write(TweedDataVisitor writer, T value, C entry, TweedWriteContext context) throws TweedEntryWriteException, TweedDataWriteException;
|
void write(TweedDataVisitor writer, @Nullable T value, C entry, TweedWriteContext context) throws TweedEntryWriteException, TweedDataWriteException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package de.siphalor.tweed5.data.extension.api.extension;
|
|||||||
import de.siphalor.tweed5.core.api.middleware.Middleware;
|
import de.siphalor.tweed5.core.api.middleware.Middleware;
|
||||||
import de.siphalor.tweed5.data.extension.api.TweedEntryReader;
|
import de.siphalor.tweed5.data.extension.api.TweedEntryReader;
|
||||||
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface ReadWriteRelatedExtension {
|
public interface ReadWriteRelatedExtension {
|
||||||
default void setupReadWriteExtension(ReadWriteExtensionSetupContext context) {
|
default void setupReadWriteExtension(ReadWriteExtensionSetupContext context) {
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.data.extension.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -8,6 +8,7 @@ import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
|||||||
import de.siphalor.tweed5.data.extension.impl.TweedEntryReaderWriterImpls;
|
import de.siphalor.tweed5.data.extension.impl.TweedEntryReaderWriterImpls;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@@ -55,11 +56,11 @@ public class TweedEntryReaderWriters {
|
|||||||
|
|
||||||
public static <T, C extends Collection<T>> TweedEntryReaderWriter<C, CollectionConfigEntry<T, C>> collectionReaderWriter() {
|
public static <T, C extends Collection<T>> TweedEntryReaderWriter<C, CollectionConfigEntry<T, C>> collectionReaderWriter() {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (TweedEntryReaderWriter<C, CollectionConfigEntry<T,C>>)(TweedEntryReaderWriter<?, ?>) TweedEntryReaderWriterImpls.COLLECTION_READER_WRITER;
|
return (TweedEntryReaderWriter<C, @NonNull CollectionConfigEntry<T, C>>) (TweedEntryReaderWriter<?, ?>) TweedEntryReaderWriterImpls.COLLECTION_READER_WRITER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> TweedEntryReaderWriter<T, CompoundConfigEntry<T>> compoundReaderWriter() {
|
public static <T> TweedEntryReaderWriter<T, CompoundConfigEntry<T>> compoundReaderWriter() {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (TweedEntryReaderWriter<T, CompoundConfigEntry<T>>)(TweedEntryReaderWriter<?, ?>) TweedEntryReaderWriterImpls.COMPOUND_READER_WRITER;
|
return (TweedEntryReaderWriter<T, @NonNull CompoundConfigEntry<T>>) (TweedEntryReaderWriter<?, ?>) TweedEntryReaderWriterImpls.COMPOUND_READER_WRITER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.data.extension.api.readwrite;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -22,6 +22,10 @@ import de.siphalor.tweed5.patchwork.impl.PatchworkClassGenerator;
|
|||||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
|
import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
import lombok.val;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -29,14 +33,16 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@AutoService(ReadWriteExtension.class)
|
@AutoService(ReadWriteExtension.class)
|
||||||
|
@NullUnmarked
|
||||||
public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
||||||
|
|
||||||
private RegisteredExtensionData<EntryExtensionsData, EntryReaderWriterDefinition> readerWriterDefinitionExtension;
|
private RegisteredExtensionData<EntryExtensionsData, EntryReaderWriterDefinition> readerWriterDefinitionExtension;
|
||||||
private RegisteredExtensionData<EntryExtensionsData, ReadWriteEntryDataExtension> readWriteEntryDataExtension;
|
private RegisteredExtensionData<EntryExtensionsData, ReadWriteEntryDataExtension> readWriteEntryDataExtension;
|
||||||
private DefaultMiddlewareContainer<TweedEntryReader<?, ?>> entryReaderMiddlewareContainer;
|
private DefaultMiddlewareContainer<TweedEntryReader<?, ?>> entryReaderMiddlewareContainer;
|
||||||
private DefaultMiddlewareContainer<TweedEntryWriter<?, ?>> entryWriterMiddlewareContainer;
|
private DefaultMiddlewareContainer<TweedEntryWriter<?, ?>> entryWriterMiddlewareContainer;
|
||||||
private Map<Class<?>, RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, ?>> readWriteContextExtensionsDataClasses;
|
private Map<Class<?>, RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, ?>>
|
||||||
private PatchworkClass<ReadWriteContextExtensionsData> readWriteContextExtensionsDataPatchwork;
|
readWriteContextExtensionsDataClasses;
|
||||||
|
private PatchworkClass<@NonNull ReadWriteContextExtensionsData> readWriteContextExtensionsDataPatchwork;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@@ -54,11 +60,17 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
|
|
||||||
ReadWriteExtensionSetupContext setupContext = new ReadWriteExtensionSetupContext() {
|
ReadWriteExtensionSetupContext setupContext = new ReadWriteExtensionSetupContext() {
|
||||||
@Override
|
@Override
|
||||||
public <E> RegisteredExtensionData<ReadWriteContextExtensionsData, E> registerReadWriteContextExtensionData(Class<E> extensionDataClass) {
|
public <E> RegisteredExtensionData<ReadWriteContextExtensionsData, E> registerReadWriteContextExtensionData(
|
||||||
|
Class<E> extensionDataClass
|
||||||
|
) {
|
||||||
if (readWriteContextExtensionsDataClasses.containsKey(extensionDataClass)) {
|
if (readWriteContextExtensionsDataClasses.containsKey(extensionDataClass)) {
|
||||||
throw new IllegalArgumentException("Context extension " + extensionDataClass.getName() + " is already registered");
|
throw new IllegalArgumentException("Context extension "
|
||||||
|
+ extensionDataClass.getName()
|
||||||
|
+ " is already registered");
|
||||||
}
|
}
|
||||||
RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, E> registeredExtensionData = new RegisteredExtensionDataImpl<>();
|
RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, E>
|
||||||
|
registeredExtensionData
|
||||||
|
= new RegisteredExtensionDataImpl<>();
|
||||||
readWriteContextExtensionsDataClasses.put(extensionDataClass, registeredExtensionData);
|
readWriteContextExtensionsDataClasses.put(extensionDataClass, registeredExtensionData);
|
||||||
return registeredExtensionData;
|
return registeredExtensionData;
|
||||||
}
|
}
|
||||||
@@ -73,11 +85,13 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
|
|
||||||
rwExtension.setupReadWriteExtension(setupContext);
|
rwExtension.setupReadWriteExtension(setupContext);
|
||||||
|
|
||||||
if (rwExtension.entryReaderMiddleware() != null) {
|
val readerMiddleware = rwExtension.entryReaderMiddleware();
|
||||||
entryReaderMiddlewareContainer.register(rwExtension.entryReaderMiddleware());
|
if (readerMiddleware != null) {
|
||||||
|
entryReaderMiddlewareContainer.register(readerMiddleware);
|
||||||
}
|
}
|
||||||
if (rwExtension.entryWriterMiddleware() != null) {
|
val writerMiddleware = rwExtension.entryWriterMiddleware();
|
||||||
entryWriterMiddlewareContainer.register(rwExtension.entryWriterMiddleware());
|
if (writerMiddleware != null) {
|
||||||
|
entryWriterMiddlewareContainer.register(writerMiddleware);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,20 +99,26 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
entryReaderMiddlewareContainer.seal();
|
entryReaderMiddlewareContainer.seal();
|
||||||
entryWriterMiddlewareContainer.seal();
|
entryWriterMiddlewareContainer.seal();
|
||||||
|
|
||||||
PatchworkClassCreator<ReadWriteContextExtensionsData> patchworkClassCreator = PatchworkClassCreator.<ReadWriteContextExtensionsData>builder()
|
val patchworkClassCreator = PatchworkClassCreator.<ReadWriteContextExtensionsData>builder()
|
||||||
.patchworkInterface(ReadWriteContextExtensionsData.class)
|
.patchworkInterface(ReadWriteContextExtensionsData.class)
|
||||||
.classPackage("de.siphalor.tweed5.data.extension.generated")
|
.classPackage("de.siphalor.tweed5.data.extension.generated")
|
||||||
.classPrefix("ReadWriteContextExtensionsData$")
|
.classPrefix("ReadWriteContextExtensionsData$")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
readWriteContextExtensionsDataPatchwork = patchworkClassCreator.createClass(readWriteContextExtensionsDataClasses.keySet());
|
readWriteContextExtensionsDataPatchwork =
|
||||||
|
patchworkClassCreator.createClass(readWriteContextExtensionsDataClasses.keySet());
|
||||||
for (PatchworkClassPart patchworkClassPart : readWriteContextExtensionsDataPatchwork.parts()) {
|
for (PatchworkClassPart patchworkClassPart : readWriteContextExtensionsDataPatchwork.parts()) {
|
||||||
RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, ?> registeredExtension = readWriteContextExtensionsDataClasses.get(patchworkClassPart.partInterface());
|
RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, ?>
|
||||||
|
registeredExtension
|
||||||
|
= readWriteContextExtensionsDataClasses.get(patchworkClassPart.partInterface());
|
||||||
registeredExtension.setter = patchworkClassPart.fieldSetter();
|
registeredExtension.setter = patchworkClassPart.fieldSetter();
|
||||||
}
|
}
|
||||||
} catch (PatchworkClassGenerator.GenerationException e) {
|
} catch (PatchworkClassGenerator.GenerationException e) {
|
||||||
throw new IllegalStateException("Failed to generate read write context extensions' data patchwork class", e);
|
throw new IllegalStateException(
|
||||||
|
"Failed to generate read write context extensions' data patchwork class",
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,14 +135,19 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
baseWriter = TweedEntryReaderWriterImpls.NOOP_READER_WRITER;
|
baseWriter = TweedEntryReaderWriterImpls.NOOP_READER_WRITER;
|
||||||
}
|
}
|
||||||
|
|
||||||
readWriteEntryDataExtension.set(configEntry.extensionsData(), new ReadWriteEntryDataExtensionImpl(
|
readWriteEntryDataExtension.set(
|
||||||
entryReaderMiddlewareContainer.process(baseReader),
|
configEntry.extensionsData(), new ReadWriteEntryDataExtensionImpl(
|
||||||
entryWriterMiddlewareContainer.process(baseWriter)
|
entryReaderMiddlewareContainer.process(baseReader),
|
||||||
));
|
entryWriterMiddlewareContainer.process(baseWriter)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEntryReaderWriterDefinition(ConfigEntry<?> entry, EntryReaderWriterDefinition readerWriterDefinition) {
|
public void setEntryReaderWriterDefinition(
|
||||||
|
@NonNull ConfigEntry<?> entry,
|
||||||
|
@NonNull EntryReaderWriterDefinition readerWriterDefinition
|
||||||
|
) {
|
||||||
readerWriterDefinitionExtension.set(entry.extensionsData(), readerWriterDefinition);
|
readerWriterDefinitionExtension.set(entry.extensionsData(), readerWriterDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +161,11 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T read(TweedDataReader reader, ConfigEntry<T> entry, ReadWriteContextExtensionsData contextExtensionsData) throws TweedEntryReadException {
|
public <T> T read(
|
||||||
|
@NonNull TweedDataReader reader,
|
||||||
|
@NonNull ConfigEntry<T> entry,
|
||||||
|
@NonNull ReadWriteContextExtensionsData contextExtensionsData
|
||||||
|
) throws TweedEntryReadException {
|
||||||
try {
|
try {
|
||||||
return getReaderChain(entry).read(reader, entry, new TweedReadWriteContextImpl(contextExtensionsData));
|
return getReaderChain(entry).read(reader, entry, new TweedReadWriteContextImpl(contextExtensionsData));
|
||||||
} catch (TweedDataReadException e) {
|
} catch (TweedDataReadException e) {
|
||||||
@@ -145,7 +174,12 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void write(TweedDataVisitor writer, T value, ConfigEntry<T> entry, ReadWriteContextExtensionsData contextExtensionsData) throws TweedEntryWriteException {
|
public <T> void write(
|
||||||
|
@NonNull TweedDataVisitor writer,
|
||||||
|
@Nullable T value,
|
||||||
|
@NonNull ConfigEntry<T> entry,
|
||||||
|
@NonNull ReadWriteContextExtensionsData contextExtensionsData
|
||||||
|
) throws TweedEntryWriteException {
|
||||||
try {
|
try {
|
||||||
getWriterChain(entry).write(writer, value, entry, new TweedReadWriteContextImpl(contextExtensionsData));
|
getWriterChain(entry).write(writer, value, entry, new TweedReadWriteContextImpl(contextExtensionsData));
|
||||||
} catch (TweedDataWriteException e) {
|
} catch (TweedDataWriteException e) {
|
||||||
@@ -160,7 +194,8 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private static class RegisteredExtensionDataImpl<U extends Patchwork<U>, E> implements RegisteredExtensionData<U, E> {
|
private static class RegisteredExtensionDataImpl<U extends Patchwork<@NonNull U>, E>
|
||||||
|
implements RegisteredExtensionData<U, E> {
|
||||||
private MethodHandle setter;
|
private MethodHandle setter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -173,13 +208,13 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> TweedEntryReader<T, ConfigEntry<T>> getReaderChain(ConfigEntry<T> elementEntry) {
|
static <T> TweedEntryReader<T, @NonNull ConfigEntry<T>> getReaderChain(ConfigEntry<T> elementEntry) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (TweedEntryReader<T, ConfigEntry<T>>) ((ReadWriteEntryDataExtension) elementEntry.extensionsData()).entryReaderChain();
|
return (TweedEntryReader<T, @NonNull ConfigEntry<T>>) ((ReadWriteEntryDataExtension) elementEntry.extensionsData()).entryReaderChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> TweedEntryWriter<T, ConfigEntry<T>> getWriterChain(ConfigEntry<T> elementEntry) {
|
static <T> TweedEntryWriter<T, @NonNull ConfigEntry<T>> getWriterChain(ConfigEntry<T> elementEntry) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (TweedEntryWriter<T, ConfigEntry<T>>) ((ReadWriteEntryDataExtension) elementEntry.extensionsData()).entryWriterChain();
|
return (TweedEntryWriter<T, @NonNull ConfigEntry<T>>) ((ReadWriteEntryDataExtension) elementEntry.extensionsData()).entryWriterChain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import de.siphalor.tweed5.dataapi.api.*;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
@@ -32,7 +35,7 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
public static final TweedEntryReaderWriter<Object, ConfigEntry<Object>> NOOP_READER_WRITER = new NoopReaderWriter();
|
public static final TweedEntryReaderWriter<Object, ConfigEntry<Object>> NOOP_READER_WRITER = new NoopReaderWriter();
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public static class NullableReader<T, C extends ConfigEntry<T>> implements TweedEntryReader<T, C> {
|
public static class NullableReader<T extends @Nullable Object, C extends ConfigEntry<T>> implements TweedEntryReader<T, C> {
|
||||||
private final TweedEntryReader<T, C> delegate;
|
private final TweedEntryReader<T, C> delegate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,7 +49,7 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public static class NullableWriter<T, C extends ConfigEntry<T>> implements TweedEntryWriter<T, C> {
|
public static class NullableWriter<T extends @Nullable Object, C extends ConfigEntry<T>> implements TweedEntryWriter<T, C> {
|
||||||
private final TweedEntryWriter<T, C> delegate;
|
private final TweedEntryWriter<T, C> delegate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -60,7 +63,7 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
private static class PrimitiveReaderWriter<T> implements TweedEntryReaderWriter<T, ConfigEntry<T>> {
|
private static class PrimitiveReaderWriter<T extends @NonNull Object> implements TweedEntryReaderWriter<T, ConfigEntry<T>> {
|
||||||
private final Function<TweedDataToken, T> readerCall;
|
private final Function<TweedDataToken, T> readerCall;
|
||||||
private final BiConsumer<TweedDataVisitor, T> writerCall;
|
private final BiConsumer<TweedDataVisitor, T> writerCall;
|
||||||
|
|
||||||
@@ -70,13 +73,13 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(TweedDataVisitor writer, T value, ConfigEntry<T> entry, TweedWriteContext context) throws TweedEntryWriteException, TweedDataWriteException {
|
public void write(TweedDataVisitor writer, @Nullable T value, ConfigEntry<T> entry, TweedWriteContext context) throws TweedEntryWriteException, TweedDataWriteException {
|
||||||
requireNonNullWriteValue(value);
|
requireNonNullWriteValue(value);
|
||||||
writerCall.accept(writer, value);
|
writerCall.accept(writer, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CollectionReaderWriter<T, C extends Collection<T>> implements TweedEntryReaderWriter<C, CollectionConfigEntry<T, C>> {
|
public static class CollectionReaderWriter<T extends @NonNull Object, C extends Collection<T>> implements TweedEntryReaderWriter<C, CollectionConfigEntry<T, C>> {
|
||||||
@Override
|
@Override
|
||||||
public C read(TweedDataReader reader, CollectionConfigEntry<T, C> entry, TweedReadContext context) throws TweedEntryReadException, TweedDataReadException {
|
public C read(TweedDataReader reader, CollectionConfigEntry<T, C> entry, TweedReadContext context) throws TweedEntryReadException, TweedDataReadException {
|
||||||
assertIsToken(reader.readToken(), TweedDataToken::isListStart, "Expected list start");
|
assertIsToken(reader.readToken(), TweedDataToken::isListStart, "Expected list start");
|
||||||
@@ -126,7 +129,7 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CompoundReaderWriter<T> implements TweedEntryReaderWriter<T, CompoundConfigEntry<T>> {
|
public static class CompoundReaderWriter<T extends @NonNull Object> implements TweedEntryReaderWriter<T, CompoundConfigEntry<T>> {
|
||||||
@Override
|
@Override
|
||||||
public T read(TweedDataReader reader, CompoundConfigEntry<T> entry, TweedReadContext context) throws TweedEntryReadException, TweedDataReadException {
|
public T read(TweedDataReader reader, CompoundConfigEntry<T> entry, TweedReadContext context) throws TweedEntryReadException, TweedDataReadException {
|
||||||
assertIsToken(reader.readToken(), TweedDataToken::isMapStart, "Expected map start");
|
assertIsToken(reader.readToken(), TweedDataToken::isMapStart, "Expected map start");
|
||||||
@@ -143,10 +146,8 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
ConfigEntry<Object> subEntry = (ConfigEntry<Object>) compoundEntries.get(key);
|
ConfigEntry<Object> subEntry = (ConfigEntry<Object>) compoundEntries.get(key);
|
||||||
TweedEntryReader<Object, ConfigEntry<Object>> subEntryReaderChain = ReadWriteExtensionImpl.getReaderChain(subEntry);
|
TweedEntryReader<Object, ConfigEntry<Object>> subEntryReaderChain = ReadWriteExtensionImpl.getReaderChain(subEntry);
|
||||||
if (subEntryReaderChain != null) {
|
Object subEntryValue = subEntryReaderChain.read(reader, subEntry, context);
|
||||||
Object subEntryValue = subEntryReaderChain.read(reader, subEntry, context);
|
entry.set(compoundValue, key, subEntryValue);
|
||||||
entry.set(compoundValue, key, subEntryValue);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw new TweedEntryReadException("Unexpected token " + token + ": Expected map key or map end");
|
throw new TweedEntryReadException("Unexpected token " + token + ": Expected map key or map end");
|
||||||
}
|
}
|
||||||
@@ -155,7 +156,7 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(TweedDataVisitor writer, T value, CompoundConfigEntry<T> entry, TweedWriteContext context) throws TweedEntryWriteException, TweedDataWriteException {
|
public void write(TweedDataVisitor writer, @Nullable T value, CompoundConfigEntry<T> entry, TweedWriteContext context) throws TweedEntryWriteException, TweedDataWriteException {
|
||||||
requireNonNullWriteValue(value);
|
requireNonNullWriteValue(value);
|
||||||
|
|
||||||
writer.visitMapStart();
|
writer.visitMapStart();
|
||||||
@@ -168,19 +169,17 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
|
|
||||||
TweedEntryWriter<Object, ConfigEntry<Object>> subEntryWriterChain = ReadWriteExtensionImpl.getWriterChain(subEntry);
|
TweedEntryWriter<Object, ConfigEntry<Object>> subEntryWriterChain = ReadWriteExtensionImpl.getWriterChain(subEntry);
|
||||||
|
|
||||||
if (subEntryWriterChain != null) {
|
writer.visitMapEntryKey(key);
|
||||||
writer.visitMapEntryKey(key);
|
subEntryWriterChain.write(writer, entry.get(value, key), subEntry, context);
|
||||||
subEntryWriterChain.write(writer, entry.get(value, key), subEntry, context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.visitMapEnd();
|
writer.visitMapEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NoopReaderWriter implements TweedEntryReaderWriter<Object, ConfigEntry<Object>> {
|
public static class NoopReaderWriter implements TweedEntryReaderWriter<@Nullable Object, ConfigEntry<Object>> {
|
||||||
@Override
|
@Override
|
||||||
public Object read(TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext context) throws TweedDataReadException {
|
public @Nullable Object read(TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext context) throws TweedDataReadException {
|
||||||
TweedDataToken token = reader.readToken();
|
TweedDataToken token = reader.readToken();
|
||||||
if (!token.isListStart() && !token.isMapStart()) {
|
if (!token.isListStart() && !token.isMapStart()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -209,7 +208,7 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(TweedDataVisitor writer, Object value, ConfigEntry<Object> entry, TweedWriteContext context) throws TweedDataWriteException {
|
public void write(TweedDataVisitor writer, @Nullable Object value, ConfigEntry<Object> entry, TweedWriteContext context) throws TweedDataWriteException {
|
||||||
writer.visitNull();
|
writer.visitNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +217,8 @@ public class TweedEntryReaderWriterImpls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> void requireNonNullWriteValue(T value) throws TweedEntryWriteException {
|
@Contract("null -> fail")
|
||||||
|
private static <T> void requireNonNullWriteValue(@Nullable T value) throws TweedEntryWriteException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new TweedEntryWriteException("Unable to write null value");
|
throw new TweedEntryWriteException("Unable to write null value");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
package de.siphalor.tweed5.data.extension.impl;
|
package de.siphalor.tweed5.data.extension.impl;
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package de.siphalor.tweed5.data.hjson;
|
|||||||
import de.siphalor.tweed5.dataapi.api.TweedDataReadException;
|
import de.siphalor.tweed5.dataapi.api.TweedDataReadException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
@@ -58,8 +58,7 @@ public class HjsonLexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private HjsonLexerToken.@Nullable Type getTerminalTokenType(int codePoint) {
|
||||||
private HjsonLexerToken.Type getTerminalTokenType(int codePoint) {
|
|
||||||
switch (codePoint) {
|
switch (codePoint) {
|
||||||
case -1: return HjsonLexerToken.Type.EOF;
|
case -1: return HjsonLexerToken.Type.EOF;
|
||||||
case '[': return HjsonLexerToken.Type.BRACKET_OPEN;
|
case '[': return HjsonLexerToken.Type.BRACKET_OPEN;
|
||||||
@@ -78,8 +77,7 @@ public class HjsonLexer {
|
|||||||
return new HjsonLexerToken(tokenType, position, position, null);
|
return new HjsonLexerToken(tokenType, position, position, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private @Nullable HjsonLexerToken tryReadQuotedString(int codePoint) throws TweedDataReadException {
|
||||||
private HjsonLexerToken tryReadQuotedString(int codePoint) throws TweedDataReadException {
|
|
||||||
if (codePoint == '"') {
|
if (codePoint == '"') {
|
||||||
return readJsonQuotedString('"');
|
return readJsonQuotedString('"');
|
||||||
} else if (codePoint == '\'') {
|
} else if (codePoint == '\'') {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package de.siphalor.tweed5.data.hjson;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
@Value
|
@Value
|
||||||
@@ -12,12 +12,10 @@ public class HjsonLexerToken {
|
|||||||
HjsonReadPosition begin;
|
HjsonReadPosition begin;
|
||||||
HjsonReadPosition end;
|
HjsonReadPosition end;
|
||||||
@EqualsAndHashCode.Exclude
|
@EqualsAndHashCode.Exclude
|
||||||
@Nullable
|
@Nullable CharSequence content;
|
||||||
CharSequence content;
|
|
||||||
|
|
||||||
@EqualsAndHashCode.Include
|
@EqualsAndHashCode.Include
|
||||||
@Nullable
|
public @Nullable String contentString() {
|
||||||
public String contentString() {
|
|
||||||
return content == null ? null : content.toString();
|
return content == null ? null : content.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package de.siphalor.tweed5.data.hjson;
|
package de.siphalor.tweed5.data.hjson;
|
||||||
|
|
||||||
import de.siphalor.tweed5.dataapi.api.*;
|
import de.siphalor.tweed5.dataapi.api.*;
|
||||||
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -10,9 +12,9 @@ public class HjsonReader implements TweedDataReader {
|
|||||||
private final Deque<Context> contexts;
|
private final Deque<Context> contexts;
|
||||||
private State state = State.BEFORE_VALUE;
|
private State state = State.BEFORE_VALUE;
|
||||||
|
|
||||||
private HjsonLexerToken peekedLexerToken;
|
private @Nullable HjsonLexerToken peekedLexerToken;
|
||||||
|
|
||||||
private TweedDataToken peekedToken;
|
private @Nullable TweedDataToken peekedToken;
|
||||||
|
|
||||||
public HjsonReader(HjsonLexer lexer) {
|
public HjsonReader(HjsonLexer lexer) {
|
||||||
this.lexer = lexer;
|
this.lexer = lexer;
|
||||||
@@ -204,6 +206,7 @@ public class HjsonReader implements TweedDataReader {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NullUnmarked
|
||||||
private TweedDataToken createNumberToken(HjsonLexerToken lexerToken) {
|
private TweedDataToken createNumberToken(HjsonLexerToken lexerToken) {
|
||||||
assert lexerToken.content() != null;
|
assert lexerToken.content() != null;
|
||||||
return new TweedDataToken() {
|
return new TweedDataToken() {
|
||||||
@@ -318,7 +321,7 @@ public class HjsonReader implements TweedDataReader {
|
|||||||
tryLong = 0L;
|
tryLong = 0L;
|
||||||
boolean inFraction = false;
|
boolean inFraction = false;
|
||||||
do {
|
do {
|
||||||
tryLong = Math.addExact(Math.multiplyExact(tryLong, 10L), (long) (codePoint - '0'));
|
tryLong = Math.addExact(Math.multiplyExact(tryLong, 10L), codePoint - '0');
|
||||||
if (inFraction) {
|
if (inFraction) {
|
||||||
fractionDigits++;
|
fractionDigits++;
|
||||||
}
|
}
|
||||||
@@ -513,7 +516,7 @@ public class HjsonReader implements TweedDataReader {
|
|||||||
@Override
|
@Override
|
||||||
public String readAsString() throws TweedDataReadException {
|
public String readAsString() throws TweedDataReadException {
|
||||||
if (lexerToken.type() == HjsonLexerToken.Type.QUOTELESS_STRING || lexerToken.type() == HjsonLexerToken.Type.MULTILINE_STRING) {
|
if (lexerToken.type() == HjsonLexerToken.Type.QUOTELESS_STRING || lexerToken.type() == HjsonLexerToken.Type.MULTILINE_STRING) {
|
||||||
return lexerToken.contentString();
|
return Objects.requireNonNull(lexerToken.contentString());
|
||||||
} else if (lexerToken.type() == HjsonLexerToken.Type.JSON_STRING) {
|
} else if (lexerToken.type() == HjsonLexerToken.Type.JSON_STRING) {
|
||||||
return readJsonString(lexerToken.content());
|
return readJsonString(lexerToken.content());
|
||||||
}
|
}
|
||||||
@@ -623,6 +626,7 @@ public class HjsonReader implements TweedDataReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Context currentContext() {
|
private Context currentContext() {
|
||||||
|
assert contexts.peek() != null;
|
||||||
return contexts.peek();
|
return contexts.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,17 @@ import de.siphalor.tweed5.dataapi.api.TweedDataReader;
|
|||||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedSerde;
|
import de.siphalor.tweed5.dataapi.api.TweedSerde;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
public class HjsonSerde implements TweedSerde {
|
public class HjsonSerde implements TweedSerde {
|
||||||
@Override
|
@Override
|
||||||
public TweedDataReader createReader(InputStream inputStream) {
|
public TweedDataReader createReader(InputStream inputStream) {
|
||||||
return null;
|
return new HjsonReader(new HjsonLexer(new InputStreamReader(inputStream)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TweedDataVisitor createWriter(OutputStream outputStream) throws IOException {
|
public TweedDataVisitor createWriter(OutputStream outputStream) throws IOException {
|
||||||
return null;
|
return new HjsonWriter(new OutputStreamWriter(outputStream), new HjsonWriter.Options());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package de.siphalor.tweed5.data.hjson;
|
|||||||
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
|
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
@@ -90,7 +89,7 @@ public class HjsonWriter implements TweedDataVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitString(@NotNull String value) {
|
public void visitString(String value) {
|
||||||
beforeValueWrite();
|
beforeValueWrite();
|
||||||
writeStringValue(getValueStringStringType(value), value);
|
writeStringValue(getValueStringStringType(value), value);
|
||||||
afterValueWrite();
|
afterValueWrite();
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.data.hjson;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -3,8 +3,7 @@ package de.siphalor.tweed5.typeutils.api.type;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
@@ -27,13 +26,11 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
* The {@link AnnotatedType} that represents the type that is actually in use (without parameters).
|
* The {@link AnnotatedType} that represents the type that is actually in use (without parameters).
|
||||||
*/
|
*/
|
||||||
@Getter(AccessLevel.PROTECTED)
|
@Getter(AccessLevel.PROTECTED)
|
||||||
@Nullable
|
private final @Nullable AnnotatedType usedType;
|
||||||
private final AnnotatedType usedType;
|
|
||||||
/**
|
/**
|
||||||
* The {@link AnnotatedParameterizedType} that represents the type that is actually in use with parameters.
|
* The {@link AnnotatedParameterizedType} that represents the type that is actually in use with parameters.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
private final @Nullable AnnotatedParameterizedType usedParameterizedType;
|
||||||
private final AnnotatedParameterizedType usedParameterizedType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of the layered annotations of this type.
|
* A representation of the layered annotations of this type.
|
||||||
@@ -45,7 +42,7 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
* Internal cache for the resolved actual type parameters.
|
* Internal cache for the resolved actual type parameters.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private List<@NotNull ActualType<?>> resolvedParameters;
|
private List<ActualType<?>> resolvedParameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a basic actual type from just a declared class.
|
* Creates a basic actual type from just a declared class.
|
||||||
@@ -64,7 +61,7 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException when the given annotated type is not yet supported by this class
|
* @throws UnsupportedOperationException when the given annotated type is not yet supported by this class
|
||||||
*/
|
*/
|
||||||
public static ActualType<?> ofUsedType(@NotNull AnnotatedType annotatedType) throws UnsupportedOperationException {
|
public static ActualType<?> ofUsedType(AnnotatedType annotatedType) throws UnsupportedOperationException {
|
||||||
Class<?> clazz = getDeclaredClassForUsedType(annotatedType);
|
Class<?> clazz = getDeclaredClassForUsedType(annotatedType);
|
||||||
|
|
||||||
LayeredTypeAnnotations layeredTypeAnnotations = new LayeredTypeAnnotations();
|
LayeredTypeAnnotations layeredTypeAnnotations = new LayeredTypeAnnotations();
|
||||||
@@ -83,7 +80,7 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException if the given parameter is not supported yet
|
* @throws UnsupportedOperationException if the given parameter is not supported yet
|
||||||
*/
|
*/
|
||||||
private static @NotNull Class<?> getDeclaredClassForUsedType(@NotNull AnnotatedType annotatedType) throws UnsupportedOperationException {
|
private static Class<?> getDeclaredClassForUsedType(AnnotatedType annotatedType) throws UnsupportedOperationException {
|
||||||
if (annotatedType.getType() instanceof Class) {
|
if (annotatedType.getType() instanceof Class) {
|
||||||
return (Class<?>) annotatedType.getType();
|
return (Class<?>) annotatedType.getType();
|
||||||
} else if (annotatedType.getType() instanceof ParameterizedType) {
|
} else if (annotatedType.getType() instanceof ParameterizedType) {
|
||||||
@@ -102,24 +99,24 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A extends Annotation> A getAnnotation(@NotNull Class<A> annotationClass) {
|
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
|
||||||
return layeredTypeAnnotations.getAnnotation(annotationClass);
|
return layeredTypeAnnotations.getAnnotation(annotationClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Annotation @NotNull [] getAnnotations() {
|
public Annotation[] getAnnotations() {
|
||||||
return layeredTypeAnnotations.getAnnotations();
|
return layeredTypeAnnotations.getAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Annotation @NotNull [] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
return layeredTypeAnnotations.getDeclaredAnnotations();
|
return layeredTypeAnnotations.getDeclaredAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the type parameters of this type as {@link ActualType}s.
|
* Resolves the type parameters of this type as {@link ActualType}s.
|
||||||
*/
|
*/
|
||||||
public @NotNull List<@NotNull ActualType<?>> parameters() {
|
public List<ActualType<?>> parameters() {
|
||||||
if (resolvedParameters != null) {
|
if (resolvedParameters != null) {
|
||||||
return resolvedParameters;
|
return resolvedParameters;
|
||||||
} else if (usedParameterizedType == null) {
|
} else if (usedParameterizedType == null) {
|
||||||
@@ -145,7 +142,7 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
* @param targetClass the class to check
|
* @param targetClass the class to check
|
||||||
* @return the list of type parameters if the given class is assignable from this type or {@code null} if not
|
* @return the list of type parameters if the given class is assignable from this type or {@code null} if not
|
||||||
*/
|
*/
|
||||||
public @Nullable List<ActualType<?>> getTypesOfSuperArguments(@NotNull Class<?> targetClass) {
|
public @Nullable List<ActualType<?>> getTypesOfSuperArguments(Class<?> targetClass) {
|
||||||
if (targetClass.getTypeParameters().length == 0) {
|
if (targetClass.getTypeParameters().length == 0) {
|
||||||
if (targetClass.isAssignableFrom(declaredType)) {
|
if (targetClass.isAssignableFrom(declaredType)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -170,7 +167,7 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
return currentType;
|
return currentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<@NotNull ActualType<?>> currentParameters = currentType.parameters();
|
List<ActualType<?>> currentParameters = currentType.parameters();
|
||||||
|
|
||||||
Map<String, AnnotatedType> paramMap;
|
Map<String, AnnotatedType> paramMap;
|
||||||
if (currentParameters.isEmpty()) {
|
if (currentParameters.isEmpty()) {
|
||||||
@@ -178,6 +175,8 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
} else {
|
} else {
|
||||||
paramMap = new HashMap<>();
|
paramMap = new HashMap<>();
|
||||||
for (int i = 0; i < currentParameters.size(); i++) {
|
for (int i = 0; i < currentParameters.size(); i++) {
|
||||||
|
// used types are always known in resolved parameters
|
||||||
|
//noinspection DataFlowIssue
|
||||||
paramMap.put(currentClass.getTypeParameters()[i].getName(), currentParameters.get(i).usedType());
|
paramMap.put(currentClass.getTypeParameters()[i].getName(), currentParameters.get(i).usedType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +184,7 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
if (targetClass.isInterface()) {
|
if (targetClass.isInterface()) {
|
||||||
for (AnnotatedType annotatedInterface : currentClass.getAnnotatedInterfaces()) {
|
for (AnnotatedType annotatedInterface : currentClass.getAnnotatedInterfaces()) {
|
||||||
ActualType<?> interfaceType = resolveTypeWithParameters(annotatedInterface, paramMap);
|
ActualType<?> interfaceType = resolveTypeWithParameters(annotatedInterface, paramMap);
|
||||||
@Nullable ActualType<?> resultType = getViewOnSuperType(targetClass, interfaceType);
|
ActualType<?> resultType = getViewOnSuperType(targetClass, interfaceType);
|
||||||
if (resultType != null) {
|
if (resultType != null) {
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
@@ -193,7 +192,7 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
}
|
}
|
||||||
if (currentClass != Object.class && !currentClass.isInterface()) {
|
if (currentClass != Object.class && !currentClass.isInterface()) {
|
||||||
ActualType<?> superType = resolveTypeWithParameters(currentClass.getAnnotatedSuperclass(), paramMap);
|
ActualType<?> superType = resolveTypeWithParameters(currentClass.getAnnotatedSuperclass(), paramMap);
|
||||||
@Nullable ActualType<?> resultType = getViewOnSuperType(targetClass, superType);
|
ActualType<?> resultType = getViewOnSuperType(targetClass, superType);
|
||||||
if (resultType != null) {
|
if (resultType != null) {
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
@@ -243,10 +242,10 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
appendAnnotationsToString(sb, usedType.getAnnotations());
|
appendAnnotationsToString(sb, usedType.getAnnotations());
|
||||||
}
|
}
|
||||||
sb.append(declaredType.getName());
|
sb.append(declaredType.getName());
|
||||||
List<@NotNull ActualType<?>> parameters = parameters();
|
List<ActualType<?>> parameters = parameters();
|
||||||
if (!parameters.isEmpty()) {
|
if (!parameters.isEmpty()) {
|
||||||
sb.append("<");
|
sb.append("<");
|
||||||
for (@NotNull ActualType<?> parameter : parameters) {
|
for (ActualType<?> parameter : parameters) {
|
||||||
sb.append(parameter);
|
sb.append(parameter);
|
||||||
sb.append(", ");
|
sb.append(", ");
|
||||||
}
|
}
|
||||||
@@ -256,8 +255,8 @@ public class ActualType<T> implements AnnotatedElement {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendAnnotationsToString(@NotNull StringBuilder sb, @NotNull Annotation[] annotations) {
|
private void appendAnnotationsToString(StringBuilder sb, Annotation[] annotations) {
|
||||||
for (@NotNull Annotation annotation : annotations) {
|
for (Annotation annotation : annotations) {
|
||||||
sb.append(annotation);
|
sb.append(annotation);
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,11 @@ package de.siphalor.tweed5.typeutils.api.type;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.typeutils.impl.type.AnnotationRepeatTypeResolver;
|
import de.siphalor.tweed5.typeutils.impl.type.AnnotationRepeatTypeResolver;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
public interface AnnotationRepeatType {
|
public interface AnnotationRepeatType {
|
||||||
static AnnotationRepeatType getType(@NotNull Class<? extends Annotation> annotationClass) {
|
static AnnotationRepeatType getType(Class<? extends Annotation> annotationClass) {
|
||||||
return AnnotationRepeatTypeResolver.getType(annotationClass);
|
return AnnotationRepeatTypeResolver.getType(annotationClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package de.siphalor.tweed5.typeutils.api.type;
|
package de.siphalor.tweed5.typeutils.api.type;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
@@ -11,7 +10,7 @@ import java.util.*;
|
|||||||
public class LayeredTypeAnnotations implements AnnotatedElement {
|
public class LayeredTypeAnnotations implements AnnotatedElement {
|
||||||
private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0];
|
private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0];
|
||||||
|
|
||||||
public static LayeredTypeAnnotations of(@NotNull TypeAnnotationLayer layer, @NotNull AnnotatedElement annotatedElement) {
|
public static LayeredTypeAnnotations of(TypeAnnotationLayer layer, AnnotatedElement annotatedElement) {
|
||||||
LayeredTypeAnnotations annotations = new LayeredTypeAnnotations();
|
LayeredTypeAnnotations annotations = new LayeredTypeAnnotations();
|
||||||
annotations.layers.add(new Layer(layer, annotatedElement));
|
annotations.layers.add(new Layer(layer, annotatedElement));
|
||||||
return annotations;
|
return annotations;
|
||||||
@@ -19,7 +18,7 @@ public class LayeredTypeAnnotations implements AnnotatedElement {
|
|||||||
|
|
||||||
private final List<Layer> layers = new ArrayList<>();
|
private final List<Layer> layers = new ArrayList<>();
|
||||||
|
|
||||||
public void appendLayerFrom(@NotNull TypeAnnotationLayer layer, @NotNull AnnotatedElement annotatedElement) {
|
public void appendLayerFrom(TypeAnnotationLayer layer, AnnotatedElement annotatedElement) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < layers.size(); i++) {
|
for (i = 0; i < layers.size(); i++) {
|
||||||
if (layer.compareTo(layers.get(i).layer()) > 0) {
|
if (layer.compareTo(layers.get(i).layer()) > 0) {
|
||||||
@@ -29,7 +28,7 @@ public class LayeredTypeAnnotations implements AnnotatedElement {
|
|||||||
layers.add(i, new Layer(layer, annotatedElement));
|
layers.add(i, new Layer(layer, annotatedElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prependLayerFrom(@NotNull TypeAnnotationLayer layer, @NotNull AnnotatedElement annotatedElement) {
|
public void prependLayerFrom(TypeAnnotationLayer layer, AnnotatedElement annotatedElement) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < layers.size(); i++) {
|
for (i = 0; i < layers.size(); i++) {
|
||||||
if (layer.compareTo(layers.get(i).layer()) >= 0) {
|
if (layer.compareTo(layers.get(i).layer()) >= 0) {
|
||||||
@@ -40,7 +39,7 @@ public class LayeredTypeAnnotations implements AnnotatedElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Annotation> T getAnnotation(@NotNull Class<T> annotationClass) {
|
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||||
if (layers.isEmpty()) {
|
if (layers.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
} else if (layers.size() == 1) {
|
} else if (layers.size() == 1) {
|
||||||
@@ -62,7 +61,7 @@ public class LayeredTypeAnnotations implements AnnotatedElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Annotation @NotNull [] getAnnotations() {
|
public Annotation[] getAnnotations() {
|
||||||
if (layers.isEmpty()) {
|
if (layers.isEmpty()) {
|
||||||
return EMPTY_ANNOTATIONS;
|
return EMPTY_ANNOTATIONS;
|
||||||
} else if (layers.size() == 1) {
|
} else if (layers.size() == 1) {
|
||||||
@@ -87,7 +86,7 @@ public class LayeredTypeAnnotations implements AnnotatedElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Annotation @NotNull [] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
if (layers.isEmpty()) {
|
if (layers.isEmpty()) {
|
||||||
return EMPTY_ANNOTATIONS;
|
return EMPTY_ANNOTATIONS;
|
||||||
} else if (layers.size() == 1) {
|
} else if (layers.size() == 1) {
|
||||||
@@ -111,7 +110,7 @@ public class LayeredTypeAnnotations implements AnnotatedElement {
|
|||||||
return annotations.values().toArray(new Annotation[0]);
|
return annotations.values().toArray(new Annotation[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T extends Annotation> @Nullable Class<? extends Annotation> getRepeatAlternativeAnnotation(@NotNull Class<T> annotationClass) {
|
private static <T extends Annotation> @Nullable Class<? extends Annotation> getRepeatAlternativeAnnotation(Class<T> annotationClass) {
|
||||||
AnnotationRepeatType annotationRepeatType = AnnotationRepeatType.getType(annotationClass);
|
AnnotationRepeatType annotationRepeatType = AnnotationRepeatType.getType(annotationClass);
|
||||||
Class<? extends Annotation> altAnnotationClass = null;
|
Class<? extends Annotation> altAnnotationClass = null;
|
||||||
if (annotationRepeatType instanceof AnnotationRepeatType.Repeatable) {
|
if (annotationRepeatType instanceof AnnotationRepeatType.Repeatable) {
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.typeutils.api.type;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
|
@NullMarked
|
||||||
package de.siphalor.tweed5.typeutils.impl;
|
package de.siphalor.tweed5.typeutils.impl;
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package de.siphalor.tweed5.typeutils.impl.type;
|
package de.siphalor.tweed5.typeutils.impl.type;
|
||||||
|
|
||||||
import de.siphalor.tweed5.typeutils.api.type.AnnotationRepeatType;
|
import de.siphalor.tweed5.typeutils.api.type.AnnotationRepeatType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.annotation.Repeatable;
|
import java.lang.annotation.Repeatable;
|
||||||
@@ -16,7 +15,7 @@ public class AnnotationRepeatTypeResolver {
|
|||||||
private static final Map<Class<? extends Annotation>, AnnotationRepeatType> CACHE = new HashMap<>();
|
private static final Map<Class<? extends Annotation>, AnnotationRepeatType> CACHE = new HashMap<>();
|
||||||
private static final ReadWriteLock CACHE_LOCK = new ReentrantReadWriteLock();
|
private static final ReadWriteLock CACHE_LOCK = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
public static AnnotationRepeatType getType(@NotNull Class<? extends Annotation> annotationClass) {
|
public static AnnotationRepeatType getType(Class<? extends Annotation> annotationClass) {
|
||||||
CACHE_LOCK.readLock().lock();
|
CACHE_LOCK.readLock().lock();
|
||||||
try {
|
try {
|
||||||
AnnotationRepeatType cachedValue = CACHE.get(annotationClass);
|
AnnotationRepeatType cachedValue = CACHE.get(annotationClass);
|
||||||
@@ -29,7 +28,7 @@ public class AnnotationRepeatTypeResolver {
|
|||||||
return determineType(annotationClass);
|
return determineType(annotationClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AnnotationRepeatType determineType(@NotNull Class<? extends Annotation> annotationClass) {
|
private static AnnotationRepeatType determineType(Class<? extends Annotation> annotationClass) {
|
||||||
Class<? extends Annotation> container = getRepeatableContainerFromComponentAnnotation(annotationClass);
|
Class<? extends Annotation> container = getRepeatableContainerFromComponentAnnotation(annotationClass);
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
CACHE_LOCK.writeLock().lock();
|
CACHE_LOCK.writeLock().lock();
|
||||||
@@ -64,8 +63,7 @@ public class AnnotationRepeatTypeResolver {
|
|||||||
return AnnotationRepeatType.NonRepeatable.instance();
|
return AnnotationRepeatType.NonRepeatable.instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private static @Nullable Class<? extends Annotation> getRepeatableContainerFromComponentAnnotation(
|
||||||
private static Class<? extends Annotation> getRepeatableContainerFromComponentAnnotation(
|
|
||||||
Class<? extends Annotation> annotationClass
|
Class<? extends Annotation> annotationClass
|
||||||
) {
|
) {
|
||||||
Repeatable repeatableDeclaration = annotationClass.getAnnotation(Repeatable.class);
|
Repeatable repeatableDeclaration = annotationClass.getAnnotation(Repeatable.class);
|
||||||
@@ -75,8 +73,7 @@ public class AnnotationRepeatTypeResolver {
|
|||||||
return repeatableDeclaration.value();
|
return repeatableDeclaration.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private static @Nullable Class<? extends Annotation> getRepeatableComponentFromContainerAnnotation(
|
||||||
private static Class<? extends Annotation> getRepeatableComponentFromContainerAnnotation(
|
|
||||||
Class<? extends Annotation> annotationClass
|
Class<? extends Annotation> annotationClass
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -3,17 +3,18 @@ package de.siphalor.tweed5.utils.api.collection;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.NonNull;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
public class ClassToInstanceMap<T> implements Iterable<T> {
|
public class ClassToInstanceMap<T extends @NonNull Object> implements Iterable<T> {
|
||||||
private final Map<Class<? extends T>, T> delegate;
|
private final Map<Class<? extends T>, T> delegate;
|
||||||
|
|
||||||
public static <T> ClassToInstanceMap<T> backedBy(Map<Class<? extends T>, T> delegate) {
|
public static <T extends @NonNull Object> ClassToInstanceMap<T> backedBy(Map<Class<? extends T>, T> delegate) {
|
||||||
return new ClassToInstanceMap<>(delegate);
|
return new ClassToInstanceMap<>(delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,11 +42,11 @@ public class ClassToInstanceMap<T> implements Iterable<T> {
|
|||||||
return (V) delegate.get(key);
|
return (V) delegate.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V extends T> V put(@NotNull V value) {
|
public <V extends T> @Nullable V put(V value) {
|
||||||
return (V) delegate.put((Class<? extends T>) value.getClass(), value);
|
return (V) delegate.put((Class<? extends T>) value.getClass(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V extends T> V remove(Class<V> key) {
|
public <V extends T> @Nullable V remove(Class<V> key) {
|
||||||
return (V) delegate.remove(key);
|
return (V) delegate.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ public class ClassToInstanceMap<T> implements Iterable<T> {
|
|||||||
public Set<T> values() {
|
public Set<T> values() {
|
||||||
return new AbstractSet<T>() {
|
return new AbstractSet<T>() {
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
Iterator<Map.Entry<Class<? extends T>, T>> entryIterator = delegate.entrySet().iterator();
|
Iterator<Map.Entry<Class<? extends T>, T>> entryIterator = delegate.entrySet().iterator();
|
||||||
return new Iterator<T>() {
|
return new Iterator<T>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -88,7 +89,7 @@ public class ClassToInstanceMap<T> implements Iterable<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return values().iterator();
|
return values().iterator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package de.siphalor.tweed5.utils.api.collection;
|
package de.siphalor.tweed5.utils.api.collection;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -33,7 +33,7 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(@NotNull Object o) {
|
public boolean contains(Object o) {
|
||||||
return delegate.getOrDefault(o.getClass(), Collections.emptyList()).contains(o);
|
return delegate.getOrDefault(o.getClass(), Collections.emptyList()).contains(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,10 +42,10 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return new Iterator<T>() {
|
return new Iterator<T>() {
|
||||||
private final Iterator<Map.Entry<Class<? extends T>, Collection<T>>> classIterator = delegate.entrySet().iterator();
|
private final Iterator<Map.Entry<Class<? extends T>, Collection<T>>> classIterator = delegate.entrySet().iterator();
|
||||||
private Iterator<? extends T> listIterator;
|
private @Nullable Iterator<? extends T> listIterator;
|
||||||
private boolean keptElement;
|
private boolean keptElement;
|
||||||
private boolean keptAnyElementInList;
|
private boolean keptAnyElementInList;
|
||||||
|
|
||||||
@@ -82,14 +82,12 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
public Object[] toArray() {
|
||||||
public Object @NotNull [] toArray() {
|
|
||||||
return delegate.values().stream().flatMap(Collection::stream).toArray();
|
return delegate.values().stream().flatMap(Collection::stream).toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
public <S> S[] toArray(S[] array) {
|
||||||
public <S> S @NotNull [] toArray(@NotNull S @NotNull [] array) {
|
|
||||||
Class<?> clazz = array.getClass().getComponentType();
|
Class<?> clazz = array.getClass().getComponentType();
|
||||||
return delegate.values().stream()
|
return delegate.values().stream()
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
@@ -97,12 +95,12 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(@NotNull T value) {
|
public boolean add(T value) {
|
||||||
return delegate.computeIfAbsent(((Class<T>) value.getClass()), clazz -> collectionSupplier.get()).add(value);
|
return delegate.computeIfAbsent(((Class<T>) value.getClass()), clazz -> collectionSupplier.get()).add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean remove(@NotNull Object value) {
|
public boolean remove(Object value) {
|
||||||
Collection<T> values = delegate.get(value.getClass());
|
Collection<T> values = delegate.get(value.getClass());
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -116,19 +114,17 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public <U extends T> Collection<U> getAll(Class<U> clazz) {
|
public <U extends T> Collection<U> getAll(Class<U> clazz) {
|
||||||
return (Collection<U>) Collections.unmodifiableCollection(delegate.getOrDefault(clazz, Collections.emptyList()));
|
return (Collection<U>) Collections.unmodifiableCollection(delegate.getOrDefault(clazz, Collections.emptyList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Collection<T> removeAll(Class<? extends T> clazz) {
|
public Collection<T> removeAll(Class<? extends T> clazz) {
|
||||||
Collection<T> removed = delegate.remove(clazz);
|
Collection<T> removed = delegate.remove(clazz);
|
||||||
return removed == null ? Collections.emptyList() : Collections.unmodifiableCollection(removed);
|
return removed == null ? Collections.emptyList() : Collections.unmodifiableCollection(removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(@NotNull Collection<?> values) {
|
public boolean containsAll(Collection<?> values) {
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
if (!contains(value)) {
|
if (!contains(value)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -138,7 +134,7 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(@NotNull Collection<? extends T> values) {
|
public boolean addAll(Collection<? extends T> values) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (T value : values) {
|
for (T value : values) {
|
||||||
changed = add(value) || changed;
|
changed = add(value) || changed;
|
||||||
@@ -147,7 +143,7 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAll(@NotNull Collection<?> values) {
|
public boolean removeAll(Collection<?> values) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
changed = remove(value) || changed;
|
changed = remove(value) || changed;
|
||||||
@@ -156,7 +152,7 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean retainAll(@NotNull Collection<?> values) {
|
public boolean retainAll(Collection<?> values) {
|
||||||
Map<Class<?>, ? extends List<?>> valuesByClass = values.stream()
|
Map<Class<?>, ? extends List<?>> valuesByClass = values.stream()
|
||||||
.collect(Collectors.groupingBy(Object::getClass));
|
.collect(Collectors.groupingBy(Object::getClass));
|
||||||
delegate.putAll((Map<Class<? extends T>, List<T>>)(Object) valuesByClass);
|
delegate.putAll((Map<Class<? extends T>, List<T>>)(Object) valuesByClass);
|
||||||
@@ -178,37 +174,37 @@ public class ClassToInstancesMultimap<T> implements Collection<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return delegate.values().stream().flatMap(Collection::stream).iterator();
|
return delegate.values().stream().flatMap(Collection::stream).iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(@NotNull T value) {
|
public boolean add(T value) {
|
||||||
throw createUnsupportedOperationException();
|
throw createUnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean remove(@NotNull Object value) {
|
public boolean remove(Object value) {
|
||||||
throw createUnsupportedOperationException();
|
throw createUnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Collection<T> removeAll(Class<? extends T> clazz) {
|
public Collection<T> removeAll(Class<? extends T> clazz) {
|
||||||
throw createUnsupportedOperationException();
|
throw createUnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(@NotNull Collection<? extends T> values) {
|
public boolean addAll(Collection<? extends T> values) {
|
||||||
throw createUnsupportedOperationException();
|
throw createUnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAll(@NotNull Collection<?> values) {
|
public boolean removeAll(Collection<?> values) {
|
||||||
throw createUnsupportedOperationException();
|
throw createUnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean retainAll(@NotNull Collection<?> values) {
|
public boolean retainAll(Collection<?> values) {
|
||||||
throw createUnsupportedOperationException();
|
throw createUnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,22 +2,24 @@ package de.siphalor.tweed5.utils.api.collection;
|
|||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@AllArgsConstructor(access = AccessLevel.PROTECTED)
|
@AllArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
public class InheritanceMap<T> {
|
public class InheritanceMap<T extends @NonNull Object> {
|
||||||
private static final InheritanceMap<Object> EMPTY = unmodifiable(new InheritanceMap<>(Object.class));
|
private static final InheritanceMap<Object> EMPTY = unmodifiable(new InheritanceMap<>(Object.class));
|
||||||
|
|
||||||
private final Class<T> baseClass;
|
private final Class<T> baseClass;
|
||||||
private final Map<T, Collection<Class<? extends T>>> instanceToClasses;
|
private final Map<T, Collection<Class<? extends T>>> instanceToClasses;
|
||||||
private final Map<Class<? extends T>, Collection<T>> classToInstances;
|
private final Map<Class<? extends T>, Collection<T>> classToInstances;
|
||||||
|
|
||||||
public static <T> InheritanceMap<T> empty() {
|
public static <T extends @NonNull Object> InheritanceMap<T> empty() {
|
||||||
return (InheritanceMap<T>) EMPTY;
|
return (InheritanceMap<T>) EMPTY;
|
||||||
}
|
}
|
||||||
public static <T> InheritanceMap<T> unmodifiable(InheritanceMap<T> map) {
|
public static <T extends @NonNull Object> InheritanceMap<T> unmodifiable(InheritanceMap<T> map) {
|
||||||
return new Unmodifiable<>(map);
|
return new Unmodifiable<>(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ public class InheritanceMap<T> {
|
|||||||
return (Collection<V>) classToInstances.getOrDefault(clazz, Collections.emptyList());
|
return (Collection<V>) classToInstances.getOrDefault(clazz, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V extends T> V getSingleInstance(Class<V> clazz) throws NonUniqueResultException {
|
public <V extends T> @Nullable V getSingleInstance(Class<V> clazz) throws NonUniqueResultException {
|
||||||
Collection<T> instances = classToInstances.getOrDefault(clazz, Collections.emptyList());
|
Collection<T> instances = classToInstances.getOrDefault(clazz, Collections.emptyList());
|
||||||
if (instances.isEmpty()) {
|
if (instances.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -87,7 +89,7 @@ public class InheritanceMap<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V extends T> V removeInstance(V instance) {
|
public <V extends T> @Nullable V removeInstance(V instance) {
|
||||||
if (!instanceToClasses.containsKey(instance)) {
|
if (!instanceToClasses.containsKey(instance)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -153,7 +155,7 @@ public class InheritanceMap<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Unmodifiable<T> extends InheritanceMap<T> {
|
private static class Unmodifiable<T extends @NonNull Object> extends InheritanceMap<T> {
|
||||||
public Unmodifiable(InheritanceMap<T> delegate) {
|
public Unmodifiable(InheritanceMap<T> delegate) {
|
||||||
super(delegate.baseClass, delegate.instanceToClasses, delegate.classToInstances);
|
super(delegate.baseClass, delegate.instanceToClasses, delegate.classToInstances);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.utils.api.collection;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -7,7 +7,7 @@ import de.siphalor.tweed5.weaver.pojo.api.weaving.WeavingContext;
|
|||||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess.TweedPojoWeavingPostProcessor;
|
import de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess.TweedPojoWeavingPostProcessor;
|
||||||
import de.siphalor.tweed5.weaver.pojoext.serde.impl.SerdePojoReaderWriterSpec;
|
import de.siphalor.tweed5.weaver.pojoext.serde.impl.SerdePojoReaderWriterSpec;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
@@ -80,8 +80,7 @@ public class ReadWritePojoPostProcessor implements TweedPojoWeavingPostProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private @Nullable EntryReaderWriterDefinition createDefinitionFromEntryConfig(EntryReadWriteConfig entryConfig, WeavingContext context) {
|
||||||
private EntryReaderWriterDefinition createDefinitionFromEntryConfig(EntryReadWriteConfig entryConfig, WeavingContext context) {
|
|
||||||
String readerSpecText = entryConfig.reader().isEmpty() ? entryConfig.value() : entryConfig.reader();
|
String readerSpecText = entryConfig.reader().isEmpty() ? entryConfig.value() : entryConfig.reader();
|
||||||
String writerSpecText = entryConfig.writer().isEmpty() ? entryConfig.value() : entryConfig.writer();
|
String writerSpecText = entryConfig.writer().isEmpty() ? entryConfig.value() : entryConfig.writer();
|
||||||
|
|
||||||
@@ -98,14 +97,14 @@ public class ReadWritePojoPostProcessor implements TweedPojoWeavingPostProcessor
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked,rawtypes
|
||||||
TweedEntryReader<?, ?> reader = readerSpec == null
|
TweedEntryReader<?, ?> reader = Optional.ofNullable(readerSpec)
|
||||||
? TweedEntryReaderWriterImpls.NOOP_READER_WRITER
|
.map((spec) -> resolveReaderWriterFromSpec((Class<TweedEntryReader<?, ?>>)(Object) TweedEntryReader.class, readerFactories, spec, context))
|
||||||
: resolveReaderWriterFromSpec((Class<TweedEntryReader<?, ?>>)(Object) TweedEntryReader.class, readerFactories, readerSpec, context);
|
.orElse(((TweedEntryReader) TweedEntryReaderWriterImpls.NOOP_READER_WRITER));
|
||||||
//noinspection unchecked
|
//noinspection unchecked,rawtypes
|
||||||
TweedEntryWriter<?, ?> writer = writerSpec == null
|
TweedEntryWriter<?, ?> writer = Optional.ofNullable(writerSpec)
|
||||||
? TweedEntryReaderWriterImpls.NOOP_READER_WRITER
|
.map((spec) -> resolveReaderWriterFromSpec((Class<TweedEntryWriter<?, ?>>)(Object) TweedEntryWriter.class, writerFactories, spec, context))
|
||||||
: resolveReaderWriterFromSpec((Class<TweedEntryWriter<?, ?>>)(Object) TweedEntryWriter.class, writerFactories, writerSpec, context);
|
.orElse(((TweedEntryWriter) TweedEntryReaderWriterImpls.NOOP_READER_WRITER));
|
||||||
|
|
||||||
return new EntryReaderWriterDefinition() {
|
return new EntryReaderWriterDefinition() {
|
||||||
@Override
|
@Override
|
||||||
@@ -120,8 +119,7 @@ public class ReadWritePojoPostProcessor implements TweedPojoWeavingPostProcessor
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private @Nullable SerdePojoReaderWriterSpec specFromText(String specText, WeavingContext context) {
|
||||||
private SerdePojoReaderWriterSpec specFromText(String specText, WeavingContext context) {
|
|
||||||
if (specText.isEmpty()) {
|
if (specText.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -137,7 +135,7 @@ public class ReadWritePojoPostProcessor implements TweedPojoWeavingPostProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T resolveReaderWriterFromSpec(
|
private <T> @Nullable T resolveReaderWriterFromSpec(
|
||||||
Class<T> baseClass,
|
Class<T> baseClass,
|
||||||
Map<String, TweedReaderWriterProvider.ReaderWriterFactory<T>> factories,
|
Map<String, TweedReaderWriterProvider.ReaderWriterFactory<T>> factories,
|
||||||
SerdePojoReaderWriterSpec spec,
|
SerdePojoReaderWriterSpec spec,
|
||||||
@@ -152,17 +150,18 @@ public class ReadWritePojoPostProcessor implements TweedPojoWeavingPostProcessor
|
|||||||
TweedReaderWriterProvider.ReaderWriterFactory<T> factory = factories.get(spec.identifier());
|
TweedReaderWriterProvider.ReaderWriterFactory<T> factory = factories.get(spec.identifier());
|
||||||
|
|
||||||
T instance;
|
T instance;
|
||||||
if (factory != null) {
|
try {
|
||||||
instance = factory.create(arguments);
|
if (factory != null) {
|
||||||
} else {
|
instance = factory.create(arguments);
|
||||||
instance = loadClassIfExists(baseClass, spec.identifier(), arguments);
|
} else {
|
||||||
}
|
instance = loadClassIfExists(baseClass, spec.identifier(), arguments);
|
||||||
|
}
|
||||||
if (instance == null) {
|
} catch (Exception e) {
|
||||||
log.warn(
|
log.warn(
|
||||||
"Failed to resolve reader or writer factory \"{}\" for entry {}, entry will not be included in serde",
|
"Failed to resolve reader or writer factory \"{}\" for entry {}, entry will not be included in serde",
|
||||||
spec.identifier(),
|
spec.identifier(),
|
||||||
context.path()
|
context.path(),
|
||||||
|
e
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -170,7 +169,7 @@ public class ReadWritePojoPostProcessor implements TweedPojoWeavingPostProcessor
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T loadClassIfExists(Class<T> baseClass, String className, T[] arguments) {
|
private <T> @Nullable T loadClassIfExists(Class<T> baseClass, String className, T[] arguments) {
|
||||||
try {
|
try {
|
||||||
Class<?> clazz = Class.forName(className);
|
Class<?> clazz = Class.forName(className);
|
||||||
Class<?>[] argClasses = new Class<?>[arguments.length];
|
Class<?>[] argClasses = new Class<?>[arguments.length];
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojoext.serde.api;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojoext.serde.impl;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -57,13 +57,13 @@ class WeaverPojoSerdeExtensionTest {
|
|||||||
public static class TestWriterProvider implements TweedReaderWriterProvider {
|
public static class TestWriterProvider implements TweedReaderWriterProvider {
|
||||||
@Override
|
@Override
|
||||||
public void provideReaderWriters(ProviderContext context) {
|
public void provideReaderWriters(ProviderContext context) {
|
||||||
context.registerWriterFactory("tweed5.test.dummy", delegates -> new TweedEntryWriter<Object, ConfigEntry<Object>>() {
|
context.registerWriterFactory("tweed5.test.dummy", delegates -> new TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>() {
|
||||||
@Override
|
@Override
|
||||||
public void write(
|
public void write(
|
||||||
TweedDataVisitor writer,
|
@NonNull TweedDataVisitor writer,
|
||||||
Object value,
|
Object value,
|
||||||
ConfigEntry<Object> entry,
|
ConfigEntry<Object> entry,
|
||||||
TweedWriteContext context
|
@NonNull TweedWriteContext context
|
||||||
) throws TweedDataWriteException {
|
) throws TweedDataWriteException {
|
||||||
writer.visitString("my cool custom writer");
|
writer.visitString("my cool custom writer");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@@ -28,9 +28,9 @@ public interface WeavableCompoundConfigEntry<T> extends CompoundConfigEntry<T> {
|
|||||||
@Value
|
@Value
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
class SubEntry {
|
class SubEntry {
|
||||||
@NotNull String name;
|
String name;
|
||||||
@NotNull ConfigEntry<?> configEntry;
|
ConfigEntry<?> configEntry;
|
||||||
@NotNull MethodHandle getter;
|
@Nullable MethodHandle getter;
|
||||||
@NotNull MethodHandle setter;
|
@Nullable MethodHandle setter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojo.api.entry;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -9,8 +9,7 @@ import de.siphalor.tweed5.weaver.pojo.impl.entry.CollectionConfigEntryImpl;
|
|||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.PojoWeavingException;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.PojoWeavingException;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.collection.CollectionWeavingConfig;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.collection.CollectionWeavingConfig;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.collection.CollectionWeavingConfigImpl;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.collection.CollectionWeavingConfigImpl;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@@ -33,7 +32,7 @@ public class CollectionPojoWeaver implements TweedPojoWeaver {
|
|||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
@Override
|
@Override
|
||||||
public @Nullable <T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
public <T> @Nullable ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
||||||
List<ActualType<?>> collectionTypeParams = valueType.getTypesOfSuperArguments(Collection.class);
|
List<ActualType<?>> collectionTypeParams = valueType.getTypesOfSuperArguments(Collection.class);
|
||||||
if (collectionTypeParams == null) {
|
if (collectionTypeParams == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -82,7 +81,7 @@ public class CollectionPojoWeaver implements TweedPojoWeaver {
|
|||||||
return CollectionWeavingConfigImpl.withOverrides(parent, local);
|
return CollectionWeavingConfigImpl.withOverrides(parent, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CollectionWeavingConfig createWeavingConfigFromAnnotations(@NotNull AnnotatedElement annotations) {
|
private @Nullable CollectionWeavingConfig createWeavingConfigFromAnnotations(AnnotatedElement annotations) {
|
||||||
CollectionWeaving annotation = annotations.getAnnotation(CollectionWeaving.class);
|
CollectionWeaving annotation = annotations.getAnnotation(CollectionWeaving.class);
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import de.siphalor.tweed5.weaver.pojo.impl.weaving.PojoClassIntrospector;
|
|||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.PojoWeavingException;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.PojoWeavingException;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.compound.CompoundWeavingConfig;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.compound.CompoundWeavingConfig;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.compound.CompoundWeavingConfigImpl;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.compound.CompoundWeavingConfigImpl;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
@@ -44,7 +43,7 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable <T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
public <T> @Nullable ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
||||||
if (context.annotations().getAnnotation(CompoundWeaving.class) == null) {
|
if (context.annotations().getAnnotation(CompoundWeaving.class) == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -88,8 +87,7 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
|||||||
return CompoundWeavingConfigImpl.withOverrides(parent, local);
|
return CompoundWeavingConfigImpl.withOverrides(parent, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private @Nullable CompoundWeavingConfig createWeavingConfigFromAnnotations(AnnotatedElement annotations) {
|
||||||
private CompoundWeavingConfig createWeavingConfigFromAnnotations(@NotNull AnnotatedElement annotations) {
|
|
||||||
CompoundWeaving annotation = annotations.getAnnotation(CompoundWeaving.class);
|
CompoundWeaving annotation = annotations.getAnnotation(CompoundWeaving.class);
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -127,7 +125,6 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
|||||||
|
|
||||||
//noinspection rawtypes
|
//noinspection rawtypes
|
||||||
Class<? extends WeavableCompoundConfigEntry> annotationEntryClass = weavingConfig.compoundEntryClass();
|
Class<? extends WeavableCompoundConfigEntry> annotationEntryClass = weavingConfig.compoundEntryClass();
|
||||||
@NotNull
|
|
||||||
Class<WeavableCompoundConfigEntry<C>> weavableEntryClass = (Class<WeavableCompoundConfigEntry<C>>) (
|
Class<WeavableCompoundConfigEntry<C>> weavableEntryClass = (Class<WeavableCompoundConfigEntry<C>>) (
|
||||||
annotationEntryClass != null
|
annotationEntryClass != null
|
||||||
? annotationEntryClass
|
? annotationEntryClass
|
||||||
@@ -143,7 +140,7 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
|||||||
return property.getter() != null && (property.setter() != null || property.isFinal());
|
return property.getter() != null && (property.setter() != null || property.isFinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull WeavableCompoundConfigEntry.SubEntry weaveCompoundSubEntry(
|
private WeavableCompoundConfigEntry.SubEntry weaveCompoundSubEntry(
|
||||||
PojoClassIntrospector.Property property,
|
PojoClassIntrospector.Property property,
|
||||||
WeavingContext.ExtensionsData newExtensionsData,
|
WeavingContext.ExtensionsData newExtensionsData,
|
||||||
WeavingContext parentContext
|
WeavingContext parentContext
|
||||||
@@ -167,7 +164,9 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull String convertName(String name, CompoundWeavingConfig weavingConfig) {
|
private String convertName(String name, CompoundWeavingConfig weavingConfig) {
|
||||||
|
// Always non-null at this point, since null values were already defaulted
|
||||||
|
//noinspection DataFlowIssue
|
||||||
return NamingFormat.convert(
|
return NamingFormat.convert(
|
||||||
name,
|
name,
|
||||||
weavingConfig.compoundSourceNamingFormat(),
|
weavingConfig.compoundSourceNamingFormat(),
|
||||||
@@ -175,7 +174,7 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull NamingFormat getNamingFormatById(String id) {
|
private NamingFormat getNamingFormatById(String id) {
|
||||||
NamingFormat namingFormat = namingFormatCollector.namingFormats().get(id);
|
NamingFormat namingFormat = namingFormatCollector.namingFormats().get(id);
|
||||||
if (namingFormat == null) {
|
if (namingFormat == null) {
|
||||||
throw new PojoWeavingException(
|
throw new PojoWeavingException(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package de.siphalor.tweed5.weaver.pojo.api.weaving;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.core.impl.entry.SimpleConfigEntryImpl;
|
import de.siphalor.tweed5.core.impl.entry.SimpleConfigEntryImpl;
|
||||||
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class TrivialPojoWeaver implements TweedPojoWeaver {
|
public class TrivialPojoWeaver implements TweedPojoWeaver {
|
||||||
@Override
|
@Override
|
||||||
@@ -12,7 +11,7 @@ public class TrivialPojoWeaver implements TweedPojoWeaver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable <T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
public <T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
||||||
SimpleConfigEntryImpl<T> entry = new SimpleConfigEntryImpl<>(valueType.declaredType());
|
SimpleConfigEntryImpl<T> entry = new SimpleConfigEntryImpl<>(valueType.declaredType());
|
||||||
entry.seal(context.configContainer());
|
entry.seal(context.configContainer());
|
||||||
return entry;
|
return entry;
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ package de.siphalor.tweed5.weaver.pojo.api.weaving;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface TweedPojoWeavingFunction {
|
public interface TweedPojoWeavingFunction {
|
||||||
@@ -12,8 +11,7 @@ public interface TweedPojoWeavingFunction {
|
|||||||
* The returned config entry must be sealed.
|
* The returned config entry must be sealed.
|
||||||
* @return The resulting, sealed config entry or {@code null}, if the weaving function is not applicable to the given parameters.
|
* @return The resulting, sealed config entry or {@code null}, if the weaving function is not applicable to the given parameters.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
<T> @Nullable ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context);
|
||||||
<T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context);
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface NonNull extends TweedPojoWeavingFunction {
|
interface NonNull extends TweedPojoWeavingFunction {
|
||||||
@@ -25,6 +23,6 @@ public interface TweedPojoWeavingFunction {
|
|||||||
* @throws RuntimeException when a valid config entry could not be resolved.
|
* @throws RuntimeException when a valid config entry could not be resolved.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@NotNull <T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context);
|
<T> @org.jspecify.annotations.NonNull ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,26 +6,19 @@ import de.siphalor.tweed5.patchwork.api.Patchwork;
|
|||||||
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public class WeavingContext implements TweedPojoWeavingFunction.NonNull {
|
public class WeavingContext implements TweedPojoWeavingFunction.NonNull {
|
||||||
@Nullable
|
@Nullable WeavingContext parent;
|
||||||
WeavingContext parent;
|
|
||||||
@Getter(AccessLevel.NONE)
|
@Getter(AccessLevel.NONE)
|
||||||
@NotNull
|
|
||||||
TweedPojoWeavingFunction.NonNull weavingFunction;
|
TweedPojoWeavingFunction.NonNull weavingFunction;
|
||||||
@NotNull
|
|
||||||
ConfigContainer<?> configContainer;
|
ConfigContainer<?> configContainer;
|
||||||
@NotNull
|
|
||||||
String[] path;
|
String[] path;
|
||||||
@NotNull
|
|
||||||
ExtensionsData extensionsData;
|
ExtensionsData extensionsData;
|
||||||
@NotNull
|
|
||||||
AnnotatedElement annotations;
|
AnnotatedElement annotations;
|
||||||
|
|
||||||
public static Builder builder(TweedPojoWeavingFunction.NonNull weavingFunction, ConfigContainer<?> configContainer) {
|
public static Builder builder(TweedPojoWeavingFunction.NonNull weavingFunction, ConfigContainer<?> configContainer) {
|
||||||
@@ -36,14 +29,14 @@ public class WeavingContext implements TweedPojoWeavingFunction.NonNull {
|
|||||||
return new Builder(null, weavingFunction, configContainer, new String[]{ baseName });
|
return new Builder(null, weavingFunction, configContainer, new String[]{ baseName });
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder subContextBuilder(@NotNull String subPathName) {
|
public Builder subContextBuilder(String subPathName) {
|
||||||
String[] newPath = Arrays.copyOf(path, path.length + 1);
|
String[] newPath = Arrays.copyOf(path, path.length + 1);
|
||||||
newPath[path.length] = subPathName;
|
newPath[path.length] = subPathName;
|
||||||
return new Builder(this, weavingFunction, configContainer, newPath).extensionsData(extensionsData);
|
return new Builder(this, weavingFunction, configContainer, newPath).extensionsData(extensionsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull <T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
public <T> ConfigEntry<T> weaveEntry(ActualType<T> valueType, WeavingContext context) {
|
||||||
return weavingFunction.weaveEntry(valueType, context);
|
return weavingFunction.weaveEntry(valueType, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojo.api.weaving;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -9,6 +9,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
@@ -18,7 +19,7 @@ import java.util.function.IntFunction;
|
|||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class CollectionConfigEntryImpl<E, T extends Collection<E>> extends BaseConfigEntry<T> implements WeavableCollectionConfigEntry<E, T> {
|
public class CollectionConfigEntryImpl<E, T extends Collection<E>> extends BaseConfigEntry<T> implements WeavableCollectionConfigEntry<E, T> {
|
||||||
private final IntFunction<T> constructor;
|
private final IntFunction<T> constructor;
|
||||||
private ConfigEntry<E> elementEntry;
|
private @Nullable ConfigEntry<E> elementEntry;
|
||||||
|
|
||||||
public CollectionConfigEntryImpl(@NotNull Class<T> valueClass, IntFunction<T> constructor) {
|
public CollectionConfigEntryImpl(@NotNull Class<T> valueClass, IntFunction<T> constructor) {
|
||||||
super(valueClass);
|
super(valueClass);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
|||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntryValueVisitor;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntryValueVisitor;
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntryVisitor;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntryVisitor;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCompoundConfigEntry;
|
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCompoundConfigEntry;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -17,7 +16,7 @@ public class StaticPojoCompoundConfigEntry<T> extends BaseConfigEntry<T> impleme
|
|||||||
private final Map<String, SubEntry> subEntries = new LinkedHashMap<>();
|
private final Map<String, SubEntry> subEntries = new LinkedHashMap<>();
|
||||||
private final Map<String, ConfigEntry<?>> subConfigEntries = new LinkedHashMap<>();
|
private final Map<String, ConfigEntry<?>> subConfigEntries = new LinkedHashMap<>();
|
||||||
|
|
||||||
public StaticPojoCompoundConfigEntry(@NotNull Class<T> valueClass, @NotNull Supplier<T> noArgsConstructor) {
|
public StaticPojoCompoundConfigEntry(Class<T> valueClass, Supplier<T> noArgsConstructor) {
|
||||||
super(valueClass);
|
super(valueClass);
|
||||||
this.noArgsConstructor = noArgsConstructor;
|
this.noArgsConstructor = noArgsConstructor;
|
||||||
}
|
}
|
||||||
@@ -91,7 +90,7 @@ public class StaticPojoCompoundConfigEntry<T> extends BaseConfigEntry<T> impleme
|
|||||||
subEntries.forEach((key, entry) -> {
|
subEntries.forEach((key, entry) -> {
|
||||||
if (visitor.enterCompoundSubEntry(key)) {
|
if (visitor.enterCompoundSubEntry(key)) {
|
||||||
try {
|
try {
|
||||||
Object subValue = entry.getter().invokeExact(value);
|
Object subValue = entry.getter().invoke(value);
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
visitor.visitEntry((ConfigEntry<Object>) entry.configEntry(), subValue);
|
visitor.visitEntry((ConfigEntry<Object>) entry.configEntry(), subValue);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
@@ -103,11 +102,11 @@ public class StaticPojoCompoundConfigEntry<T> extends BaseConfigEntry<T> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull T deepCopy(@NotNull T value) {
|
public T deepCopy(T value) {
|
||||||
T copy = instantiateCompoundValue();
|
T copy = instantiateCompoundValue();
|
||||||
for (SubEntry subEntry : subEntries.values()) {
|
for (SubEntry subEntry : subEntries.values()) {
|
||||||
try {
|
try {
|
||||||
Object subValue = subEntry.getter().invokeExact(value);
|
Object subValue = subEntry.getter().invoke(value);
|
||||||
subEntry.setter().invoke(copy, subValue);
|
subEntry.setter().invoke(copy, subValue);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException("Failed to copy value of sub entry \"" + subEntry.name() + "\"", e);
|
throw new RuntimeException("Failed to copy value of sub entry \"" + subEntry.name() + "\"", e);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojo.impl.entry;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -5,7 +5,7 @@ import lombok.Builder;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@@ -23,7 +23,7 @@ public class PojoClassIntrospector {
|
|||||||
private final Class<?> clazz;
|
private final Class<?> clazz;
|
||||||
private final MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
private final MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||||
|
|
||||||
private Map<String, Property> properties;
|
private @Nullable Map<String, Property> properties;
|
||||||
|
|
||||||
public static PojoClassIntrospector forClass(Class<?> clazz) {
|
public static PojoClassIntrospector forClass(Class<?> clazz) {
|
||||||
if ((clazz.getModifiers() & Modifier.PUBLIC) == 0) {
|
if ((clazz.getModifiers() & Modifier.PUBLIC) == 0) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import de.siphalor.tweed5.weaver.pojo.api.weaving.WeavingContext;
|
|||||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess.TweedPojoWeavingPostProcessor;
|
import de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess.TweedPojoWeavingPostProcessor;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package de.siphalor.tweed5.weaver.pojo.impl.weaving.collection;
|
package de.siphalor.tweed5.weaver.pojo.impl.weaving.collection;
|
||||||
|
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCollectionConfigEntry;
|
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCollectionConfigEntry;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface CollectionWeavingConfig {
|
public interface CollectionWeavingConfig {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Nullable
|
@Nullable Class<? extends WeavableCollectionConfigEntry> collectionEntryClass();
|
||||||
Class<? extends WeavableCollectionConfigEntry> collectionEntryClass();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,14 @@ package de.siphalor.tweed5.weaver.pojo.impl.weaving.collection;
|
|||||||
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCollectionConfigEntry;
|
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCollectionConfigEntry;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public class CollectionWeavingConfigImpl implements CollectionWeavingConfig {
|
public class CollectionWeavingConfigImpl implements CollectionWeavingConfig {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Nullable
|
@Nullable Class<? extends WeavableCollectionConfigEntry> collectionEntryClass;
|
||||||
Class<? extends WeavableCollectionConfigEntry> collectionEntryClass;
|
|
||||||
|
|
||||||
public static CollectionWeavingConfigImpl withOverrides(CollectionWeavingConfig self, CollectionWeavingConfig overrides) {
|
public static CollectionWeavingConfigImpl withOverrides(CollectionWeavingConfig self, CollectionWeavingConfig overrides) {
|
||||||
return CollectionWeavingConfigImpl.builder()
|
return CollectionWeavingConfigImpl.builder()
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojo.impl.weaving.collection;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -2,14 +2,13 @@ package de.siphalor.tweed5.weaver.pojo.impl.weaving.compound;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.namingformat.api.NamingFormat;
|
import de.siphalor.tweed5.namingformat.api.NamingFormat;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCompoundConfigEntry;
|
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCompoundConfigEntry;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public interface CompoundWeavingConfig {
|
public interface CompoundWeavingConfig {
|
||||||
NamingFormat compoundSourceNamingFormat();
|
@Nullable NamingFormat compoundSourceNamingFormat();
|
||||||
|
|
||||||
NamingFormat compoundTargetNamingFormat();
|
@Nullable NamingFormat compoundTargetNamingFormat();
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Nullable
|
@Nullable Class<? extends WeavableCompoundConfigEntry> compoundEntryClass();
|
||||||
Class<? extends WeavableCompoundConfigEntry> compoundEntryClass();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,17 +4,16 @@ import de.siphalor.tweed5.namingformat.api.NamingFormat;
|
|||||||
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCompoundConfigEntry;
|
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCompoundConfigEntry;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public class CompoundWeavingConfigImpl implements CompoundWeavingConfig {
|
public class CompoundWeavingConfigImpl implements CompoundWeavingConfig {
|
||||||
|
|
||||||
NamingFormat compoundSourceNamingFormat;
|
@Nullable NamingFormat compoundSourceNamingFormat;
|
||||||
NamingFormat compoundTargetNamingFormat;
|
@Nullable NamingFormat compoundTargetNamingFormat;
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Nullable
|
@Nullable Class<? extends WeavableCompoundConfigEntry> compoundEntryClass;
|
||||||
Class<? extends WeavableCompoundConfigEntry> compoundEntryClass;
|
|
||||||
|
|
||||||
public static CompoundWeavingConfigImpl withOverrides(CompoundWeavingConfig self, CompoundWeavingConfig overrides) {
|
public static CompoundWeavingConfigImpl withOverrides(CompoundWeavingConfig self, CompoundWeavingConfig overrides) {
|
||||||
return CompoundWeavingConfigImpl.builder()
|
return CompoundWeavingConfigImpl.builder()
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojo.impl.weaving.compound;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package de.siphalor.tweed5.weaver.pojo.impl.weaving;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
Reference in New Issue
Block a user