1616package io .qameta .allure .util ;
1717
1818import io .qameta .allure .LabelAnnotation ;
19+ import io .qameta .allure .LinkAnnotation ;
1920import io .qameta .allure .model .Label ;
2021import io .qameta .allure .model .Link ;
2122import org .slf4j .Logger ;
2627import java .lang .reflect .AnnotatedElement ;
2728import java .lang .reflect .InvocationTargetException ;
2829import java .lang .reflect .Method ;
29- import java .util .ArrayList ;
30- import java .util .Arrays ;
3130import java .util .Collection ;
3231import java .util .Collections ;
3332import java .util .List ;
33+ import java .util .ArrayList ;
3434import java .util .Objects ;
3535import java .util .Set ;
3636import java .util .function .Function ;
3737import java .util .stream .Collectors ;
3838import java .util .stream .Stream ;
3939
40+ import static java .util .Arrays .asList ;
41+
4042/**
4143 * Collection of utils used by Allure integration to extract meta information from
4244 * test cases via reflection.
@@ -64,6 +66,7 @@ public static List<Link> getLinks(final AnnotatedElement annotatedElement) {
6466 result .addAll (extractLinks (annotatedElement , io .qameta .allure .Link .class , ResultsUtils ::createLink ));
6567 result .addAll (extractLinks (annotatedElement , io .qameta .allure .Issue .class , ResultsUtils ::createLink ));
6668 result .addAll (extractLinks (annotatedElement , io .qameta .allure .TmsLink .class , ResultsUtils ::createLink ));
69+ result .addAll (extractCustomLinks (asList (annotatedElement .getDeclaredAnnotations ())));
6770 return result ;
6871 }
6972
@@ -74,7 +77,7 @@ public static List<Link> getLinks(final AnnotatedElement annotatedElement) {
7477 * @return discovered links.
7578 */
7679 public static List <Link > getLinks (final Annotation ... annotations ) {
77- return getLinks (Arrays . asList (annotations ));
80+ return getLinks (asList (annotations ));
7881 }
7982
8083 /**
@@ -88,6 +91,7 @@ public static List<Link> getLinks(final Collection<Annotation> annotations) {
8891 result .addAll (extractLinks (annotations , io .qameta .allure .Link .class , ResultsUtils ::createLink ));
8992 result .addAll (extractLinks (annotations , io .qameta .allure .Issue .class , ResultsUtils ::createLink ));
9093 result .addAll (extractLinks (annotations , io .qameta .allure .TmsLink .class , ResultsUtils ::createLink ));
94+ result .addAll (extractCustomLinks (annotations ));
9195 return result ;
9296 }
9397
@@ -109,7 +113,7 @@ public static Set<Label> getLabels(final AnnotatedElement annotatedElement) {
109113 * @return discovered labels.
110114 */
111115 public static Set <Label > getLabels (final Annotation ... annotations ) {
112- return getLabels (Arrays . asList (annotations ));
116+ return getLabels (asList (annotations ));
113117 }
114118
115119 /**
@@ -129,6 +133,7 @@ public static Set<Label> getLabels(final Collection<Annotation> annotations) {
129133 private static <T extends Annotation > Set <Link > extractLinks (final AnnotatedElement element ,
130134 final Class <T > annotationType ,
131135 final Function <T , Link > mapper ) {
136+
132137 return Stream .of (element .getAnnotationsByType (annotationType ))
133138 .map (mapper )
134139 .collect (Collectors .toSet ());
@@ -146,6 +151,32 @@ private static <T extends Annotation> Set<Link> extractLinks(final Collection<An
146151 .collect (Collectors .toSet ());
147152 }
148153
154+ private static Collection <? extends Link > extractCustomLinks (final Collection <Annotation > annotations ) {
155+ return annotations .stream ()
156+ .flatMap (AnnotationUtils ::extractRepeatable )
157+ .filter (annotation -> annotation .annotationType ().isAnnotationPresent (LinkAnnotation .class ))
158+ .flatMap (annotation -> AnnotationUtils .toLink (annotation ).stream ())
159+ .collect (Collectors .toSet ());
160+ }
161+
162+ private static Set <Link > toLink (final Annotation annotation ) {
163+ final LinkAnnotation linkAnnotation = annotation .annotationType ().getAnnotation (LinkAnnotation .class );
164+
165+ try {
166+ final Method method = annotation .annotationType ().getMethod (VALUE_METHOD_NAME );
167+ final Object object = method .invoke (annotation );
168+ return objectToStringStream (object )
169+ .map (value -> ResultsUtils .createLink ("" , value , "" , linkAnnotation .type ()))
170+ .collect (Collectors .toSet ());
171+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e ) {
172+ LOGGER .error (
173+ "Invalid annotation {}: marker annotations should contains value() method" ,
174+ annotation
175+ );
176+ }
177+ return Collections .emptySet ();
178+ }
179+
149180 private static Set <Label > getMarks (final Annotation annotation ) {
150181 return Stream .of (annotation .annotationType ().getAnnotationsByType (LabelAnnotation .class ))
151182 .map (marker -> getLabel (annotation , marker ))
0 commit comments