001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.http.annotation; 014 015import static java.lang.annotation.ElementType.*; 016import static java.lang.annotation.RetentionPolicy.*; 017import static org.apache.juneau.common.internal.StringUtils.*; 018import static org.apache.juneau.internal.ArrayUtils.*; 019 020import java.lang.annotation.*; 021import java.lang.reflect.*; 022 023import org.apache.juneau.*; 024import org.apache.juneau.annotation.*; 025import org.apache.juneau.httppart.*; 026import org.apache.juneau.reflect.*; 027import org.apache.juneau.svl.*; 028 029/** 030 * Utility classes and methods for the {@link Header @Header} annotation. 031 * 032 * <h5 class='section'>See Also:</h5><ul> 033 * </ul> 034 */ 035public class HeaderAnnotation { 036 037 //----------------------------------------------------------------------------------------------------------------- 038 // Static 039 //----------------------------------------------------------------------------------------------------------------- 040 041 /** Default value */ 042 public static final Header DEFAULT = create().build(); 043 044 /** 045 * Instantiates a new builder for this class. 046 * 047 * @return A new builder object. 048 */ 049 public static Builder create() { 050 return new Builder(); 051 } 052 053 /** 054 * Instantiates a new builder for this class. 055 * 056 * @param on The targets this annotation applies to. 057 * @return A new builder object. 058 */ 059 public static Builder create(Class<?>...on) { 060 return create().on(on); 061 } 062 063 /** 064 * Instantiates a new builder for this class. 065 * 066 * @param on The targets this annotation applies to. 067 * @return A new builder object. 068 */ 069 public static Builder create(String...on) { 070 return create().on(on); 071 } 072 073 /** 074 * Returns <jk>true</jk> if the specified annotation contains all default values. 075 * 076 * @param a The annotation to check. 077 * @return <jk>true</jk> if the specified annotation contains all default values. 078 */ 079 public static boolean empty(Header a) { 080 return a == null || DEFAULT.equals(a); 081 } 082 083 /** 084 * Finds the name from the specified lists of annotations. 085 * 086 * <p> 087 * The last matching name found is returned. 088 * 089 * @param pi The parameter. 090 * @return The last matching name, or {@link Value#empty()} if not found. 091 */ 092 public static Value<String> findName(ParamInfo pi) { 093 Value<String> n = Value.empty(); 094 pi.forEachAnnotation(Header.class, x -> isNotEmpty(x.value()), x -> n.set(x.value())); 095 pi.forEachAnnotation(Header.class, x -> isNotEmpty(x.name()), x -> n.set(x.name())); 096 return n; 097 } 098 099 /** 100 * Finds the default value from the specified list of annotations. 101 * 102 * @param pi The parameter. 103 * @return The last matching default value, or {@link Value#empty()} if not found. 104 */ 105 public static Value<String> findDef(ParamInfo pi) { 106 Value<String> n = Value.empty(); 107 pi.forEachAnnotation(Header.class, x -> isNotEmpty(x.def()), x -> n.set(x.def())); 108 return n; 109 } 110 111 //----------------------------------------------------------------------------------------------------------------- 112 // Builder 113 //----------------------------------------------------------------------------------------------------------------- 114 115 /** 116 * Builder class. 117 * 118 * <h5 class='section'>See Also:</h5><ul> 119 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)} 120 * </ul> 121 */ 122 public static class Builder extends TargetedAnnotationTMFBuilder { 123 124 Class<? extends HttpPartParser> parser = HttpPartParser.Void.class; 125 Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class; 126 Schema schema = SchemaAnnotation.DEFAULT; 127 String name="", value="", def=""; 128 129 /** 130 * Constructor. 131 */ 132 protected Builder() { 133 super(Header.class); 134 } 135 136 /** 137 * Instantiates a new {@link Header @Header} object initialized with this builder. 138 * 139 * @return A new {@link Header @Header} object. 140 */ 141 public Header build() { 142 return new Impl(this); 143 } 144 145 /** 146 * Sets the {@link Header#def} property on this annotation. 147 * 148 * @param value The new value for this property. 149 * @return This object. 150 */ 151 public Builder def(String value) { 152 this.def = value; 153 return this; 154 } 155 156 /** 157 * Sets the {@link Header#name} property on this annotation. 158 * 159 * @param value The new value for this property. 160 * @return This object. 161 */ 162 public Builder name(String value) { 163 this.name = value; 164 return this; 165 } 166 167 /** 168 * Sets the {@link Header#parser} property on this annotation. 169 * 170 * @param value The new value for this property. 171 * @return This object. 172 */ 173 public Builder parser(Class<? extends HttpPartParser> value) { 174 this.parser = value; 175 return this; 176 } 177 178 /** 179 * Sets the {@link Header#schema} property on this annotation. 180 * 181 * @param value The new value for this property. 182 * @return This object. 183 */ 184 public Builder schema(Schema value) { 185 this.schema = value; 186 return this; 187 } 188 189 /** 190 * Sets the {@link Header#serializer} property on this annotation. 191 * 192 * @param value The new value for this property. 193 * @return This object. 194 */ 195 public Builder serializer(Class<? extends HttpPartSerializer> value) { 196 this.serializer = value; 197 return this; 198 } 199 200 /** 201 * Sets the {@link Header#value} property on this annotation. 202 * 203 * @param value The new value for this property. 204 * @return This object. 205 */ 206 public Builder value(String value) { 207 this.value = value; 208 return this; 209 } 210 211 // <FluentSetters> 212 213 @Override /* GENERATED - TargetedAnnotationBuilder */ 214 public Builder on(String...values) { 215 super.on(values); 216 return this; 217 } 218 219 @Override /* GENERATED - TargetedAnnotationTBuilder */ 220 public Builder on(java.lang.Class<?>...value) { 221 super.on(value); 222 return this; 223 } 224 225 @Override /* GENERATED - TargetedAnnotationTBuilder */ 226 public Builder onClass(java.lang.Class<?>...value) { 227 super.onClass(value); 228 return this; 229 } 230 231 @Override /* GENERATED - TargetedAnnotationTMFBuilder */ 232 public Builder on(Field...value) { 233 super.on(value); 234 return this; 235 } 236 237 @Override /* GENERATED - TargetedAnnotationTMFBuilder */ 238 public Builder on(Method...value) { 239 super.on(value); 240 return this; 241 } 242 243 // </FluentSetters> 244 } 245 246 //----------------------------------------------------------------------------------------------------------------- 247 // Implementation 248 //----------------------------------------------------------------------------------------------------------------- 249 250 private static class Impl extends TargetedAnnotationTImpl implements Header { 251 252 private final Class<? extends HttpPartParser> parser; 253 private final Class<? extends HttpPartSerializer> serializer; 254 private final String name, value, def; 255 private final Schema schema; 256 257 Impl(Builder b) { 258 super(b); 259 this.def = b.def; 260 this.name = b.name; 261 this.parser = b.parser; 262 this.schema = b.schema; 263 this.serializer = b.serializer; 264 this.value = b.value; 265 postConstruct(); 266 } 267 268 @Override /* Header */ 269 public String def() { 270 return def; 271 } 272 273 @Override /* Header */ 274 public String name() { 275 return name; 276 } 277 278 @Override /* Header */ 279 public Class<? extends HttpPartParser> parser() { 280 return parser; 281 } 282 283 @Override /* Header */ 284 public Schema schema() { 285 return schema; 286 } 287 288 @Override /* Header */ 289 public Class<? extends HttpPartSerializer> serializer() { 290 return serializer; 291 } 292 293 @Override /* Header */ 294 public String value() { 295 return value; 296 } 297 } 298 299 //----------------------------------------------------------------------------------------------------------------- 300 // Appliers 301 //----------------------------------------------------------------------------------------------------------------- 302 303 /** 304 * Applies targeted {@link Header} annotations to a {@link org.apache.juneau.BeanContext.Builder}. 305 */ 306 public static class Applier extends AnnotationApplier<Header,BeanContext.Builder> { 307 308 /** 309 * Constructor. 310 * 311 * @param vr The resolver for resolving values in annotations. 312 */ 313 public Applier(VarResolverSession vr) { 314 super(Header.class, BeanContext.Builder.class, vr); 315 } 316 317 @Override 318 public void apply(AnnotationInfo<Header> ai, BeanContext.Builder b) { 319 Header a = ai.inner(); 320 if (isEmptyArray(a.on(), a.onClass())) 321 return; 322 b.annotations(a); 323 } 324 } 325 326 //----------------------------------------------------------------------------------------------------------------- 327 // Other 328 //----------------------------------------------------------------------------------------------------------------- 329 330 /** 331 * A collection of {@link Header @Header annotations}. 332 */ 333 @Documented 334 @Target({METHOD,TYPE}) 335 @Retention(RUNTIME) 336 @Inherited 337 public static @interface Array { 338 339 /** 340 * The child annotations. 341 * 342 * @return The annotation value. 343 */ 344 Header[] value(); 345 } 346}