View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau;
18  
19  import static org.apache.juneau.commons.utils.AssertionUtils.*;
20  import static org.apache.juneau.commons.utils.Utils.*;
21  
22  import java.lang.annotation.*;
23  import java.lang.reflect.*;
24  import java.util.*;
25  import java.util.stream.*;
26  
27  import org.apache.juneau.annotation.*;
28  import org.apache.juneau.commons.reflect.*;
29  import org.apache.juneau.svl.*;
30  
31  /**
32   * A list of {@link AnnotationWork} objects.
33   *
34   * @serial exclude
35   */
36  public class AnnotationWorkList extends ArrayList<AnnotationWork> {
37  	private static final long serialVersionUID = 1L;
38  
39  	/**
40  	 * Static creator.
41  	 *
42  	 * @return A new list.
43  	 */
44  	public static AnnotationWorkList create() {
45  		return new AnnotationWorkList(VarResolver.DEFAULT.createSession());
46  	}
47  
48  	/**
49  	 * Static creator.
50  	 *
51  	 * @param vrs The variable resolver.
52  	 * @return A new list.
53  	 */
54  	public static AnnotationWorkList create(VarResolverSession vrs) {
55  		return new AnnotationWorkList(vrs);
56  	}
57  
58  	/**
59  	 * Static creator.
60  	 *
61  	 * @param annotations The annotations to create work from.
62  	 * @return A new list.
63  	 */
64  	public static AnnotationWorkList of(Stream<AnnotationInfo<? extends Annotation>> annotations) {
65  		return create().add(annotations);
66  	}
67  
68  	/**
69  	 * Static creator.
70  	 *
71  	 * @param vrs The variable resolver.
72  	 * @param annotations The annotations to create work from.
73  	 * @return A new list.
74  	 */
75  	public static AnnotationWorkList of(VarResolverSession vrs, Stream<AnnotationInfo<? extends Annotation>> annotations) {
76  		return create(vrs).add(annotations);
77  	}
78  
79  	private final VarResolverSession vrs;
80  
81  	private AnnotationWorkList(VarResolverSession vrs) {
82  		this.vrs = assertArgNotNull("vrs", vrs);
83  	}
84  
85  	/**
86  	 * Adds an entry to this list.
87  	 *
88  	 * @param ai The annotation being applied.
89  	 * @param aa The applier for the annotation.
90  	 * @return This object.
91  	 */
92  	public AnnotationWorkList add(AnnotationInfo<?> ai, AnnotationApplier<Annotation,Object> aa) {
93  		add(new AnnotationWork(ai, aa));
94  		return this;
95  	}
96  
97  	/**
98  	 * Adds entries for the specified annotations to this work list.
99  	 *
100 	 * @param annotations The annotations to create work from.
101 	 * @return This object.
102 	 */
103 	public AnnotationWorkList add(Stream<AnnotationInfo<? extends Annotation>> annotations) {
104 		annotations.sorted(Comparator.comparingInt(AnnotationInfo::getRank)).forEach(this::applyAnnotation);
105 		return this;
106 	}
107 
108 	/**
109 	 * Helper method to extract and apply annotation appliers for a given annotation.
110 	 *
111 	 * @param ai The annotation info to process.
112 	 */
113 	@SuppressWarnings("unchecked")
114 	private void applyAnnotation(AnnotationInfo<?> ai) {
115 		var a = ai.inner();
116 		var cpa = assertNotNull(a.annotationType().getAnnotation(ContextApply.class), "Annotation found without @ContextApply: %s", cn(ai.annotationType()));
117 		Arrays.stream(cpa.value())
118 			.map(x -> safe(() -> (Constructor<? extends AnnotationApplier<?,?>>)x.getConstructor(VarResolverSession.class)))
119 			.forEach(applyConstructor -> {
120 				var applier = safe(() -> (AnnotationApplier<Annotation,Object>)applyConstructor.newInstance(vrs));
121 				add(ai, applier);
122 			});
123 	}
124 }