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.http.annotation; 018 019import static java.lang.annotation.ElementType.*; 020import static java.lang.annotation.RetentionPolicy.*; 021import static org.apache.juneau.commons.utils.CollectionUtils.*; 022import static org.apache.juneau.commons.utils.Utils.*; 023 024import java.lang.annotation.*; 025import java.lang.reflect.*; 026import java.util.*; 027 028import org.apache.juneau.*; 029import org.apache.juneau.annotation.*; 030import org.apache.juneau.httppart.*; 031import org.apache.juneau.commons.annotation.*; 032import org.apache.juneau.commons.reflect.*; 033import org.apache.juneau.svl.*; 034 035/** 036 * Utility classes and methods for the {@link PathRemainder @PathRemainder} annotation. 037 * 038 * <h5 class='section'>See Also:</h5><ul> 039 * <li class='ja'>{@link PathRemainder} 040 * <li class='ja'>{@link Path} 041 * </ul> 042 * 043 * @since 9.2.0 044 */ 045public class PathRemainderAnnotation { 046 047 private static final AnnotationProvider AP = AnnotationProvider.INSTANCE; 048 049 /** 050 * Applies targeted {@link PathRemainder} annotations to a {@link org.apache.juneau.BeanContext.Builder}. 051 */ 052 public static class Applier extends AnnotationApplier<PathRemainder,BeanContext.Builder> { 053 054 /** 055 * Constructor. 056 * 057 * @param vr The resolver for resolving values in annotations. 058 */ 059 public Applier(VarResolverSession vr) { 060 super(PathRemainder.class, BeanContext.Builder.class, vr); 061 } 062 063 @Override 064 public void apply(AnnotationInfo<PathRemainder> ai, BeanContext.Builder b) { 065 PathRemainder a = ai.inner(); 066 if (isEmptyArray(a.on()) && isEmptyArray(a.onClass())) 067 return; 068 b.annotations(a); 069 } 070 } 071 072 /** 073 * A collection of {@link PathRemainder @PathRemainder annotations}. 074 */ 075 @Documented 076 @Target({ METHOD, TYPE }) 077 @Retention(RUNTIME) 078 @Inherited 079 public static @interface Array { 080 081 /** 082 * The child annotations. 083 * 084 * @return The annotation value. 085 */ 086 PathRemainder[] value(); 087 } 088 089 /** 090 * Builder class. 091 * 092 * <h5 class='section'>See Also:</h5><ul> 093 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)} 094 * </ul> 095 */ 096 public static class Builder extends AppliedAnnotationObject.BuilderTMF { 097 098 private Class<? extends HttpPartParser> parser = HttpPartParser.Void.class; 099 private String[] description = {}; 100 private Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class; 101 private Schema schema = SchemaAnnotation.DEFAULT; 102 private String def = ""; 103 104 /** 105 * Constructor. 106 */ 107 protected Builder() { 108 super(PathRemainder.class); 109 } 110 111 /** 112 * Instantiates a new {@link PathRemainder @PathRemainder} object initialized with this builder. 113 * 114 * @return A new {@link PathRemainder @PathRemainder} object. 115 */ 116 public PathRemainder build() { 117 return new Object(this); 118 } 119 120 /** 121 * Sets the {@link PathRemainder#def} property on this annotation. 122 * 123 * @param value The new value for this property. 124 * @return This object. 125 */ 126 public Builder def(String value) { 127 def = value; 128 return this; 129 } 130 131 /** 132 * Sets the {@link PathRemainder#description} property on this annotation. 133 * 134 * @param value The new value for this property. 135 * @return This object. 136 */ 137 public Builder description(String...value) { 138 description = value; 139 return this; 140 } 141 142 /** 143 * Sets the {@link PathRemainder#parser} property on this annotation. 144 * 145 * @param value The new value for this property. 146 * @return This object. 147 */ 148 public Builder parser(Class<? extends HttpPartParser> value) { 149 parser = value; 150 return this; 151 } 152 153 /** 154 * Sets the {@link PathRemainder#schema} property on this annotation. 155 * 156 * @param value The new value for this property. 157 * @return This object. 158 */ 159 public Builder schema(Schema value) { 160 schema = value; 161 return this; 162 } 163 164 /** 165 * Sets the {@link PathRemainder#serializer} property on this annotation. 166 * 167 * @param value The new value for this property. 168 * @return This object. 169 */ 170 public Builder serializer(Class<? extends HttpPartSerializer> value) { 171 serializer = value; 172 return this; 173 } 174 175 @Override /* Overridden from AppliedAnnotationObject.Builder */ 176 public Builder on(String...value) { 177 super.on(value); 178 return this; 179 } 180 181 @Override /* Overridden from AppliedAnnotationObject.BuilderT */ 182 public Builder on(Class<?>...value) { 183 super.on(value); 184 return this; 185 } 186 187 @Override /* Overridden from AppliedOnClassAnnotationObject.Builder */ 188 public Builder onClass(Class<?>...value) { 189 super.onClass(value); 190 return this; 191 } 192 193 @Override /* Overridden from AppliedAnnotationObject.BuilderM */ 194 public Builder on(Method...value) { 195 super.on(value); 196 return this; 197 } 198 199 @Override /* Overridden from AppliedAnnotationObject.BuilderMF */ 200 public Builder on(Field...value) { 201 super.on(value); 202 return this; 203 } 204 205 @Override /* Overridden from AppliedAnnotationObject.BuilderT */ 206 public Builder on(ClassInfo...value) { 207 super.on(value); 208 return this; 209 } 210 211 @Override /* Overridden from AppliedAnnotationObject.BuilderT */ 212 public Builder onClass(ClassInfo...value) { 213 super.onClass(value); 214 return this; 215 } 216 217 @Override /* Overridden from AppliedAnnotationObject.BuilderTMF */ 218 public Builder on(FieldInfo...value) { 219 super.on(value); 220 return this; 221 } 222 223 @Override /* Overridden from AppliedAnnotationObject.BuilderTMF */ 224 public Builder on(MethodInfo...value) { 225 super.on(value); 226 return this; 227 } 228 229 } 230 231 private static class Object extends AppliedOnClassAnnotationObject implements PathRemainder { 232 233 private final String[] description; 234 private final Class<? extends HttpPartParser> parser; 235 private final Class<? extends HttpPartSerializer> serializer; 236 private final String def; 237 private final Schema schema; 238 239 Object(PathRemainderAnnotation.Builder b) { 240 super(b); 241 description = copyOf(b.description); 242 def = b.def; 243 parser = b.parser; 244 schema = b.schema; 245 serializer = b.serializer; 246 } 247 248 @Override /* Overridden from PathRemainder */ 249 public String def() { 250 return def; 251 } 252 253 @Override /* Overridden from PathRemainder */ 254 public Class<? extends HttpPartParser> parser() { 255 return parser; 256 } 257 258 @Override /* Overridden from PathRemainder */ 259 public Schema schema() { 260 return schema; 261 } 262 263 @Override /* Overridden from PathRemainder */ 264 public Class<? extends HttpPartSerializer> serializer() { 265 return serializer; 266 } 267 268 @Override /* Overridden from annotation */ 269 public String[] description() { 270 return description; 271 } 272 } 273 274 /** Default value */ 275 public static final PathRemainder DEFAULT = create().build(); 276 277 /** 278 * Instantiates a new builder for this class. 279 * 280 * @return A new builder object. 281 */ 282 public static Builder create() { 283 return new Builder(); 284 } 285 286 /** 287 * Instantiates a new builder for this class. 288 * 289 * @param on The targets this annotation applies to. 290 * @return A new builder object. 291 */ 292 public static Builder create(Class<?>...on) { 293 return create().on(on); 294 } 295 296 /** 297 * Instantiates a new builder for this class. 298 * 299 * @param on The targets this annotation applies to. 300 * @return A new builder object. 301 */ 302 public static Builder create(String...on) { 303 return create().on(on); 304 } 305 306 /** 307 * Returns <jk>true</jk> if the specified annotation contains all default values. 308 * 309 * @param a The annotation to check. 310 * @return <jk>true</jk> if the specified annotation contains all default values. 311 */ 312 public static boolean empty(PathRemainder a) { 313 return a == null || DEFAULT.equals(a); 314 } 315 316 /** 317 * Finds the default value from the specified list of annotations. 318 * 319 * @param pi The parameter. 320 * @return The last matching default value, or empty if not found. 321 */ 322 public static Optional<String> findDef(ParameterInfo pi) { 323 // @formatter:off 324 return AP.find(PathRemainder.class, pi) 325 .stream() 326 .map(AnnotationInfo::inner) 327 .filter(x -> ne(x.def())) 328 .findFirst() 329 .map(x -> x.def()); 330 // @formatter:on 331 } 332}