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 java.lang.annotation.RetentionPolicy.*;
020
021import java.lang.annotation.*;
022
023import org.apache.juneau.marshall.encoders.*;
024import org.apache.juneau.marshall.httppart.*;
025import org.apache.juneau.marshall.serializer.*;
026import org.apache.juneau.rest.server.arg.*;
027import org.apache.juneau.rest.server.converter.*;
028import org.apache.juneau.rest.server.guard.*;
029import org.apache.juneau.rest.server.processor.*;
030
031/**
032 * Rich mixin definition for the {@link Rest#mixinDefs() @Rest(mixinDefs=...)} attribute.
033 *
034 * <p>
035 * Declares a mixin class <b>and</b> lets the <i>host</i> override selected {@code @Rest}-level settings for
036 * that mixin's mixed-in endpoints &mdash; in one place, without subclassing or editing the mixin class.  This
037 * is the host-side complement to {@link Rest#mixins() @Rest(mixins=...)} (which takes bare classes and offers
038 * no override hook).
039 *
040 * <h5 class='section'>Example:</h5>
041 * <p class='bjava'>
042 *    <ja>@Rest</ja>(
043 *       mixinDefs=<ja>@Mixin</ja>(type=FooMixin.<jk>class</jk>, guards=AdminGuard.<jk>class</jk>)
044 *    )
045 *    <jk>public class</jk> MyResource { ... }
046 * </p>
047 *
048 * <p>
049 * Here {@code AdminGuard} is applied to {@code FooMixin}'s endpoints as declared by the host, without
050 * {@code FooMixin} having to declare it.
051 *
052 * <h5 class='section'>Override semantics</h5>
053 * <p>
054 * The override slots mirror the same {@code @Rest} attributes and resolve through the existing host&rarr;mixin
055 * inheritance chain, exactly as if the value had been declared on the mixin class itself, but at the
056 * most-derived position so a host override wins over the mixin class's own same-property declaration:
057 * <ul>
058 *    <li><b>List-shaped</b> ({@code guards}, {@code converters}, {@code encoders}, {@code serializers},
059 *       {@code parsers}, {@code responseProcessors}, {@code restOpArgs}, default headers/attributes,
060 *       {@code produces}/{@code consumes}) &mdash; appended after the host chain that the mixin inherits.
061 *    <li><b>Replace-shaped</b> ({@code partSerializer}, {@code partParser},
062 *       {@code defaultAccept}/{@code defaultContentType}/{@code defaultCharset}, {@code maxInput},
063 *       {@code roleGuard}/{@code rolesDeclared}, {@code messages}) &mdash; the host override wins when set.
064 * </ul>
065 *
066 * <p>
067 * {@link #noInherit()} is the {@code @Mixin}'s own inheritance-cutoff list, applied to this mixin's
068 * sub-context: a token here cuts the host&rarr;mixin inheritance walk for that property (same token set as
069 * {@link Rest#noInherit()}).  The host override is authoritative <i>but</i> overridable by these
070 * {@code noInherit} rules &mdash; e.g. {@code @Mixin(type=X.class, noInherit="guards")} removes the host's
071 * guard chain from {@code X}'s endpoints entirely.
072 *
073 * <p>
074 * {@link #path()}/{@link #paths()} re-mount the mixin's endpoints under host-chosen prefix(es).
075 *
076 * <h5 class='section'>Merging a mixin's list attributes into the host</h5>
077 * <p>
078 * The override slots above apply the <i>host's</i> values to the <i>mixin's</i> endpoints.  The separate opt-in
079 * {@link #mergeIntoHost()} directive does the reverse: it appends the <i>mixin's</i> own list-shaped
080 * {@code @Rest} attributes (e.g. {@code responseProcessors}) into the <i>host's</i> own chains, so the host's own
081 * {@code @RestOp} methods pick them up too.  It defaults to {@code false} (host endpoints see only the host's
082 * chain, as before) and is only settable on a rich {@code @Mixin} &mdash; see {@link #mergeIntoHost()}.
083 *
084 * <h5 class='section'>See Also:</h5><ul>
085 *    <li class='ja'>{@link Rest#mixinDefs()}
086 *    <li class='ja'>{@link Rest#mixins()}
087 * </ul>
088 *
089 * @since 10.0.0
090 */
091@Target({})
092@Retention(RUNTIME)
093public @interface Mixin {
094
095   /**
096    * The mixin class to compose into the host resource.
097    *
098    * <p>
099    * Required.  Equivalent to a bare entry in {@link Rest#mixins()}, but with the override slots below.
100    *
101    * @return The mixin class.
102    */
103   Class<?> type();
104
105   /**
106    * Opt-in directive: fold this mixin's <b>list-shaped</b> {@code @Rest} attributes into the <i>host</i>
107    * resource's own corresponding chains (not just the mixin's own endpoints).
108    *
109    * <p>
110    * By default ({@code false}) a mixin's list-shaped {@code @Rest} contributions apply only to the mixin's own
111    * endpoints &mdash; a host's own {@code @RestOp} methods see only the host's chain (the standard
112    * {@link Rest#mixins() mixin} inheritance rule "host's chain runs first, then the mixin's appended; host
113    * endpoints see only the host's chain"), so a mixin's e.g. {@code responseProcessors} are effectively dropped
114    * for host endpoints.  Setting this to {@code true} additionally <b>appends</b> the adopted mixin's own
115    * list-shaped {@code @Rest} attributes to the end of the host's corresponding chains, so the host's own
116    * endpoints pick them up too.
117    *
118    * <p>
119    * The folded set is the list-shaped contribution attributes: {@code serializers}, {@code parsers},
120    * {@code encoders}, {@code converters}, {@code guards}, {@code responseProcessors}, {@code restOpArgs},
121    * {@code defaultRequestHeaders}, {@code defaultResponseHeaders}, {@code defaultRequestAttributes},
122    * {@code produces}, and {@code consumes}.  Replace-shaped attributes (e.g. {@code partSerializer},
123    * {@code partParser}) and host-only attributes ({@code path}/{@code paths}/{@code children}) are never
124    * folded.  Same-class de-duplication applies, so a class the host already declares is not added twice.
125    *
126    * <p>
127    * This is strictly opt-in: it has no effect on a bare {@link Rest#mixins()} entry (which cannot set it) or a
128    * {@code @Mixin} that leaves it {@code false}, so existing resources are unaffected.  The mixin still mounts
129    * its own endpoints as usual &mdash; this directive is purely additive to the host chain.
130    *
131    * <h5 class='section'>Example:</h5>
132    * <p class='bjava'>
133    *    <jc>// Auto-wire JspMixin's JspViewRenderer into the host so the host's own @RestOp methods can</jc>
134    *    <jc>// return JspView (no need to also list JspViewRenderer in the host's @Rest(responseProcessors)).</jc>
135    *    <ja>@Rest</ja>(mixinDefs=<ja>@Mixin</ja>(type=JspMixin.<jk>class</jk>, mergeIntoHost=<jk>true</jk>))
136    *    <jk>public class</jk> AppResource <jk>extends</jk> RestServlet { ... }
137    * </p>
138    *
139    * @return The annotation value.
140    * @since 10.0.0
141    */
142   boolean mergeIntoHost() default false;
143
144   //-----------------------------------------------------------------------------------------------------------------
145   // Override slots — mirror the corresponding @Rest attribute signatures.
146   //-----------------------------------------------------------------------------------------------------------------
147
148   /**
149    * Host-declared {@link Rest#guards() guards} override for this mixin's endpoints (appended after the host chain).
150    *
151    * @return The annotation value.
152    */
153   Class<? extends RestGuard>[] guards() default {};
154
155   /**
156    * Host-declared {@link Rest#roleGuard() roleGuard} override for this mixin's endpoints.
157    *
158    * @return The annotation value.
159    */
160   String roleGuard() default "";
161
162   /**
163    * Host-declared {@link Rest#rolesDeclared() rolesDeclared} override for this mixin's endpoints.
164    *
165    * @return The annotation value.
166    */
167   String rolesDeclared() default "";
168
169   /**
170    * Host-declared {@link Rest#converters() converters} override for this mixin's endpoints.
171    *
172    * @return The annotation value.
173    */
174   Class<? extends RestConverter>[] converters() default {};
175
176   /**
177    * Host-declared {@link Rest#encoders() encoders} override for this mixin's endpoints.
178    *
179    * @return The annotation value.
180    */
181   Class<? extends Encoder>[] encoders() default {};
182
183   /**
184    * Host-declared {@link Rest#serializers() serializers} override for this mixin's endpoints.
185    *
186    * @return The annotation value.
187    */
188   Class<? extends Serializer>[] serializers() default {};
189
190   /**
191    * Host-declared {@link Rest#parsers() parsers} override for this mixin's endpoints.
192    *
193    * @return The annotation value.
194    */
195   Class<?>[] parsers() default {};
196
197   /**
198    * Host-declared {@link Rest#responseProcessors() responseProcessors} override for this mixin's endpoints.
199    *
200    * @return The annotation value.
201    */
202   Class<? extends ResponseProcessor>[] responseProcessors() default {};
203
204   /**
205    * Host-declared {@link Rest#restOpArgs() restOpArgs} override for this mixin's endpoints.
206    *
207    * @return The annotation value.
208    */
209   Class<? extends RestOpArg>[] restOpArgs() default {};
210
211   /**
212    * Host-declared {@link Rest#partSerializer() partSerializer} override for this mixin's endpoints.
213    *
214    * @return The annotation value.
215    */
216   Class<? extends HttpPartSerializer> partSerializer() default HttpPartSerializer.Void.class;
217
218   /**
219    * Host-declared {@link Rest#partParser() partParser} override for this mixin's endpoints.
220    *
221    * @return The annotation value.
222    */
223   Class<? extends HttpPartParser> partParser() default HttpPartParser.Void.class;
224
225   /**
226    * Host-declared {@link Rest#messages() messages} override for this mixin's endpoints.
227    *
228    * @return The annotation value.
229    */
230   String messages() default "";
231
232   /**
233    * Host-declared {@link Rest#defaultRequestHeaders() defaultRequestHeaders} override for this mixin's endpoints.
234    *
235    * @return The annotation value.
236    */
237   String[] defaultRequestHeaders() default {};
238
239   /**
240    * Host-declared {@link Rest#defaultResponseHeaders() defaultResponseHeaders} override for this mixin's endpoints.
241    *
242    * @return The annotation value.
243    */
244   String[] defaultResponseHeaders() default {};
245
246   /**
247    * Host-declared {@link Rest#defaultRequestAttributes() defaultRequestAttributes} override for this mixin's endpoints.
248    *
249    * @return The annotation value.
250    */
251   String[] defaultRequestAttributes() default {};
252
253   /**
254    * Host-declared {@link Rest#produces() produces} override for this mixin's endpoints.
255    *
256    * @return The annotation value.
257    */
258   String[] produces() default {};
259
260   /**
261    * Host-declared {@link Rest#consumes() consumes} override for this mixin's endpoints.
262    *
263    * @return The annotation value.
264    */
265   String[] consumes() default {};
266
267   /**
268    * Host-declared {@link Rest#defaultAccept() defaultAccept} override for this mixin's endpoints.
269    *
270    * @return The annotation value.
271    */
272   String defaultAccept() default "";
273
274   /**
275    * Host-declared {@link Rest#defaultContentType() defaultContentType} override for this mixin's endpoints.
276    *
277    * @return The annotation value.
278    */
279   String defaultContentType() default "";
280
281   /**
282    * Host-declared {@link Rest#defaultCharset() defaultCharset} override for this mixin's endpoints.
283    *
284    * @return The annotation value.
285    */
286   String defaultCharset() default "";
287
288   /**
289    * Host-declared {@link Rest#maxInput() maxInput} override for this mixin's endpoints.
290    *
291    * @return The annotation value.
292    */
293   String maxInput() default "";
294
295   /**
296    * Host-chosen single mount prefix for this mixin's endpoints (re-mount).
297    *
298    * @return The annotation value.
299    */
300   String path() default "";
301
302   /**
303    * Host-chosen multi-mount prefixes for this mixin's endpoints (re-mount).
304    *
305    * @return The annotation value.
306    */
307   String[] paths() default {};
308
309   /**
310    * Inheritance-cutoff list for this mixin's sub-context.
311    *
312    * <p>
313    * Each token names a property whose host&rarr;mixin inheritance walk is cut for this mixin (same token set
314    * as {@link Rest#noInherit()}).  Authoritative over the host override slots above.
315    *
316    * @return The annotation value.
317    */
318   String[] noInherit() default {};
319}