ObjectSynthesizer.java
- package com.github.dakusui.osynth;
- import com.github.dakusui.osynth.core.*;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Method;
- import java.util.Arrays;
- import java.util.Objects;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.function.Function;
- import java.util.function.Predicate;
- import java.util.regex.Pattern;
- import static com.github.dakusui.osynth.core.AbstractObjectSynthesizer.Preprocessor.importDescriptorFromAnotherSynthesizedObject;
- import static com.github.dakusui.osynth.core.utils.MethodUtils.*;
- import static java.lang.String.format;
- /**
- * The main entry pont of the `osynth` object synthesizer library.
- */
- public class ObjectSynthesizer extends AbstractObjectSynthesizer<ObjectSynthesizer> {
- public ObjectSynthesizer() {
- super(new SynthesizedObject.Descriptor.Builder()
- .fallbackObject(DEFAULT_FALLBACK_OBJECT));
- }
- public ObjectSynthesizer(SynthesizedObject.Descriptor descriptor) {
- super(new SynthesizedObject.Descriptor.Builder(descriptor));
- }
- public static MethodHandlerEntry.Builder methodCall(String methodName, Class<?>... parameterTypes) {
- return methodCall(MethodSignature.create(methodName, parameterTypes));
- }
- public static MethodHandlerEntry.Builder methodCall(MethodSignature methodSignature) {
- return new MethodHandlerEntry.Builder().matcher(matchingExactly(methodSignature));
- }
- public static MethodHandlerEntry.Builder methodCall(MethodMatcher matcher) {
- return new MethodHandlerEntry.Builder().matcher(matcher);
- }
- public static MethodMatcher matchingExactly(MethodSignature signature) {
- return MethodMatcher.overrideToString(mm -> ("matchingExactly:" + mm.toString()), nameMatchingExactly(signature.name()).and(parameterTypesMatchingExactly(signature.parameterTypes())));
- }
- /**
- * Returns a "lenient" method matcher by signature.
- * The returned matcher checks if
- *
- * 1. The name of a method to be tested if it is matching the name of the `targetMethodSignature` as a regular expression.
- * 2. Every parameter types of the method to be tested is equal to or more special than the corresponding parameter type in the `signature`.
- *
- * If the signature doesn't have any parameter types, it matches a method without
- * any parameters.
- * In case you want to create a matcher that matches a method with a specific name but
- * doesn't care any parameter types, use {@link ObjectSynthesizer#nameMatchingRegex(String)}
- * or {@link ObjectSynthesizer#nameMatchingExactly(String)}.
- *
- * ,@param signature The method signature that matches a returned matcher.
- *
- * @return A method matcher by signature.
- */
- public static MethodMatcher matchingLeniently(MethodSignature signature) {
- return MethodMatcher.overrideToString(mm -> ("matchingLeniently:" + mm.toString()), nameMatchingRegex(signature.name()).and(parameterTypesMatchingLeniently(signature.parameterTypes())));
- }
- public static MethodMatcher nameMatchingExactly(String methodName) {
- return MethodMatcher.create(
- (mm) -> format("nameMatchingExactly[%s]", methodName),
- method -> Objects.equals(methodName, method.getName()));
- }
- public static MethodMatcher nameMatchingRegex(String regexForMethodName) {
- Pattern regex = Pattern.compile(regexForMethodName);
- return MethodMatcher.create(
- (mm) -> format("nameMatchingRegex[%s]", regexForMethodName),
- method -> regex.matcher(method.getName()).matches());
- }
- public static MethodMatcher parameterTypesMatchingExactly(Class<?>[] parameterTypes) {
- return MethodMatcher.create(
- (mm) -> format("parameterTypesMatchingExactly%s", Arrays.toString(parameterTypes)),
- method -> Arrays.equals(parameterTypes, method.getParameterTypes())
- );
- }
- public static MethodMatcher parameterTypesMatchingLeniently(Class<?>[] parameterTypes) {
- return MethodMatcher.create(
- (mm) -> format("parameterTypesMatchingLeniently%s", Arrays.toString(parameterTypes)),
- method -> {
- AtomicInteger i = new AtomicInteger(0);
- return parameterTypes.length == method.getParameterTypes().length &&
- Arrays.stream(method.getParameterTypes())
- .allMatch(type -> type.isAssignableFrom(parameterTypes[i.getAndIncrement()]));
- }
- );
- }
- public static <A extends Annotation> MethodMatcher annotatedWith(Class<A> annotationClass) {
- return matching(
- m -> "annotatedWith(@" + simpleClassNameOf(annotationClass) + ")",
- method -> method.isAnnotationPresent(annotationClass));
- }
- public static <A extends Annotation> MethodMatcher annotatedWith(Class<A> annotationClass, Predicate<A> annotationPredicate) {
- return annotatedWith(annotationClass).and(
- matching(
- m -> "satisfying:" + prettierToString(m),
- m -> annotationPredicate.test(m.getAnnotation(annotationClass))));
- }
- public static MethodMatcher matching(Function<MethodMatcher, String> nameComposer, Predicate<Method> p) {
- return MethodMatcher.create(nameComposer, p);
- }
- public static ObjectSynthesizer from(SynthesizedObject.Descriptor descriptor) {
- ObjectSynthesizer ret;
- return (ret = new ObjectSynthesizer()).preprocessWith(Preprocessor.sequence(
- importDescriptorFromAnotherSynthesizedObject(descriptor),
- ret.preprocessor()));
- }
- }