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 RestPut @RestPut} 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 RestPutAnnotation {
045
046   //-----------------------------------------------------------------------------------------------------------------
047   // Static
048   //-----------------------------------------------------------------------------------------------------------------
049
050   /** Default value */
051   public static final RestPut 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      Class<?>[] parsers={};
082      OpSwagger swagger = OpSwaggerAnnotation.DEFAULT;
083      String clientVersion="", debug="", defaultAccept="", defaultCharset="", defaultContentType="", maxInput="", rolesDeclared="", roleGuard="", summary="", value="";
084      String[] consumes={}, defaultRequestFormData={}, defaultRequestQueryData={}, defaultRequestAttributes={}, defaultRequestHeaders={}, defaultResponseHeaders={}, path={}, produces={};
085
086      /**
087       * Constructor.
088       */
089      protected Builder() {
090         super(RestPut.class);
091      }
092
093      /**
094       * Instantiates a new {@link RestPut @RestPut} object initialized with this builder.
095       *
096       * @return A new {@link RestPut @RestPut} object.
097       */
098      public RestPut build() {
099         return new Impl(this);
100      }
101
102      /**
103       * Sets the {@link RestPut#clientVersion()} property on this annotation.
104       *
105       * @param value The new value for this property.
106       * @return This object.
107       */
108      public Builder clientVersion(String value) {
109         this.clientVersion = value;
110         return this;
111      }
112
113      /**
114       * Sets the {@link RestPut#consumes()} property on this annotation.
115       *
116       * @param value The new value for this property.
117       * @return This object.
118       */
119      public Builder consumes(String...value) {
120         this.consumes = value;
121         return this;
122      }
123
124      /**
125       * Sets the {@link RestPut#converters()} property on this annotation.
126       *
127       * @param value The new value for this property.
128       * @return This object.
129       */
130      @SafeVarargs
131      public final Builder converters(Class<? extends RestConverter>...value) {
132         this.converters = value;
133         return this;
134      }
135
136      /**
137       * Sets the {@link RestPut#debug()} property on this annotation.
138       *
139       * @param value The new value for this property.
140       * @return This object.
141       */
142      public Builder debug(String value) {
143         this.debug = value;
144         return this;
145      }
146
147      /**
148       * Sets the {@link RestPut#defaultAccept()} property on this annotation.
149       *
150       * @param value The new value for this property.
151       * @return This object.
152       */
153      public Builder defaultAccept(String value) {
154         this.defaultAccept = value;
155         return this;
156      }
157
158      /**
159       * Sets the {@link RestPut#defaultCharset()} property on this annotation.
160       *
161       * @param value The new value for this property.
162       * @return This object.
163       */
164      public Builder defaultCharset(String value) {
165         this.defaultCharset = value;
166         return this;
167      }
168
169      /**
170       * Sets the {@link RestPut#defaultContentType()} property on this annotation.
171       *
172       * @param value The new value for this property.
173       * @return This object.
174       */
175      public Builder defaultContentType(String value) {
176         this.defaultContentType = value;
177         return this;
178      }
179
180      /**
181       * Sets the {@link RestPut#defaultRequestFormData()} property on this annotation.
182       *
183       * @param value The new value for this property.
184       * @return This object.
185       */
186      public Builder defaultRequestFormData(String...value) {
187         this.defaultRequestFormData = value;
188         return this;
189      }
190
191      /**
192       * Sets the {@link RestPut#defaultRequestQueryData()} property on this annotation.
193       *
194       * @param value The new value for this property.
195       * @return This object.
196       */
197      public Builder defaultRequestQueryData(String...value) {
198         this.defaultRequestQueryData = value;
199         return this;
200      }
201
202      /**
203       * Sets the {@link RestPut#defaultRequestAttributes()} property on this annotation.
204       *
205       * @param value The new value for this property.
206       * @return This object.
207       */
208      public Builder defaultRequestAttributes(String...value) {
209         this.defaultRequestAttributes = value;
210         return this;
211      }
212
213      /**
214       * Sets the {@link RestPut#defaultRequestHeaders()} property on this annotation.
215       *
216       * @param value The new value for this property.
217       * @return This object.
218       */
219      public Builder defaultRequestHeaders(String...value) {
220         this.defaultRequestHeaders = value;
221         return this;
222      }
223
224      /**
225       * Sets the {@link RestPut#defaultResponseHeaders()} property on this annotation.
226       *
227       * @param value The new value for this property.
228       * @return This object.
229       */
230      public Builder defaultResponseHeaders(String...value) {
231         this.defaultResponseHeaders = value;
232         return this;
233      }
234
235      /**
236       * Sets the {@link RestPut#encoders()} property on this annotation.
237       *
238       * @param value The new value for this property.
239       * @return This object.
240       */
241      @SafeVarargs
242      public final Builder encoders(Class<? extends Encoder>...value) {
243         this.encoders = value;
244         return this;
245      }
246
247      /**
248       * Sets the {@link RestPut#guards()} property on this annotation.
249       *
250       * @param value The new value for this property.
251       * @return This object.
252       */
253      @SafeVarargs
254      public final Builder guards(Class<? extends RestGuard>...value) {
255         this.guards = value;
256         return this;
257      }
258
259      /**
260       * Sets the {@link RestPut#matchers()} property on this annotation.
261       *
262       * @param value The new value for this property.
263       * @return This object.
264       */
265      @SafeVarargs
266      public final Builder matchers(Class<? extends RestMatcher>...value) {
267         this.matchers = value;
268         return this;
269      }
270
271      /**
272       * Sets the {@link RestPut#maxInput()} property on this annotation.
273       *
274       * @param value The new value for this property.
275       * @return This object.
276       */
277      public Builder maxInput(String value) {
278         this.maxInput = value;
279         return this;
280      }
281
282      /**
283       * Sets the {@link RestPut#parsers()} property on this annotation.
284       *
285       * @param value The new value for this property.
286       * @return This object.
287       */
288      public Builder parsers(Class<?>...value) {
289         this.parsers = value;
290         return this;
291      }
292
293      /**
294       * Sets the {@link RestPut#path()} property on this annotation.
295       *
296       * @param value The new value for this property.
297       * @return This object.
298       */
299      public Builder path(String...value) {
300         this.path = value;
301         return this;
302      }
303
304      /**
305       * Sets the {@link RestPut#produces()} property on this annotation.
306       *
307       * @param value The new value for this property.
308       * @return This object.
309       */
310      public Builder produces(String...value) {
311         this.produces = value;
312         return this;
313      }
314
315      /**
316       * Sets the {@link RestPut#roleGuard()} property on this annotation.
317       *
318       * @param value The new value for this property.
319       * @return This object.
320       */
321      public Builder roleGuard(String value) {
322         this.roleGuard = value;
323         return this;
324      }
325
326      /**
327       * Sets the {@link RestPut#rolesDeclared()} property on this annotation.
328       *
329       * @param value The new value for this property.
330       * @return This object.
331       */
332      public Builder rolesDeclared(String value) {
333         this.rolesDeclared = value;
334         return this;
335      }
336
337      /**
338       * Sets the {@link RestPut#serializers()} property on this annotation.
339       *
340       * @param value The new value for this property.
341       * @return This object.
342       */
343      @SafeVarargs
344      public final Builder serializers(Class<? extends Serializer>...value) {
345         this.serializers = value;
346         return this;
347      }
348
349      /**
350       * Sets the {@link RestPut#summary()} property on this annotation.
351       *
352       * @param value The new value for this property.
353       * @return This object.
354       */
355      public Builder summary(String value) {
356         this.summary = value;
357         return this;
358      }
359
360      /**
361       * Sets the {@link RestPut#swagger()} property on this annotation.
362       *
363       * @param value The new value for this property.
364       * @return This object.
365       */
366      public Builder swagger(OpSwagger value) {
367         this.swagger = value;
368         return this;
369      }
370
371      /**
372       * Sets the {@link RestPut#value()} property on this annotation.
373       *
374       * @param value The new value for this property.
375       * @return This object.
376       */
377      public Builder value(String value) {
378         this.value = value;
379         return this;
380      }
381
382   }
383
384   //-----------------------------------------------------------------------------------------------------------------
385   // Implementation
386   //-----------------------------------------------------------------------------------------------------------------
387
388   private static class Impl extends TargetedAnnotationImpl implements RestPut {
389
390      private final Class<? extends RestConverter>[] converters;
391      private final Class<? extends RestGuard>[] guards;
392      private final Class<? extends RestMatcher>[] matchers;
393      private final Class<? extends Encoder>[] encoders;
394      private final Class<? extends Serializer>[] serializers;
395      private final Class<?>[] parsers;
396      private final OpSwagger swagger;
397      private final String clientVersion, debug, defaultAccept, defaultCharset, defaultContentType, maxInput, rolesDeclared, roleGuard, summary, value;
398      private final String[] consumes, defaultRequestFormData, defaultRequestQueryData, defaultRequestAttributes, defaultRequestHeaders, defaultResponseHeaders, path, produces;
399
400      Impl(Builder b) {
401         super(b);
402         this.clientVersion = b.clientVersion;
403         this.consumes = copyOf(b.consumes);
404         this.converters = copyOf(b.converters);
405         this.debug = b.debug;
406         this.defaultAccept = b.defaultAccept;
407         this.defaultCharset = b.defaultCharset;
408         this.defaultContentType = b.defaultContentType;
409         this.defaultRequestFormData = copyOf(b.defaultRequestFormData);
410         this.defaultRequestQueryData = copyOf(b.defaultRequestQueryData);
411         this.defaultRequestAttributes = copyOf(b.defaultRequestAttributes);
412         this.defaultRequestHeaders = copyOf(b.defaultRequestHeaders);
413         this.defaultResponseHeaders = copyOf(b.defaultResponseHeaders);
414         this.encoders = copyOf(b.encoders);
415         this.guards = copyOf(b.guards);
416         this.matchers = copyOf(b.matchers);
417         this.maxInput = b.maxInput;
418         this.parsers = copyOf(b.parsers);
419         this.path = copyOf(b.path);
420         this.produces = copyOf(b.produces);
421         this.roleGuard = b.roleGuard;
422         this.rolesDeclared = b.rolesDeclared;
423         this.serializers = copyOf(b.serializers);
424         this.summary = b.summary;
425         this.swagger = b.swagger;
426         this.value = b.value;
427         postConstruct();
428      }
429
430      @Override /* RestPut */
431      public String clientVersion() {
432         return clientVersion;
433      }
434
435      @Override /* RestPut */
436      public String[] consumes() {
437         return consumes;
438      }
439
440      @Override /* RestPut */
441      public Class<? extends RestConverter>[] converters() {
442         return converters;
443      }
444
445      @Override /* RestPut */
446      public String debug() {
447         return debug;
448      }
449
450      @Override /* RestPut */
451      public String defaultAccept() {
452         return defaultAccept;
453      }
454
455      @Override /* RestPut */
456      public String defaultCharset() {
457         return defaultCharset;
458      }
459
460      @Override /* RestPut */
461      public String defaultContentType() {
462         return defaultContentType;
463      }
464
465      @Override /* RestPut */
466      public String[] defaultRequestFormData() {
467         return defaultRequestFormData;
468      }
469
470      @Override /* RestPut */
471      public String[] defaultRequestQueryData() {
472         return defaultRequestQueryData;
473      }
474
475      @Override /* RestPut */
476      public String[] defaultRequestAttributes() {
477         return defaultRequestAttributes;
478      }
479
480      @Override /* RestPut */
481      public String[] defaultRequestHeaders() {
482         return defaultRequestHeaders;
483      }
484
485      @Override /* RestPut */
486      public String[] defaultResponseHeaders() {
487         return defaultResponseHeaders;
488      }
489
490      @Override /* RestPut */
491      public Class<? extends Encoder>[] encoders() {
492         return encoders;
493      }
494
495      @Override /* RestPut */
496      public Class<? extends RestGuard>[] guards() {
497         return guards;
498      }
499
500      @Override /* RestPut */
501      public Class<? extends RestMatcher>[] matchers() {
502         return matchers;
503      }
504
505      @Override /* RestPut */
506      public String maxInput() {
507         return maxInput;
508      }
509
510      @Override /* RestPut */
511      public Class<?>[] parsers() {
512         return parsers;
513      }
514
515      @Override /* RestPut */
516      public String[] path() {
517         return path;
518      }
519
520      @Override /* RestPut */
521      public String[] produces() {
522         return produces;
523      }
524
525      @Override /* RestPut */
526      public String roleGuard() {
527         return roleGuard;
528      }
529
530      @Override /* RestPut */
531      public String rolesDeclared() {
532         return rolesDeclared;
533      }
534
535      @Override /* RestPut */
536      public Class<? extends Serializer>[] serializers() {
537         return serializers;
538      }
539
540      @Override /* RestPut */
541      public String summary() {
542         return summary;
543      }
544
545      @Override /* RestPut */
546      public OpSwagger swagger() {
547         return swagger;
548      }
549
550      @Override /* RestPut */
551      public String value() {
552         return value;
553      }
554   }
555
556   //-----------------------------------------------------------------------------------------------------------------
557   // Appliers
558   //-----------------------------------------------------------------------------------------------------------------
559
560   /**
561    * Applies {@link RestPut} annotations to a {@link org.apache.juneau.rest.RestOpContext.Builder}.
562    */
563   public static class RestOpContextApply extends AnnotationApplier<RestPut,RestOpContext.Builder> {
564
565      /**
566       * Constructor.
567       *
568       * @param vr The resolver for resolving values in annotations.
569       */
570      public RestOpContextApply(VarResolverSession vr) {
571         super(RestPut.class, RestOpContext.Builder.class, vr);
572      }
573
574      @Override
575      public void apply(AnnotationInfo<RestPut> ai, RestOpContext.Builder b) {
576         RestPut a = ai.inner();
577
578         b.httpMethod("put");
579
580         classes(a.serializers()).ifPresent(x -> b.serializers().set(x));
581         classes(a.parsers()).ifPresent(x -> b.parsers().set(x));
582         classes(a.encoders()).ifPresent(x -> b.encoders().set(x));
583         stream(a.produces()).map(MediaType::of).forEach(x -> b.produces(x));
584         stream(a.consumes()).map(MediaType::of).forEach(x -> b.consumes(x));
585         stream(a.defaultRequestHeaders()).map(HttpHeaders::stringHeader).forEach(x -> b.defaultRequestHeaders().setDefault(x));
586         stream(a.defaultResponseHeaders()).map(HttpHeaders::stringHeader).forEach(x -> b.defaultResponseHeaders().setDefault(x));
587         stream(a.defaultRequestAttributes()).map(BasicNamedAttribute::ofPair).forEach(x -> b.defaultRequestAttributes().add(x));
588         stream(a.defaultRequestQueryData()).map(HttpParts::basicPart).forEach(x -> b.defaultRequestQueryData().setDefault(x));
589         stream(a.defaultRequestFormData()).map(HttpParts::basicPart).forEach(x -> b.defaultRequestFormData().setDefault(x));
590         string(a.defaultAccept()).map(HttpHeaders::accept).ifPresent(x -> b.defaultRequestHeaders().setDefault(x));
591         string(a.defaultContentType()).map(HttpHeaders::contentType).ifPresent(x -> b.defaultRequestHeaders().setDefault(x));
592         b.converters().append(a.converters());
593         b.guards().append(a.guards());
594         b.matchers().append(a.matchers());
595         string(a.clientVersion()).ifPresent(x -> b.clientVersion(x));
596         string(a.defaultCharset()).map(Charset::forName).ifPresent(x -> b.defaultCharset(x));
597         string(a.maxInput()).ifPresent(x -> b.maxInput(x));
598         stream(a.path()).forEach(x -> b.path(x));
599         string(a.value()).ifPresent(x -> b.path(x));
600         cdl(a.rolesDeclared()).forEach(x -> b.rolesDeclared(x));
601         string(a.roleGuard()).ifPresent(x -> b.roleGuard(x));
602         string(a.debug()).map(Enablement::fromString).ifPresent(x -> b.debug(x));
603      }
604   }
605}