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.server;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.lang.annotation.*;
022import java.util.function.*;
023
024import org.apache.juneau.commons.*;
025import org.apache.juneau.commons.reflect.*;
026import org.apache.juneau.marshall.encoders.*;
027import org.apache.juneau.marshall.serializer.*;
028import org.apache.juneau.rest.server.converter.*;
029import org.apache.juneau.rest.server.guard.*;
030import org.apache.juneau.rest.server.matcher.*;
031
032/**
033 * Utility classes and methods for the {@link RestOp @RestOp} annotation.
034 *
035 * <h5 class='section'>See Also:</h5><ul>
036 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestOpAnnotatedMethods">@RestOp-Annotated Method</a>
037 * </ul>
038 */
039public class RestOpAnnotation {
040
041   /**
042    * Private constructor to prevent instantiation.
043    */
044   private RestOpAnnotation() {
045      // Utility class - prevent instantiation
046   }
047
048   /**
049    * Builder class.
050    *
051    * <h5 class='section'>See Also:</h5><ul>
052    *    <li class='jm'>{@link org.apache.juneau.marshall.MarshallingContext.Builder#annotations(Annotation...)}
053    * </ul>
054    */
055   @SuppressWarnings({
056      "unchecked" // Type erasure requires cast for Builder inheritance
057   })
058   public static class Builder extends AnnotationObject.Builder {
059
060      private String[] description = {};
061      private Class<? extends RestConverter>[] converters = new Class[0];
062      private Class<? extends RestGuard>[] guards = new Class[0];
063      private Class<? extends RestMatcher>[] matchers = new Class[0];
064      private Class<? extends Encoder>[] encoders = new Class[0];
065      private Class<? extends Serializer>[] serializers = new Class[0];
066      private Class<?>[] parsers = {};
067      private OpSwagger swagger = OpSwaggerAnnotation.DEFAULT;
068      private String clientVersion = "";
069      private String defaultAccept = "";
070      private String defaultCharset = "";
071      private String defaultContentType = "";
072      private String maxInput = "";
073      private String method = "";
074      private String observability = "";
075      private String metricName = "";
076      private String metricTags = "";
077      private String problemDetails = "";
078      private String debugMarshalling = "";
079      private String virtualThreads = "";
080      private String asyncTimeoutMillis = "";
081      private String asyncCompletionExecutor = "";
082      private String rolesDeclared = "";
083      private String roleGuard = "";
084      private String summary = "";
085      private String value = "";
086      private String[] consumes = {};
087      private String[] defaultRequestFormData = {};
088      private String[] defaultRequestQueryData = {};
089      private String[] defaultRequestAttributes = {};
090      private String[] defaultRequestHeaders = {};
091      private String[] defaultResponseHeaders = {};
092      private String[] path = {};
093      private String[] produces = {};
094      private String[] allowedSerializerOptions = {};
095      private String[] allowedParserOptions = {};
096      private String[] noInherit = {};
097      private boolean read;
098
099      /**
100       * Constructor.
101       */
102      protected Builder() {
103         super(RestOp.class);
104      }
105
106      /**
107       * Instantiates a new {@link RestOp @RestOp} object initialized with this builder.
108       *
109       * @return A new {@link RestOp @RestOp} object.
110       */
111      public RestOp build() {
112         return new Object(this);
113      }
114
115      /**
116       * Sets the description property on this annotation.
117       *
118       * @param value The new value for this property.
119       * @return This object.
120       */
121      public Builder description(String...value) {
122         description = value;
123         return this;
124      }
125
126      /**
127       * Sets the {@link RestOp#clientVersion()} property on this annotation.
128       *
129       * @param value The new value for this property.
130       * @return This object.
131       */
132      public Builder clientVersion(String value) {
133         clientVersion = value;
134         return this;
135      }
136
137      /**
138       * Sets the {@link RestOp#consumes()} property on this annotation.
139       *
140       * @param value The new value for this property.
141       * @return This object.
142       */
143      public Builder consumes(String...value) {
144         consumes = value;
145         return this;
146      }
147
148      /**
149       * Sets the {@link RestOp#converters()} property on this annotation.
150       *
151       * @param value The new value for this property.
152       * @return This object.
153       */
154      @SafeVarargs
155      public final Builder converters(Class<? extends RestConverter>...value) {
156         converters = value;
157         return this;
158      }
159
160      /**
161       * Sets the {@link RestOp#defaultAccept()} property on this annotation.
162       *
163       * @param value The new value for this property.
164       * @return This object.
165       */
166      public Builder defaultAccept(String value) {
167         defaultAccept = value;
168         return this;
169      }
170
171      /**
172       * Sets the {@link RestOp#defaultCharset()} property on this annotation.
173       *
174       * @param value The new value for this property.
175       * @return This object.
176       */
177      public Builder defaultCharset(String value) {
178         defaultCharset = value;
179         return this;
180      }
181
182      /**
183       * Sets the {@link RestOp#defaultContentType()} property on this annotation.
184       *
185       * @param value The new value for this property.
186       * @return This object.
187       */
188      public Builder defaultContentType(String value) {
189         defaultContentType = value;
190         return this;
191      }
192
193      /**
194       * Sets the {@link RestOp#defaultRequestAttributes()} property on this annotation.
195       *
196       * @param value The new value for this property.
197       * @return This object.
198       */
199      public Builder defaultRequestAttributes(String...value) {
200         defaultRequestAttributes = value;
201         return this;
202      }
203
204      /**
205       * Sets the {@link RestOp#defaultRequestFormData()} property on this annotation.
206       *
207       * @param value The new value for this property.
208       * @return This object.
209       */
210      public Builder defaultRequestFormData(String...value) {
211         defaultRequestFormData = value;
212         return this;
213      }
214
215      /**
216       * Sets the {@link RestOp#defaultRequestHeaders()} property on this annotation.
217       *
218       * @param value The new value for this property.
219       * @return This object.
220       */
221      public Builder defaultRequestHeaders(String...value) {
222         defaultRequestHeaders = value;
223         return this;
224      }
225
226      /**
227       * Sets the {@link RestOp#defaultRequestQueryData()} property on this annotation.
228       *
229       * @param value The new value for this property.
230       * @return This object.
231       */
232      public Builder defaultRequestQueryData(String...value) {
233         defaultRequestQueryData = value;
234         return this;
235      }
236
237      /**
238       * Sets the {@link RestOp#defaultResponseHeaders()} property on this annotation.
239       *
240       * @param value The new value for this property.
241       * @return This object.
242       */
243      public Builder defaultResponseHeaders(String...value) {
244         defaultResponseHeaders = value;
245         return this;
246      }
247
248      /**
249       * Sets the {@link RestOp#encoders()} property on this annotation.
250       *
251       * @param value The new value for this property.
252       * @return This object.
253       */
254      @SafeVarargs
255      public final Builder encoders(Class<? extends Encoder>...value) {
256         encoders = value;
257         return this;
258      }
259
260      /**
261       * Sets the {@link RestOp#guards()} property on this annotation.
262       *
263       * @param value The new value for this property.
264       * @return This object.
265       */
266      @SafeVarargs
267      public final Builder guards(Class<? extends RestGuard>...value) {
268         guards = value;
269         return this;
270      }
271
272      /**
273       * Sets the {@link RestOp#matchers()} property on this annotation.
274       *
275       * @param value The new value for this property.
276       * @return This object.
277       */
278      @SafeVarargs
279      public final Builder matchers(Class<? extends RestMatcher>...value) {
280         matchers = value;
281         return this;
282      }
283
284      /**
285       * Sets the {@link RestOp#maxInput()} property on this annotation.
286       *
287       * @param value The new value for this property.
288       * @return This object.
289       */
290      public Builder maxInput(String value) {
291         maxInput = value;
292         return this;
293      }
294
295      /**
296       * Sets the {@link RestOp#method()} property on this annotation.
297       *
298       * @param value The new value for this property.
299       * @return This object.
300       */
301      public Builder method(String value) {
302         method = value;
303         return this;
304      }
305
306      /**
307       * Sets the {@link RestOp#parsers()} property on this annotation.
308       *
309       * @param value The new value for this property.
310       * @return This object.
311       */
312      public Builder parsers(Class<?>...value) {
313         parsers = value;
314         return this;
315      }
316
317      /**
318       * Sets the {@link RestOp#path()} property on this annotation.
319       *
320       * @param value The new value for this property.
321       * @return This object.
322       */
323      public Builder path(String...value) {
324         path = value;
325         return this;
326      }
327
328      /**
329       * Sets the {@link RestOp#problemDetails()} property on this annotation.
330       *
331       * @param value The new value for this property.
332       * @return This object.
333       */
334      public Builder problemDetails(String value) {
335         problemDetails = value;
336         return this;
337      }
338
339      /**
340       * Sets the {@link RestOp#debugMarshalling()} property on this annotation.
341       *
342       * @param value The new value for this property.
343       * @return This object.
344       */
345      public Builder debugMarshalling(String value) {
346         debugMarshalling = value;
347         return this;
348      }
349
350      /**
351       * Sets the {@link RestOp#observability()} property on this annotation.
352       *
353       * @param value The new value for this property.
354       * @return This object.
355       */
356      public Builder observability(String value) {
357         observability = value;
358         return this;
359      }
360
361      /**
362       * Sets the {@link RestOp#metricName()} property on this annotation.
363       *
364       * @param value The new value for this property.
365       * @return This object.
366       */
367      public Builder metricName(String value) {
368         metricName = value;
369         return this;
370      }
371
372      /**
373       * Sets the {@link RestOp#metricTags()} property on this annotation.
374       *
375       * @param value The new value for this property.
376       * @return This object.
377       */
378      public Builder metricTags(String value) {
379         metricTags = value;
380         return this;
381      }
382
383      /**
384       * Sets the {@link RestOp#virtualThreads()} property on this annotation.
385       *
386       * @param value The new value for this property.
387       * @return This object.
388       */
389      public Builder virtualThreads(String value) {
390         virtualThreads = value;
391         return this;
392      }
393
394      /**
395       * Sets the {@link RestOp#asyncTimeoutMillis()} property on this annotation.
396       *
397       * @param value The new value for this property.
398       * @return This object.
399       */
400      public Builder asyncTimeoutMillis(String value) {
401         asyncTimeoutMillis = value;
402         return this;
403      }
404
405      /**
406       * Sets the {@link RestOp#asyncCompletionExecutor()} property on this annotation.
407       *
408       * @param value The new value for this property.
409       * @return This object.
410       */
411      public Builder asyncCompletionExecutor(String value) {
412         asyncCompletionExecutor = value;
413         return this;
414      }
415
416      /**
417       * Sets the {@link RestOp#produces()} property on this annotation.
418       *
419       * @param value The new value for this property.
420       * @return This object.
421       */
422      public Builder produces(String...value) {
423         produces = value;
424         return this;
425      }
426
427      /**
428       * Sets the {@link RestOp#allowedSerializerOptions()} property on this annotation.
429       *
430       * @param value The new value for this property.
431       * @return This object.
432       */
433      public Builder allowedSerializerOptions(String...value) {
434         allowedSerializerOptions = value;
435         return this;
436      }
437
438      /**
439       * Sets the {@link RestOp#allowedParserOptions()} property on this annotation.
440       *
441       * @param value The new value for this property.
442       * @return This object.
443       */
444      public Builder allowedParserOptions(String...value) {
445         allowedParserOptions = value;
446         return this;
447      }
448
449      /**
450       * Sets the {@link RestOp#noInherit()} property on this annotation.
451       *
452       * @param value The new value for this property.
453       * @return This object.
454       */
455      public Builder noInherit(String...value) {
456         noInherit = value;
457         return this;
458      }
459
460      /**
461       * Sets the {@link RestOp#read()} property on this annotation.
462       *
463       * @param value The new value for this property.
464       * @return This object.
465       * @since 10.0.0
466       */
467      public Builder read(boolean value) {
468         read = value;
469         return this;
470      }
471
472      /**
473       * Sets the {@link RestOp#roleGuard()} property on this annotation.
474       *
475       * @param value The new value for this property.
476       * @return This object.
477       */
478      public Builder roleGuard(String value) {
479         roleGuard = value;
480         return this;
481      }
482
483      /**
484       * Sets the {@link RestOp#rolesDeclared()} property on this annotation.
485       *
486       * @param value The new value for this property.
487       * @return This object.
488       */
489      public Builder rolesDeclared(String value) {
490         rolesDeclared = value;
491         return this;
492      }
493
494      /**
495       * Sets the {@link RestOp#serializers()} property on this annotation.
496       *
497       * @param value The new value for this property.
498       * @return This object.
499       */
500      @SafeVarargs
501      public final Builder serializers(Class<? extends Serializer>...value) {
502         serializers = value;
503         return this;
504      }
505
506      /**
507       * Sets the {@link RestOp#summary()} property on this annotation.
508       *
509       * @param value The new value for this property.
510       * @return This object.
511       */
512      public Builder summary(String value) {
513         summary = value;
514         return this;
515      }
516
517      /**
518       * Sets the {@link RestOp#swagger()} property on this annotation.
519       *
520       * @param value The new value for this property.
521       * @return This object.
522       */
523      public Builder swagger(OpSwagger value) {
524         swagger = value;
525         return this;
526      }
527
528      /**
529       * Sets the {@link RestOp#value()} property on this annotation.
530       *
531       * @param value The new value for this property.
532       * @return This object.
533       */
534      public Builder value(String value) {
535         this.value = value;
536         return this;
537      }
538   }
539
540   @SuppressWarnings({
541      "java:S2160" // equals() inherited from AnnotationObject compares all annotation interface methods; subclass fields are accessed via those methods
542   })
543   private static class Object extends AnnotationObject implements RestOp {
544
545      private final String[] description;
546      private final Class<? extends RestConverter>[] converters;
547      private final Class<? extends RestGuard>[] guards;
548      private final Class<? extends RestMatcher>[] matchers;
549      private final Class<? extends Encoder>[] encoders;
550      private final Class<? extends Serializer>[] serializers;
551      private final Class<?>[] parsers;
552      private final OpSwagger swagger;
553      private final String clientVersion;
554      private final String defaultAccept;
555      private final String defaultCharset;
556      private final String defaultContentType;
557      private final String maxInput;
558      private final String method;
559      private final String observability;
560      private final String metricName;
561      private final String metricTags;
562      private final String problemDetails;
563      private final String debugMarshalling;
564      private final String virtualThreads;
565      private final String asyncTimeoutMillis;
566      private final String asyncCompletionExecutor;
567      private final String rolesDeclared;
568      private final String roleGuard;
569      private final String summary;
570      private final String value;
571      private final String[] consumes;
572      private final String[] defaultRequestFormData;
573      private final String[] defaultRequestQueryData;
574      private final String[] defaultRequestAttributes;
575      private final String[] defaultRequestHeaders;
576      private final String[] defaultResponseHeaders;
577      private final String[] path;
578      private final String[] produces;
579      private final String[] allowedSerializerOptions;
580      private final String[] allowedParserOptions;
581      private final String[] noInherit;
582      private final boolean read;
583
584      Object(RestOpAnnotation.Builder b) {
585         super(b);
586         description = cp(b.description);
587         clientVersion = b.clientVersion;
588         consumes = cp(b.consumes);
589         converters = cp(b.converters);
590         defaultAccept = b.defaultAccept;
591         defaultCharset = b.defaultCharset;
592         defaultContentType = b.defaultContentType;
593         defaultRequestFormData = cp(b.defaultRequestFormData);
594         defaultRequestQueryData = cp(b.defaultRequestQueryData);
595         defaultRequestAttributes = cp(b.defaultRequestAttributes);
596         defaultRequestHeaders = cp(b.defaultRequestHeaders);
597         defaultResponseHeaders = cp(b.defaultResponseHeaders);
598         encoders = cp(b.encoders);
599         guards = cp(b.guards);
600         matchers = cp(b.matchers);
601         maxInput = b.maxInput;
602         method = b.method;
603         parsers = cp(b.parsers);
604         path = cp(b.path);
605         observability = b.observability;
606         metricName = b.metricName;
607         metricTags = b.metricTags;
608         problemDetails = b.problemDetails;
609         debugMarshalling = b.debugMarshalling;
610         virtualThreads = b.virtualThreads;
611         asyncTimeoutMillis = b.asyncTimeoutMillis;
612         asyncCompletionExecutor = b.asyncCompletionExecutor;
613         produces = cp(b.produces);
614         allowedSerializerOptions = cp(b.allowedSerializerOptions);
615         allowedParserOptions = cp(b.allowedParserOptions);
616         noInherit = cp(b.noInherit);
617         read = b.read;
618         roleGuard = b.roleGuard;
619         rolesDeclared = b.rolesDeclared;
620         serializers = cp(b.serializers);
621         summary = b.summary;
622         swagger = b.swagger;
623         value = b.value;
624      }
625
626      @Override /* Overridden from RestOp */
627      public String clientVersion() {
628         return clientVersion;
629      }
630
631      @Override /* Overridden from RestOp */
632      public String[] consumes() {
633         return consumes;
634      }
635
636      @Override /* Overridden from RestOp */
637      public Class<? extends RestConverter>[] converters() {
638         return converters;
639      }
640
641      @Override /* Overridden from RestOp */
642      public String defaultAccept() {
643         return defaultAccept;
644      }
645
646      @Override /* Overridden from RestOp */
647      public String defaultCharset() {
648         return defaultCharset;
649      }
650
651      @Override /* Overridden from RestOp */
652      public String defaultContentType() {
653         return defaultContentType;
654      }
655
656      @Override /* Overridden from RestOp */
657      public String[] defaultRequestAttributes() {
658         return defaultRequestAttributes;
659      }
660
661      @Override /* Overridden from RestOp */
662      public String[] defaultRequestFormData() {
663         return defaultRequestFormData;
664      }
665
666      @Override /* Overridden from RestOp */
667      public String[] defaultRequestHeaders() {
668         return defaultRequestHeaders;
669      }
670
671      @Override /* Overridden from RestOp */
672      public String[] defaultRequestQueryData() {
673         return defaultRequestQueryData;
674      }
675
676      @Override /* Overridden from RestOp */
677      public String[] defaultResponseHeaders() {
678         return defaultResponseHeaders;
679      }
680
681      @Override /* Overridden from RestOp */
682      public Class<? extends Encoder>[] encoders() {
683         return encoders;
684      }
685
686      @Override /* Overridden from RestOp */
687      public Class<? extends RestGuard>[] guards() {
688         return guards;
689      }
690
691      @Override /* Overridden from RestOp */
692      public Class<? extends RestMatcher>[] matchers() {
693         return matchers;
694      }
695
696      @Override /* Overridden from RestOp */
697      public String maxInput() {
698         return maxInput;
699      }
700
701      @Override /* Overridden from RestOp */
702      public String method() {
703         return method;
704      }
705
706      @Override /* Overridden from RestOp */
707      public Class<?>[] parsers() {
708         return parsers;
709      }
710
711      @Override /* Overridden from RestOp */
712      public String[] path() {
713         return path;
714      }
715
716      @Override /* Overridden from RestOp */
717      public String observability() {
718         return observability;
719      }
720
721      @Override /* Overridden from RestOp */
722      public String metricName() {
723         return metricName;
724      }
725
726      @Override /* Overridden from RestOp */
727      public String metricTags() {
728         return metricTags;
729      }
730
731      @Override /* Overridden from RestOp */
732      public String problemDetails() {
733         return problemDetails;
734      }
735
736      @Override /* Overridden from RestOp */
737      public String debugMarshalling() {
738         return debugMarshalling;
739      }
740
741      @Override /* Overridden from RestOp */
742      public String virtualThreads() {
743         return virtualThreads;
744      }
745
746      @Override /* Overridden from RestOp */
747      public String asyncTimeoutMillis() {
748         return asyncTimeoutMillis;
749      }
750
751      @Override /* Overridden from RestOp */
752      public String asyncCompletionExecutor() {
753         return asyncCompletionExecutor;
754      }
755
756      @Override /* Overridden from RestOp */
757      public String[] produces() {
758         return produces;
759      }
760
761      @Override /* Overridden from RestOp */
762      public String[] allowedSerializerOptions() {
763         return allowedSerializerOptions;
764      }
765
766      @Override /* Overridden from RestOp */
767      public String[] allowedParserOptions() {
768         return allowedParserOptions;
769      }
770
771      @Override /* Overridden from RestOp */
772      public String[] noInherit() {
773         return noInherit;
774      }
775
776      @Override /* Overridden from RestOp */
777      public boolean read() {
778         return read;
779      }
780
781      @Override /* Overridden from RestOp */
782      public String roleGuard() {
783         return roleGuard;
784      }
785
786      @Override /* Overridden from RestOp */
787      public String rolesDeclared() {
788         return rolesDeclared;
789      }
790
791      @Override /* Overridden from RestOp */
792      public Class<? extends Serializer>[] serializers() {
793         return serializers;
794      }
795
796      @Override /* Overridden from RestOp */
797      public String summary() {
798         return summary;
799      }
800
801      @Override /* Overridden from RestOp */
802      public OpSwagger swagger() {
803         return swagger;
804      }
805
806      @Override /* Overridden from RestOp */
807      public String value() {
808         return value;
809      }
810
811      @Override /* Overridden from annotation */
812      public String[] description() {
813         return description;
814      }
815   }
816
817   /** Default value */
818   public static final RestOp DEFAULT = create().build();
819   /**
820    * Predicate that can be used to filter annotation streams.
821    *
822    * <p>
823    * Example: <c>classInfo.getAnnotations().stream().filter(REST_OP_GROUP)</c>
824    */
825   public static final Predicate<AnnotationInfo<?>> REST_OP_GROUP = x -> x.isInGroup(RestOp.class);
826
827   /**
828    * Instantiates a new builder for this class.
829    *
830    * @return A new builder object.
831    */
832   public static Builder create() {
833      return new Builder();
834   }
835}