Cutin/lib/src/main/java/net/tomatentum/cutin/container/MultiMethodContainer.java
tueem c0da5ee75d
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
feat(container): add chaining, single method add method for overriding, key getter and protected entries getter
2025-04-10 14:44:57 +02:00

129 lines
4.0 KiB
Java

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 java.util.stream.Collectors;
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<I extends Object> implements MethodContainer<I> {
private Set<Entry<I>> entries;
private ReflectedMethodFactory factory;
public MultiMethodContainer(ReflectedMethodFactory factory) {
this.entries = new HashSet<>();
this.factory = factory;
}
@Override
public MethodContainer<I> addMethod(ReflectedMethod<I> method) {
Optional<Entry<I>> oentry = this.entries.stream()
.filter(e -> method.identifier().equals(e.identifier()))
.findFirst();
Entry<I> entry = oentry.orElse(new Entry<>(method.identifier())).addMethod(method);
if (oentry.isEmpty()) this.entries.add(entry);
return this;
}
@Override
public MethodContainer<I> addMethods(Object containingObject, Method... methods) {
for (Method method : methods)
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
public Collection<ReflectedMethod<I>> methods() {
return this.entries.stream()
.flatMap(e -> e.methods.stream())
.toList();
}
@Override
public Collection<ReflectedMethod<I>> findFor(I identifier) {
return this.entries.stream()
.filter(e -> e.identifier().equals(identifier))
.flatMap(e -> e.methods.stream())
.toList();
}
@Override
public Optional<ReflectedMethod<I>> findFirstFor(I identifier) {
return this.entries.stream()
.filter(e -> e.identifier().equals(identifier))
.flatMap(e -> e.methods.stream())
.findFirst();
}
protected Set<Entry<I>> entries() {
return this.entries;
}
public static record Entry<I extends Object>(I identifier, Set<ReflectedMethod<I>> methods) {
public Entry(I identifier) {
this(identifier, new HashSet<>());
}
private static Logger logger = LoggerFactory.getLogger(Entry.class);
public Entry<I> addMethod(ReflectedMethod<I> 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());
}
}
}