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