Compare commits
	
		
			11 Commits
		
	
	
		
			v0.1.0
			...
			dd4e048ce5
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| dd4e048ce5 | |||
| deabaaf22f | |||
| 7f5c242173 | |||
| 7ec05d4e8a | |||
| 535a0dad58 | |||
| 2a6eba871d | |||
| 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); |  | ||||||
|     } |  | ||||||
|      |  | ||||||
| } |  | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| package net.tomatentum.cutin; | package net.tomatentum.cutin; | ||||||
|  |  | ||||||
| public interface MethodExecutor { | public interface MethodExecutor<C extends Object> { | ||||||
|  |  | ||||||
|     void handle(Object context); |     void handle(C context); | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,8 +2,8 @@ package net.tomatentum.cutin; | |||||||
|  |  | ||||||
| import net.tomatentum.cutin.container.MethodContainer; | import net.tomatentum.cutin.container.MethodContainer; | ||||||
|  |  | ||||||
| public interface MethodProcessor<I extends Object> { | public interface MethodProcessor<I extends Object, C extends Object> { | ||||||
|  |  | ||||||
|     void process(Object context, MethodContainer<I> methodContainer); |     void process(Object context, MethodContainer<I, C> methodContainer); | ||||||
|      |      | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,10 +2,10 @@ package net.tomatentum.cutin; | |||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  |  | ||||||
| public interface ProcessorContainer<I> { | public interface ProcessorContainer<I extends Object, C extends Object> { | ||||||
|  |  | ||||||
|     ProcessorContainer<I> addProcessor(MethodProcessor<I> processor); |     ProcessorContainer<I, C> addProcessor(MethodProcessor<I, C> processor); | ||||||
|  |  | ||||||
|     Collection<MethodProcessor<I>> processor(); |     Collection<MethodProcessor<I, C>> processor(); | ||||||
|      |      | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,26 +9,26 @@ import org.slf4j.LoggerFactory; | |||||||
|  |  | ||||||
| import net.tomatentum.cutin.container.MethodContainer; | import net.tomatentum.cutin.container.MethodContainer; | ||||||
|  |  | ||||||
| public class ProcessorMethodExecutor<I extends Object> implements MethodExecutor, ProcessorContainer<I> { | public class ProcessorMethodExecutor<I extends Object, C extends Object> implements MethodExecutor<C>, ProcessorContainer<I, C> { | ||||||
|  |  | ||||||
|     private Logger logger = LoggerFactory.getLogger(getClass()); |     private Logger logger = LoggerFactory.getLogger(getClass()); | ||||||
|  |  | ||||||
|     private MethodContainer<I> methodContainer; |     private MethodContainer<I, C> methodContainer; | ||||||
|     private Set<MethodProcessor<I>> processors; |     private Set<MethodProcessor<I, C>> processors; | ||||||
|  |  | ||||||
|     public ProcessorMethodExecutor(MethodContainer<I> methodContainer) { |     public ProcessorMethodExecutor(MethodContainer<I, C> methodContainer) { | ||||||
|         this.methodContainer = methodContainer; |         this.methodContainer = methodContainer; | ||||||
|         this.processors = new HashSet<>(); |         this.processors = new HashSet<>(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public ProcessorContainer<I> addProcessor(MethodProcessor<I> processor) { |     public ProcessorContainer<I, C> addProcessor(MethodProcessor<I, C> processor) { | ||||||
|         processors.add(processor); |         processors.add(processor); | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Collection<MethodProcessor<I>> processor() { |     public Collection<MethodProcessor<I, C>> processor() { | ||||||
|         return this.processors; |         return this.processors; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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, C extends Object> { | ||||||
|  |     Optional<ReflectedMethod<I, C>> produce(Method method, Object containingClass); | ||||||
|  |     ReflectedMethodFactory<I, C> addFactory(Factory<I, C> factory); | ||||||
|  |  | ||||||
|         Optional<ReflectedMethod> produce(Method method, Object containingObject); |     public interface Factory<I extends Object, C extends Object> { | ||||||
|         void addParser(ReflectedMethod method, List<MethodParser> parser); |  | ||||||
|  |         Optional<ReflectedMethod<I, C>> produce(Method method, Object containingObject); | ||||||
|  |         void addParser(ReflectedMethod<I, C> 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, C extends Object> implements ReflectedMethodFactory<I, C> { | ||||||
|  |  | ||||||
|     private Logger logger = LoggerFactory.getLogger(getClass()); |     private Logger logger = LoggerFactory.getLogger(getClass()); | ||||||
|  |  | ||||||
|     private List<Factory> factories; |     private List<Factory<I, C>> factories; | ||||||
|  |  | ||||||
|     public ReflectedMethodFactoryImpl() { |     public ReflectedMethodFactoryImpl() { | ||||||
|         this(new ArrayList<>()); |         this(new ArrayList<>()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public ReflectedMethodFactoryImpl(List<Factory> factories) { |     public ReflectedMethodFactoryImpl(List<Factory<I, C>> factories) { | ||||||
|         this.factories = factories; |         this.factories = factories; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Optional<ReflectedMethod> produce(Method method, Object containingClass) { |     public Optional<ReflectedMethod<I, C>> produce(Method method, Object containingClass) { | ||||||
|         Optional<ReflectedMethod> rmethod = this.factories.stream() |         Optional<ReflectedMethod<I, C>> 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, C> addFactory(Factory<I, C> 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, C>> factoryProduce(Factory<I, C> 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, C>> 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,45 +6,57 @@ 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, C extends Object> implements MethodContainer<I, C> { | ||||||
|  |  | ||||||
|     private Map<I, ReflectedMethod<I>> methodStore; |     private Map<I, ReflectedMethod<I, C>> methodStore; | ||||||
|     private ReflectedMethodFactory factory; |     private ReflectedMethodFactory<I, C> factory; | ||||||
|  |  | ||||||
|     public LoneMethodContainer(ReflectedMethodFactory factory) { |     public LoneMethodContainer(ReflectedMethodFactory<I, C> 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, C> addMethod(ReflectedMethod<I, C> 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, C> 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 |     @Override | ||||||
|     public Collection<ReflectedMethod<I>> methods() { |     public Set<I> identifiers() { | ||||||
|  |         return methodStore.keySet(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Collection<ReflectedMethod<I, C>> methods() { | ||||||
|         return this.methodStore.values(); |         return this.methodStore.values(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Collection<ReflectedMethod<I>> findFor(I identifier) { |     public Collection<ReflectedMethod<I, C>> findFor(I identifier) { | ||||||
|         return Arrays.asList(this.methodStore.get(identifier)); |         return Arrays.asList(this.methodStore.get(identifier)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Optional<ReflectedMethod<I>> findFirstFor(I identifier) { |     public Optional<ReflectedMethod<I, C>> findFirstFor(I identifier) { | ||||||
|         return findFor(identifier).stream().findFirst(); |         return findFor(identifier).stream().findFirst(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public ReflectedMethodFactory<I, C> factory() { | ||||||
|  |         return this.factory; | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,19 +3,28 @@ 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, C extends Object> { | ||||||
|  |  | ||||||
|     void addMethods(ReflectedMethod<I>... methods); |     MethodContainer<I, C> addMethod(ReflectedMethod<I, C> method); | ||||||
|     void addMethods(Object containingObject, Method... methods); |     default MethodContainer<I, C> addMethods(ReflectedMethod<I, C>[] methods) { | ||||||
|     default void addAllMethods(Object containingObject) { |         for (ReflectedMethod<I, C> reflectedMethod : methods) { | ||||||
|  |             this.addMethod(reflectedMethod); | ||||||
|  |         } | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |     MethodContainer<I, C> addMethods(Object containingObject, Method... methods); | ||||||
|  |     default MethodContainer<I, C> addAllMethods(Object containingObject) { | ||||||
|         this.addMethods(containingObject, containingObject.getClass().getDeclaredMethods()); |         this.addMethods(containingObject, containingObject.getClass().getDeclaredMethods()); | ||||||
|     }; |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     Collection<ReflectedMethod<I>> methods(); |     Set<I> identifiers(); | ||||||
|     Collection<ReflectedMethod<I>> findFor(I identifier); |     Collection<ReflectedMethod<I, C>> methods(); | ||||||
|     Optional<ReflectedMethod<I>> findFirstFor(I identifier); |     Collection<ReflectedMethod<I, C>> findFor(I identifier); | ||||||
|  |     Optional<ReflectedMethod<I, C>> findFirstFor(I identifier); | ||||||
|      |      | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,50 +5,59 @@ 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, C extends Object> implements MethodContainer<I, C> { | ||||||
|  |  | ||||||
|     private Set<Entry<I>> entries; |     private Set<Entry<I, C>> entries; | ||||||
|     private ReflectedMethodFactory factory; |     private ReflectedMethodFactory<I, C> factory; | ||||||
|  |  | ||||||
|     public MultiMethodContainer(ReflectedMethodFactory factory) { |     public MultiMethodContainer(ReflectedMethodFactory<I, C> 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, C> addMethod(ReflectedMethod<I, C> method) { | ||||||
|         for (ReflectedMethod<I> rMethod : methods) { |             Optional<Entry<I, C>> oentry = this.entries.stream() | ||||||
|             Optional<Entry<I>> oentry = this.entries.stream() |                 .filter(e -> method.identifier().equals(e.identifier())) | ||||||
|                 .filter(e -> rMethod.identifier().equals(e.identifier())) |  | ||||||
|                 .findFirst(); |                 .findFirst(); | ||||||
|             Entry<I> entry = oentry.orElse(new Entry<>(rMethod.identifier())).addMethod(rMethod); |             Entry<I, C> 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, C> 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 |     @Override | ||||||
|     public Collection<ReflectedMethod<I>> methods() { |     public Set<I> identifiers() { | ||||||
|  |         return entries().stream() | ||||||
|  |             .map(Entry::identifier) | ||||||
|  |             .collect(Collectors.toSet()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Collection<ReflectedMethod<I, C>> methods() { | ||||||
|         return this.entries.stream() |         return this.entries.stream() | ||||||
|             .flatMap(e -> e.methods.stream()) |             .flatMap(e -> e.methods.stream()) | ||||||
|             .toList(); |             .toList(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Collection<ReflectedMethod<I>> findFor(I identifier) { |     public Collection<ReflectedMethod<I, C>> findFor(I identifier) { | ||||||
|         return this.entries.stream() |         return this.entries.stream() | ||||||
|             .filter(e -> e.identifier().equals(identifier)) |             .filter(e -> e.identifier().equals(identifier)) | ||||||
|             .flatMap(e -> e.methods.stream()) |             .flatMap(e -> e.methods.stream()) | ||||||
| @@ -56,14 +65,22 @@ public class MultiMethodContainer<I extends Object> implements MethodContainer<I | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Optional<ReflectedMethod<I>> findFirstFor(I identifier) { |     public Optional<ReflectedMethod<I, C>> findFirstFor(I identifier) { | ||||||
|         return this.entries.stream() |         return this.entries.stream() | ||||||
|             .filter(e -> e.identifier().equals(identifier)) |             .filter(e -> e.identifier().equals(identifier)) | ||||||
|             .flatMap(e -> e.methods.stream()) |             .flatMap(e -> e.methods.stream()) | ||||||
|             .findFirst(); |             .findFirst(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static record Entry<I extends Object>(I identifier, Set<ReflectedMethod<I>> methods) { |     protected Set<Entry<I, C>> entries() { | ||||||
|  |         return this.entries; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public ReflectedMethodFactory<I, C> factory() { | ||||||
|  |         return this.factory; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static record Entry<I extends Object, C extends Object>(I identifier, Set<ReflectedMethod<I, C>> methods) { | ||||||
|  |  | ||||||
|         public Entry(I identifier) { |         public Entry(I identifier) { | ||||||
|             this(identifier, new HashSet<>()); |             this(identifier, new HashSet<>()); | ||||||
| @@ -71,7 +88,7 @@ public class MultiMethodContainer<I extends Object> implements MethodContainer<I | |||||||
|  |  | ||||||
|         private static Logger logger = LoggerFactory.getLogger(Entry.class); |         private static Logger logger = LoggerFactory.getLogger(Entry.class); | ||||||
|          |          | ||||||
|         public Entry<I> addMethod(ReflectedMethod<I> method) { |         public Entry<I, C> addMethod(ReflectedMethod<I, C> method) { | ||||||
|             I midentifier = method.identifier(); |             I midentifier = method.identifier(); | ||||||
|  |  | ||||||
|             if (!this.identifier().equals(midentifier)) |             if (!this.identifier().equals(midentifier)) | ||||||
| @@ -82,7 +99,7 @@ public class MultiMethodContainer<I extends Object> implements MethodContainer<I | |||||||
|             return this; |             return this; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public Object[] runAll(Object context) { |         public Object[] runAll(C context) { | ||||||
|             logger.trace("Running all Methods from {} with context {}", this, context); |             logger.trace("Running all Methods from {} with context {}", this, context); | ||||||
|             return this.methods.stream() |             return this.methods.stream() | ||||||
|                 .map(x -> { |                 .map(x -> { | ||||||
| @@ -97,7 +114,7 @@ public class MultiMethodContainer<I extends Object> implements MethodContainer<I | |||||||
|         public boolean equals(Object obj) { |         public boolean equals(Object obj) { | ||||||
|             if (!(obj instanceof Entry)) |             if (!(obj instanceof Entry)) | ||||||
|                 return false; |                 return false; | ||||||
|             Entry<?> other = (Entry<?>) obj; |             Entry<?, ?> other = (Entry<?, ?>) obj; | ||||||
|             return other.identifier().equals(identifier()); |             return other.identifier().equals(identifier()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -0,0 +1,89 @@ | |||||||
|  | package net.tomatentum.cutin.method; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Objects; | ||||||
|  | import java.util.Optional; | ||||||
|  |  | ||||||
|  | import net.tomatentum.cutin.ReflectedMethodFactory; | ||||||
|  | import net.tomatentum.cutin.container.MethodContainer; | ||||||
|  | import net.tomatentum.cutin.util.ReflectionUtil; | ||||||
|  |  | ||||||
|  | public abstract class BestCandidateMethod<I extends Object, C extends Object> extends ReflectedMethod<I, C> { | ||||||
|  |  | ||||||
|  |     private String methodName; | ||||||
|  |      | ||||||
|  |     protected BestCandidateMethod(String methodName, Object containingObject) { | ||||||
|  |         super(getMethod(containingObject, methodName), containingObject); | ||||||
|  |         this.methodName = methodName; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Object run(C context) { | ||||||
|  |         Method[] methods = Arrays.stream(containingObject.getClass().getDeclaredMethods()) | ||||||
|  |             .filter(x -> x.getName().equals(methodName)) | ||||||
|  |             .filter(x -> !x.isBridge()) | ||||||
|  |             .toArray(Method[]::new); | ||||||
|  |         Class<?>[] parameters = getCurrentParameterList(context).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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private List<Object> getCurrentParameterList(C context) { | ||||||
|  |         List<Object> parameters = new ArrayList<>(); | ||||||
|  |         int c = 0; | ||||||
|  |         Object last; | ||||||
|  |         while ((last = getParameter(context, c)) != null) { | ||||||
|  |             parameters.add(last); | ||||||
|  |             c++; | ||||||
|  |         } | ||||||
|  |         return parameters; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public abstract static class Factory<I extends Object, C extends Object> implements ReflectedMethodFactory.Factory<I, C> { | ||||||
|  |  | ||||||
|  |         private MethodContainer<I, C> methodContainer; | ||||||
|  |         private String methodName; | ||||||
|  |  | ||||||
|  |         protected Factory(MethodContainer<I, C> methodContainer, String methodName) { | ||||||
|  |             this.methodContainer = methodContainer; | ||||||
|  |             this.methodName = methodName; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         @Override | ||||||
|  |         public Optional<ReflectedMethod<I, C>> produce(Method method, Object containingObject) { | ||||||
|  |             Optional<BestCandidateMethod<I, C>> bcMethod = bcProduce(methodName, containingObject); | ||||||
|  |             if (bcMethod.isEmpty() || methodContainer.methods().contains(bcMethod.get())) | ||||||
|  |                 return Optional.empty(); | ||||||
|  |             return Optional.of(bcMethod.get()); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         protected abstract Optional<BestCandidateMethod<I, C>> bcProduce(String methodName, Object containingObject); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -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; | ||||||
| @@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory; | |||||||
| 
 | 
 | ||||||
| import net.tomatentum.cutin.util.ReflectionUtil; | import net.tomatentum.cutin.util.ReflectionUtil; | ||||||
| 
 | 
 | ||||||
| public abstract class ReflectedMethod<I extends Object> { | public abstract class ReflectedMethod<I extends Object, C extends Object> { | ||||||
| 
 | 
 | ||||||
|     private Logger logger = LoggerFactory.getLogger(getClass()); |     private Logger logger = LoggerFactory.getLogger(getClass()); | ||||||
| 
 | 
 | ||||||
| @@ -26,11 +26,11 @@ public abstract class ReflectedMethod<I extends Object> { | |||||||
|         this.containingObject = containingObject; |         this.containingObject = containingObject; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public abstract Object getParameter(Object context, int index); |     public abstract Object getParameter(C context, int index); | ||||||
| 
 | 
 | ||||||
|     public abstract I identifier(); |     public abstract I identifier(); | ||||||
| 
 | 
 | ||||||
|     public Object run(Object context) { |     public Object run(C context) { | ||||||
|         method.setAccessible(true); |         method.setAccessible(true); | ||||||
|         try { |         try { | ||||||
|             return method.invoke(containingObject, getParameters(context)); |             return method.invoke(containingObject, getParameters(context)); | ||||||
| @@ -48,17 +48,12 @@ public abstract class ReflectedMethod<I extends Object> { | |||||||
|         return this.containingObject; |         return this.containingObject; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private Object[] getParameters(Object context) { |     private Object[] getParameters(C context) { | ||||||
|         int parameterCount = method.getParameterCount(); |         int parameterCount = method.getParameterCount(); | ||||||
|         List<Object> parameters = new ArrayList<>(); |         List<Object> parameters = new ArrayList<>(); | ||||||
|          |          | ||||||
|         for (int i = 0; i < parameterCount; i++) { |         for (int i = 0; i < parameterCount; i++) { | ||||||
|             Object parameter; |             Object parameter = getParameter(context, i); | ||||||
|             if (i == 0) { |  | ||||||
|                 parameter = context; |  | ||||||
|             }else |  | ||||||
|                 parameter = getParameter(context, i-1); |  | ||||||
| 
 |  | ||||||
|             logger.trace("Found parameter {}={} for method {}", parameter != null ? parameter.getClass().toString() : " ", parameter, ReflectionUtil.getFullMethodName(method)); |             logger.trace("Found parameter {}={} for method {}", parameter != null ? parameter.getClass().toString() : " ", parameter, ReflectionUtil.getFullMethodName(method)); | ||||||
|             parameters.add(parameter);    |             parameters.add(parameter);    | ||||||
|         } |         } | ||||||
| @@ -4,23 +4,25 @@ 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.ReflectedMethod; | ||||||
|  |  | ||||||
| class ReflectedMethodTest { | class ReflectedMethodTest { | ||||||
|      |      | ||||||
|     @Test |     @Test | ||||||
|     void methodTest() { |     void methodTest() { | ||||||
|         ReflectedMethod<String> method = new TestReflectedMethod(new TestMethodClass()); |         ReflectedMethod<String, String> method = new TestReflectedMethod(new TestMethodClass()); | ||||||
|         Object result = method.run("testContext"); |         Object result = method.run("testContext"); | ||||||
|         assertTrue((boolean)result); |         assertTrue((boolean)result); | ||||||
|  |         System.out.println("Success"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Test |     @Test | ||||||
|     void testBCMethod() { |     void testBCMethod() { | ||||||
|         ReflectedMethod<?> method = new BestCandidateMethod<String>( |         ReflectedMethod<String, Double> method = new TestBestCandidateMethod( | ||||||
|             "test",  |             "test",  | ||||||
|             new TestMethodClass(), |             new TestMethodClass()); | ||||||
|             "ident", |  | ||||||
|              "testString"); |  | ||||||
|         Object result = method.run((double)4); |         Object result = method.run((double)4); | ||||||
|         assertTrue((boolean)result); |         assertTrue((boolean)result); | ||||||
|  |         System.out.println("Success"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,28 @@ | |||||||
|  | package net.tomatentum.cutin; | ||||||
|  |  | ||||||
|  | import net.tomatentum.cutin.method.BestCandidateMethod; | ||||||
|  |  | ||||||
|  | public class TestBestCandidateMethod extends BestCandidateMethod<String, Double> { | ||||||
|  |  | ||||||
|  |     protected TestBestCandidateMethod(String methodName, Object containingObject) { | ||||||
|  |         super(methodName, containingObject); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Object getParameter(Double context, int index) { | ||||||
|  |         switch (index) { | ||||||
|  |             case 0: | ||||||
|  |                 return context; | ||||||
|  |             case 1: | ||||||
|  |                 return "testString"; | ||||||
|  |             default: | ||||||
|  |                 return null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String identifier() { | ||||||
|  |         return "ident"; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
| @@ -2,7 +2,9 @@ package net.tomatentum.cutin; | |||||||
|  |  | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
|  |  | ||||||
| public class TestReflectedMethod extends ReflectedMethod<String> { | import net.tomatentum.cutin.method.ReflectedMethod; | ||||||
|  |  | ||||||
|  | public class TestReflectedMethod extends ReflectedMethod<String, String> { | ||||||
|  |  | ||||||
|     protected TestReflectedMethod(Object containingObject) { |     protected TestReflectedMethod(Object containingObject) { | ||||||
|         super(getMethod(containingObject), containingObject); |         super(getMethod(containingObject), containingObject); | ||||||
| @@ -10,8 +12,15 @@ public class TestReflectedMethod extends ReflectedMethod<String> { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Object getParameter(Object context, int index) { |     public Object getParameter(String context, int index) { | ||||||
|  |         switch (index) { | ||||||
|  |             case 0: | ||||||
|  |                 return context; | ||||||
|  |             case 1: | ||||||
|                 return 2; |                 return 2; | ||||||
|  |             default: | ||||||
|  |                 return null; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user