MethodHandlerDecorator.java
package com.github.dakusui.osynth.core;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
import static com.github.dakusui.osynth.core.SynthesizedObject.BUILT_IN_METHODS;
import static com.github.dakusui.osynth.core.SynthesizedObject.RESERVED_METHODS;
import static java.util.Collections.unmodifiableSet;
import static java.util.stream.Collectors.toSet;
/**
* This interface is applied to a method handler right after it is figured out
* by the `osynth`'s method handler looking up mechanism is finished.
*
* The returned method handler is used by the rest of the library thereafter.
*
* This mechanism is useful to construct an "AOP"-like feature such as auto-logging, etc.
*/
public interface MethodHandlerDecorator extends BiFunction<Method, MethodHandler, MethodHandler> {
MethodHandlerDecorator IDENTITY = (method, methodHandler) -> methodHandler;
Set<MethodSignature> PASS_THROUGH_METHOD_SIGNATURES = unmodifiableSet(new HashSet<MethodSignature>() {
{
this.addAll(RESERVED_METHODS.stream().map(MethodSignature::create).collect(toSet()));
this.addAll(BUILT_IN_METHODS.stream().map(MethodSignature::create).collect(toSet()));
}
});
static MethodHandlerDecorator chainMethodHandlerDecorators(MethodHandlerDecorator methodHandlerDecorator, MethodHandlerDecorator methodHandlerDecorator1) {
return methodHandlerDecorator == null ?
methodHandlerDecorator1 :
methodHandlerDecorator.andThen(methodHandlerDecorator1);
}
default MethodHandlerDecorator compose(MethodHandlerDecorator before) {
return (method, methodHandler) -> MethodHandlerDecorator.this.apply(method, before.apply(method, methodHandler));
}
default MethodHandlerDecorator andThen(MethodHandlerDecorator after) {
return (method, methodHandler) -> after.apply(method, MethodHandlerDecorator.this.apply(method, methodHandler));
}
static MethodHandlerDecorator filterOutPredefinedMethods(MethodHandlerDecorator decorator) {
class PredefinedMethodFilteringOutMethodHandlerDecorator implements MethodHandlerDecorator {
final MethodHandlerDecorator childDecorator = decorator;
@Override
public MethodHandler apply(Method method, MethodHandler methodHandler) {
if (isPassThroughMethod(method))
return methodHandler;
return decorator.apply(method, methodHandler);
}
public int hashCode() {
return this.childDecorator.hashCode();
}
public boolean equals(Object anotherObject) {
if (this == anotherObject)
return true;
if (!(anotherObject instanceof PredefinedMethodFilteringOutMethodHandlerDecorator))
return false;
PredefinedMethodFilteringOutMethodHandlerDecorator another = (PredefinedMethodFilteringOutMethodHandlerDecorator) anotherObject;
return Objects.equals(this.childDecorator, another.childDecorator);
}
}
return new PredefinedMethodFilteringOutMethodHandlerDecorator();
}
static boolean isPassThroughMethod(Method method) {
return PASS_THROUGH_METHOD_SIGNATURES.contains(MethodSignature.create(method));
}
}