AnnotationHelper.java

  1. package com.soebes.itf.jupiter.extension;

  2. /*
  3.  * Licensed to the Apache Software Foundation (ASF) under one
  4.  * or more contributor license agreements.  See the NOTICE file
  5.  * distributed with this work for additional information
  6.  * regarding copyright ownership.  The ASF licenses this file
  7.  * to you under the Apache License, Version 2.0 (the
  8.  * "License"); you may not use this file except in compliance
  9.  * with the License.  You may obtain a copy of the License at
  10.  *
  11.  *  http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing,
  14.  * software distributed under the License is distributed on an
  15.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16.  * KIND, either express or implied.  See the License for the
  17.  * specific language governing permissions and limitations
  18.  * under the License.
  19.  */

  20. import org.junit.jupiter.api.extension.ExtensionContext;
  21. import org.junit.platform.commons.support.AnnotationSupport;

  22. import java.lang.annotation.Annotation;
  23. import java.lang.reflect.Method;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import java.util.Optional;
  27. import java.util.stream.Collectors;
  28. import java.util.stream.Stream;

  29. /**
  30.  * @author Karl Heinz Marbaise
  31.  */
  32. class AnnotationHelper {

  33.   private AnnotationHelper() {
  34.     // prevent instantiation.
  35.   }

  36.   /**
  37.    * @param context {@link ExtensionContext}
  38.    * @return {@code true} if we have any {@link MavenProfile @MavenProfile} defined or {@code false} otherwise.
  39.    */
  40.   static boolean hasProfiles(ExtensionContext context) {
  41.     return !profiles(context).isEmpty();
  42.   }

  43.   /**
  44.    * Get the profiles from the annotation.
  45.    *
  46.    * @param context {@link ExtensionContext}
  47.    * @return The stream with the profiles.
  48.    */
  49.   static List<String> profiles(ExtensionContext context) {
  50.     Method method = context.getTestMethod().orElseThrow(IllegalStateException::new);

  51.     List<MavenProfile> profiles = new ArrayList<>(AnnotationSupport.findRepeatableAnnotations(method, MavenProfile.class));

  52.     List<Object> allInstances = context.getTestInstances().orElseThrow(IllegalStateException::new).getAllInstances();
  53.     for (int i = allInstances.size()-1; i >=0; i--) {
  54.       List<MavenProfile> repeatableAnnotations = AnnotationSupport.findRepeatableAnnotations(allInstances.get(i).getClass(), MavenProfile.class);
  55.       profiles.addAll(repeatableAnnotations);
  56.     }

  57.     return profiles.stream().flatMap(profile -> Stream.of(profile.value())).collect(Collectors.toList());
  58.   }
  59.   /**
  60.    * @param context {@link ExtensionContext}
  61.    * @return {@code true} if we have any {@link MavenGoal @MavenGoal} defined or {@code false} otherwise.
  62.    */
  63.   static boolean hasGoals(ExtensionContext context) {
  64.     return !goals(context).isEmpty();
  65.   }

  66.   /**
  67.    * Get the goals from the annotation either on test method level
  68.    * or on test class level.
  69.    *
  70.    * @param context {@link ExtensionContext}
  71.    * @return The stream with the goals.
  72.    */
  73.   static List<String> goals(ExtensionContext context) {
  74.     Method method = context.getTestMethod().orElseThrow(IllegalStateException::new);

  75.     List<MavenGoal> goalAnnotations = new ArrayList<>(AnnotationSupport.findRepeatableAnnotations(method, MavenGoal.class));

  76.     List<Object> allInstances = context.getTestInstances().orElseThrow(IllegalStateException::new).getAllInstances();
  77.     for (int i = allInstances.size()-1; i >=0; i--) {
  78.       goalAnnotations.addAll(AnnotationSupport.findRepeatableAnnotations(allInstances.get(i).getClass(), MavenGoal.class));
  79.     }

  80.     return goalAnnotations.stream().flatMap(goal -> Stream.of(goal.value())).collect(Collectors.toList());
  81.   }

  82.   /**
  83.    * @param context {@link ExtensionContext}
  84.    * @return {@code true} if we have any {@link MavenOption @MavenOption} defined or {@code false} otherwise.
  85.    */
  86.   static boolean hasOptions(ExtensionContext context) {
  87.     return !options(context).isEmpty();
  88.   }

  89.   /**
  90.    * Get the options from the class level, method level or nested class level.
  91.    *
  92.    * @param context {@link ExtensionContext}
  93.    * @return The stream with the options.
  94.    */
  95.   static List<String> options(ExtensionContext context) {
  96.     Method method = context.getTestMethod().orElseThrow(IllegalStateException::new);

  97.     List<MavenOption> options = new ArrayList<>(AnnotationSupport.findRepeatableAnnotations(method, MavenOption.class));

  98.     List<Object> allInstances = context.getTestInstances().orElseThrow(IllegalStateException::new).getAllInstances();
  99.     for (int i = allInstances.size()-1; i >=0; i--) {
  100.       options.addAll(AnnotationSupport.findRepeatableAnnotations(allInstances.get(i).getClass(), MavenOption.class));
  101.     }

  102.     return options.stream().flatMap(option -> option.parameter().isEmpty() ? Stream.of(option.value()) : Stream.of(option.value(), option.parameter()))
  103.         .collect(Collectors.toList());
  104.   }

  105.   /**
  106.    * @param context {@link ExtensionContext}
  107.    * @return {@code true} if we have any {@link SystemProperty @SystemProperty} defined or {@code false} otherwise.
  108.    */
  109.   static boolean hasSystemProperties(ExtensionContext context) {
  110.     return !systemProperties(context).isEmpty();
  111.   }

  112.   private static Optional<Class<?>> findAnnotation(ExtensionContext context,
  113.                                                    Class<? extends Annotation> annotationClass) {
  114.     Optional<ExtensionContext> current = Optional.of(context);
  115.     while (current.isPresent()) {
  116.       Optional<Class<?>> testClassNumber1 = current.get().getTestClass();
  117.       if (testClassNumber1.isPresent()) {
  118.         Class<?> testClass = testClassNumber1.get();
  119.         if (testClass.isAnnotationPresent(annotationClass)) {
  120.           return Optional.of(testClass);
  121.         }
  122.       }
  123.       current = current.get().getParent();
  124.     }
  125.     return Optional.empty();
  126.   }

  127.   static Optional<Class<?>> findMavenRepositoryAnnotation(ExtensionContext context) {
  128.     return findAnnotation(context, MavenRepository.class);
  129.   }

  130.   static Optional<Class<?>> findMavenProjectAnnotation(ExtensionContext context) {
  131.     return findAnnotation(context, MavenProject.class);
  132.   }

  133.   static Optional<MavenProjectSources> findMavenProjectSourcesAnnotation(ExtensionContext context) {
  134.     Method method = context.getTestMethod().orElseThrow(IllegalStateException::new);

  135.     boolean methodAnnotationPresent = method.isAnnotationPresent(MavenProjectSources.class);
  136.     if (methodAnnotationPresent) {
  137.       return Optional.of(method.getAnnotation(MavenProjectSources.class));
  138.     }

  139.     Optional<Class<?>> firstFinding = findAnnotation(context, MavenProjectSources.class);
  140.     if (firstFinding.isPresent()) {
  141.       MavenProjectSources annotation = firstFinding.get().getAnnotation(MavenProjectSources.class);
  142.       return Optional.of(annotation);
  143.     }

  144.     Optional<MavenProjectSources> mavenProjectLocationAnnotation = AnnotationSupport.findAnnotation(context.getTestClass(), MavenProjectSources.class);
  145.     if (mavenProjectLocationAnnotation.isPresent()) {
  146.       MavenProjectSources annotation = mavenProjectLocationAnnotation.get();
  147.       return Optional.of(annotation);
  148.     }

  149.     return Optional.empty();
  150.   }

  151.   static List<SystemProperty> systemProperties(ExtensionContext context) {
  152.     Method method = context.getTestMethod().orElseThrow(IllegalStateException::new);

  153.     List<SystemProperty> properties = new ArrayList<>(AnnotationSupport.findRepeatableAnnotations(method, SystemProperty.class));

  154.     List<Object> allInstances = context.getTestInstances().orElseThrow(IllegalStateException::new).getAllInstances();
  155.     for (int i = allInstances.size()-1; i >=0; i--) {
  156.       properties.addAll(AnnotationSupport.findRepeatableAnnotations(allInstances.get(i).getClass(), SystemProperty.class));
  157.     }

  158.     return properties;
  159.   }

  160.   static Optional<Class<?>> findMavenPredefinedRepositoryAnnotation(ExtensionContext context) {
  161.     return findAnnotation(context, MavenPredefinedRepository.class);
  162.   }

  163.   static Optional<MavenProjectLocation> findMavenProjectLocationAnnotation(ExtensionContext context) {
  164.     Method method = context.getTestMethod().orElseThrow(IllegalStateException::new);

  165.     boolean methodAnnotationPresent = method.isAnnotationPresent(MavenProjectLocation.class);
  166.     if (methodAnnotationPresent) {
  167.       return Optional.of(method.getAnnotation(MavenProjectLocation.class));
  168.     }

  169.     Optional<Class<?>> mavenProjectLocationAnnotation = findAnnotation(context, MavenProjectLocation.class);
  170.     if (mavenProjectLocationAnnotation.isPresent()) {
  171.       MavenProjectLocation annotation = mavenProjectLocationAnnotation.get().getAnnotation(MavenProjectLocation.class);
  172.       return Optional.of(annotation);
  173.     }

  174.     return Optional.empty();
  175.   }

  176. }