From 2c06ee6641cc8c08bbe3aafd393d0a7f65501fc7 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 13:45:53 +0200 Subject: [PATCH 01/12] add override methods definition and builder for it also add logic to add predicate inside listener and return statement annotation --- README.md | 6 +- .../core/annotations/PayloadPredicate.java | 11 + .../core/annotations/ReturnStatement.java | 14 + .../DefaultOverridingMethodsDefinition.java | 278 ++++++++++++++++++ .../OverridingMethodsDefinition.java | 50 ++++ .../OverridingMethodsDefinitionBuilder.java | 51 ++++ .../methods/InterceptMethodsContainer.java | 32 ++ .../methods/OverridingMethodsFactory.java | 99 +++---- .../ParametersWithNameReceivers.java | 6 + 9 files changed, 488 insertions(+), 59 deletions(-) create mode 100644 core/src/main/java/io/github/fa4nir/core/annotations/PayloadPredicate.java create mode 100644 core/src/main/java/io/github/fa4nir/core/annotations/ReturnStatement.java create mode 100644 core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java create mode 100644 core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java create mode 100644 core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java create mode 100644 core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java diff --git a/README.md b/README.md index 480b19d..c428c01 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ to listening your notifications. ## Build ``` - gradle clean jar fatJar + gradle clean build ``` ## Tests @@ -24,6 +24,6 @@ to listening your notifications. ## Dependencies ``` - implementation 'io.github.fa4nir:fa4nir:1.0.0' - annotationProcessor 'io.github.fa4nir:fa4nir:1.0.0' + implementation 'io.github.fa4nir:fa4nir:1.0.1' + annotationProcessor 'io.github.fa4nir:fa4nir:1.0.1' ``` \ No newline at end of file diff --git a/core/src/main/java/io/github/fa4nir/core/annotations/PayloadPredicate.java b/core/src/main/java/io/github/fa4nir/core/annotations/PayloadPredicate.java new file mode 100644 index 0000000..7890901 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/annotations/PayloadPredicate.java @@ -0,0 +1,11 @@ +package io.github.fa4nir.core.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface PayloadPredicate { +} diff --git a/core/src/main/java/io/github/fa4nir/core/annotations/ReturnStatement.java b/core/src/main/java/io/github/fa4nir/core/annotations/ReturnStatement.java new file mode 100644 index 0000000..39da389 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/annotations/ReturnStatement.java @@ -0,0 +1,14 @@ +package io.github.fa4nir.core.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ReturnStatement { + + boolean isAlwaysNull() default false; + +} diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java new file mode 100644 index 0000000..ccd89a5 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java @@ -0,0 +1,278 @@ +package io.github.fa4nir.core.definitions; + +import io.github.fa4nir.core.annotations.DelegateResultTo; +import io.github.fa4nir.core.annotations.FallBackMethod; +import io.github.fa4nir.core.annotations.NotifyTo; +import io.github.fa4nir.core.annotations.PayloadPredicate; +import io.github.fa4nir.core.factories.MethodParametersExtractor; +import org.apache.commons.lang3.StringUtils; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import java.beans.Introspector; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class DefaultOverridingMethodsDefinition implements OverridingMethodsDefinitionBuilder, MethodParametersExtractor { + + private ExecutableElement sourceMethod; + + private Element target; + + private NotifyTo annotationNotifyTo; + + private FallBackMethod annotationFallBackMethod; + + private List targetMethods; + + private List sourceParameters; + + private Map groupOfSourceParameters; + + private String targetFieldName; + + private ExecutableElement targetMethod; + + private String resultName; + + private DelegateResultTo[] delegateResultToAnnotations; + + private ExecutableElement fallBackMethod; + + private TypeMirror targetMethodReturnType; + + private List targetParameters; + + private List predicateMethods; + + private String notifyToTarget; + + private String fallBackMethodName; + + DefaultOverridingMethodsDefinition() { + } + + private String createResultName(List sourceParameters, ExecutableElement targetMethod) { + String resultName = "result"; + boolean isResultMatch = sourceParameters.stream().anyMatch(param -> param.getSimpleName().toString().equals("result")); + if (isResultMatch) { + resultName = String.format("%sFrom%s", resultName, StringUtils.capitalize(targetMethod.getSimpleName().toString())); + } + return resultName; + } + + private ExecutableElement findMethod(Element target, String name) { + return target.getEnclosedElements().stream() + .filter(method -> method instanceof ExecutableElement) + .map(method -> (ExecutableElement) method) + .filter(method -> method.getSimpleName().toString().equals(name)) + .findFirst().orElse(null); + } + + @Override + public OverridingMethodsDefinitionBuilder sourceMethod(ExecutableElement sourceMethod) { + this.sourceMethod = sourceMethod; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder target(Element target) { + this.target = target; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder annotationNotifyTo(NotifyTo annotationNotifyTo) { + this.annotationNotifyTo = annotationNotifyTo; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder annotationFallBackMethod(FallBackMethod annotationFallBackMethod) { + this.annotationFallBackMethod = annotationFallBackMethod; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetMethods() { + this.targetMethods = this.target.getEnclosedElements(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder sourceParameters() { + this.sourceParameters = this.sourceMethod.getParameters(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder groupOfSourceParameters() { + this.groupOfSourceParameters = this.sourceParameters.stream() + .collect(Collectors.toMap(k -> k.getSimpleName().toString(), Function.identity())); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetFieldName() { + this.targetFieldName = Introspector.decapitalize(this.target.getSimpleName().toString()); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetMethod() { + this.targetMethod = findMethod(this.target, this.notifyToTarget); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder resultName() { + this.resultName = createResultName(this.sourceParameters, this.targetMethod); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder delegateResultToAnnotations() { + this.delegateResultToAnnotations = this.targetMethod.getAnnotationsByType(DelegateResultTo.class); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder fallBackMethod() { + this.fallBackMethod = findMethod(this.target, this.fallBackMethodName); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetMethodReturnType() { + this.targetMethodReturnType = this.targetMethod.getReturnType(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetParameters() { + this.targetParameters = Objects.requireNonNull( + this.targetMethod, String.format("Cannot find method %s", this.targetMethod.getSimpleName()) + ).getParameters(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder predicateMethods() { + this.predicateMethods = this.targetMethods.stream() + .filter(method -> method instanceof ExecutableElement) + .filter(method -> Objects.nonNull(method.getAnnotation(PayloadPredicate.class))) + .map(method -> ((ExecutableElement) method)) + .collect(Collectors.toList()); + if (this.predicateMethods.size() > 1) { + throw new IllegalArgumentException("Only one predicate method."); + } + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder notifyToTarget() { + this.notifyToTarget = this.annotationNotifyTo.name(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder fallBackMethodName() { + this.fallBackMethodName = Objects.nonNull(this.annotationFallBackMethod) ? this.annotationFallBackMethod.name() : ""; + return this; + } + + @Override + public OverridingMethodsDefinition build() { + return new OverridingMethodsDefinition() { + @Override + public ExecutableElement getSourceMethod() { + return sourceMethod; + } + + @Override + public Element getTarget() { + return target; + } + + @Override + public NotifyTo getAnnotationNotifyTo() { + return annotationNotifyTo; + } + + @Override + public FallBackMethod getAnnotationFallBackMethod() { + return annotationFallBackMethod; + } + + @Override + public List getTargetMethods() { + return targetMethods; + } + + @Override + public List getSourceParameters() { + return sourceParameters; + } + + @Override + public Map getGroupOfSourceParameters() { + return groupOfSourceParameters; + } + + @Override + public String getTargetFieldName() { + return targetFieldName; + } + + @Override + public ExecutableElement getTargetMethod() { + return targetMethod; + } + + @Override + public String getResultName() { + return resultName; + } + + @Override + public DelegateResultTo[] getDelegateResultToAnnotations() { + return delegateResultToAnnotations; + } + + @Override + public ExecutableElement getFallBackMethod() { + return fallBackMethod; + } + + @Override + public TypeMirror getTargetMethodReturnType() { + return targetMethodReturnType; + } + + @Override + public List getTargetParameters() { + return targetParameters; + } + + @Override + public List getPredicateMethods() { + return predicateMethods; + } + + @Override + public String getNotifyToTarget() { + return notifyToTarget; + } + + @Override + public String getFallBackMethodName() { + return fallBackMethodName; + } + }; + } +} diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java new file mode 100644 index 0000000..14dbe70 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java @@ -0,0 +1,50 @@ +package io.github.fa4nir.core.definitions; + +import io.github.fa4nir.core.annotations.DelegateResultTo; +import io.github.fa4nir.core.annotations.FallBackMethod; +import io.github.fa4nir.core.annotations.NotifyTo; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import java.util.List; +import java.util.Map; + +public interface OverridingMethodsDefinition { + + ExecutableElement getSourceMethod(); + + Element getTarget(); + + NotifyTo getAnnotationNotifyTo(); + + FallBackMethod getAnnotationFallBackMethod(); + + List getTargetMethods(); + + List getSourceParameters(); + + Map getGroupOfSourceParameters(); + + String getTargetFieldName(); + + ExecutableElement getTargetMethod(); + + String getResultName(); + + DelegateResultTo[] getDelegateResultToAnnotations(); + + ExecutableElement getFallBackMethod(); + + TypeMirror getTargetMethodReturnType(); + + List getTargetParameters(); + + List getPredicateMethods(); + + String getNotifyToTarget(); + + String getFallBackMethodName(); + +} diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java new file mode 100644 index 0000000..3371665 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java @@ -0,0 +1,51 @@ +package io.github.fa4nir.core.definitions; + +import io.github.fa4nir.core.annotations.FallBackMethod; +import io.github.fa4nir.core.annotations.NotifyTo; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; + +public interface OverridingMethodsDefinitionBuilder { + + static OverridingMethodsDefinitionBuilder newBuilder() { + return new DefaultOverridingMethodsDefinition(); + } + + OverridingMethodsDefinitionBuilder sourceMethod(ExecutableElement sourceMethod); + + OverridingMethodsDefinitionBuilder target(Element target); + + OverridingMethodsDefinitionBuilder annotationNotifyTo(NotifyTo annotationNotifyTo); + + OverridingMethodsDefinitionBuilder annotationFallBackMethod(FallBackMethod annotationFallBackMethod); + + OverridingMethodsDefinitionBuilder targetMethods(); + + OverridingMethodsDefinitionBuilder sourceParameters(); + + OverridingMethodsDefinitionBuilder groupOfSourceParameters(); + + OverridingMethodsDefinitionBuilder targetFieldName(); + + OverridingMethodsDefinitionBuilder targetMethod(); + + OverridingMethodsDefinitionBuilder resultName(); + + OverridingMethodsDefinitionBuilder delegateResultToAnnotations(); + + OverridingMethodsDefinitionBuilder fallBackMethod(); + + OverridingMethodsDefinitionBuilder targetMethodReturnType(); + + OverridingMethodsDefinitionBuilder notifyToTarget(); + + OverridingMethodsDefinitionBuilder targetParameters(); + + OverridingMethodsDefinitionBuilder predicateMethods(); + + OverridingMethodsDefinitionBuilder fallBackMethodName(); + + OverridingMethodsDefinition build(); + +} diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java new file mode 100644 index 0000000..9659912 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java @@ -0,0 +1,32 @@ +package io.github.fa4nir.core.factories.methods; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +public class InterceptMethodsContainer { + + private static InterceptMethodsContainer instance = null; + + private final Map interceptMethod; + + private InterceptMethodsContainer() { + this.interceptMethod = new ConcurrentHashMap<>(); + } + + public static InterceptMethodsContainer getInstance() { + if (Objects.isNull(instance)) { + instance = new InterceptMethodsContainer(); + } + return instance; + } + + public void put(String key, InterceptMethodFactory value) { + this.interceptMethod.put(key, value); + } + + public InterceptMethodFactory get(String key) { + return this.interceptMethod.get(key); + } + +} diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java index f5fcce5..8112ef7 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java @@ -4,23 +4,20 @@ import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; -import io.github.fa4nir.core.annotations.DelegateResultTo; import io.github.fa4nir.core.annotations.FallBackMethod; import io.github.fa4nir.core.annotations.FetchParam; import io.github.fa4nir.core.annotations.NotifyTo; import io.github.fa4nir.core.definitions.DelegateMethodsDefinitionBuilder; +import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; +import io.github.fa4nir.core.definitions.OverridingMethodsDefinitionBuilder; import io.github.fa4nir.core.factories.fallbacks.FallBackMethodFactory; -import org.apache.commons.lang3.StringUtils; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; -import java.beans.Introspector; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Function; import java.util.stream.Collectors; public class OverridingMethodsFactory implements InterceptMethodFactory { @@ -37,64 +34,54 @@ public MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target) FallBackMethod annotationFallBackMethod = sourceMethod.getAnnotation(FallBackMethod.class); if (Objects.nonNull(annotationNotifyTo)) { MethodSpec.Builder builder = MethodSpec.overriding(sourceMethod); - List sourceParameters = sourceMethod.getParameters(); - Map groupOfSourceParameters = sourceParameters.stream() - .collect(Collectors.toMap(k -> k.getSimpleName().toString(), Function.identity())); - String targetFieldName = Introspector.decapitalize(target.getSimpleName().toString()); - String notifyToTarget = annotationNotifyTo.name(); - String fallBackMethodName = Objects.nonNull(annotationFallBackMethod) ? annotationFallBackMethod.name() : ""; - ExecutableElement targetMethod = findMethod(target, notifyToTarget); - String resultName = createResultName(sourceParameters, targetMethod); - DelegateResultTo[] delegateResultToAnnotations = targetMethod.getAnnotationsByType(DelegateResultTo.class); - ExecutableElement fallBackMethod = findMethod(target, fallBackMethodName); - TypeMirror targetMethodReturnType = targetMethod.getReturnType(); - List targetParameters = Objects.requireNonNull( - targetMethod, String.format("Cannot find method %s", targetMethod.getSimpleName()) - ).getParameters(); - builder.beginControlFlow("try"); - String parametersAsString = parametersAsString(sourceParameters, groupOfSourceParameters, targetParameters); - if (Objects.nonNull(delegateResultToAnnotations) && delegateResultToAnnotations.length > 0) { - builder.addStatement("$T $N = this.$N.$N($N)", ParameterizedTypeName.get(targetMethodReturnType), resultName, - targetFieldName, targetMethod.getSimpleName().toString(), parametersAsString); - List callsToDelegateMethods = DelegateMethodsDefinitionBuilder.newBuilder() - .setResultName(resultName) - .setTargetEnclosedElements(target.getEnclosedElements()) - .setTargetFieldName(targetFieldName) - .setSourceParameters(sourceParameters) - .setGroupOfSourceParameters(groupOfSourceParameters) - .setDelegateResultToAnnotations(delegateResultToAnnotations) + OverridingMethodsDefinition definition = OverridingMethodsDefinitionBuilder.newBuilder() + .sourceMethod(sourceMethod).target(target).annotationNotifyTo(annotationNotifyTo) + .annotationFallBackMethod(annotationFallBackMethod).notifyToTarget().targetMethods().sourceParameters() + .groupOfSourceParameters().targetFieldName().targetMethod() + .resultName().delegateResultToAnnotations().fallBackMethod().targetMethodReturnType() + .targetParameters().predicateMethods().fallBackMethodName() + .build(); + if (definition.getPredicateMethods().size() > 0) { + ExecutableElement predicate = definition.getPredicateMethods().get(0); + String predicateSimpleName = predicate.getSimpleName().toString(); + List predicateParameters = predicate.getParameters(); + String strPredicateParameters = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), predicateParameters); + builder.beginControlFlow("if(this.$N.$N($N))", definition.getTargetFieldName(), predicateSimpleName, strPredicateParameters); + return decorateMethodSpec(definition, builder) + .endControlFlow() .build(); - callsToDelegateMethods.forEach(builder::addStatement); - } else { - builder.addStatement("this.$N.$N($N)", - targetFieldName, targetMethod.getSimpleName().toString(), parametersAsString); } - CodeBlock fallBackMethodAsString = this.fallBackMethodFactory - .newFallBackCodeBlock(fallBackMethod, targetFieldName, sourceParameters); - return builder - .nextControlFlow("catch($T e)", ClassName.get(Exception.class)) - .addCode(fallBackMethodAsString) - .endControlFlow() - .build(); + return decorateMethodSpec(definition, builder).build(); } return MethodSpec.overriding(sourceMethod).build(); } - private String createResultName(List sourceParameters, ExecutableElement targetMethod) { - String resultName = "result"; - boolean isResultMatch = sourceParameters.stream().anyMatch(param -> param.getSimpleName().toString().equals("result")); - if (isResultMatch) { - resultName = String.format("%sFrom%s", resultName, StringUtils.capitalize(targetMethod.getSimpleName().toString())); + private MethodSpec.Builder decorateMethodSpec(OverridingMethodsDefinition definition, + MethodSpec.Builder builder) { + builder.beginControlFlow("try"); + String parametersAsString = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), definition.getTargetParameters()); + if (Objects.nonNull(definition.getDelegateResultToAnnotations()) && definition.getDelegateResultToAnnotations().length > 0) { + builder.addStatement("$T $N = this.$N.$N($N)", ParameterizedTypeName.get(definition.getTargetMethodReturnType()), definition.getResultName(), + definition.getTargetFieldName(), definition.getTargetMethod().getSimpleName().toString(), parametersAsString); + List callsToDelegateMethods = DelegateMethodsDefinitionBuilder.newBuilder() + .setResultName(definition.getResultName()) + .setTargetEnclosedElements(definition.getTargetMethods()) + .setTargetFieldName(definition.getTargetFieldName()) + .setSourceParameters(definition.getSourceParameters()) + .setGroupOfSourceParameters(definition.getGroupOfSourceParameters()) + .setDelegateResultToAnnotations(definition.getDelegateResultToAnnotations()) + .build(); + callsToDelegateMethods.forEach(builder::addStatement); + } else { + builder.addStatement("this.$N.$N($N)", + definition.getTargetFieldName(), definition.getTargetMethod().getSimpleName().toString(), parametersAsString); } - return resultName; - } - - private ExecutableElement findMethod(Element target, String name) { - return target.getEnclosedElements().stream() - .filter(method -> method instanceof ExecutableElement) - .map(method -> (ExecutableElement) method) - .filter(method -> method.getSimpleName().toString().equals(name)) - .findFirst().orElse(null); + CodeBlock fallBackMethodAsString = this.fallBackMethodFactory + .newFallBackCodeBlock(definition.getFallBackMethod(), definition.getTargetFieldName(), definition.getSourceParameters()); + return builder + .nextControlFlow("catch($T e)", ClassName.get(Exception.class)) + .addCode(fallBackMethodAsString) + .endControlFlow(); } private String parametersAsString(List targetParameters, diff --git a/examples/src/main/java/io/github/fa4nir/examples/receivers/ParametersWithNameReceivers.java b/examples/src/main/java/io/github/fa4nir/examples/receivers/ParametersWithNameReceivers.java index d6165d4..e8bfdcf 100644 --- a/examples/src/main/java/io/github/fa4nir/examples/receivers/ParametersWithNameReceivers.java +++ b/examples/src/main/java/io/github/fa4nir/examples/receivers/ParametersWithNameReceivers.java @@ -3,6 +3,7 @@ import io.github.fa4nir.core.annotations.*; import io.github.fa4nir.examples.Person; +import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; @@ -11,6 +12,11 @@ public class ParametersWithNameReceivers { private static final Logger log = Logger.getLogger(ParametersWithNameReceivers.class.getName()); + @PayloadPredicate + public boolean isPayloadNotNull(@FetchParam(name = "personName") String payload) { + return Objects.nonNull(payload); + } + @DelegateResultTo(method = "receivePersonWithName") @DelegateResultTo(method = "receivePersonWithNameAndWeight") public Person listenerWithParametersName(@FetchParam(name = "personName") String name) { From b4fb9b539d00469daed7cb6d3121badd5102c65e Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 15:21:50 +0200 Subject: [PATCH 02/12] add wrappers and refactoring OverrideMethodWrapper --- .../DefaultOverridingMethodsDefinition.java | 5 ++ .../OverridingMethodsDefinition.java | 2 + .../TransmitterContainerFactory.java | 14 ++++- .../methods/OverridingMethodsFactory.java | 63 +++++-------------- .../core/wrappers/BodyMethodBaseWrapper.java | 35 +++++++++++ .../core/wrappers/OverrideMethodWrapper.java | 10 +++ .../core/wrappers/PredicateMethodWrapper.java | 48 ++++++++++++++ .../wrappers/TryCatchMethodBaseWrapper.java | 31 +++++++++ 8 files changed, 160 insertions(+), 48 deletions(-) create mode 100644 core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java create mode 100644 core/src/main/java/io/github/fa4nir/core/wrappers/OverrideMethodWrapper.java create mode 100644 core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java create mode 100644 core/src/main/java/io/github/fa4nir/core/wrappers/TryCatchMethodBaseWrapper.java diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java index ccd89a5..8531d21 100644 --- a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java +++ b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java @@ -273,6 +273,11 @@ public String getNotifyToTarget() { public String getFallBackMethodName() { return fallBackMethodName; } + + @Override + public boolean isPredicateMethodsSize() { + return predicateMethods.size() == 1; + } }; } } diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java index 14dbe70..3dc6775 100644 --- a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java +++ b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java @@ -47,4 +47,6 @@ public interface OverridingMethodsDefinition { String getFallBackMethodName(); + boolean isPredicateMethodsSize(); + } diff --git a/core/src/main/java/io/github/fa4nir/core/factories/TransmitterContainerFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/TransmitterContainerFactory.java index 8f5f7ee..64e955c 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/TransmitterContainerFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/TransmitterContainerFactory.java @@ -8,6 +8,10 @@ import io.github.fa4nir.core.factories.types.AnnotationTransferFactory; import io.github.fa4nir.core.factories.types.TransmitterAbstractClassFactory; import io.github.fa4nir.core.factories.types.TransmitterInterfaceFactory; +import io.github.fa4nir.core.wrappers.BodyMethodBaseWrapper; +import io.github.fa4nir.core.wrappers.OverrideMethodWrapper; +import io.github.fa4nir.core.wrappers.PredicateMethodWrapper; +import io.github.fa4nir.core.wrappers.TryCatchMethodBaseWrapper; public class TransmitterContainerFactory { @@ -20,11 +24,19 @@ public static AnnotationTransferFactory transmitterAbstractClassFactory() { } public static InterceptMethodFactory overridingMethodFactory() { - return new OverridingMethodsFactory(exceptionFallBackMethodFactory()); + return new OverridingMethodsFactory(tryCatchMethodBaseWrapper(), predicateWrapper()); } public static FallBackMethodFactory exceptionFallBackMethodFactory() { return new ExceptionFallBackMethodFactory(); } + public static OverrideMethodWrapper tryCatchMethodBaseWrapper() { + return new TryCatchMethodBaseWrapper(exceptionFallBackMethodFactory(), new BodyMethodBaseWrapper()); + } + + public static OverrideMethodWrapper predicateWrapper() { + return new PredicateMethodWrapper(new TryCatchMethodBaseWrapper(exceptionFallBackMethodFactory(), new BodyMethodBaseWrapper())); + } + } diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java index 8112ef7..34ade55 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java @@ -1,16 +1,12 @@ package io.github.fa4nir.core.factories.methods; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterizedTypeName; import io.github.fa4nir.core.annotations.FallBackMethod; import io.github.fa4nir.core.annotations.FetchParam; import io.github.fa4nir.core.annotations.NotifyTo; -import io.github.fa4nir.core.definitions.DelegateMethodsDefinitionBuilder; import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; import io.github.fa4nir.core.definitions.OverridingMethodsDefinitionBuilder; -import io.github.fa4nir.core.factories.fallbacks.FallBackMethodFactory; +import io.github.fa4nir.core.wrappers.OverrideMethodWrapper; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; @@ -22,10 +18,13 @@ public class OverridingMethodsFactory implements InterceptMethodFactory { - private final FallBackMethodFactory fallBackMethodFactory; + private final OverrideMethodWrapper tryCatchMethodBaseWrapper; - public OverridingMethodsFactory(FallBackMethodFactory fallBackMethodFactory) { - this.fallBackMethodFactory = fallBackMethodFactory; + private final OverrideMethodWrapper predicateWrapper; + + public OverridingMethodsFactory(OverrideMethodWrapper tryCatchMethodBaseWrapper, OverrideMethodWrapper predicateWrapper) { + this.tryCatchMethodBaseWrapper = tryCatchMethodBaseWrapper; + this.predicateWrapper = predicateWrapper; } @Override @@ -38,52 +37,22 @@ public MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target) .sourceMethod(sourceMethod).target(target).annotationNotifyTo(annotationNotifyTo) .annotationFallBackMethod(annotationFallBackMethod).notifyToTarget().targetMethods().sourceParameters() .groupOfSourceParameters().targetFieldName().targetMethod() - .resultName().delegateResultToAnnotations().fallBackMethod().targetMethodReturnType() - .targetParameters().predicateMethods().fallBackMethodName() + .resultName().delegateResultToAnnotations().fallBackMethodName() + .fallBackMethod().targetMethodReturnType() + .targetParameters().predicateMethods() .build(); - if (definition.getPredicateMethods().size() > 0) { - ExecutableElement predicate = definition.getPredicateMethods().get(0); - String predicateSimpleName = predicate.getSimpleName().toString(); - List predicateParameters = predicate.getParameters(); - String strPredicateParameters = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), predicateParameters); - builder.beginControlFlow("if(this.$N.$N($N))", definition.getTargetFieldName(), predicateSimpleName, strPredicateParameters); - return decorateMethodSpec(definition, builder) - .endControlFlow() + String parametersAsString = parametersAsString(definition.getSourceParameters(), + definition.getGroupOfSourceParameters(), + definition.getTargetParameters()); + if (definition.isPredicateMethodsSize()) { + return this.predicateWrapper.wrap(parametersAsString, definition, builder) .build(); } - return decorateMethodSpec(definition, builder).build(); + return this.tryCatchMethodBaseWrapper.wrap(parametersAsString, definition, builder).build(); } return MethodSpec.overriding(sourceMethod).build(); } - private MethodSpec.Builder decorateMethodSpec(OverridingMethodsDefinition definition, - MethodSpec.Builder builder) { - builder.beginControlFlow("try"); - String parametersAsString = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), definition.getTargetParameters()); - if (Objects.nonNull(definition.getDelegateResultToAnnotations()) && definition.getDelegateResultToAnnotations().length > 0) { - builder.addStatement("$T $N = this.$N.$N($N)", ParameterizedTypeName.get(definition.getTargetMethodReturnType()), definition.getResultName(), - definition.getTargetFieldName(), definition.getTargetMethod().getSimpleName().toString(), parametersAsString); - List callsToDelegateMethods = DelegateMethodsDefinitionBuilder.newBuilder() - .setResultName(definition.getResultName()) - .setTargetEnclosedElements(definition.getTargetMethods()) - .setTargetFieldName(definition.getTargetFieldName()) - .setSourceParameters(definition.getSourceParameters()) - .setGroupOfSourceParameters(definition.getGroupOfSourceParameters()) - .setDelegateResultToAnnotations(definition.getDelegateResultToAnnotations()) - .build(); - callsToDelegateMethods.forEach(builder::addStatement); - } else { - builder.addStatement("this.$N.$N($N)", - definition.getTargetFieldName(), definition.getTargetMethod().getSimpleName().toString(), parametersAsString); - } - CodeBlock fallBackMethodAsString = this.fallBackMethodFactory - .newFallBackCodeBlock(definition.getFallBackMethod(), definition.getTargetFieldName(), definition.getSourceParameters()); - return builder - .nextControlFlow("catch($T e)", ClassName.get(Exception.class)) - .addCode(fallBackMethodAsString) - .endControlFlow(); - } - private String parametersAsString(List targetParameters, Map groupOfSourceParameters, List parameters) { diff --git a/core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java b/core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java new file mode 100644 index 0000000..67eb22d --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java @@ -0,0 +1,35 @@ +package io.github.fa4nir.core.wrappers; + +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import io.github.fa4nir.core.definitions.DelegateMethodsDefinitionBuilder; +import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; + +import java.util.List; +import java.util.Objects; + +public class BodyMethodBaseWrapper implements OverrideMethodWrapper { + + @Override + public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefinition definition, MethodSpec.Builder builder) { + if (Objects.nonNull(definition.getDelegateResultToAnnotations()) && definition.getDelegateResultToAnnotations().length > 0) { + builder.addStatement("$T $N = this.$N.$N($N)", ParameterizedTypeName.get(definition.getTargetMethodReturnType()), definition.getResultName(), + definition.getTargetFieldName(), definition.getTargetMethod().getSimpleName().toString(), parametersAsString); + List callsToDelegateMethods = DelegateMethodsDefinitionBuilder.newBuilder() + .setResultName(definition.getResultName()) + .setTargetEnclosedElements(definition.getTargetMethods()) + .setTargetFieldName(definition.getTargetFieldName()) + .setSourceParameters(definition.getSourceParameters()) + .setGroupOfSourceParameters(definition.getGroupOfSourceParameters()) + .setDelegateResultToAnnotations(definition.getDelegateResultToAnnotations()) + .build(); + callsToDelegateMethods.forEach(builder::addStatement); + } else { + builder.addStatement("this.$N.$N($N)", + definition.getTargetFieldName(), definition.getTargetMethod().getSimpleName().toString(), parametersAsString); + } + return builder; + } + +} diff --git a/core/src/main/java/io/github/fa4nir/core/wrappers/OverrideMethodWrapper.java b/core/src/main/java/io/github/fa4nir/core/wrappers/OverrideMethodWrapper.java new file mode 100644 index 0000000..30956be --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/wrappers/OverrideMethodWrapper.java @@ -0,0 +1,10 @@ +package io.github.fa4nir.core.wrappers; + +import com.squareup.javapoet.MethodSpec; +import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; + +public interface OverrideMethodWrapper { + + MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefinition definition, MethodSpec.Builder builder); + +} diff --git a/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java b/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java new file mode 100644 index 0000000..88cc940 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java @@ -0,0 +1,48 @@ +package io.github.fa4nir.core.wrappers; + +import com.squareup.javapoet.MethodSpec; +import io.github.fa4nir.core.annotations.FetchParam; +import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; +import io.github.fa4nir.core.factories.MethodParametersExtractor; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class PredicateMethodWrapper implements OverrideMethodWrapper, MethodParametersExtractor { + + private final OverrideMethodWrapper wrapper; + + public PredicateMethodWrapper(OverrideMethodWrapper wrapper) { + this.wrapper = wrapper; + } + + @Override + public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefinition definition, MethodSpec.Builder builder) { + if (definition.getPredicateMethods().size() > 0) { + ExecutableElement predicate = definition.getPredicateMethods().get(0); + String predicateSimpleName = predicate.getSimpleName().toString(); + List predicateParameters = predicate.getParameters(); + String strPredicateParameters = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), predicateParameters); + builder.beginControlFlow("if(this.$N.$N($N))", definition.getTargetFieldName(), predicateSimpleName, strPredicateParameters); + return this.wrapper.wrap(parametersAsString, definition, builder) + .endControlFlow(); + } + return this.wrapper.wrap(parametersAsString, definition, builder); + } + + private String parametersAsString(List targetParameters, + Map groupOfSourceParameters, + List parameters) { + return parameters.stream() + .map(parameter -> parameter.getAnnotation(FetchParam.class)) + .filter(Objects::nonNull) + .map(annotation -> getVariableElement(targetParameters, groupOfSourceParameters, annotation)) + .map(VariableElement::getSimpleName) + .collect(Collectors.joining(",")); + } + +} diff --git a/core/src/main/java/io/github/fa4nir/core/wrappers/TryCatchMethodBaseWrapper.java b/core/src/main/java/io/github/fa4nir/core/wrappers/TryCatchMethodBaseWrapper.java new file mode 100644 index 0000000..b543d78 --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/wrappers/TryCatchMethodBaseWrapper.java @@ -0,0 +1,31 @@ +package io.github.fa4nir.core.wrappers; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.MethodSpec; +import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; +import io.github.fa4nir.core.factories.fallbacks.FallBackMethodFactory; + +public class TryCatchMethodBaseWrapper implements OverrideMethodWrapper { + + private final FallBackMethodFactory fallBackMethodFactory; + + private final OverrideMethodWrapper wrapper; + + public TryCatchMethodBaseWrapper(FallBackMethodFactory fallBackMethodFactory, OverrideMethodWrapper wrapper) { + this.fallBackMethodFactory = fallBackMethodFactory; + this.wrapper = wrapper; + } + + @Override + public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefinition definition, MethodSpec.Builder builder) { + builder.beginControlFlow("try"); + CodeBlock fallBackMethodAsString = this.fallBackMethodFactory + .newFallBackCodeBlock(definition.getFallBackMethod(), definition.getTargetFieldName(), definition.getSourceParameters()); + return this.wrapper.wrap(parametersAsString, definition, builder) + .nextControlFlow("catch($T e)", ClassName.get(Exception.class)) + .addCode(fallBackMethodAsString) + .endControlFlow(); + } + +} From 94f49f566b2ff12cfcfc8cce83723c1e7c9e650b Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 15:32:20 +0200 Subject: [PATCH 03/12] update override method factory --- .../methods/OverridingMethodsFactory.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java index 34ade55..5d0b429 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java @@ -41,14 +41,16 @@ public MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target) .fallBackMethod().targetMethodReturnType() .targetParameters().predicateMethods() .build(); - String parametersAsString = parametersAsString(definition.getSourceParameters(), + String parametersAsString = parametersAsString( + definition.getSourceParameters(), definition.getGroupOfSourceParameters(), - definition.getTargetParameters()); - if (definition.isPredicateMethodsSize()) { - return this.predicateWrapper.wrap(parametersAsString, definition, builder) - .build(); - } - return this.tryCatchMethodBaseWrapper.wrap(parametersAsString, definition, builder).build(); + definition.getTargetParameters() + ); + return definition.isPredicateMethodsSize() ? + this.predicateWrapper.wrap(parametersAsString, definition, builder) + .build() : + this.tryCatchMethodBaseWrapper.wrap(parametersAsString, definition, builder) + .build(); } return MethodSpec.overriding(sourceMethod).build(); } From 598ae9243fa8c8eb250f6483b8bdde9669e2a724 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 15:40:51 +0200 Subject: [PATCH 04/12] remove useless class --- .../methods/InterceptMethodsContainer.java | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java deleted file mode 100644 index 9659912..0000000 --- a/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodsContainer.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.fa4nir.core.factories.methods; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -public class InterceptMethodsContainer { - - private static InterceptMethodsContainer instance = null; - - private final Map interceptMethod; - - private InterceptMethodsContainer() { - this.interceptMethod = new ConcurrentHashMap<>(); - } - - public static InterceptMethodsContainer getInstance() { - if (Objects.isNull(instance)) { - instance = new InterceptMethodsContainer(); - } - return instance; - } - - public void put(String key, InterceptMethodFactory value) { - this.interceptMethod.put(key, value); - } - - public InterceptMethodFactory get(String key) { - return this.interceptMethod.get(key); - } - -} From 97530ae710499982ee40d0c2f3abb1c81745d0e3 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 22:03:48 +0200 Subject: [PATCH 05/12] create ParametersUtils and remove useless interface --- .../DefaultOverridingMethodsDefinition.java | 3 +- .../DelegateMethodsDefinition.java | 10 ++- .../factories/MethodParametersExtractor.java | 25 -------- .../ExceptionFallBackMethodFactory.java | 3 +- .../fallbacks/FallBackMethodFactory.java | 3 +- .../methods/InterceptMethodFactory.java | 3 +- .../methods/OverridingMethodsFactory.java | 21 ++----- .../fa4nir/core/utils/ParametersUtils.java | 38 ++++++++++++ .../core/wrappers/PredicateMethodWrapper.java | 62 +++++++------------ 9 files changed, 78 insertions(+), 90 deletions(-) delete mode 100644 core/src/main/java/io/github/fa4nir/core/factories/MethodParametersExtractor.java create mode 100644 core/src/main/java/io/github/fa4nir/core/utils/ParametersUtils.java diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java index 8531d21..3377bb2 100644 --- a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java +++ b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java @@ -4,7 +4,6 @@ import io.github.fa4nir.core.annotations.FallBackMethod; import io.github.fa4nir.core.annotations.NotifyTo; import io.github.fa4nir.core.annotations.PayloadPredicate; -import io.github.fa4nir.core.factories.MethodParametersExtractor; import org.apache.commons.lang3.StringUtils; import javax.lang.model.element.Element; @@ -18,7 +17,7 @@ import java.util.function.Function; import java.util.stream.Collectors; -public class DefaultOverridingMethodsDefinition implements OverridingMethodsDefinitionBuilder, MethodParametersExtractor { +public class DefaultOverridingMethodsDefinition implements OverridingMethodsDefinitionBuilder { private ExecutableElement sourceMethod; diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/DelegateMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/DelegateMethodsDefinition.java index 71f2f3c..01b1089 100644 --- a/core/src/main/java/io/github/fa4nir/core/definitions/DelegateMethodsDefinition.java +++ b/core/src/main/java/io/github/fa4nir/core/definitions/DelegateMethodsDefinition.java @@ -4,7 +4,7 @@ import io.github.fa4nir.core.annotations.DelegateResultTo; import io.github.fa4nir.core.annotations.FetchParam; import io.github.fa4nir.core.annotations.FetchResult; -import io.github.fa4nir.core.factories.MethodParametersExtractor; +import io.github.fa4nir.core.utils.ParametersUtils; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; @@ -12,7 +12,7 @@ import java.util.*; import java.util.stream.Collectors; -public class DelegateMethodsDefinition implements DelegateMethodsDefinitionBuilder, MethodParametersExtractor { +public class DelegateMethodsDefinition implements DelegateMethodsDefinitionBuilder { private String resultName; @@ -106,7 +106,11 @@ private String retrieveLink(String resultName, if (Objects.nonNull(actualResult)) { return resultName; } else if (Objects.nonNull(fetchParam)) { - return getVariableElement(targetParameters, groupOfSourceParameters, fetchParam).getSimpleName().toString(); + return ParametersUtils.getVariableElement( + targetParameters, + groupOfSourceParameters, + fetchParam + ).getSimpleName().toString(); } return ""; } diff --git a/core/src/main/java/io/github/fa4nir/core/factories/MethodParametersExtractor.java b/core/src/main/java/io/github/fa4nir/core/factories/MethodParametersExtractor.java deleted file mode 100644 index c6a1107..0000000 --- a/core/src/main/java/io/github/fa4nir/core/factories/MethodParametersExtractor.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.fa4nir.core.factories; - -import io.github.fa4nir.core.annotations.FetchParam; -import org.apache.commons.lang3.StringUtils; - -import javax.lang.model.element.VariableElement; -import java.util.List; -import java.util.Map; - -public interface MethodParametersExtractor { - - default VariableElement getVariableElement(List targetParameters, - Map groupOfSourceParameters, - FetchParam annotation) { - String name = annotation.name(); - int num = annotation.num(); - if (num != -1) { - return targetParameters.get(num); - } else if (StringUtils.isNoneBlank(name)) { - return groupOfSourceParameters.get(name); - } - throw new IllegalArgumentException("Cannot find parameter in annotation " + annotation.getClass()); - } - -} diff --git a/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/ExceptionFallBackMethodFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/ExceptionFallBackMethodFactory.java index 92a7c7f..da9e4c3 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/ExceptionFallBackMethodFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/ExceptionFallBackMethodFactory.java @@ -3,6 +3,7 @@ import com.squareup.javapoet.CodeBlock; import io.github.fa4nir.core.annotations.ErrorSignal; import io.github.fa4nir.core.annotations.FetchParam; +import io.github.fa4nir.core.utils.ParametersUtils; import org.apache.commons.lang3.StringUtils; import javax.lang.model.element.Element; @@ -51,7 +52,7 @@ private String getParameterName(List targetParameters if (Objects.nonNull(errorSignal)) { return "e"; } else if (Objects.nonNull(fetchParam)) { - return getVariableElement(targetParameters, groupOfSourceParameters, fetchParam) + return ParametersUtils.getVariableElement(targetParameters, groupOfSourceParameters, fetchParam) .getSimpleName().toString(); } else { return null; diff --git a/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/FallBackMethodFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/FallBackMethodFactory.java index f8f22d0..1a93a79 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/FallBackMethodFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/fallbacks/FallBackMethodFactory.java @@ -1,13 +1,12 @@ package io.github.fa4nir.core.factories.fallbacks; import com.squareup.javapoet.CodeBlock; -import io.github.fa4nir.core.factories.MethodParametersExtractor; import javax.lang.model.element.Element; import javax.lang.model.element.VariableElement; import java.util.List; -public interface FallBackMethodFactory extends MethodParametersExtractor { +public interface FallBackMethodFactory { CodeBlock newFallBackCodeBlock(Element fallBackMethod, String currentClassFieldName, List sourceParameters); diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodFactory.java index 53efec8..4240127 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/methods/InterceptMethodFactory.java @@ -1,12 +1,11 @@ package io.github.fa4nir.core.factories.methods; import com.squareup.javapoet.MethodSpec; -import io.github.fa4nir.core.factories.MethodParametersExtractor; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -public interface InterceptMethodFactory extends MethodParametersExtractor { +public interface InterceptMethodFactory { MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target); diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java index 5d0b429..1f5753d 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java @@ -2,7 +2,6 @@ import com.squareup.javapoet.MethodSpec; import io.github.fa4nir.core.annotations.FallBackMethod; -import io.github.fa4nir.core.annotations.FetchParam; import io.github.fa4nir.core.annotations.NotifyTo; import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; import io.github.fa4nir.core.definitions.OverridingMethodsDefinitionBuilder; @@ -10,11 +9,9 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import java.util.List; -import java.util.Map; import java.util.Objects; -import java.util.stream.Collectors; + +import static io.github.fa4nir.core.utils.ParametersUtils.parametersAsString; public class OverridingMethodsFactory implements InterceptMethodFactory { @@ -35,7 +32,8 @@ public MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target) MethodSpec.Builder builder = MethodSpec.overriding(sourceMethod); OverridingMethodsDefinition definition = OverridingMethodsDefinitionBuilder.newBuilder() .sourceMethod(sourceMethod).target(target).annotationNotifyTo(annotationNotifyTo) - .annotationFallBackMethod(annotationFallBackMethod).notifyToTarget().targetMethods().sourceParameters() + .annotationFallBackMethod(annotationFallBackMethod).notifyToTarget() + .targetMethods().sourceParameters() .groupOfSourceParameters().targetFieldName().targetMethod() .resultName().delegateResultToAnnotations().fallBackMethodName() .fallBackMethod().targetMethodReturnType() @@ -55,15 +53,4 @@ public MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target) return MethodSpec.overriding(sourceMethod).build(); } - private String parametersAsString(List targetParameters, - Map groupOfSourceParameters, - List parameters) { - return parameters.stream() - .map(parameter -> parameter.getAnnotation(FetchParam.class)) - .filter(Objects::nonNull) - .map(annotation -> getVariableElement(targetParameters, groupOfSourceParameters, annotation)) - .map(VariableElement::getSimpleName) - .collect(Collectors.joining(",")); - } - } diff --git a/core/src/main/java/io/github/fa4nir/core/utils/ParametersUtils.java b/core/src/main/java/io/github/fa4nir/core/utils/ParametersUtils.java new file mode 100644 index 0000000..6fbfbfd --- /dev/null +++ b/core/src/main/java/io/github/fa4nir/core/utils/ParametersUtils.java @@ -0,0 +1,38 @@ +package io.github.fa4nir.core.utils; + +import io.github.fa4nir.core.annotations.FetchParam; +import org.apache.commons.lang3.StringUtils; + +import javax.lang.model.element.VariableElement; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class ParametersUtils { + + public static String parametersAsString(List targetParameters, + Map groupOfSourceParameters, + List parameters) { + return parameters.stream() + .map(parameter -> parameter.getAnnotation(FetchParam.class)) + .filter(Objects::nonNull) + .map(annotation -> getVariableElement(targetParameters, groupOfSourceParameters, annotation)) + .map(VariableElement::getSimpleName) + .collect(Collectors.joining(",")); + } + + public static VariableElement getVariableElement(List targetParameters, + Map groupOfSourceParameters, + FetchParam annotation) { + String name = annotation.name(); + int num = annotation.num(); + if (num != -1) { + return targetParameters.get(num); + } else if (StringUtils.isNoneBlank(name)) { + return groupOfSourceParameters.get(name); + } + throw new IllegalArgumentException("Cannot find parameter in annotation " + annotation.getClass()); + } + +} diff --git a/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java b/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java index 88cc940..231f81e 100644 --- a/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java +++ b/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java @@ -1,48 +1,34 @@ package io.github.fa4nir.core.wrappers; import com.squareup.javapoet.MethodSpec; -import io.github.fa4nir.core.annotations.FetchParam; import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; -import io.github.fa4nir.core.factories.MethodParametersExtractor; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -public class PredicateMethodWrapper implements OverrideMethodWrapper, MethodParametersExtractor { - - private final OverrideMethodWrapper wrapper; - - public PredicateMethodWrapper(OverrideMethodWrapper wrapper) { - this.wrapper = wrapper; - } - - @Override - public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefinition definition, MethodSpec.Builder builder) { - if (definition.getPredicateMethods().size() > 0) { - ExecutableElement predicate = definition.getPredicateMethods().get(0); - String predicateSimpleName = predicate.getSimpleName().toString(); - List predicateParameters = predicate.getParameters(); - String strPredicateParameters = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), predicateParameters); - builder.beginControlFlow("if(this.$N.$N($N))", definition.getTargetFieldName(), predicateSimpleName, strPredicateParameters); - return this.wrapper.wrap(parametersAsString, definition, builder) - .endControlFlow(); - } - return this.wrapper.wrap(parametersAsString, definition, builder); - } - - private String parametersAsString(List targetParameters, - Map groupOfSourceParameters, - List parameters) { - return parameters.stream() - .map(parameter -> parameter.getAnnotation(FetchParam.class)) - .filter(Objects::nonNull) - .map(annotation -> getVariableElement(targetParameters, groupOfSourceParameters, annotation)) - .map(VariableElement::getSimpleName) - .collect(Collectors.joining(",")); - } + +import static io.github.fa4nir.core.utils.ParametersUtils.parametersAsString; + +public class PredicateMethodWrapper implements OverrideMethodWrapper { + + private final OverrideMethodWrapper wrapper; + + public PredicateMethodWrapper(OverrideMethodWrapper wrapper) { + this.wrapper = wrapper; + } + + @Override + public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefinition definition, MethodSpec.Builder builder) { + if (definition.getPredicateMethods().size() > 0) { + ExecutableElement predicate = definition.getPredicateMethods().get(0); + String predicateSimpleName = predicate.getSimpleName().toString(); + List predicateParameters = predicate.getParameters(); + String predicateParametersAsString = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), predicateParameters); + builder.beginControlFlow("if(this.$N.$N($N))", definition.getTargetFieldName(), predicateSimpleName, predicateParametersAsString); + return this.wrapper.wrap(parametersAsString, definition, builder) + .endControlFlow(); + } + return this.wrapper.wrap(parametersAsString, definition, builder); + } } From daf161eed3b6d9ee863505f4c8802ef669c1baa6 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 22:09:10 +0200 Subject: [PATCH 06/12] add validation to predicate method --- .../definitions/DefaultOverridingMethodsDefinition.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java index 3377bb2..8d43237 100644 --- a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java +++ b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java @@ -9,6 +9,7 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import java.beans.Introspector; import java.util.List; @@ -169,6 +170,11 @@ public OverridingMethodsDefinitionBuilder predicateMethods() { .collect(Collectors.toList()); if (this.predicateMethods.size() > 1) { throw new IllegalArgumentException("Only one predicate method."); + } else if (this.predicateMethods.size() == 1) { + TypeMirror type = this.predicateMethods.get(0).getReturnType(); + if (!TypeKind.BOOLEAN.equals(type.getKind())) { + throw new IllegalArgumentException("Method predicate should return boolean"); + } } return this; } From 74705fed05b9ed0fb60c2d13f0a75cf7eba322b8 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 22:12:20 +0200 Subject: [PATCH 07/12] refactoring definition --- .../DefaultOverridingMethodsDefinition.java | 288 ------------------ .../OverridingMethodsDefinition.java | 36 +-- .../OverridingMethodsDefinitionBuilder.java | 281 +++++++++++++++++ 3 files changed, 299 insertions(+), 306 deletions(-) delete mode 100644 core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java deleted file mode 100644 index 8d43237..0000000 --- a/core/src/main/java/io/github/fa4nir/core/definitions/DefaultOverridingMethodsDefinition.java +++ /dev/null @@ -1,288 +0,0 @@ -package io.github.fa4nir.core.definitions; - -import io.github.fa4nir.core.annotations.DelegateResultTo; -import io.github.fa4nir.core.annotations.FallBackMethod; -import io.github.fa4nir.core.annotations.NotifyTo; -import io.github.fa4nir.core.annotations.PayloadPredicate; -import org.apache.commons.lang3.StringUtils; - -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import java.beans.Introspector; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class DefaultOverridingMethodsDefinition implements OverridingMethodsDefinitionBuilder { - - private ExecutableElement sourceMethod; - - private Element target; - - private NotifyTo annotationNotifyTo; - - private FallBackMethod annotationFallBackMethod; - - private List targetMethods; - - private List sourceParameters; - - private Map groupOfSourceParameters; - - private String targetFieldName; - - private ExecutableElement targetMethod; - - private String resultName; - - private DelegateResultTo[] delegateResultToAnnotations; - - private ExecutableElement fallBackMethod; - - private TypeMirror targetMethodReturnType; - - private List targetParameters; - - private List predicateMethods; - - private String notifyToTarget; - - private String fallBackMethodName; - - DefaultOverridingMethodsDefinition() { - } - - private String createResultName(List sourceParameters, ExecutableElement targetMethod) { - String resultName = "result"; - boolean isResultMatch = sourceParameters.stream().anyMatch(param -> param.getSimpleName().toString().equals("result")); - if (isResultMatch) { - resultName = String.format("%sFrom%s", resultName, StringUtils.capitalize(targetMethod.getSimpleName().toString())); - } - return resultName; - } - - private ExecutableElement findMethod(Element target, String name) { - return target.getEnclosedElements().stream() - .filter(method -> method instanceof ExecutableElement) - .map(method -> (ExecutableElement) method) - .filter(method -> method.getSimpleName().toString().equals(name)) - .findFirst().orElse(null); - } - - @Override - public OverridingMethodsDefinitionBuilder sourceMethod(ExecutableElement sourceMethod) { - this.sourceMethod = sourceMethod; - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder target(Element target) { - this.target = target; - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder annotationNotifyTo(NotifyTo annotationNotifyTo) { - this.annotationNotifyTo = annotationNotifyTo; - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder annotationFallBackMethod(FallBackMethod annotationFallBackMethod) { - this.annotationFallBackMethod = annotationFallBackMethod; - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder targetMethods() { - this.targetMethods = this.target.getEnclosedElements(); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder sourceParameters() { - this.sourceParameters = this.sourceMethod.getParameters(); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder groupOfSourceParameters() { - this.groupOfSourceParameters = this.sourceParameters.stream() - .collect(Collectors.toMap(k -> k.getSimpleName().toString(), Function.identity())); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder targetFieldName() { - this.targetFieldName = Introspector.decapitalize(this.target.getSimpleName().toString()); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder targetMethod() { - this.targetMethod = findMethod(this.target, this.notifyToTarget); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder resultName() { - this.resultName = createResultName(this.sourceParameters, this.targetMethod); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder delegateResultToAnnotations() { - this.delegateResultToAnnotations = this.targetMethod.getAnnotationsByType(DelegateResultTo.class); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder fallBackMethod() { - this.fallBackMethod = findMethod(this.target, this.fallBackMethodName); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder targetMethodReturnType() { - this.targetMethodReturnType = this.targetMethod.getReturnType(); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder targetParameters() { - this.targetParameters = Objects.requireNonNull( - this.targetMethod, String.format("Cannot find method %s", this.targetMethod.getSimpleName()) - ).getParameters(); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder predicateMethods() { - this.predicateMethods = this.targetMethods.stream() - .filter(method -> method instanceof ExecutableElement) - .filter(method -> Objects.nonNull(method.getAnnotation(PayloadPredicate.class))) - .map(method -> ((ExecutableElement) method)) - .collect(Collectors.toList()); - if (this.predicateMethods.size() > 1) { - throw new IllegalArgumentException("Only one predicate method."); - } else if (this.predicateMethods.size() == 1) { - TypeMirror type = this.predicateMethods.get(0).getReturnType(); - if (!TypeKind.BOOLEAN.equals(type.getKind())) { - throw new IllegalArgumentException("Method predicate should return boolean"); - } - } - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder notifyToTarget() { - this.notifyToTarget = this.annotationNotifyTo.name(); - return this; - } - - @Override - public OverridingMethodsDefinitionBuilder fallBackMethodName() { - this.fallBackMethodName = Objects.nonNull(this.annotationFallBackMethod) ? this.annotationFallBackMethod.name() : ""; - return this; - } - - @Override - public OverridingMethodsDefinition build() { - return new OverridingMethodsDefinition() { - @Override - public ExecutableElement getSourceMethod() { - return sourceMethod; - } - - @Override - public Element getTarget() { - return target; - } - - @Override - public NotifyTo getAnnotationNotifyTo() { - return annotationNotifyTo; - } - - @Override - public FallBackMethod getAnnotationFallBackMethod() { - return annotationFallBackMethod; - } - - @Override - public List getTargetMethods() { - return targetMethods; - } - - @Override - public List getSourceParameters() { - return sourceParameters; - } - - @Override - public Map getGroupOfSourceParameters() { - return groupOfSourceParameters; - } - - @Override - public String getTargetFieldName() { - return targetFieldName; - } - - @Override - public ExecutableElement getTargetMethod() { - return targetMethod; - } - - @Override - public String getResultName() { - return resultName; - } - - @Override - public DelegateResultTo[] getDelegateResultToAnnotations() { - return delegateResultToAnnotations; - } - - @Override - public ExecutableElement getFallBackMethod() { - return fallBackMethod; - } - - @Override - public TypeMirror getTargetMethodReturnType() { - return targetMethodReturnType; - } - - @Override - public List getTargetParameters() { - return targetParameters; - } - - @Override - public List getPredicateMethods() { - return predicateMethods; - } - - @Override - public String getNotifyToTarget() { - return notifyToTarget; - } - - @Override - public String getFallBackMethodName() { - return fallBackMethodName; - } - - @Override - public boolean isPredicateMethodsSize() { - return predicateMethods.size() == 1; - } - }; - } -} diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java index 3dc6775..4a4bc82 100644 --- a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java +++ b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinition.java @@ -13,40 +13,40 @@ public interface OverridingMethodsDefinition { - ExecutableElement getSourceMethod(); + ExecutableElement getSourceMethod(); - Element getTarget(); + Element getTarget(); - NotifyTo getAnnotationNotifyTo(); + NotifyTo getAnnotationNotifyTo(); - FallBackMethod getAnnotationFallBackMethod(); + FallBackMethod getAnnotationFallBackMethod(); - List getTargetMethods(); + List getTargetMethods(); - List getSourceParameters(); + List getSourceParameters(); - Map getGroupOfSourceParameters(); + Map getGroupOfSourceParameters(); - String getTargetFieldName(); + String getTargetFieldName(); - ExecutableElement getTargetMethod(); + ExecutableElement getTargetMethod(); - String getResultName(); + String getResultName(); - DelegateResultTo[] getDelegateResultToAnnotations(); + DelegateResultTo[] getDelegateResultToAnnotations(); - ExecutableElement getFallBackMethod(); + ExecutableElement getFallBackMethod(); - TypeMirror getTargetMethodReturnType(); + TypeMirror getTargetMethodReturnType(); - List getTargetParameters(); + List getTargetParameters(); - List getPredicateMethods(); + List getPredicateMethods(); - String getNotifyToTarget(); + String getNotifyToTarget(); - String getFallBackMethodName(); + String getFallBackMethodName(); - boolean isPredicateMethodsSize(); + boolean isPredicateMethodsSize(); } diff --git a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java index 3371665..d8f46c6 100644 --- a/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java +++ b/core/src/main/java/io/github/fa4nir/core/definitions/OverridingMethodsDefinitionBuilder.java @@ -1,10 +1,22 @@ package io.github.fa4nir.core.definitions; +import io.github.fa4nir.core.annotations.DelegateResultTo; import io.github.fa4nir.core.annotations.FallBackMethod; import io.github.fa4nir.core.annotations.NotifyTo; +import io.github.fa4nir.core.annotations.PayloadPredicate; +import org.apache.commons.lang3.StringUtils; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import java.beans.Introspector; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; public interface OverridingMethodsDefinitionBuilder { @@ -48,4 +60,273 @@ static OverridingMethodsDefinitionBuilder newBuilder() { OverridingMethodsDefinition build(); + class DefaultOverridingMethodsDefinition implements OverridingMethodsDefinitionBuilder { + + private ExecutableElement sourceMethod; + + private Element target; + + private NotifyTo annotationNotifyTo; + + private FallBackMethod annotationFallBackMethod; + + private List targetMethods; + + private List sourceParameters; + + private Map groupOfSourceParameters; + + private String targetFieldName; + + private ExecutableElement targetMethod; + + private String resultName; + + private DelegateResultTo[] delegateResultToAnnotations; + + private ExecutableElement fallBackMethod; + + private TypeMirror targetMethodReturnType; + + private List targetParameters; + + private List predicateMethods; + + private String notifyToTarget; + + private String fallBackMethodName; + + DefaultOverridingMethodsDefinition() { + } + + private String createResultName(List sourceParameters, ExecutableElement targetMethod) { + String resultName = "result"; + boolean isResultMatch = sourceParameters.stream().anyMatch(param -> param.getSimpleName().toString().equals("result")); + if (isResultMatch) { + resultName = String.format("%sFrom%s", resultName, StringUtils.capitalize(targetMethod.getSimpleName().toString())); + } + return resultName; + } + + private ExecutableElement findMethod(Element target, String name) { + return target.getEnclosedElements().stream() + .filter(method -> method instanceof ExecutableElement) + .map(method -> (ExecutableElement) method) + .filter(method -> method.getSimpleName().toString().equals(name)) + .findFirst().orElse(null); + } + + @Override + public OverridingMethodsDefinitionBuilder sourceMethod(ExecutableElement sourceMethod) { + this.sourceMethod = sourceMethod; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder target(Element target) { + this.target = target; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder annotationNotifyTo(NotifyTo annotationNotifyTo) { + this.annotationNotifyTo = annotationNotifyTo; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder annotationFallBackMethod(FallBackMethod annotationFallBackMethod) { + this.annotationFallBackMethod = annotationFallBackMethod; + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetMethods() { + this.targetMethods = this.target.getEnclosedElements(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder sourceParameters() { + this.sourceParameters = this.sourceMethod.getParameters(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder groupOfSourceParameters() { + this.groupOfSourceParameters = this.sourceParameters.stream() + .collect(Collectors.toMap(k -> k.getSimpleName().toString(), Function.identity())); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetFieldName() { + this.targetFieldName = Introspector.decapitalize(this.target.getSimpleName().toString()); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetMethod() { + this.targetMethod = findMethod(this.target, this.notifyToTarget); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder resultName() { + this.resultName = createResultName(this.sourceParameters, this.targetMethod); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder delegateResultToAnnotations() { + this.delegateResultToAnnotations = this.targetMethod.getAnnotationsByType(DelegateResultTo.class); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder fallBackMethod() { + this.fallBackMethod = findMethod(this.target, this.fallBackMethodName); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetMethodReturnType() { + this.targetMethodReturnType = this.targetMethod.getReturnType(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder targetParameters() { + this.targetParameters = Objects.requireNonNull( + this.targetMethod, String.format("Cannot find method %s", this.targetMethod.getSimpleName()) + ).getParameters(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder predicateMethods() { + this.predicateMethods = this.targetMethods.stream() + .filter(method -> method instanceof ExecutableElement) + .filter(method -> Objects.nonNull(method.getAnnotation(PayloadPredicate.class))) + .map(method -> ((ExecutableElement) method)) + .collect(Collectors.toList()); + if (this.predicateMethods.size() > 1) { + throw new IllegalArgumentException("Only one predicate method."); + } else if (this.predicateMethods.size() == 1) { + TypeMirror type = this.predicateMethods.get(0).getReturnType(); + if (!TypeKind.BOOLEAN.equals(type.getKind())) { + throw new IllegalArgumentException("Method predicate should return boolean"); + } + } + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder notifyToTarget() { + this.notifyToTarget = this.annotationNotifyTo.name(); + return this; + } + + @Override + public OverridingMethodsDefinitionBuilder fallBackMethodName() { + this.fallBackMethodName = Objects.nonNull(this.annotationFallBackMethod) ? this.annotationFallBackMethod.name() : ""; + return this; + } + + @Override + public OverridingMethodsDefinition build() { + return new OverridingMethodsDefinition() { + @Override + public ExecutableElement getSourceMethod() { + return sourceMethod; + } + + @Override + public Element getTarget() { + return target; + } + + @Override + public NotifyTo getAnnotationNotifyTo() { + return annotationNotifyTo; + } + + @Override + public FallBackMethod getAnnotationFallBackMethod() { + return annotationFallBackMethod; + } + + @Override + public List getTargetMethods() { + return targetMethods; + } + + @Override + public List getSourceParameters() { + return sourceParameters; + } + + @Override + public Map getGroupOfSourceParameters() { + return groupOfSourceParameters; + } + + @Override + public String getTargetFieldName() { + return targetFieldName; + } + + @Override + public ExecutableElement getTargetMethod() { + return targetMethod; + } + + @Override + public String getResultName() { + return resultName; + } + + @Override + public DelegateResultTo[] getDelegateResultToAnnotations() { + return delegateResultToAnnotations; + } + + @Override + public ExecutableElement getFallBackMethod() { + return fallBackMethod; + } + + @Override + public TypeMirror getTargetMethodReturnType() { + return targetMethodReturnType; + } + + @Override + public List getTargetParameters() { + return targetParameters; + } + + @Override + public List getPredicateMethods() { + return predicateMethods; + } + + @Override + public String getNotifyToTarget() { + return notifyToTarget; + } + + @Override + public String getFallBackMethodName() { + return fallBackMethodName; + } + + @Override + public boolean isPredicateMethodsSize() { + return predicateMethods.size() == 1; + } + }; + } + } + } From 8621e39b6c52d402a848b955079ebec122cbd146 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Sun, 12 Mar 2023 22:21:03 +0200 Subject: [PATCH 08/12] refactoring BodyMethodBaseWrapper, OverridingMethodsFactory --- .../methods/OverridingMethodsFactory.java | 25 ++++++++++++------- .../core/wrappers/BodyMethodBaseWrapper.java | 20 +++++++++------ 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java index 1f5753d..18fb3cf 100644 --- a/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java +++ b/core/src/main/java/io/github/fa4nir/core/factories/methods/OverridingMethodsFactory.java @@ -30,15 +30,9 @@ public MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target) FallBackMethod annotationFallBackMethod = sourceMethod.getAnnotation(FallBackMethod.class); if (Objects.nonNull(annotationNotifyTo)) { MethodSpec.Builder builder = MethodSpec.overriding(sourceMethod); - OverridingMethodsDefinition definition = OverridingMethodsDefinitionBuilder.newBuilder() - .sourceMethod(sourceMethod).target(target).annotationNotifyTo(annotationNotifyTo) - .annotationFallBackMethod(annotationFallBackMethod).notifyToTarget() - .targetMethods().sourceParameters() - .groupOfSourceParameters().targetFieldName().targetMethod() - .resultName().delegateResultToAnnotations().fallBackMethodName() - .fallBackMethod().targetMethodReturnType() - .targetParameters().predicateMethods() - .build(); + OverridingMethodsDefinition definition = ofDefinitions( + sourceMethod, target, annotationNotifyTo, annotationFallBackMethod + ); String parametersAsString = parametersAsString( definition.getSourceParameters(), definition.getGroupOfSourceParameters(), @@ -53,4 +47,17 @@ public MethodSpec newMethodSpec(ExecutableElement sourceMethod, Element target) return MethodSpec.overriding(sourceMethod).build(); } + private OverridingMethodsDefinition ofDefinitions(ExecutableElement sourceMethod, Element target, + NotifyTo annotationNotifyTo, FallBackMethod annotationFallBackMethod) { + return OverridingMethodsDefinitionBuilder.newBuilder() + .sourceMethod(sourceMethod).target(target).annotationNotifyTo(annotationNotifyTo) + .annotationFallBackMethod(annotationFallBackMethod).notifyToTarget() + .targetMethods().sourceParameters() + .groupOfSourceParameters().targetFieldName().targetMethod() + .resultName().delegateResultToAnnotations().fallBackMethodName() + .fallBackMethod().targetMethodReturnType() + .targetParameters().predicateMethods() + .build(); + } + } diff --git a/core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java b/core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java index 67eb22d..5a26659 100644 --- a/core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java +++ b/core/src/main/java/io/github/fa4nir/core/wrappers/BodyMethodBaseWrapper.java @@ -16,14 +16,7 @@ public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefin if (Objects.nonNull(definition.getDelegateResultToAnnotations()) && definition.getDelegateResultToAnnotations().length > 0) { builder.addStatement("$T $N = this.$N.$N($N)", ParameterizedTypeName.get(definition.getTargetMethodReturnType()), definition.getResultName(), definition.getTargetFieldName(), definition.getTargetMethod().getSimpleName().toString(), parametersAsString); - List callsToDelegateMethods = DelegateMethodsDefinitionBuilder.newBuilder() - .setResultName(definition.getResultName()) - .setTargetEnclosedElements(definition.getTargetMethods()) - .setTargetFieldName(definition.getTargetFieldName()) - .setSourceParameters(definition.getSourceParameters()) - .setGroupOfSourceParameters(definition.getGroupOfSourceParameters()) - .setDelegateResultToAnnotations(definition.getDelegateResultToAnnotations()) - .build(); + List callsToDelegateMethods = ofDelegateDefinitions(definition); callsToDelegateMethods.forEach(builder::addStatement); } else { builder.addStatement("this.$N.$N($N)", @@ -32,4 +25,15 @@ public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefin return builder; } + private List ofDelegateDefinitions(OverridingMethodsDefinition definition) { + return DelegateMethodsDefinitionBuilder.newBuilder() + .setResultName(definition.getResultName()) + .setTargetEnclosedElements(definition.getTargetMethods()) + .setTargetFieldName(definition.getTargetFieldName()) + .setSourceParameters(definition.getSourceParameters()) + .setGroupOfSourceParameters(definition.getGroupOfSourceParameters()) + .setDelegateResultToAnnotations(definition.getDelegateResultToAnnotations()) + .build(); + } + } From ed9ecc922c07ed60d9e0e1a808554bdcd5ed1afa Mon Sep 17 00:00:00 2001 From: hellcrow Date: Mon, 13 Mar 2023 21:03:26 +0200 Subject: [PATCH 09/12] add examples to README.md --- README.md | 221 +++++++++++++++++- .../fa4nir/examples/CustomListenerClass2.java | 2 +- 2 files changed, 220 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c428c01..e06e8de 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,226 @@ to listening your notifications. gradle :fa4nir-test:test ``` -## Dependencies +## Dependencies ``` implementation 'io.github.fa4nir:fa4nir:1.0.1' annotationProcessor 'io.github.fa4nir:fa4nir:1.0.1' -``` \ No newline at end of file +``` + +# Examples + +To define Transmitter, write interface and define `beanName` to named generated class and define `receiverName` to find +necessary receiver. Also you should override methods which need to use in receiver class and not necessary define as +default. Method which we want to use should have annotations ``` @NotifyTo and @FallBackMethod ``` +if necessary. + +```java + +@Transmitter(beanName = "CustomListenerImpl", receiverName = "custom-listener-receiver") +public interface TransmitterTemplate extends CustomListener { + @Override + @NotifyTo(name = "receiverMethod") + @FallBackMethod(name = "fallBackForReceiverMethod") + void onSuccess(String parameter0, + Integer parameter1, + List parameters2); + + @Override + default void onFailure(Throwable t) { + } + + @Override + default void onSuccess(String r) { + } + + @Override + default void onSuccess1(String parameter0, Double parameters2) { + } +} +``` + +The next step is provide receiver. On this stem You should annotate your class as `@Receiver` and define unique name for +it, define base method with name which we write in previous step `@NotifyTo(name = "receiverMethod")` and define +parameters use annotation `@FetchParam(num = 0)` where num is index in base method parameters also you can use name to +find parameters by name. and if you use annotation `@FallBackMethod(name = "fallBackForReceiverMethod")` create method +fallback. You can delegate return statement to another methods to do +this `@DelegateResultTo(method = "delegatorAcceptor")` where put method name which should received result and can +receive parameters of base method too. Result should be mapped as `@FetchResult`. + +```java + +@Receiver(name = "custom-listener-receiver") +public class ReceiverTemplate { + + private static final Logger log = Logger.getLogger(CustomListenerClass2.class.getName()); + + @DelegateResultTo(method = "delegatorAcceptor") + public Person receiverMethod(@FetchParam(num = 0) String name, @FetchParam(name = "parameters2") List payload) { + log.log(Level.INFO, "Enter: {0}, {1}", new Object[]{name, payload}); + return new Person(1L, "Mit9i", "mit9i@gmail.com"); + } + + public void delegatorAcceptor(@FetchResult Person person, + @FetchParam(num = 0) String name, + @FetchParam(num = 1) Integer payload) { + log.log(Level.INFO, "Message {0}, {1}, {2}", new Object[]{person, name, payload}); + } + + public void fallBackForReceiverMethod(@ErrorSignal Exception e, @FetchParam(num = 1) Integer number) { + log.log(Level.WARNING, "Message: {0}, {1}", new Object[]{e.getMessage(), number}); + } + +} + +``` + +Generated code: + +```java +package io.github.fa4nir.examples.impl; + +import io.github.fa4nir.examples.CustomListenerClass2; +import io.github.fa4nir.examples.Person; + +import java.lang.Exception; +import java.lang.Integer; +import java.lang.Override; +import java.lang.String; +import java.util.List; + +public class CustomListenerImpl implements CustomListener { + private final ReceiverTemplate receiverTemplate; + + public CustomListenerCase2(ReceiverTemplate receiverTemplate) { + this.receiverTemplate = receiverTemplate; + } + + @Override + public void onSuccess(String parameter0, Integer parameter1, List parameters2) { + try { + Person result = this.receiverTemplate.receiverMethod(parameter0, parameters2); + this.receiverTemplate.delegatorAcceptor(result, parameter0, parameter1); + } catch (Exception e) { + this.receiverTemplate.fallBackForReceiverMethod(e, parameter1); + } + } + + // Start block_1 + @Override + void onFailure(Throwable t) { + } + + @Override + void onSuccess(String r) { + } + + @Override + void onSuccess1(String parameter0, Double parameters2) { + } + // End block_1 + +} +``` + +But if you can see `block_1` is useless code, so remove it. To do this +`@Transmitter(beanName = "CustomListenerImpl", receiverName = "custom-listener-receiver", isSupper=false)` +use this `isSupper` and set false to it. + +Generated code: + +`Tip: because default methods` + +```java +package io.github.fa4nir.examples.impl; + +import io.github.fa4nir.examples.CustomListenerClass2; +import io.github.fa4nir.examples.Person; + +import java.lang.Exception; +import java.lang.Integer; +import java.lang.Override; +import java.lang.String; +import java.util.List; + +public class CustomListenerImpl implements TransmitterTemplate { + private final ReceiverTemplate receiverTemplate; + + public CustomListenerCase2(ReceiverTemplate receiverTemplate) { + this.receiverTemplate = receiverTemplate; + } + + @Override + public void onSuccess(String parameter0, Integer parameter1, List parameters2) { + try { + Person result = this.receiverTemplate.receiverMethod(parameter0, parameters2); + this.receiverTemplate.delegatorAcceptor(result, parameter0, parameter1); + } catch (Exception e) { + this.receiverTemplate.fallBackForReceiverMethod(e, parameter1); + } + } +} +``` + +The next is method fallback: + +If you do not need parameters, define like this: + +```java + +@Receiver(name = "custom-listener-receiver") +public class ReceiverTemplate { + public void fallBackForReceiverMethod(Exception e) { + } + //... +} +``` + +If you need parameters, define like this: where annotation `@ErrorSignal` is required. + +```java + +@Receiver(name = "custom-listener-receiver") +public class ReceiverTemplate { + public void fallBackForReceiverMethod(@ErrorSignal Exception e, @FetchParam(name = "parameters1") Integer number) { + } + //... +} +``` + +Predicate (mark method as `@PayloadPredicate`, and required is method should return boolean) + +```java + +@Receiver(name = "ReceiverBase") +public class ReceiverWithNameReceivers { + + private static final Logger log = Logger.getLogger(ParametersWithNameReceivers.class.getName()); + + @PayloadPredicate + public boolean isPayloadNotNull(@FetchParam(name = "personName") String payload) { + return Objects.nonNull(payload); + } + //... +} +``` + +Example: + +```java + public class TransmitterWithNameInParameters implements ParametersWithNameTransmitter { + @Override + public void onSuccess1(String personName, Double personEight) { + // should be like this + if (this.parametersWithNameReceivers.isPayloadNotNull(personName)) { + try { + Person result = this.parametersWithNameReceivers.listenerWithParametersName(personName); + this.parametersWithNameReceivers.receivePersonWithName(result, personName); + this.parametersWithNameReceivers.receivePersonWithNameAndWeight(result, personEight); + } catch (Exception e) { + this.parametersWithNameReceivers.fallbackListenerWithParametersName(e, personName); + } + } + } +} +``` diff --git a/examples/src/main/java/io/github/fa4nir/examples/CustomListenerClass2.java b/examples/src/main/java/io/github/fa4nir/examples/CustomListenerClass2.java index 2c4e92c..88d05bc 100644 --- a/examples/src/main/java/io/github/fa4nir/examples/CustomListenerClass2.java +++ b/examples/src/main/java/io/github/fa4nir/examples/CustomListenerClass2.java @@ -27,7 +27,7 @@ public void fallBackForCustomListener(@ErrorSignal Exception e, @FetchParam(num log.log(Level.WARNING, "Message: {0}, {1}", new Object[]{e.getMessage(), number}); } - @Transmitter(beanName = "CustomListenerCase2", receiverName = "custom-listener-case-2", isSupper = false) + @Transmitter(beanName = "CustomListenerCase2", receiverName = "custom-listener-case-2") public interface TransmitterCase2Template extends Custom3 { @Override @NotifyTo(name = "customListener") From 837c75cbae9dc4b1e3826619fbd26bfdf4931698 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Mon, 13 Mar 2023 21:07:43 +0200 Subject: [PATCH 10/12] update README.md --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index e06e8de..02bf8a9 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,31 @@ public class ReceiverTemplate { } ``` +`@DelegateResultTo` can be used for any delegated methods: + +Example: + +```java + +@Receiver(name = "custom-listener-receiver") +public class ReceiverTemplate { + + private static final Logger log = Logger.getLogger(CustomListenerClass2.class.getName()); + + @DelegateResultTo(method = "delegatorAcceptor0") + @DelegateResultTo(method = "delegatorAcceptor1") + @DelegateResultTo(method = "delegatorAcceptor2") + //... any + public Person receiverMethod(@FetchParam(num = 0) String name, @FetchParam(name = "parameters2") List payload) { + log.log(Level.INFO, "Enter: {0}, {1}", new Object[]{name, payload}); + return new Person(1L, "Mit9i", "mit9i@gmail.com"); + } + + //... + +} +``` + Predicate (mark method as `@PayloadPredicate`, and required is method should return boolean) ```java From a1f2c3fd79aae4c6ba5e5b2a9404143ea268eac2 Mon Sep 17 00:00:00 2001 From: hellcrow Date: Wed, 15 Mar 2023 20:19:58 +0200 Subject: [PATCH 11/12] add tests to predicate method --- .../core/wrappers/PredicateMethodWrapper.java | 4 ++ .../fa4nir/TransmitterProcessorCases.java | 55 ++++++++++++++++++ .../test/resources/input/input-stub-10.java | 56 +++++++++++++++++++ .../test/resources/input/input-stub-10_1.java | 56 +++++++++++++++++++ .../test/resources/input/input-stub-10_2.java | 56 +++++++++++++++++++ .../test/resources/output/output-stub-10.java | 28 ++++++++++ .../output/output-stub-10_1.error.txt | 1 + .../output/output-stub-10_2.error.txt | 1 + 8 files changed, 257 insertions(+) create mode 100644 fa4nir-tests/src/test/resources/input/input-stub-10.java create mode 100644 fa4nir-tests/src/test/resources/input/input-stub-10_1.java create mode 100644 fa4nir-tests/src/test/resources/input/input-stub-10_2.java create mode 100644 fa4nir-tests/src/test/resources/output/output-stub-10.java create mode 100644 fa4nir-tests/src/test/resources/output/output-stub-10_1.error.txt create mode 100644 fa4nir-tests/src/test/resources/output/output-stub-10_2.error.txt diff --git a/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java b/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java index 231f81e..32295a6 100644 --- a/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java +++ b/core/src/main/java/io/github/fa4nir/core/wrappers/PredicateMethodWrapper.java @@ -2,6 +2,7 @@ import com.squareup.javapoet.MethodSpec; import io.github.fa4nir.core.definitions.OverridingMethodsDefinition; +import org.apache.commons.lang3.StringUtils; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; @@ -24,6 +25,9 @@ public MethodSpec.Builder wrap(String parametersAsString, OverridingMethodsDefin String predicateSimpleName = predicate.getSimpleName().toString(); List predicateParameters = predicate.getParameters(); String predicateParametersAsString = parametersAsString(definition.getSourceParameters(), definition.getGroupOfSourceParameters(), predicateParameters); + if (StringUtils.isBlank(predicateParametersAsString)) { + throw new IllegalArgumentException("Predicate mast contains any of parameters."); + } builder.beginControlFlow("if(this.$N.$N($N))", definition.getTargetFieldName(), predicateSimpleName, predicateParametersAsString); return this.wrapper.wrap(parametersAsString, definition, builder) .endControlFlow(); diff --git a/fa4nir-tests/src/test/java/io/github/fa4nir/TransmitterProcessorCases.java b/fa4nir-tests/src/test/java/io/github/fa4nir/TransmitterProcessorCases.java index 5cf7643..f977213 100644 --- a/fa4nir-tests/src/test/java/io/github/fa4nir/TransmitterProcessorCases.java +++ b/fa4nir-tests/src/test/java/io/github/fa4nir/TransmitterProcessorCases.java @@ -4,6 +4,7 @@ import com.google.testing.compile.JavaFileObjects; import com.google.testing.compile.JavaSourcesSubjectFactory; import io.github.fa4nir.processor.TransmitterProcessor; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import javax.tools.JavaFileObject; @@ -214,4 +215,58 @@ void givenInputAnnotationClass_whenRunProcessor_thenReceivedOutputFile_9() throw .generatesSources(output); } + @Test + void givenInputAnnotationClass_whenRunProcessor_thenReceivedOutputFile_10() throws URISyntaxException, IOException { + String inputFileName = "input/input-stub-10.java"; + String outputFileName = "output/output-stub-10.java"; + JavaFileObject input = JavaFileObjects.forSourceString( + "com.github.interceptors.CaseCustomListenerSpec", loadJavaFileAsString(inputFileName) + ); + JavaFileObject output = JavaFileObjects.forSourceString( + "com.github.interceptors.impl.TransmitterTemplateBeanCaseZeroImpl", loadJavaFileAsString(outputFileName) + ); + Truth.assert_() + .about(JavaSourcesSubjectFactory.javaSources()) + .that(List.of(input)) + .processedWith(new TransmitterProcessor()) + .compilesWithoutError() + .and() + .generatesSources(output); + } + + @Test + void givenInputAnnotationClass_whenRunProcessor_thenReceivedOutputFile_10_1() throws URISyntaxException, IOException { + String inputFileName = "input/input-stub-10_1.java"; + String outputFileName = "output/output-stub-10_1.error.txt"; + JavaFileObject input = JavaFileObjects.forSourceString( + "com.github.interceptors.CaseCustomListenerSpec", loadJavaFileAsString(inputFileName) + ); + String output = loadJavaFileAsString(outputFileName); + Assertions.assertThrows(RuntimeException.class, () -> { + Truth.assert_() + .about(JavaSourcesSubjectFactory.javaSources()) + .that(List.of(input)) + .processedWith(new TransmitterProcessor()) + .failsToCompile(); + }, output); + + } + + @Test + void givenInputAnnotationClass_whenRunProcessor_thenReceivedOutputFile_10_2() throws URISyntaxException, IOException { + String inputFileName = "input/input-stub-10_2.java"; + String outputFileName = "output/output-stub-10_2.error.txt"; + JavaFileObject input = JavaFileObjects.forSourceString( + "com.github.interceptors.CaseCustomListenerSpec", loadJavaFileAsString(inputFileName) + ); + String output = loadJavaFileAsString(outputFileName); + Assertions.assertThrows(RuntimeException.class, () -> { + Truth.assert_() + .about(JavaSourcesSubjectFactory.javaSources()) + .that(List.of(input)) + .processedWith(new TransmitterProcessor()) + .failsToCompile(); + }, output); + } + } diff --git a/fa4nir-tests/src/test/resources/input/input-stub-10.java b/fa4nir-tests/src/test/resources/input/input-stub-10.java new file mode 100644 index 0000000..0aba641 --- /dev/null +++ b/fa4nir-tests/src/test/resources/input/input-stub-10.java @@ -0,0 +1,56 @@ +package com.github.interceptors; + +import com.google.common.util.concurrent.FutureCallback; +import io.github.fa4nir.core.annotations.*; + +import java.util.Objects; + +@Receiver(name = "ReceiverCustomListenerId") +public class CaseCustomListenerSpec { + + @PayloadPredicate + public boolean isPayloadNotNull(@FetchParam(name = "result") String payload) { + return Objects.nonNull(payload); + } + + @DelegateResultTo(method = "delegatorAcceptor") + @DelegateResultTo(method = "supperDelegatorAcceptor") + public String customListener(@FetchParam(num = 0) String payload) { + return "test-string"; + } + + public void delegatorAcceptor(@FetchResult String payload) { + + } + + public void delegatorAcceptor(@FetchResult String payload, + @FetchParam(num = 0) Object param0) { + + } + + public void supperDelegatorAcceptor(@FetchParam(num = 0) Object param0, + @FetchResult String payload) { + + } + + public void fallBackForCustomListener(@ErrorSignal Exception e) { + + } + + @Transmitter( + beanName = "TransmitterTemplateBeanCaseZero", + receiverName = "ReceiverCustomListenerId", + isSupper = false + ) + public interface TransmitterTemplate extends FutureCallback { + @Override + @NotifyTo(name = "customListener") + @FallBackMethod(name = "fallBackForCustomListener") + void onSuccess(String result); + + @Override + default void onFailure(Throwable t) { + } + } + +} diff --git a/fa4nir-tests/src/test/resources/input/input-stub-10_1.java b/fa4nir-tests/src/test/resources/input/input-stub-10_1.java new file mode 100644 index 0000000..0c8156c --- /dev/null +++ b/fa4nir-tests/src/test/resources/input/input-stub-10_1.java @@ -0,0 +1,56 @@ +package com.github.interceptors; + +import com.google.common.util.concurrent.FutureCallback; +import io.github.fa4nir.core.annotations.*; + +import java.util.Objects; + +@Receiver(name = "ReceiverCustomListenerId") +public class CaseCustomListenerSpec { + + @PayloadPredicate + public String isPayloadNotNull(@FetchParam(name = "result") String payload) { + return payload; + } + + @DelegateResultTo(method = "delegatorAcceptor") + @DelegateResultTo(method = "supperDelegatorAcceptor") + public String customListener(@FetchParam(num = 0) String payload) { + return "test-string"; + } + + public void delegatorAcceptor(@FetchResult String payload) { + + } + + public void delegatorAcceptor(@FetchResult String payload, + @FetchParam(num = 0) Object param0) { + + } + + public void supperDelegatorAcceptor(@FetchParam(num = 0) Object param0, + @FetchResult String payload) { + + } + + public void fallBackForCustomListener(@ErrorSignal Exception e) { + + } + + @Transmitter( + beanName = "TransmitterTemplateBeanCaseZero", + receiverName = "ReceiverCustomListenerId", + isSupper = false + ) + public interface TransmitterTemplate extends FutureCallback { + @Override + @NotifyTo(name = "customListener") + @FallBackMethod(name = "fallBackForCustomListener") + void onSuccess(String result); + + @Override + default void onFailure(Throwable t) { + } + } + +} diff --git a/fa4nir-tests/src/test/resources/input/input-stub-10_2.java b/fa4nir-tests/src/test/resources/input/input-stub-10_2.java new file mode 100644 index 0000000..3dd9d07 --- /dev/null +++ b/fa4nir-tests/src/test/resources/input/input-stub-10_2.java @@ -0,0 +1,56 @@ +package com.github.interceptors; + +import com.google.common.util.concurrent.FutureCallback; +import io.github.fa4nir.core.annotations.*; + +import java.util.Objects; + +@Receiver(name = "ReceiverCustomListenerId") +public class CaseCustomListenerSpec { + + @PayloadPredicate + public boolean isPayloadNotNull() { + return Objects.nonNull(""); + } + + @DelegateResultTo(method = "delegatorAcceptor") + @DelegateResultTo(method = "supperDelegatorAcceptor") + public String customListener(@FetchParam(num = 0) String payload) { + return "test-string"; + } + + public void delegatorAcceptor(@FetchResult String payload) { + + } + + public void delegatorAcceptor(@FetchResult String payload, + @FetchParam(num = 0) Object param0) { + + } + + public void supperDelegatorAcceptor(@FetchParam(num = 0) Object param0, + @FetchResult String payload) { + + } + + public void fallBackForCustomListener(@ErrorSignal Exception e) { + + } + + @Transmitter( + beanName = "TransmitterTemplateBeanCaseZero", + receiverName = "ReceiverCustomListenerId", + isSupper = false + ) + public interface TransmitterTemplate extends FutureCallback { + @Override + @NotifyTo(name = "customListener") + @FallBackMethod(name = "fallBackForCustomListener") + void onSuccess(String result); + + @Override + default void onFailure(Throwable t) { + } + } + +} diff --git a/fa4nir-tests/src/test/resources/output/output-stub-10.java b/fa4nir-tests/src/test/resources/output/output-stub-10.java new file mode 100644 index 0000000..5da6291 --- /dev/null +++ b/fa4nir-tests/src/test/resources/output/output-stub-10.java @@ -0,0 +1,28 @@ +package com.github.interceptors.impl; + +import com.github.interceptors.CaseCustomListenerSpec; +import java.lang.Exception; +import java.lang.Override; +import java.lang.String; + +public class TransmitterTemplateBeanCaseZero implements CaseCustomListenerSpec.TransmitterTemplate { + private final CaseCustomListenerSpec caseCustomListenerSpec; + + public TransmitterTemplateBeanCaseZeroImpl(CaseCustomListenerSpec caseCustomListenerSpec) { + this.caseCustomListenerSpec = caseCustomListenerSpec; + } + + @Override + public void onSuccess(String result) { + if(this.caseCustomListenerSpec.isPayloadNotNull(result)) { + try { + String resultFromCustomListener = this.caseCustomListenerSpec.customListener(result); + this.caseCustomListenerSpec.delegatorAcceptor(resultFromCustomListener); + this.caseCustomListenerSpec.delegatorAcceptor(resultFromCustomListener, result); + this.caseCustomListenerSpec.supperDelegatorAcceptor(result, resultFromCustomListener); + } catch (Exception e) { + this.caseCustomListenerSpec.fallBackForCustomListener(e); + } + } + } +} diff --git a/fa4nir-tests/src/test/resources/output/output-stub-10_1.error.txt b/fa4nir-tests/src/test/resources/output/output-stub-10_1.error.txt new file mode 100644 index 0000000..65b3d6b --- /dev/null +++ b/fa4nir-tests/src/test/resources/output/output-stub-10_1.error.txt @@ -0,0 +1 @@ +Method predicate should return boolean \ No newline at end of file diff --git a/fa4nir-tests/src/test/resources/output/output-stub-10_2.error.txt b/fa4nir-tests/src/test/resources/output/output-stub-10_2.error.txt new file mode 100644 index 0000000..1024ba8 --- /dev/null +++ b/fa4nir-tests/src/test/resources/output/output-stub-10_2.error.txt @@ -0,0 +1 @@ +Predicate mast contains any of parameters. \ No newline at end of file From 8d4420368e2b13f9d8651e11be80d496e9a2cfca Mon Sep 17 00:00:00 2001 From: hellcrow Date: Wed, 15 Mar 2023 20:25:43 +0200 Subject: [PATCH 12/12] change version of project --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4bde7ec..b0a8e2e 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ allprojects { apply plugin: 'java-library' group = 'io.github.fa4nir' - version = '1.0.1' + version = '1.0.2' repositories { mavenCentral() @@ -119,7 +119,7 @@ publishing { groupId = 'io.github.fa4nir' artifactId = 'fa4nir' - version = '1.0.1' + version = '1.0.2' artifact(sourceJar) artifact(javadocJar)