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 org.apache.juneau.commons.*;
022import org.apache.juneau.marshall.encoders.*;
023import org.apache.juneau.marshall.httppart.*;
024import org.apache.juneau.marshall.serializer.*;
025import org.apache.juneau.rest.server.arg.*;
026import org.apache.juneau.rest.server.converter.*;
027import org.apache.juneau.rest.server.guard.*;
028import org.apache.juneau.rest.server.processor.*;
029
030/**
031 * Utility classes and methods for the {@link Mixin @Mixin} annotation.
032 *
033 * <h5 class='section'>See Also:</h5><ul>
034 *    <li class='ja'>{@link Mixin}
035 *    <li class='ja'>{@link Rest#mixinDefs()}
036 * </ul>
037 *
038 * @since 10.0.0
039 */
040public class MixinAnnotation {
041
042   /**
043    * Prevents instantiation.
044    */
045   private MixinAnnotation() {}
046
047   /**
048    * Builder class.
049    */
050   @SuppressWarnings({
051      "unchecked" // Type erasure requires cast for generic class-array fields.
052   })
053   public static class Builder extends AnnotationObject.Builder {
054
055      Class<?> type = Object.class;
056      boolean mergeIntoHost = false;
057      Class<? extends RestGuard>[] guards = new Class[0];
058      String roleGuard = "";
059      String rolesDeclared = "";
060      Class<? extends RestConverter>[] converters = new Class[0];
061      Class<? extends Encoder>[] encoders = new Class[0];
062      Class<? extends Serializer>[] serializers = new Class[0];
063      Class<?>[] parsers = {};
064      Class<? extends ResponseProcessor>[] responseProcessors = new Class[0];
065      Class<? extends RestOpArg>[] restOpArgs = new Class[0];
066      Class<? extends HttpPartSerializer> partSerializer = HttpPartSerializer.Void.class;
067      Class<? extends HttpPartParser> partParser = HttpPartParser.Void.class;
068      String messages = "";
069      String[] defaultRequestHeaders = {};
070      String[] defaultResponseHeaders = {};
071      String[] defaultRequestAttributes = {};
072      String[] produces = {};
073      String[] consumes = {};
074      String defaultAccept = "";
075      String defaultContentType = "";
076      String defaultCharset = "";
077      String maxInput = "";
078      String path = "";
079      String[] paths = {};
080      String[] noInherit = {};
081
082      /**
083       * Constructor.
084       */
085      protected Builder() {
086         super(Mixin.class);
087      }
088
089      /**
090       * Sets the {@link Mixin#type()} property on this annotation.
091       *
092       * @param value The new value for this property.
093       * @return This object.
094       */
095      public Builder type(Class<?> value) { type = value; return this; }
096
097      /**
098       * Sets the {@link Mixin#mergeIntoHost()} property on this annotation.
099       *
100       * @param value The new value for this property.
101       * @return This object.
102       */
103      public Builder mergeIntoHost(boolean value) { mergeIntoHost = value; return this; }
104
105      /**
106       * Sets the {@link Mixin#guards()} property on this annotation.
107       *
108       * @param value The new value for this property.
109       * @return This object.
110       */
111      public Builder guards(Class<? extends RestGuard>... value) { guards = value; return this; }
112
113      /**
114       * Sets the {@link Mixin#roleGuard()} property on this annotation.
115       *
116       * @param value The new value for this property.
117       * @return This object.
118       */
119      public Builder roleGuard(String value) { roleGuard = value; return this; }
120
121      /**
122       * Sets the {@link Mixin#rolesDeclared()} property on this annotation.
123       *
124       * @param value The new value for this property.
125       * @return This object.
126       */
127      public Builder rolesDeclared(String value) { rolesDeclared = value; return this; }
128
129      /**
130       * Sets the {@link Mixin#converters()} property on this annotation.
131       *
132       * @param value The new value for this property.
133       * @return This object.
134       */
135      public Builder converters(Class<? extends RestConverter>... value) { converters = value; return this; }
136
137      /**
138       * Sets the {@link Mixin#encoders()} property on this annotation.
139       *
140       * @param value The new value for this property.
141       * @return This object.
142       */
143      public Builder encoders(Class<? extends Encoder>... value) { encoders = value; return this; }
144
145      /**
146       * Sets the {@link Mixin#serializers()} property on this annotation.
147       *
148       * @param value The new value for this property.
149       * @return This object.
150       */
151      public Builder serializers(Class<? extends Serializer>... value) { serializers = value; return this; }
152
153      /**
154       * Sets the {@link Mixin#parsers()} property on this annotation.
155       *
156       * @param value The new value for this property.
157       * @return This object.
158       */
159      public Builder parsers(Class<?>... value) { parsers = value; return this; }
160
161      /**
162       * Sets the {@link Mixin#responseProcessors()} property on this annotation.
163       *
164       * @param value The new value for this property.
165       * @return This object.
166       */
167      public Builder responseProcessors(Class<? extends ResponseProcessor>... value) { responseProcessors = value; return this; }
168
169      /**
170       * Sets the {@link Mixin#restOpArgs()} property on this annotation.
171       *
172       * @param value The new value for this property.
173       * @return This object.
174       */
175      public Builder restOpArgs(Class<? extends RestOpArg>... value) { restOpArgs = value; return this; }
176
177      /**
178       * Sets the {@link Mixin#partSerializer()} property on this annotation.
179       *
180       * @param value The new value for this property.
181       * @return This object.
182       */
183      public Builder partSerializer(Class<? extends HttpPartSerializer> value) { partSerializer = value; return this; }
184
185      /**
186       * Sets the {@link Mixin#partParser()} property on this annotation.
187       *
188       * @param value The new value for this property.
189       * @return This object.
190       */
191      public Builder partParser(Class<? extends HttpPartParser> value) { partParser = value; return this; }
192
193      /**
194       * Sets the {@link Mixin#messages()} property on this annotation.
195       *
196       * @param value The new value for this property.
197       * @return This object.
198       */
199      public Builder messages(String value) { messages = value; return this; }
200
201      /**
202       * Sets the {@link Mixin#defaultRequestHeaders()} property on this annotation.
203       *
204       * @param value The new value for this property.
205       * @return This object.
206       */
207      public Builder defaultRequestHeaders(String... value) { defaultRequestHeaders = value; return this; }
208
209      /**
210       * Sets the {@link Mixin#defaultResponseHeaders()} property on this annotation.
211       *
212       * @param value The new value for this property.
213       * @return This object.
214       */
215      public Builder defaultResponseHeaders(String... value) { defaultResponseHeaders = value; return this; }
216
217      /**
218       * Sets the {@link Mixin#defaultRequestAttributes()} property on this annotation.
219       *
220       * @param value The new value for this property.
221       * @return This object.
222       */
223      public Builder defaultRequestAttributes(String... value) { defaultRequestAttributes = value; return this; }
224
225      /**
226       * Sets the {@link Mixin#produces()} property on this annotation.
227       *
228       * @param value The new value for this property.
229       * @return This object.
230       */
231      public Builder produces(String... value) { produces = value; return this; }
232
233      /**
234       * Sets the {@link Mixin#consumes()} property on this annotation.
235       *
236       * @param value The new value for this property.
237       * @return This object.
238       */
239      public Builder consumes(String... value) { consumes = value; return this; }
240
241      /**
242       * Sets the {@link Mixin#defaultAccept()} property on this annotation.
243       *
244       * @param value The new value for this property.
245       * @return This object.
246       */
247      public Builder defaultAccept(String value) { defaultAccept = value; return this; }
248
249      /**
250       * Sets the {@link Mixin#defaultContentType()} property on this annotation.
251       *
252       * @param value The new value for this property.
253       * @return This object.
254       */
255      public Builder defaultContentType(String value) { defaultContentType = value; return this; }
256
257      /**
258       * Sets the {@link Mixin#defaultCharset()} property on this annotation.
259       *
260       * @param value The new value for this property.
261       * @return This object.
262       */
263      public Builder defaultCharset(String value) { defaultCharset = value; return this; }
264
265      /**
266       * Sets the {@link Mixin#maxInput()} property on this annotation.
267       *
268       * @param value The new value for this property.
269       * @return This object.
270       */
271      public Builder maxInput(String value) { maxInput = value; return this; }
272
273      /**
274       * Sets the {@link Mixin#path()} property on this annotation.
275       *
276       * @param value The new value for this property.
277       * @return This object.
278       */
279      public Builder path(String value) { path = value; return this; }
280
281      /**
282       * Sets the {@link Mixin#paths()} property on this annotation.
283       *
284       * @param value The new value for this property.
285       * @return This object.
286       */
287      public Builder paths(String... value) { paths = value; return this; }
288
289      /**
290       * Sets the {@link Mixin#noInherit()} property on this annotation.
291       *
292       * @param value The new value for this property.
293       * @return This object.
294       */
295      public Builder noInherit(String... value) { noInherit = value; return this; }
296
297      /**
298       * Instantiates a new {@link Mixin @Mixin} object initialized with this builder.
299       *
300       * @return A new {@link Mixin @Mixin} object.
301       */
302      public Mixin build() {
303         return new Impl(this);
304      }
305   }
306
307   @SuppressWarnings({
308      "java:S2160" // equals() inherited from AnnotationObject compares all annotation interface methods; subclass fields are accessed via those methods.
309   })
310   private static class Impl extends AnnotationObject implements Mixin {
311
312      private final Class<?> type;
313      private final boolean mergeIntoHost;
314      private final Class<? extends RestGuard>[] guards;
315      private final String roleGuard;
316      private final String rolesDeclared;
317      private final Class<? extends RestConverter>[] converters;
318      private final Class<? extends Encoder>[] encoders;
319      private final Class<? extends Serializer>[] serializers;
320      private final Class<?>[] parsers;
321      private final Class<? extends ResponseProcessor>[] responseProcessors;
322      private final Class<? extends RestOpArg>[] restOpArgs;
323      private final Class<? extends HttpPartSerializer> partSerializer;
324      private final Class<? extends HttpPartParser> partParser;
325      private final String messages;
326      private final String[] defaultRequestHeaders;
327      private final String[] defaultResponseHeaders;
328      private final String[] defaultRequestAttributes;
329      private final String[] produces;
330      private final String[] consumes;
331      private final String defaultAccept;
332      private final String defaultContentType;
333      private final String defaultCharset;
334      private final String maxInput;
335      private final String path;
336      private final String[] paths;
337      private final String[] noInherit;
338
339      Impl(MixinAnnotation.Builder b) {
340         super(b);
341         type = b.type;
342         mergeIntoHost = b.mergeIntoHost;
343         guards = cp(b.guards);
344         roleGuard = b.roleGuard;
345         rolesDeclared = b.rolesDeclared;
346         converters = cp(b.converters);
347         encoders = cp(b.encoders);
348         serializers = cp(b.serializers);
349         parsers = cp(b.parsers);
350         responseProcessors = cp(b.responseProcessors);
351         restOpArgs = cp(b.restOpArgs);
352         partSerializer = b.partSerializer;
353         partParser = b.partParser;
354         messages = b.messages;
355         defaultRequestHeaders = cp(b.defaultRequestHeaders);
356         defaultResponseHeaders = cp(b.defaultResponseHeaders);
357         defaultRequestAttributes = cp(b.defaultRequestAttributes);
358         produces = cp(b.produces);
359         consumes = cp(b.consumes);
360         defaultAccept = b.defaultAccept;
361         defaultContentType = b.defaultContentType;
362         defaultCharset = b.defaultCharset;
363         maxInput = b.maxInput;
364         path = b.path;
365         paths = cp(b.paths);
366         noInherit = cp(b.noInherit);
367      }
368
369      @Override /* Overridden from Mixin */ public Class<?> type() { return type; }
370      @Override /* Overridden from Mixin */ public boolean mergeIntoHost() { return mergeIntoHost; }
371      @Override /* Overridden from Mixin */ public Class<? extends RestGuard>[] guards() { return cp(guards); }
372      @Override /* Overridden from Mixin */ public String roleGuard() { return roleGuard; }
373      @Override /* Overridden from Mixin */ public String rolesDeclared() { return rolesDeclared; }
374      @Override /* Overridden from Mixin */ public Class<? extends RestConverter>[] converters() { return cp(converters); }
375      @Override /* Overridden from Mixin */ public Class<? extends Encoder>[] encoders() { return cp(encoders); }
376      @Override /* Overridden from Mixin */ public Class<? extends Serializer>[] serializers() { return cp(serializers); }
377      @Override /* Overridden from Mixin */ public Class<?>[] parsers() { return cp(parsers); }
378      @Override /* Overridden from Mixin */ public Class<? extends ResponseProcessor>[] responseProcessors() { return cp(responseProcessors); }
379      @Override /* Overridden from Mixin */ public Class<? extends RestOpArg>[] restOpArgs() { return cp(restOpArgs); }
380      @Override /* Overridden from Mixin */ public Class<? extends HttpPartSerializer> partSerializer() { return partSerializer; }
381      @Override /* Overridden from Mixin */ public Class<? extends HttpPartParser> partParser() { return partParser; }
382      @Override /* Overridden from Mixin */ public String messages() { return messages; }
383      @Override /* Overridden from Mixin */ public String[] defaultRequestHeaders() { return cp(defaultRequestHeaders); }
384      @Override /* Overridden from Mixin */ public String[] defaultResponseHeaders() { return cp(defaultResponseHeaders); }
385      @Override /* Overridden from Mixin */ public String[] defaultRequestAttributes() { return cp(defaultRequestAttributes); }
386      @Override /* Overridden from Mixin */ public String[] produces() { return cp(produces); }
387      @Override /* Overridden from Mixin */ public String[] consumes() { return cp(consumes); }
388      @Override /* Overridden from Mixin */ public String defaultAccept() { return defaultAccept; }
389      @Override /* Overridden from Mixin */ public String defaultContentType() { return defaultContentType; }
390      @Override /* Overridden from Mixin */ public String defaultCharset() { return defaultCharset; }
391      @Override /* Overridden from Mixin */ public String maxInput() { return maxInput; }
392      @Override /* Overridden from Mixin */ public String path() { return path; }
393      @Override /* Overridden from Mixin */ public String[] paths() { return cp(paths); }
394      @Override /* Overridden from Mixin */ public String[] noInherit() { return cp(noInherit); }
395   }
396
397   /**
398    * Builder creator.
399    *
400    * @return A new builder.
401    */
402   public static Builder create() {
403      return new Builder();
404   }
405
406   /** Default {@link Mixin} instance (empty overrides; {@code type=Object.class}). */
407   public static final Mixin DEFAULT = create().build();
408}