ReflectionUtils.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *********************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  12.  * the License. You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
  23.  * git clone https://github.com/tidalwave-it/thesefoolishthings-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.messagebus.spi;

  28. import java.lang.annotation.Annotation;
  29. import java.lang.reflect.Method;
  30. import javax.annotation.Nonnull;
  31. import java.util.ArrayList;
  32. import java.util.Collections;
  33. import java.util.List;

  34. /***********************************************************************************************************************
  35.  *
  36.  * @author  Fabrizio Giudici
  37.  *
  38.  **********************************************************************************************************************/
  39. public class ReflectionUtils
  40.   {
  41.     /*******************************************************************************************************************
  42.      *
  43.      *
  44.      *
  45.      ******************************************************************************************************************/
  46.     public static interface MethodProcessor
  47.       {
  48.         enum FilterResult { ACCEPT, IGNORE }

  49.         public FilterResult filter (@Nonnull Class<?> clazz);

  50.         public void process (@Nonnull Method method);
  51.       }

  52.     /*******************************************************************************************************************
  53.      *
  54.      *
  55.      *
  56.      ******************************************************************************************************************/
  57.     public static class MethodProcessorSupport implements MethodProcessor
  58.       {
  59.         @Override @Nonnull
  60.         public FilterResult filter (@Nonnull final Class<?> clazz)
  61.           {
  62.             return FilterResult.ACCEPT;
  63.           }

  64.         @Override
  65.         public void process (@Nonnull final Method method)
  66.           {
  67.           }
  68.       }

  69.     /*******************************************************************************************************************
  70.      *
  71.      * Navigates the hierarchy of the given object, top down, and applies the {@link MethodProcessor} to all the
  72.      * methods of each class, if not filtered out by the processor itself.
  73.      *
  74.      * @param object            the object at the bottom of the hierarchy
  75.      * @param processor         the processor
  76.      *
  77.      ******************************************************************************************************************/
  78.     public static void forEachMethodInTopDownHierarchy (@Nonnull final Object object,
  79.                                                         @Nonnull final MethodProcessor processor)
  80.       {
  81.         for (final Class<?> clazz : getClassHierarchy(object.getClass()))
  82.           {
  83.             for (final Method method : clazz.getDeclaredMethods())
  84.               {
  85.                 processor.process(method);
  86.               }
  87.           }
  88.       }

  89.     /*******************************************************************************************************************
  90.      *
  91.      * Navigates the hierarchy of the given object, bottom up, and applies the {@link MethodProcessor} to all the
  92.      * methods of each class, if not filtered out by the processor itself.
  93.      *
  94.      * @param object            the object at the bottom of the hierarchy
  95.      * @param processor         the processor
  96.      *
  97.      ******************************************************************************************************************/
  98.     public static void forEachMethodInBottomUpHierarchy (@Nonnull final Object object,
  99.                                                          @Nonnull final MethodProcessor processor)
  100.       {
  101.         final List<Class<?>> hierarchy = getClassHierarchy(object.getClass());
  102.         Collections.reverse(hierarchy);

  103.         for (final Class<?> clazz : hierarchy)
  104.           {
  105.             if (processor.filter(clazz) == MethodProcessor.FilterResult.ACCEPT)
  106.               {
  107.                 for (final Method method : clazz.getDeclaredMethods())
  108.                   {
  109.                     processor.process(method);
  110.                   }
  111.               }
  112.           }
  113.       }

  114.     /*******************************************************************************************************************
  115.      *
  116.      * Returns the hierarchy of the given class, top down.
  117.      *
  118.      * @param   clazz               the clazz at the bottom of the hierarchy
  119.      * @return                      the hierarchy
  120.      *
  121.      ******************************************************************************************************************/
  122.     @Nonnull
  123.     private static List<Class<?>> getClassHierarchy (@Nonnull final Class<?> clazz)
  124.       {
  125.         final List<Class<?>> hierarchy = new ArrayList<>();

  126.         for (Class<?> ancestor = clazz; ancestor != null; ancestor = ancestor.getSuperclass())
  127.           {
  128.             hierarchy.add(0, ancestor);
  129.           }

  130.         return hierarchy;
  131.       }

  132.     /*******************************************************************************************************************
  133.      *
  134.      * Checks whether an array of annotations contains an annotation of the given type.
  135.      *
  136.      * @param   annotations         the annotations to check
  137.      * @param   annotationClass     the type of the required annotation
  138.      * @return                      true if the annotation is found
  139.      *
  140.      ******************************************************************************************************************/
  141.     public static boolean containsAnnotation (@Nonnull final Annotation[] annotations,
  142.                                               @Nonnull final Class<?> annotationClass)
  143.       {
  144.         for (final Annotation annotation : annotations)
  145.           {
  146.             if (annotationClass.isAssignableFrom(annotation.getClass()))
  147.               {
  148.                 return true;
  149.               }
  150.           }

  151.         return false;
  152.       }
  153.   }