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