diff --git a/lib/src/main/java/net/tomatentum/cutin/container/LoneMethodContainer.java b/lib/src/main/java/net/tomatentum/cutin/container/LoneMethodContainer.java new file mode 100644 index 0000000..11a4e59 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/cutin/container/LoneMethodContainer.java @@ -0,0 +1,50 @@ +package net.tomatentum.cutin.container; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import net.tomatentum.cutin.ReflectedMethod; +import net.tomatentum.cutin.ReflectedMethodFactory; + +public class LoneMethodContainer implements MethodContainer { + + private Map> methodStore; + private ReflectedMethodFactory factory; + + public LoneMethodContainer(ReflectedMethodFactory factory) { + this.methodStore = new HashMap<>(); + this.factory = factory; + } + + @Override + public void addMethods(ReflectedMethod... methods) { + for (ReflectedMethod reflectedMethod : methods) + this.methodStore.put(reflectedMethod.identifier(), reflectedMethod); + } + + @Override + public void addMethods(Object containingObject, Method... methods) { + for (Method method : methods) + this.addMethods(this.factory.produce(method, containingObject)); + } + + @Override + public Collection> methods() { + return this.methodStore.values(); + } + + @Override + public Collection> findFor(I identifier) { + return Arrays.asList(this.methodStore.get(identifier)); + } + + @Override + public Optional> findFirstFor(I identifier) { + return findFor(identifier).stream().findFirst(); + } + +} diff --git a/lib/src/main/java/net/tomatentum/cutin/container/MethodContainer.java b/lib/src/main/java/net/tomatentum/cutin/container/MethodContainer.java new file mode 100644 index 0000000..62f64e0 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/cutin/container/MethodContainer.java @@ -0,0 +1,21 @@ +package net.tomatentum.cutin.container; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Optional; + +import net.tomatentum.cutin.ReflectedMethod; + +public interface MethodContainer { + + void addMethods(ReflectedMethod... methods); + void addMethods(Object containingObject, Method... methods); + default void addAllMethods(Object containingObject) { + this.addMethods(containingObject, containingObject.getClass().getDeclaredMethods()); + }; + + Collection> methods(); + Collection> findFor(I identifier); + Optional> findFirstFor(I identifier); + +} diff --git a/lib/src/main/java/net/tomatentum/cutin/container/MultiMethodContainer.java b/lib/src/main/java/net/tomatentum/cutin/container/MultiMethodContainer.java new file mode 100644 index 0000000..3838c41 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/cutin/container/MultiMethodContainer.java @@ -0,0 +1,115 @@ +package net.tomatentum.cutin.container; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.tomatentum.cutin.ReflectedMethod; +import net.tomatentum.cutin.ReflectedMethodFactory; +import net.tomatentum.cutin.util.ReflectionUtil; + +public class MultiMethodContainer implements MethodContainer { + + private Set> entries; + private ReflectedMethodFactory factory; + + public MultiMethodContainer(ReflectedMethodFactory factory) { + this.entries = new HashSet<>(); + this.factory = factory; + } + + @Override + public void addMethods(ReflectedMethod... methods) { + for (ReflectedMethod rMethod : methods) { + Optional> oentry = this.entries.stream() + .filter(e -> rMethod.identifier().equals(e.identifier())) + .findFirst(); + Entry entry = oentry.orElse(new Entry<>(rMethod.identifier())).addMethod(rMethod); + if (oentry.isEmpty()) this.entries.add(entry); + } + } + + @Override + public void addMethods(Object containingObject, Method... methods) { + for (Method method : methods) + this.addMethods(this.factory.produce(method, containingObject)); + } + + @Override + public Collection> methods() { + return this.entries.stream() + .flatMap(e -> e.methods.stream()) + .toList(); + } + + @Override + public Collection> findFor(I identifier) { + return this.entries.stream() + .filter(e -> e.identifier().equals(identifier)) + .flatMap(e -> e.methods.stream()) + .toList(); + } + + @Override + public Optional> findFirstFor(I identifier) { + return this.entries.stream() + .filter(e -> e.identifier().equals(identifier)) + .flatMap(e -> e.methods.stream()) + .findFirst(); + } + + public static record Entry(I identifier, Set> methods) { + + public Entry(I identifier) { + this(identifier, new HashSet<>()); + } + + private static Logger logger = LoggerFactory.getLogger(Entry.class); + + public Entry addMethod(ReflectedMethod method) { + I midentifier = method.identifier(); + + if (!this.identifier().equals(midentifier)) + throw new IllegalArgumentException("Method's identifier did not equal the entry's identifier"); + + this.methods.add(method); + logger.debug("Added method {} to entry {}", method.method().getName(), this); + return this; + } + + public Object[] runAll(Object context) { + logger.trace("Running all Methods from {} with context {}", this, context); + return this.methods.stream() + .map(x -> { + logger.debug("Running Method {} from {} with context {}", x, this, context); + return x.run(context); + }) + .flatMap(ReflectionUtil::getReturnAsStream) + .toArray(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Entry)) + return false; + Entry other = (Entry) obj; + return other.identifier().equals(identifier()); + } + + @Override + public int hashCode() { + return this.identifier().hashCode(); + } + + @Override + public String toString() { + return "Content(%s)".formatted(identifier().toString()); + } + } + +}