This is an automated email from the ASF dual-hosted git repository. ibzib pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push: new b9f0538 [BEAM-10925] Move general-usage helper methods from DoFnSignatures to ReflectHelpers. new 019ebb5 Merge pull request #13304 from ibzib/reflect-helpers b9f0538 is described below commit b9f0538290375ab17ec3814e327c7c2a9dcc9a50 Author: Kyle Weaver <kcwea...@google.com> AuthorDate: Fri Oct 30 18:25:33 2020 -0700 [BEAM-10925] Move general-usage helper methods from DoFnSignatures to ReflectHelpers. --- .../sdk/transforms/reflect/DoFnSignatures.java | 77 ++++------------------ .../beam/sdk/util/common/ReflectHelpers.java | 60 +++++++++++++++++ 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnSignatures.java b/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnSignatures.java index 550b547..e730e8a 100644 --- a/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnSignatures.java +++ b/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnSignatures.java @@ -21,7 +21,6 @@ import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Prec import com.google.auto.value.AutoValue; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -33,7 +32,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -542,7 +540,7 @@ public class DoFnSignatures { findAnnotatedMethod(errors, DoFn.NewWatermarkEstimator.class, fnClass, false); Collection<Method> onTimerMethods = - declaredMethodsWithAnnotation(DoFn.OnTimer.class, fnClass, DoFn.class); + ReflectHelpers.declaredMethodsWithAnnotation(DoFn.OnTimer.class, fnClass, DoFn.class); HashMap<String, DoFnSignature.OnTimerMethod> onTimerMethodMap = Maps.newHashMapWithExpectedSize(onTimerMethods.size()); for (Method onTimerMethod : onTimerMethods) { @@ -569,7 +567,7 @@ public class DoFnSignatures { // Check for TimerFamily Collection<Method> onTimerFamilyMethods = - declaredMethodsWithAnnotation(DoFn.OnTimerFamily.class, fnClass, DoFn.class); + ReflectHelpers.declaredMethodsWithAnnotation(DoFn.OnTimerFamily.class, fnClass, DoFn.class); HashMap<String, DoFnSignature.OnTimerFamilyMethod> onTimerFamilyMethodMap = Maps.newHashMapWithExpectedSize(onTimerFamilyMethods.size()); @@ -1867,7 +1865,8 @@ public class DoFnSignatures { private static ImmutableMap<String, TimerFamilyDeclaration> analyzeTimerFamilyDeclarations( ErrorReporter errors, Class<?> fnClazz) { Map<String, TimerFamilyDeclaration> declarations = new HashMap<>(); - for (Field field : declaredFieldsWithAnnotation(DoFn.TimerFamily.class, fnClazz, DoFn.class)) { + for (Field field : + ReflectHelpers.declaredFieldsWithAnnotation(DoFn.TimerFamily.class, fnClazz, DoFn.class)) { // TimerSpec fields may generally be private, but will be accessed via the signature field.setAccessible(true); String id = @@ -1882,7 +1881,8 @@ public class DoFnSignatures { private static ImmutableMap<String, TimerDeclaration> analyzeTimerDeclarations( ErrorReporter errors, Class<?> fnClazz) { Map<String, DoFnSignature.TimerDeclaration> declarations = new HashMap<>(); - for (Field field : declaredFieldsWithAnnotation(DoFn.TimerId.class, fnClazz, DoFn.class)) { + for (Field field : + ReflectHelpers.declaredFieldsWithAnnotation(DoFn.TimerId.class, fnClazz, DoFn.class)) { // TimerSpec fields may generally be private, but will be accessed via the signature field.setAccessible(true); // Add fixed prefix to avoid key collision with TimerFamily. @@ -2200,66 +2200,11 @@ public class DoFnSignatures { return DoFnSignature.GetSizeMethod.create(m, windowT, methodContext.getExtraParameters()); } - private static Collection<Method> declaredMethodsWithAnnotation( - Class<? extends Annotation> anno, Class<?> startClass, Class<?> stopClass) { - return declaredMembersWithAnnotation(anno, startClass, stopClass, GET_METHODS); - } - - private static Collection<Field> declaredFieldsWithAnnotation( - Class<? extends Annotation> anno, Class<?> startClass, Class<?> stopClass) { - return declaredMembersWithAnnotation(anno, startClass, stopClass, GET_FIELDS); - } - - private interface MemberGetter<MemberT> { - MemberT[] getMembers(Class<?> clazz); - } - - private static final MemberGetter<Method> GET_METHODS = Class::getDeclaredMethods; - - private static final MemberGetter<Field> GET_FIELDS = Class::getDeclaredFields; - - private static <MemberT extends AnnotatedElement> - Collection<MemberT> declaredMembersWithAnnotation( - Class<? extends Annotation> anno, - Class<?> startClass, - Class<?> stopClass, - MemberGetter<MemberT> getter) { - Collection<MemberT> matches = new ArrayList<>(); - - Class<?> clazz = startClass; - LinkedHashSet<Class<?>> interfaces = new LinkedHashSet<>(); - - // First, find all declared methods on the startClass and parents (up to stopClass) - while (clazz != null && !clazz.equals(stopClass)) { - for (MemberT member : getter.getMembers(clazz)) { - if (member.isAnnotationPresent(anno)) { - matches.add(member); - } - } - - // Add all interfaces, including transitive - for (TypeDescriptor<?> iface : TypeDescriptor.of(clazz).getInterfaces()) { - interfaces.add(iface.getRawType()); - } - - clazz = clazz.getSuperclass(); - } - - // Now, iterate over all the discovered interfaces - for (Class<?> iface : interfaces) { - for (MemberT member : getter.getMembers(iface)) { - if (member.isAnnotationPresent(anno)) { - matches.add(member); - } - } - } - return matches; - } - private static Map<String, DoFnSignature.FieldAccessDeclaration> analyzeFieldAccessDeclaration( ErrorReporter errors, Class<?> fnClazz) { Map<String, FieldAccessDeclaration> fieldAccessDeclarations = new HashMap<>(); - for (Field field : declaredFieldsWithAnnotation(DoFn.FieldAccess.class, fnClazz, DoFn.class)) { + for (Field field : + ReflectHelpers.declaredFieldsWithAnnotation(DoFn.FieldAccess.class, fnClazz, DoFn.class)) { field.setAccessible(true); DoFn.FieldAccess fieldAccessAnnotation = field.getAnnotation(DoFn.FieldAccess.class); if (!Modifier.isFinal(field.getModifiers())) { @@ -2286,7 +2231,8 @@ public class DoFnSignatures { Map<String, DoFnSignature.StateDeclaration> declarations = new HashMap<>(); - for (Field field : declaredFieldsWithAnnotation(DoFn.StateId.class, fnClazz, DoFn.class)) { + for (Field field : + ReflectHelpers.declaredFieldsWithAnnotation(DoFn.StateId.class, fnClazz, DoFn.class)) { // StateSpec fields may generally be private, but will be accessed via the signature field.setAccessible(true); String id = field.getAnnotation(DoFn.StateId.class).value(); @@ -2349,7 +2295,8 @@ public class DoFnSignatures { private static @Nullable Method findAnnotatedMethod( ErrorReporter errors, Class<? extends Annotation> anno, Class<?> fnClazz, boolean required) { - Collection<Method> matches = declaredMethodsWithAnnotation(anno, fnClazz, DoFn.class); + Collection<Method> matches = + ReflectHelpers.declaredMethodsWithAnnotation(anno, fnClazz, DoFn.class); if (matches.isEmpty()) { errors.checkArgument(!required, "No method annotated with @%s found", format(anno)); diff --git a/sdks/java/core/src/main/java/org/apache/beam/sdk/util/common/ReflectHelpers.java b/sdks/java/core/src/main/java/org/apache/beam/sdk/util/common/ReflectHelpers.java index bd47037..9c3652d 100644 --- a/sdks/java/core/src/main/java/org/apache/beam/sdk/util/common/ReflectHelpers.java +++ b/sdks/java/core/src/main/java/org/apache/beam/sdk/util/common/ReflectHelpers.java @@ -22,6 +22,8 @@ import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Prec import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Preconditions.checkNotNull; import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; @@ -32,8 +34,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; +import java.util.LinkedHashSet; import java.util.Queue; import java.util.ServiceLoader; +import org.apache.beam.sdk.values.TypeDescriptor; import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Function; import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Joiner; import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.FluentIterable; @@ -274,4 +278,60 @@ public class ReflectHelpers { } return false; } + + public static Collection<Method> declaredMethodsWithAnnotation( + Class<? extends Annotation> anno, Class<?> startClass, Class<?> stopClass) { + return declaredMembersWithAnnotation(anno, startClass, stopClass, GET_METHODS); + } + + public static Collection<Field> declaredFieldsWithAnnotation( + Class<? extends Annotation> anno, Class<?> startClass, Class<?> stopClass) { + return declaredMembersWithAnnotation(anno, startClass, stopClass, GET_FIELDS); + } + + private interface MemberGetter<MemberT> { + MemberT[] getMembers(Class<?> clazz); + } + + private static final MemberGetter<Method> GET_METHODS = Class::getDeclaredMethods; + + private static final MemberGetter<Field> GET_FIELDS = Class::getDeclaredFields; + + private static <MemberT extends AnnotatedElement> + Collection<MemberT> declaredMembersWithAnnotation( + Class<? extends Annotation> anno, + Class<?> startClass, + Class<?> stopClass, + MemberGetter<MemberT> getter) { + Collection<MemberT> matches = new ArrayList<>(); + + Class<?> clazz = startClass; + LinkedHashSet<Class<?>> interfaces = new LinkedHashSet<>(); + + // First, find all declared methods on the startClass and parents (up to stopClass) + while (clazz != null && !clazz.equals(stopClass)) { + for (MemberT member : getter.getMembers(clazz)) { + if (member.isAnnotationPresent(anno)) { + matches.add(member); + } + } + + // Add all interfaces, including transitive + for (TypeDescriptor<?> iface : TypeDescriptor.of(clazz).getInterfaces()) { + interfaces.add(iface.getRawType()); + } + + clazz = clazz.getSuperclass(); + } + + // Now, iterate over all the discovered interfaces + for (Class<?> iface : interfaces) { + for (MemberT member : getter.getMembers(iface)) { + if (member.isAnnotationPresent(anno)) { + matches.add(member); + } + } + } + return matches; + } }