Mostly javadoc, and also some fixes there and there

This commit is contained in:
2022-08-10 03:04:12 +02:00
parent f976350ee1
commit 54bc8ab99a
42 changed files with 1671 additions and 733 deletions

View File

@@ -12,5 +12,9 @@ import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ConcreteWrapper {
/**
* The class representing a dummy implementation of the annotated wrapper interface.
* @return the class representing a dummy implementation of the annotated wrapper interface.
*/
Class<? extends ReflectWrapper> value();
}

View File

@@ -6,6 +6,11 @@ import java.util.function.Supplier;
import fr.pandacube.lib.util.MappedListView;
/**
* A wrapper for a list of wrapped object. It is an extension of {@link MappedListView} that is used to transparently
* wrap/unwrap the elements of the backend list.
* @param <W> the type of the reflect wrapper for the elements of this list.
*/
public class ReflectListWrapper<W extends ReflectWrapperI> extends MappedListView<Object, W> implements ReflectWrapperTypedI<List<Object>> {
private final Class<W> expectedWrapperClass;
@@ -14,11 +19,12 @@ public class ReflectListWrapper<W extends ReflectWrapperI> extends MappedListVie
this(ArrayList::new, expectedWrapperClass);
}
/* package */
@SuppressWarnings("unchecked")
ReflectListWrapper(Supplier<List<?>> listCreator, Class<W> expectedWrapperClass) {
/* package */ ReflectListWrapper(Supplier<List<?>> listCreator, Class<W> expectedWrapperClass) {
this((List<Object>) (listCreator == null ? new ArrayList<>() : listCreator.get()), expectedWrapperClass);
}
/* package */ ReflectListWrapper(List<Object> wrappedList, Class<W> expectedWrapperClass) {
super(wrappedList, el -> ReflectWrapper.wrap(el, expectedWrapperClass), ReflectWrapper::unwrap);
this.expectedWrapperClass = expectedWrapperClass;

View File

@@ -10,25 +10,79 @@ import java.util.Objects;
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
/**
* Superclass of all reflect wrapper objects.
*/
public abstract class ReflectWrapper implements ReflectWrapperI {
private static final Map<Object, ReflectWrapperI> objectWrapperCache = new MapMaker().weakKeys().makeMap();
/**
* Unwraps the object from the provided reflect wrapper.
* @param wr the reflect wrapper from which to get the object.
* @return the object from the provided reflect wrapper.
*/
public static Object unwrap(ReflectWrapperI wr) {
return wr == null ? null : wr.__getRuntimeInstance();
}
/**
* Unwraps the object from the provided reflect wrapper.
* @param wr the reflect wrapper from which to get the object.
* @param <T> the type of the wrapped object.
* @return the object from the provided reflect wrapper.
*/
public static <T> T unwrap(ReflectWrapperTypedI<T> wr) {
return wr == null ? null : wr.__getRuntimeInstance();
}
public static <W extends ReflectWrapperI> W wrap(Object runtimeObj) {
/**
* Wraps the provided runtime object into a reflect wrapper.
* If a wrapper instance is already known, it will return it instead of instanciating a new one.
* It is better to call {@link #wrap(Object, Class)} if you know the type of wrapper needed.
* @param runtimeObj the object to wrap.
* @return the reflect wrapper wrapping the provided object.
* @throws ClassCastException if the runtime class of the object is not handled by the expected wrapper class or its
* subclasses.
* @throws IllegalArgumentException if the runtime class of the object is not handled by any of the registered
* wrapper classes.
*/
public static ReflectWrapperI wrap(Object runtimeObj) {
return wrap(runtimeObj, null);
}
/**
* Wraps the provided runtime object (with has a known type) into a reflect wrapper.
* If a wrapper instance is already known, it will return it instead of instanciating a new one.
* It is better to call {@link #wrap(Object, Class)} if you know the type of wrapper needed.
* @param runtimeObj the object to wrap.
* @param expectedWrapperClass the reflect wrapper class expected to be returned.
* @param <W> the type of the reflect wrapper.
* @param <T> the type of the wrapped object.
* @return the reflect wrapper wrapping the provided object.
* @throws ClassCastException if the runtime class of the object is not handled by the expected wrapper class or its
* subclasses.
* @throws IllegalArgumentException if the runtime class of the object is not handled by any of the registered
* wrapper classes.
*/
public static <T, W extends ReflectWrapperTypedI<T>> W wrapTyped(T runtimeObj, Class<W> expectedWrapperClass) {
return wrap(runtimeObj, expectedWrapperClass);
}
/**
* Wraps the provided runtime object into a reflect wrapper.
* If a wrapper instance is already known, it will return it instead of instanciating a new one.
* It is better to call {@link #wrap(Object, Class)} if you know the type of wrapper needed.
* @param runtimeObj the object to wrap.
* @param expectedWrapperClass the reflect wrapper class expected to be returned.
* @param <W> the type of the reflect wrapper.
* @return the reflect wrapper wrapping the provided object.
* @throws ClassCastException if the runtime class of the object is not handled by the expected wrapper class or its
* subclasses.
* @throws IllegalArgumentException if the runtime class of the object is not handled by any of the registered
* wrapper classes.
*/
public static <W extends ReflectWrapperI> W wrap(Object runtimeObj, Class<W> expectedWrapperClass) {
if (runtimeObj == null)
return null;
@@ -73,16 +127,36 @@ public abstract class ReflectWrapper implements ReflectWrapperI {
}
}
/**
* Wraps the provided runtime list into a reflect list wrapper.
* @param runtimeList the list of runtime object to wrap.
* @param expectedWrapperClass the wrapper class of the objects in this list.
* @param <W> the type of reflect wrapper for the objects in this list.
* @return a reflect list wrapper wrapping the provided list.
*/
public static <W extends ReflectWrapperI> ReflectListWrapper<W> wrapList(List<Object> runtimeList, Class<W> expectedWrapperClass) {
return new ReflectListWrapper<>(runtimeList, expectedWrapperClass);
}
protected final Object reflectObject;
private final Object reflectObject;
/**
* Instanciate this Reflect Wrapper with the provided object.
* Any subclasses should not make their constructor public since the instanciation is managed by {@link #wrap(Object, Class) wrap(...)}.
* @param obj the object to wrap. It must be an instance of the {@link #__getRuntimeClass() runtime class} of this
* wrapper class.
*/
protected ReflectWrapper(Object obj) {
Objects.requireNonNull(obj);
if (!__getRuntimeClass().isInstance(obj)) {

View File

@@ -1,11 +1,22 @@
package fr.pandacube.lib.reflect.wrapper;
/**
* Interface implemented by all reflect wrapper objects.
*/
public interface ReflectWrapperI {
/**
* Gets the class of the wrapped object.
* @return the class of the wrapped object.
*/
default Class<?> __getRuntimeClass() {
return WrapperRegistry.getRuntimeClassOfWrapperClass(getClass());
}
/**
* Returns the wrapped object.
* @return the wrapped object.
*/
Object __getRuntimeInstance();

View File

@@ -1,7 +1,17 @@
package fr.pandacube.lib.reflect.wrapper;
/**
* Superclass of all reflect wrapper objects which wrapped objet type is statically known.
* @param <T> the type (or supertype) of the wrapped object.
*/
public abstract class ReflectWrapperTyped<T> extends ReflectWrapper implements ReflectWrapperTypedI<T> {
/**
* Instanciate this Reflect Wrapper with the provided object.
* Any subclasses should not make their constructor public since the instanciation is managed by {@link #wrap(Object, Class) wrap(...)}.
* @param obj the object to wrap. It must be an instance of the {@link #__getRuntimeClass() runtime class} of this
* wrapper class.
*/
protected ReflectWrapperTyped(Object obj) {
super(obj);
}

View File

@@ -1,5 +1,9 @@
package fr.pandacube.lib.reflect.wrapper;
/**
* Interface implemented by all reflect wrapper objects which wrapped objet type is statically known.
* @param <T> the type (or supertype) of the wrapped object.
*/
public interface ReflectWrapperTypedI<T> extends ReflectWrapperI {
@SuppressWarnings("unchecked")
@Override