Compare commits

5 Commits

Author SHA1 Message Date
c44b874b41 feat(method): add Factory to BestCandidateMethod
All checks were successful
Build / Gradle-Build (push) Successful in 1m43s
Publish / Gradle-Publish (push) Successful in 11s
Test / Gradle-Test (push) Successful in 13s
2025-04-11 13:44:10 +02:00
8842e9d8e1 refactor(method): move Method related classes to method package 2025-04-11 12:16:58 +02:00
1891037ed7 feat(factory): add Identifier Generic
All checks were successful
Build / Gradle-Build (push) Successful in 13s
Publish / Gradle-Publish (push) Successful in 12s
Test / Gradle-Test (push) Successful in 14s
2025-04-10 15:05:46 +02:00
c0da5ee75d feat(container): add chaining, single method add method for overriding, key getter and protected entries getter
All checks were successful
Build / Gradle-Build (push) Successful in 16s
Publish / Gradle-Publish (push) Successful in 12s
Test / Gradle-Test (push) Successful in 12s
2025-04-10 14:44:57 +02:00
3deee2fd5d bump version 2025-04-10 14:25:12 +02:00
11 changed files with 178 additions and 92 deletions

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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);
} }
} }

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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) {