001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.lang.annotation.*; 023import java.lang.reflect.*; 024import java.util.*; 025import java.util.stream.*; 026 027import org.apache.juneau.annotation.*; 028import org.apache.juneau.commons.reflect.*; 029import org.apache.juneau.svl.*; 030 031/** 032 * A list of {@link AnnotationWork} objects. 033 * 034 * @serial exclude 035 */ 036public class AnnotationWorkList extends ArrayList<AnnotationWork> { 037 private static final long serialVersionUID = 1L; 038 039 /** 040 * Static creator. 041 * 042 * @return A new list. 043 */ 044 public static AnnotationWorkList create() { 045 return new AnnotationWorkList(VarResolver.DEFAULT.createSession()); 046 } 047 048 /** 049 * Static creator. 050 * 051 * @param vrs The variable resolver. 052 * @return A new list. 053 */ 054 public static AnnotationWorkList create(VarResolverSession vrs) { 055 return new AnnotationWorkList(vrs); 056 } 057 058 /** 059 * Static creator. 060 * 061 * @param annotations The annotations to create work from. 062 * @return A new list. 063 */ 064 public static AnnotationWorkList of(Stream<AnnotationInfo<? extends Annotation>> annotations) { 065 return create().add(annotations); 066 } 067 068 /** 069 * Static creator. 070 * 071 * @param vrs The variable resolver. 072 * @param annotations The annotations to create work from. 073 * @return A new list. 074 */ 075 public static AnnotationWorkList of(VarResolverSession vrs, Stream<AnnotationInfo<? extends Annotation>> annotations) { 076 return create(vrs).add(annotations); 077 } 078 079 private final VarResolverSession vrs; 080 081 private AnnotationWorkList(VarResolverSession vrs) { 082 this.vrs = assertArgNotNull("vrs", vrs); 083 } 084 085 /** 086 * Adds an entry to this list. 087 * 088 * @param ai The annotation being applied. 089 * @param aa The applier for the annotation. 090 * @return This object. 091 */ 092 public AnnotationWorkList add(AnnotationInfo<?> ai, AnnotationApplier<Annotation,Object> aa) { 093 add(new AnnotationWork(ai, aa)); 094 return this; 095 } 096 097 /** 098 * Adds entries for the specified annotations to this work list. 099 * 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}