Compare commits
5 Commits
v0.1.0
...
c44b874b41
Author | SHA1 | Date | |
---|---|---|---|
c44b874b41
|
|||
8842e9d8e1
|
|||
1891037ed7
|
|||
c0da5ee75d
|
|||
3deee2fd5d
|
@@ -6,7 +6,7 @@ plugins {
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "net.tomatentum.cutin"
|
group = "net.tomatentum.cutin"
|
||||||
version = "0.1.0" + (if (!project.hasProperty("release")) ("-" + getGitHash()) else "")
|
version = "0.1.1" + (if (!project.hasProperty("release")) ("-" + getGitHash()) else "")
|
||||||
description = "A lightweight Reflection abstraction specifically but not exclusively made for tueem/Marinara."
|
description = "A lightweight Reflection abstraction specifically but not exclusively made for tueem/Marinara."
|
||||||
plugins.withType<JavaPlugin> {
|
plugins.withType<JavaPlugin> {
|
||||||
tasks.withType<Jar>().configureEach {
|
tasks.withType<Jar>().configureEach {
|
||||||
|
@@ -1,53 +0,0 @@
|
|||||||
package net.tomatentum.cutin;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import net.tomatentum.cutin.util.ReflectionUtil;
|
|
||||||
|
|
||||||
public class BestCandidateMethod<I> extends ReflectedMethod<I> {
|
|
||||||
|
|
||||||
private String methodName;
|
|
||||||
private I identifier;
|
|
||||||
private List<Object> additionalParameters;
|
|
||||||
|
|
||||||
protected BestCandidateMethod(String methodName, Object containingObject, I identifer, Object... additionalParameters) {
|
|
||||||
super(getMethod(containingObject, methodName), containingObject);
|
|
||||||
this.methodName = methodName;
|
|
||||||
this.identifier = identifer;
|
|
||||||
this.additionalParameters = Arrays.asList(additionalParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getParameter(Object context, int index) {
|
|
||||||
return additionalParameters.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public I identifier() {
|
|
||||||
return this.identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object run(Object context) {
|
|
||||||
Method[] methods = Arrays.stream(containingObject.getClass().getDeclaredMethods())
|
|
||||||
.filter(x -> x.getName().equals(methodName))
|
|
||||||
.filter(x -> !x.isBridge())
|
|
||||||
.toArray(Method[]::new);
|
|
||||||
Class<?>[] parameters = Stream.concat(
|
|
||||||
Stream.of(context.getClass()),
|
|
||||||
additionalParameters.stream().map(Object::getClass)
|
|
||||||
).toArray(Class<?>[]::new);
|
|
||||||
super.method = ReflectionUtil.getMostSpecificMethod(methods, parameters);
|
|
||||||
return super.run(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Method getMethod(Object containingMethod, String methodName) {
|
|
||||||
return Arrays.stream(containingMethod.getClass().getDeclaredMethods())
|
|
||||||
.filter(m -> m.getName().equals(methodName))
|
|
||||||
.findFirst().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -4,15 +4,17 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import net.tomatentum.cutin.method.ReflectedMethod;
|
||||||
|
|
||||||
public interface ReflectedMethodFactory {
|
|
||||||
Optional<ReflectedMethod> produce(Method method, Object containingClass);
|
|
||||||
ReflectedMethodFactory addFactory(Factory factory);
|
|
||||||
|
|
||||||
public interface Factory {
|
public interface ReflectedMethodFactory<I extends Object> {
|
||||||
|
Optional<ReflectedMethod<I>> produce(Method method, Object containingClass);
|
||||||
|
ReflectedMethodFactory<I> addFactory(Factory<I> factory);
|
||||||
|
|
||||||
Optional<ReflectedMethod> produce(Method method, Object containingObject);
|
public interface Factory<I extends Object> {
|
||||||
void addParser(ReflectedMethod method, List<MethodParser> parser);
|
|
||||||
|
Optional<ReflectedMethod<I>> produce(Method method, Object containingObject);
|
||||||
|
void addParser(ReflectedMethod<I> method, List<MethodParser> parser);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,26 +8,27 @@ import java.util.Optional;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import net.tomatentum.cutin.method.ReflectedMethod;
|
||||||
import net.tomatentum.cutin.util.ReflectionUtil;
|
import net.tomatentum.cutin.util.ReflectionUtil;
|
||||||
|
|
||||||
|
|
||||||
public class ReflectedMethodFactoryImpl implements ReflectedMethodFactory {
|
public class ReflectedMethodFactoryImpl<I extends Object> implements ReflectedMethodFactory<I> {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private List<Factory> factories;
|
private List<Factory<I>> factories;
|
||||||
|
|
||||||
public ReflectedMethodFactoryImpl() {
|
public ReflectedMethodFactoryImpl() {
|
||||||
this(new ArrayList<>());
|
this(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReflectedMethodFactoryImpl(List<Factory> factories) {
|
public ReflectedMethodFactoryImpl(List<Factory<I>> factories) {
|
||||||
this.factories = factories;
|
this.factories = factories;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<ReflectedMethod> produce(Method method, Object containingClass) {
|
public Optional<ReflectedMethod<I>> produce(Method method, Object containingClass) {
|
||||||
Optional<ReflectedMethod> rmethod = this.factories.stream()
|
Optional<ReflectedMethod<I>> rmethod = this.factories.stream()
|
||||||
.map(f -> factoryProduce(f, method, containingClass))
|
.map(f -> factoryProduce(f, method, containingClass))
|
||||||
.filter(Optional::isPresent)
|
.filter(Optional::isPresent)
|
||||||
.map(Optional::get)
|
.map(Optional::get)
|
||||||
@@ -41,14 +42,14 @@ public class ReflectedMethodFactoryImpl implements ReflectedMethodFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReflectedMethodFactory addFactory(Factory factory) {
|
public ReflectedMethodFactory<I> addFactory(Factory<I> factory) {
|
||||||
this.factories.add(factory);
|
this.factories.add(factory);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<ReflectedMethod> factoryProduce(Factory factory, Method method, Object containingClass) {
|
private Optional<ReflectedMethod<I>> factoryProduce(Factory<I> factory, Method method, Object containingClass) {
|
||||||
List<MethodParser> parser = new ArrayList<>();
|
List<MethodParser> parser = new ArrayList<>();
|
||||||
Optional<ReflectedMethod> m = factory.produce(method, containingClass);
|
Optional<ReflectedMethod<I>> m = factory.produce(method, containingClass);
|
||||||
m.ifPresent(x -> {
|
m.ifPresent(x -> {
|
||||||
factory.addParser(x, parser);
|
factory.addParser(x, parser);
|
||||||
parser.forEach(MethodParser::parse);
|
parser.forEach(MethodParser::parse);
|
||||||
|
@@ -6,30 +6,38 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import net.tomatentum.cutin.ReflectedMethod;
|
|
||||||
import net.tomatentum.cutin.ReflectedMethodFactory;
|
import net.tomatentum.cutin.ReflectedMethodFactory;
|
||||||
|
import net.tomatentum.cutin.method.ReflectedMethod;
|
||||||
|
|
||||||
public class LoneMethodContainer<I extends Object> implements MethodContainer<I> {
|
public class LoneMethodContainer<I extends Object> implements MethodContainer<I> {
|
||||||
|
|
||||||
private Map<I, ReflectedMethod<I>> methodStore;
|
private Map<I, ReflectedMethod<I>> methodStore;
|
||||||
private ReflectedMethodFactory factory;
|
private ReflectedMethodFactory<I> factory;
|
||||||
|
|
||||||
public LoneMethodContainer(ReflectedMethodFactory factory) {
|
public LoneMethodContainer(ReflectedMethodFactory<I> factory) {
|
||||||
this.methodStore = new HashMap<>();
|
this.methodStore = new HashMap<>();
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMethods(ReflectedMethod<I>... methods) {
|
public MethodContainer<I> addMethod(ReflectedMethod<I> method) {
|
||||||
for (ReflectedMethod<I> reflectedMethod : methods)
|
this.methodStore.put(method.identifier(), method);
|
||||||
this.methodStore.put(reflectedMethod.identifier(), reflectedMethod);
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMethods(Object containingObject, Method... methods) {
|
public MethodContainer<I> addMethods(Object containingObject, Method... methods) {
|
||||||
for (Method method : methods)
|
for (Method method : methods)
|
||||||
this.addMethods(this.factory.produce(method, containingObject));
|
this.factory.produce(method, containingObject)
|
||||||
|
.ifPresent(this::addMethod);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<I> identifiers() {
|
||||||
|
return methodStore.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -3,17 +3,26 @@ package net.tomatentum.cutin.container;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import net.tomatentum.cutin.ReflectedMethod;
|
import net.tomatentum.cutin.method.ReflectedMethod;
|
||||||
|
|
||||||
public interface MethodContainer<I extends Object> {
|
public interface MethodContainer<I extends Object> {
|
||||||
|
|
||||||
void addMethods(ReflectedMethod<I>... methods);
|
MethodContainer<I> addMethod(ReflectedMethod<I> method);
|
||||||
void addMethods(Object containingObject, Method... methods);
|
default MethodContainer<I> addMethods(ReflectedMethod<I>[] methods) {
|
||||||
default void addAllMethods(Object containingObject) {
|
for (ReflectedMethod<I> reflectedMethod : methods) {
|
||||||
|
this.addMethod(reflectedMethod);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
MethodContainer<I> addMethods(Object containingObject, Method... methods);
|
||||||
|
default MethodContainer<I> addAllMethods(Object containingObject) {
|
||||||
this.addMethods(containingObject, containingObject.getClass().getDeclaredMethods());
|
this.addMethods(containingObject, containingObject.getClass().getDeclaredMethods());
|
||||||
};
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<I> identifiers();
|
||||||
Collection<ReflectedMethod<I>> methods();
|
Collection<ReflectedMethod<I>> methods();
|
||||||
Collection<ReflectedMethod<I>> findFor(I identifier);
|
Collection<ReflectedMethod<I>> findFor(I identifier);
|
||||||
Optional<ReflectedMethod<I>> findFirstFor(I identifier);
|
Optional<ReflectedMethod<I>> findFirstFor(I identifier);
|
||||||
|
@@ -5,39 +5,48 @@ import java.util.Collection;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import net.tomatentum.cutin.ReflectedMethod;
|
|
||||||
import net.tomatentum.cutin.ReflectedMethodFactory;
|
import net.tomatentum.cutin.ReflectedMethodFactory;
|
||||||
|
import net.tomatentum.cutin.method.ReflectedMethod;
|
||||||
import net.tomatentum.cutin.util.ReflectionUtil;
|
import net.tomatentum.cutin.util.ReflectionUtil;
|
||||||
|
|
||||||
public class MultiMethodContainer<I extends Object> implements MethodContainer<I> {
|
public class MultiMethodContainer<I extends Object> implements MethodContainer<I> {
|
||||||
|
|
||||||
private Set<Entry<I>> entries;
|
private Set<Entry<I>> entries;
|
||||||
private ReflectedMethodFactory factory;
|
private ReflectedMethodFactory<I> factory;
|
||||||
|
|
||||||
public MultiMethodContainer(ReflectedMethodFactory factory) {
|
public MultiMethodContainer(ReflectedMethodFactory<I> factory) {
|
||||||
this.entries = new HashSet<>();
|
this.entries = new HashSet<>();
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMethods(ReflectedMethod<I>... methods) {
|
public MethodContainer<I> addMethod(ReflectedMethod<I> method) {
|
||||||
for (ReflectedMethod<I> rMethod : methods) {
|
|
||||||
Optional<Entry<I>> oentry = this.entries.stream()
|
Optional<Entry<I>> oentry = this.entries.stream()
|
||||||
.filter(e -> rMethod.identifier().equals(e.identifier()))
|
.filter(e -> method.identifier().equals(e.identifier()))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
Entry<I> entry = oentry.orElse(new Entry<>(rMethod.identifier())).addMethod(rMethod);
|
Entry<I> entry = oentry.orElse(new Entry<>(method.identifier())).addMethod(method);
|
||||||
if (oentry.isEmpty()) this.entries.add(entry);
|
if (oentry.isEmpty()) this.entries.add(entry);
|
||||||
}
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMethods(Object containingObject, Method... methods) {
|
public MethodContainer<I> addMethods(Object containingObject, Method... methods) {
|
||||||
for (Method method : methods)
|
for (Method method : methods)
|
||||||
this.addMethods(this.factory.produce(method, containingObject));
|
this.factory.produce(method, containingObject)
|
||||||
|
.ifPresent(this::addMethod);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<I> identifiers() {
|
||||||
|
return entries().stream()
|
||||||
|
.map(Entry::identifier)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -63,6 +72,10 @@ public class MultiMethodContainer<I extends Object> implements MethodContainer<I
|
|||||||
.findFirst();
|
.findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Set<Entry<I>> entries() {
|
||||||
|
return this.entries;
|
||||||
|
}
|
||||||
|
|
||||||
public static record Entry<I extends Object>(I identifier, Set<ReflectedMethod<I>> methods) {
|
public static record Entry<I extends Object>(I identifier, Set<ReflectedMethod<I>> methods) {
|
||||||
|
|
||||||
public Entry(I identifier) {
|
public Entry(I identifier) {
|
||||||
|
@@ -0,0 +1,101 @@
|
|||||||
|
package net.tomatentum.cutin.method;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import net.tomatentum.cutin.ReflectedMethodFactory;
|
||||||
|
import net.tomatentum.cutin.container.MethodContainer;
|
||||||
|
import net.tomatentum.cutin.util.ReflectionUtil;
|
||||||
|
|
||||||
|
public class BestCandidateMethod<I> extends ReflectedMethod<I> {
|
||||||
|
|
||||||
|
private String methodName;
|
||||||
|
private I identifier;
|
||||||
|
private List<Object> additionalParameters;
|
||||||
|
|
||||||
|
public BestCandidateMethod(String methodName, Object containingObject, I identifer, Object... additionalParameters) {
|
||||||
|
super(getMethod(containingObject, methodName), containingObject);
|
||||||
|
this.methodName = methodName;
|
||||||
|
this.identifier = identifer;
|
||||||
|
this.additionalParameters = Arrays.asList(additionalParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BestCandidateMethod(String methodName, Object containingObject, Object... additionalParameters) {
|
||||||
|
super(getMethod(containingObject, methodName), containingObject);
|
||||||
|
this.methodName = methodName;
|
||||||
|
this.identifier = null;
|
||||||
|
this.additionalParameters = Arrays.asList(additionalParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getParameter(Object context, int index) {
|
||||||
|
return additionalParameters.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public I identifier() {
|
||||||
|
return this.identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object run(Object context) {
|
||||||
|
Method[] methods = Arrays.stream(containingObject.getClass().getDeclaredMethods())
|
||||||
|
.filter(x -> x.getName().equals(methodName))
|
||||||
|
.filter(x -> !x.isBridge())
|
||||||
|
.toArray(Method[]::new);
|
||||||
|
Class<?>[] parameters = Stream.concat(
|
||||||
|
Stream.of(context.getClass()),
|
||||||
|
additionalParameters.stream().map(Object::getClass)
|
||||||
|
).toArray(Class<?>[]::new);
|
||||||
|
super.method = ReflectionUtil.getMostSpecificMethod(methods, parameters);
|
||||||
|
return super.run(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Method getMethod(Object containingMethod, String methodName) {
|
||||||
|
return Arrays.stream(containingMethod.getClass().getDeclaredMethods())
|
||||||
|
.filter(m -> m.getName().equals(methodName))
|
||||||
|
.findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof BestCandidateMethod<?> bcMethod) {
|
||||||
|
return this.containingObject().getClass().equals(bcMethod.containingObject().getClass()) &&
|
||||||
|
this.methodName.equals(bcMethod.methodName);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(containingObject.getClass(), methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class Factory<I extends Object> implements ReflectedMethodFactory.Factory<I> {
|
||||||
|
|
||||||
|
private MethodContainer<I> methodContainer;
|
||||||
|
private String methodName;
|
||||||
|
private Object[] additionalParameters;
|
||||||
|
|
||||||
|
protected Factory(MethodContainer<I> methodContainer, String methodName, Object... additionalParameters) {
|
||||||
|
this.methodContainer = methodContainer;
|
||||||
|
this.methodName = methodName;
|
||||||
|
this.additionalParameters = additionalParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ReflectedMethod<I>> produce(Method method, Object containingObject) {
|
||||||
|
BestCandidateMethod<I> bcMethod = new BestCandidateMethod<>(
|
||||||
|
methodName, containingObject, additionalParameters);
|
||||||
|
if (methodContainer.methods().contains(bcMethod))
|
||||||
|
return Optional.empty();
|
||||||
|
return Optional.of(bcMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package net.tomatentum.cutin;
|
package net.tomatentum.cutin.method;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
@@ -4,6 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import net.tomatentum.cutin.method.BestCandidateMethod;
|
||||||
|
import net.tomatentum.cutin.method.ReflectedMethod;
|
||||||
|
|
||||||
class ReflectedMethodTest {
|
class ReflectedMethodTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -2,6 +2,8 @@ package net.tomatentum.cutin;
|
|||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import net.tomatentum.cutin.method.ReflectedMethod;
|
||||||
|
|
||||||
public class TestReflectedMethod extends ReflectedMethod<String> {
|
public class TestReflectedMethod extends ReflectedMethod<String> {
|
||||||
|
|
||||||
protected TestReflectedMethod(Object containingObject) {
|
protected TestReflectedMethod(Object containingObject) {
|
||||||
|
Reference in New Issue
Block a user