
ru.progrm_jarvis.javacommons.delegate.DelegateFactory Maven / Gradle / Ivy
package ru.progrm_jarvis.javacommons.delegate;
import lombok.NonNull;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.function.Supplier;
/**
* Factory capable of creating type-safe delegating wrappers.
* A good use-case is wrapping {@link ru.progrm_jarvis.javacommons.lazy.Lazy} so that the object becomes Lazy
* yet being of its original type
*/
@FunctionalInterface
public interface DelegateFactory {
/**
* Creates a delegating wrapper of the given type using the provided {@link Supplier} for its backend.
*
* @param type of implemented wrapper
* @param targetType type of implemented wrapper
* @param supplier supplier to handle access to the underlying object
* @return created delegating wrapper for the given supplier
*
* @throws IllegalArgumentException if {@code targetType} cannot be directly implemented or inherited,
* i.e. if it is {@code private} or it is not an interface
* and is {@code final} or does not contain an empty non-{@code private} constructor,
* {@link #verifyTargetType(Class)} should be used for this verification
*
* @apiNote if the original type declares fields or its non-{@code public} methods are visible
* to the owner of this object than access to them will lead to undefined behaviour
* and most probably will cause logical issues
*/
@NotNull T createWrapper(@NonNull Class targetType, @NonNull Supplier supplier);
/**
* Verifies the target type is valid as a target type for {@link #createWrapper(Class, Supplier) wrapper creation}.
*
* @param targetType target type of {@link #createWrapper(Class, Supplier) wrapper creation}
* which should be verified against method's contract
*
* @throws IllegalArgumentException if {@code targetType}
* is not a valid type for {@link #createWrapper(Class, Supplier) wrapper creation}
*/
static void verifyTargetType(final @NonNull Class> targetType) {
final int targetTypeModifiers;
if (Modifier.isPrivate(targetTypeModifiers = targetType.getModifiers())) throw new IllegalArgumentException(
"target-type cannot be private"
);
if (!targetType.isInterface()) {
if (Modifier.isFinal(targetTypeModifiers)) throw new IllegalArgumentException(
"target-type cannot be final"
);
{
final Constructor> constructor;
try {
constructor = targetType.getConstructor();
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException("target-type does not have an empty constructor", e);
}
if (Modifier.isPrivate(constructor.getModifiers())) throw new IllegalArgumentException(
"target-type's empty constructor cannot be private"
);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy