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.rest.annotation;
014
015import static org.apache.juneau.http.HttpHeaders.*;
016import static org.apache.juneau.internal.ArrayUtils.*;
017import static org.apache.juneau.http.HttpParts.*;
018
019import java.lang.annotation.*;
020import java.nio.charset.*;
021
022import org.apache.juneau.*;
023import org.apache.juneau.annotation.*;
024import org.apache.juneau.encoders.*;
025import org.apache.juneau.reflect.*;
026import org.apache.juneau.rest.*;
027import org.apache.juneau.rest.converter.*;
028import org.apache.juneau.rest.guard.*;
029import org.apache.juneau.rest.httppart.*;
030import org.apache.juneau.rest.matcher.*;
031import org.apache.juneau.serializer.*;
032import org.apache.juneau.svl.*;
033
034/**
035 * Utility classes and methods for the {@link RestGet @RestGet} annotation.
036 *
037 * <h5 class='section'>See Also:</h5><ul>
038 *    <li class='link'><a class="doclink" href="../../../../../index.html#jrs.RestOpAnnotatedMethods">@RestOp-Annotated Methods</a>
039 * </ul>
040 */
041public class RestGetAnnotation {
042
043   //-----------------------------------------------------------------------------------------------------------------
044   // Static
045   //-----------------------------------------------------------------------------------------------------------------
046
047   /** Default value */
048   public static final RestGet DEFAULT = create().build();
049
050   /**
051    * Instantiates a new builder for this class.
052    *
053    * @return A new builder object.
054    */
055   public static Builder create() {
056      return new Builder();
057   }
058
059   //-----------------------------------------------------------------------------------------------------------------
060   // Builder
061   //-----------------------------------------------------------------------------------------------------------------
062
063   /**
064    * Builder class.
065    *
066    * <h5 class='section'>See Also:</h5><ul>
067    *    <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)}
068    * </ul>
069    */
070   @SuppressWarnings("unchecked")
071   public static class Builder extends TargetedAnnotationMBuilder {
072
073      Class<? extends RestConverter>[] converters = new Class[0];
074      Class<? extends RestGuard>[] guards = new Class[0];
075      Class<? extends RestMatcher>[] matchers = new Class[0];
076      Class<? extends Encoder>[] encoders = new Class[0];
077      Class<? extends Serializer>[] serializers = new Class[0];
078      OpSwagger swagger = OpSwaggerAnnotation.DEFAULT;
079      String clientVersion="", debug="", defaultAccept="", defaultCharset="", rolesDeclared="", roleGuard="", summary="", value="";
080      String[] defaultRequestQueryData={}, defaultRequestAttributes={}, defaultRequestHeaders={}, defaultResponseHeaders={}, description={}, path={}, produces={};
081
082      /**
083       * Constructor.
084       */
085      protected Builder() {
086         super(RestGet.class);
087      }
088
089      /**
090       * Instantiates a new {@link RestGet @RestGet} object initialized with this builder.
091       *
092       * @return A new {@link RestGet @RestGet} object.
093       */
094      public RestGet build() {
095         return new Impl(this);
096      }
097
098      /**
099       * Sets the {@link RestGet#clientVersion()} property on this annotation.
100       *
101       * @param value The new value for this property.
102       * @return This object.
103       */
104      public Builder clientVersion(String value) {
105         this.clientVersion = value;
106         return this;
107      }
108
109      /**
110       * Sets the {@link RestGet#converters()} property on this annotation.
111       *
112       * @param value The new value for this property.
113       * @return This object.
114       */
115      public Builder converters(Class<? extends RestConverter>...value) {
116         this.converters = value;
117         return this;
118      }
119
120      /**
121       * Sets the {@link RestGet#debug()} property on this annotation.
122       *
123       * @param value The new value for this property.
124       * @return This object.
125       */
126      public Builder debug(String value) {
127         this.debug = value;
128         return this;
129      }
130
131      /**
132       * Sets the {@link RestGet#defaultAccept()} property on this annotation.
133       *
134       * @param value The new value for this property.
135       * @return This object.
136       */
137      public Builder defaultAccept(String value) {
138         this.defaultAccept = value;
139         return this;
140      }
141
142      /**
143       * Sets the {@link RestGet#defaultCharset()} property on this annotation.
144       *
145       * @param value The new value for this property.
146       * @return This object.
147       */
148      public Builder defaultCharset(String value) {
149         this.defaultCharset = value;
150         return this;
151      }
152
153      /**
154       * Sets the {@link RestGet#defaultRequestQueryData()} property on this annotation.
155       *
156       * @param value The new value for this property.
157       * @return This object.
158       */
159      public Builder defaultRequestQueryData(String...value) {
160         this.defaultRequestQueryData = value;
161         return this;
162      }
163
164      /**
165       * Sets the {@link RestGet#defaultRequestAttributes()} property on this annotation.
166       *
167       * @param value The new value for this property.
168       * @return This object.
169       */
170      public Builder defaultRequestAttributes(String...value) {
171         this.defaultRequestAttributes = value;
172         return this;
173      }
174
175      /**
176       * Sets the {@link RestGet#defaultRequestHeaders()} property on this annotation.
177       *
178       * @param value The new value for this property.
179       * @return This object.
180       */
181      public Builder defaultRequestHeaders(String...value) {
182         this.defaultRequestHeaders = value;
183         return this;
184      }
185
186      /**
187       * Sets the {@link RestGet#defaultResponseHeaders()} property on this annotation.
188       *
189       * @param value The new value for this property.
190       * @return This object.
191       */
192      public Builder defaultResponseHeaders(String...value) {
193         this.defaultResponseHeaders = value;
194         return this;
195      }
196
197      /**
198       * Sets the {@link RestGet#description()} property on this annotation.
199       *
200       * @param value The new value for this property.
201       * @return This object.
202       */
203      public Builder description(String...value) {
204         this.description = value;
205         return this;
206      }
207
208      /**
209       * Sets the {@link RestGet#encoders()} property on this annotation.
210       *
211       * @param value The new value for this property.
212       * @return This object.
213       */
214      public Builder encoders(Class<? extends Encoder>...value) {
215         this.encoders = value;
216         return this;
217      }
218
219      /**
220       * Sets the {@link RestGet#guards()} property on this annotation.
221       *
222       * @param value The new value for this property.
223       * @return This object.
224       */
225      public Builder guards(Class<? extends RestGuard>...value) {
226         this.guards = value;
227         return this;
228      }
229
230      /**
231       * Sets the {@link RestGet#matchers()} property on this annotation.
232       *
233       * @param value The new value for this property.
234       * @return This object.
235       */
236      public Builder matchers(Class<? extends RestMatcher>...value) {
237         this.matchers = value;
238         return this;
239      }
240
241      /**
242       * Sets the {@link RestGet#path()} property on this annotation.
243       *
244       * @param value The new value for this property.
245       * @return This object.
246       */
247      public Builder path(String...value) {
248         this.path = value;
249         return this;
250      }
251
252      /**
253       * Sets the {@link RestGet#produces()} property on this annotation.
254       *
255       * @param value The new value for this property.
256       * @return This object.
257       */
258      public Builder produces(String...value) {
259         this.produces = value;
260         return this;
261      }
262
263      /**
264       * Sets the {@link RestGet#roleGuard()} property on this annotation.
265       *
266       * @param value The new value for this property.
267       * @return This object.
268       */
269      public Builder roleGuard(String value) {
270         this.roleGuard = value;
271         return this;
272      }
273
274      /**
275       * Sets the {@link RestGet#rolesDeclared()} property on this annotation.
276       *
277       * @param value The new value for this property.
278       * @return This object.
279       */
280      public Builder rolesDeclared(String value) {
281         this.rolesDeclared = value;
282         return this;
283      }
284
285      /**
286       * Sets the {@link RestGet#serializers()} property on this annotation.
287       *
288       * @param value The new value for this property.
289       * @return This object.
290       */
291      public Builder serializers(Class<? extends Serializer>...value) {
292         this.serializers = value;
293         return this;
294      }
295
296      /**
297       * Sets the {@link RestGet#summary()} property on this annotation.
298       *
299       * @param value The new value for this property.
300       * @return This object.
301       */
302      public Builder summary(String value) {
303         this.summary = value;
304         return this;
305      }
306
307      /**
308       * Sets the {@link RestGet#swagger()} property on this annotation.
309       *
310       * @param value The new value for this property.
311       * @return This object.
312       */
313      public Builder swagger(OpSwagger value) {
314         this.swagger = value;
315         return this;
316      }
317
318      /**
319       * Sets the {@link RestGet#value()} property on this annotation.
320       *
321       * @param value The new value for this property.
322       * @return This object.
323       */
324      public Builder value(String value) {
325         this.value = value;
326         return this;
327      }
328
329      // <FluentSetters>
330
331      @Override /* GENERATED - TargetedAnnotationBuilder */
332      public Builder on(String...values) {
333         super.on(values);
334         return this;
335      }
336
337      @Override /* GENERATED - TargetedAnnotationTMBuilder */
338      public Builder on(java.lang.reflect.Method...value) {
339         super.on(value);
340         return this;
341      }
342
343      // </FluentSetters>
344   }
345
346   //-----------------------------------------------------------------------------------------------------------------
347   // Implementation
348   //-----------------------------------------------------------------------------------------------------------------
349
350   private static class Impl extends TargetedAnnotationImpl implements RestGet {
351
352      private final Class<? extends RestConverter>[] converters;
353      private final Class<? extends RestGuard>[] guards;
354      private final Class<? extends RestMatcher>[] matchers;
355      private final Class<? extends Encoder>[] encoders;
356      private final Class<? extends Serializer>[] serializers;
357      private final OpSwagger swagger;
358      private final String clientVersion, debug, defaultAccept, defaultCharset, rolesDeclared, roleGuard, summary, value;
359      private final String[] defaultRequestQueryData, defaultRequestAttributes, defaultRequestHeaders, defaultResponseHeaders, description, path, produces;
360
361      Impl(Builder b) {
362         super(b);
363         this.clientVersion = b.clientVersion;
364         this.converters = copyOf(b.converters);
365         this.debug = b.debug;
366         this.defaultAccept = b.defaultAccept;
367         this.defaultCharset = b.defaultCharset;
368         this.defaultRequestQueryData = copyOf(b.defaultRequestQueryData);
369         this.defaultRequestAttributes = copyOf(b.defaultRequestAttributes);
370         this.defaultRequestHeaders = copyOf(b.defaultRequestHeaders);
371         this.defaultResponseHeaders = copyOf(b.defaultResponseHeaders);
372         this.description = copyOf(b.description);
373         this.encoders = copyOf(b.encoders);
374         this.guards = copyOf(b.guards);
375         this.matchers = copyOf(b.matchers);
376         this.path = copyOf(b.path);
377         this.produces = copyOf(b.produces);
378         this.roleGuard = b.roleGuard;
379         this.rolesDeclared = b.rolesDeclared;
380         this.serializers = copyOf(b.serializers);
381         this.summary = b.summary;
382         this.swagger = b.swagger;
383         this.value = b.value;
384         postConstruct();
385      }
386
387      @Override /* RestGet */
388      public String clientVersion() {
389         return clientVersion;
390      }
391
392      @Override /* RestGet */
393      public Class<? extends RestConverter>[] converters() {
394         return converters;
395      }
396
397      @Override /* RestGet */
398      public String debug() {
399         return debug;
400      }
401
402      @Override /* RestGet */
403      public String defaultAccept() {
404         return defaultAccept;
405      }
406
407      @Override /* RestGet */
408      public String defaultCharset() {
409         return defaultCharset;
410      }
411
412      @Override /* RestGet */
413      public String[] defaultRequestQueryData() {
414         return defaultRequestQueryData;
415      }
416
417      @Override /* RestGet */
418      public String[] defaultRequestAttributes() {
419         return defaultRequestAttributes;
420      }
421
422      @Override /* RestGet */
423      public String[] defaultRequestHeaders() {
424         return defaultRequestHeaders;
425      }
426
427      @Override /* RestGet */
428      public String[] defaultResponseHeaders() {
429         return defaultResponseHeaders;
430      }
431
432      @Override /* RestGet */
433      public String[] description() {
434         return description;
435      }
436
437      @Override /* RestGet */
438      public Class<? extends Encoder>[] encoders() {
439         return encoders;
440      }
441
442      @Override /* RestGet */
443      public Class<? extends RestGuard>[] guards() {
444         return guards;
445      }
446
447      @Override /* RestGet */
448      public Class<? extends RestMatcher>[] matchers() {
449         return matchers;
450      }
451
452      @Override /* RestGet */
453      public String[] path() {
454         return path;
455      }
456
457      @Override /* RestGet */
458      public String[] produces() {
459         return produces;
460      }
461
462      @Override /* RestGet */
463      public String roleGuard() {
464         return roleGuard;
465      }
466
467      @Override /* RestGet */
468      public String rolesDeclared() {
469         return rolesDeclared;
470      }
471
472      @Override /* RestGet */
473      public Class<? extends Serializer>[] serializers() {
474         return serializers;
475      }
476
477      @Override /* RestGet */
478      public String summary() {
479         return summary;
480      }
481
482      @Override /* RestGet */
483      public OpSwagger swagger() {
484         return swagger;
485      }
486
487      @Override /* RestGet */
488      public String value() {
489         return value;
490      }
491   }
492
493   //-----------------------------------------------------------------------------------------------------------------
494   // Appliers
495   //-----------------------------------------------------------------------------------------------------------------
496
497   /**
498    * Applies {@link RestGet} annotations to a {@link org.apache.juneau.rest.RestOpContext.Builder}.
499    */
500   public static class RestOpContextApply extends AnnotationApplier<RestGet,RestOpContext.Builder> {
501
502      /**
503       * Constructor.
504       *
505       * @param vr The resolver for resolving values in annotations.
506       */
507      public RestOpContextApply(VarResolverSession vr) {
508         super(RestGet.class, RestOpContext.Builder.class, vr);
509      }
510
511      @Override
512      public void apply(AnnotationInfo<RestGet> ai, RestOpContext.Builder b) {
513         RestGet a = ai.inner();
514
515         b.httpMethod("get");
516
517         classes(a.serializers()).ifPresent(x -> b.serializers().set(x));
518         classes(a.encoders()).ifPresent(x -> b.encoders().set(x));
519         stream(a.produces()).map(MediaType::of).forEach(x -> b.produces(x));
520         stream(a.defaultRequestHeaders()).map(x -> stringHeader(x)).forEach(x -> b.defaultRequestHeaders().setDefault(x));
521         stream(a.defaultResponseHeaders()).map(x -> stringHeader(x)).forEach(x -> b.defaultResponseHeaders().setDefault(x));
522         stream(a.defaultRequestAttributes()).map(x -> BasicNamedAttribute.ofPair(x)).forEach(x -> b.defaultRequestAttributes().add(x));
523         stream(a.defaultRequestQueryData()).map(x -> basicPart(x)).forEach(x -> b.defaultRequestQueryData().setDefault(x));
524         string(a.defaultAccept()).map(x -> accept(x)).ifPresent(x -> b.defaultRequestHeaders().setDefault(x));
525         b.converters().append(a.converters());
526         b.guards().append(a.guards());
527         b.matchers().append(a.matchers());
528         string(a.clientVersion()).ifPresent(x -> b.clientVersion(x));
529         string(a.defaultCharset()).map(Charset::forName).ifPresent(x -> b.defaultCharset(x));
530         stream(a.path()).forEach(x -> b.path(x));
531         string(a.value()).ifPresent(x -> b.path(x));
532         cdl(a.rolesDeclared()).forEach(x -> b.rolesDeclared(x));
533         string(a.roleGuard()).ifPresent(x -> b.roleGuard(x));
534         string(a.debug()).map(Enablement::fromString).ifPresent(x -> b.debug(x));
535      }
536   }
537}