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.swagger;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.util.*;
022import java.util.function.*;
023
024import org.apache.juneau.bean.swagger.Swagger;
025import org.apache.juneau.commons.inject.*;
026import org.apache.juneau.commons.svl.*;
027import org.apache.juneau.http.response.*;
028import org.apache.juneau.marshall.cp.*;
029import org.apache.juneau.marshall.jsonschema.*;
030import org.apache.juneau.rest.server.*;
031
032/**
033 * Interface for retrieving Swagger on a REST resource.
034 *
035 * <h5 class='section'>See Also:</h5><ul>
036 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
037 * </ul>
038 */
039@SuppressWarnings({
040   "java:S9398" // Nested types are public API; moving them would break callers.
041})
042public interface SwaggerProvider {
043
044   /**
045    * Builder class.
046    */
047   public class Builder {
048
049      final BeanStore beanStore;
050      Class<?> resourceClass;
051      Supplier<VarResolver> varResolver;
052      Supplier<JsonSchemaGenerator> jsonSchemaGenerator;
053      Supplier<Messages> messages;
054      Supplier<FileFinder> fileFinder;
055      private SwaggerProvider impl;
056      private Class<? extends SwaggerProvider> implType;
057
058      /**
059       * Constructor.
060       *
061       * @param beanStore The bean store to use for creating beans.
062       */
063      protected Builder(BeanStore beanStore) {
064         this.beanStore = beanStore;
065      }
066
067      /**
068       * Creates a new {@link SwaggerProvider} object from this builder.
069       *
070       * <p>
071       * Instantiates an instance of the {@link #type(Class) implementation class} or
072       * else {@link BasicSwaggerProvider} if implementation class was not specified.
073       *
074       * @return A new {@link SwaggerProvider} object.
075       */
076      public SwaggerProvider build() {
077         try {
078            if (impl != null)
079               return impl;
080            var t = or(implType, BasicSwaggerProvider.class);
081            return BeanInstantiator.of(SwaggerProvider.class, beanStore)
082               .type(t)
083               .noBuilder()
084               .addBean(Builder.class, this)
085               .run();
086         } catch (Exception e) {
087            throw new InternalServerError(e);
088         }
089      }
090
091      /**
092       * Returns the file finder in this builder if it's been specified.
093       *
094       * @return The file finder.
095       */
096      public Optional<FileFinder> fileFinder() {
097         return o(fileFinder).map(Supplier::get);
098      }
099
100      /**
101       * Specifies the file-finder to use for the {@link SwaggerProvider} object.
102       *
103       * @param value The new value for this setting.
104       * @return  This object.
105       */
106      public Builder fileFinder(Supplier<FileFinder> value) {
107         fileFinder = value;
108         return this;
109      }
110
111      /**
112       * Specifies an already-instantiated bean for the {@link #build()} method too return.
113       *
114       * @param value The new value for this setting.
115       *    <br>Can be <jk>null</jk> (the {@link #build()} method instantiates the {@link #type(Class) type} instead).
116       * @return  This object.
117       */
118      public Builder impl(SwaggerProvider value) {
119         this.impl = value;
120         return this;
121      }
122
123      /**
124       * Returns the JSON schema generator in this builder if it's been specified.
125       *
126       * @return The JSON schema generator.
127       */
128      public Optional<JsonSchemaGenerator> jsonSchemaGenerator() {
129         return o(jsonSchemaGenerator).map(Supplier::get);
130      }
131
132      /**
133       * Specifies the JSON-schema generator to use for the {@link SwaggerProvider} object.
134       *
135       * @param value The new value for this setting.
136       * @return  This object.
137       */
138      public Builder jsonSchemaGenerator(Supplier<JsonSchemaGenerator> value) {
139         jsonSchemaGenerator = value;
140         return this;
141      }
142
143      /**
144       * Returns the messages in this builder if it's been specified.
145       *
146       * @return The messages.
147       */
148      public Optional<Messages> messages() {
149         return o(messages).map(Supplier::get);
150      }
151
152      /**
153       * Specifies the messages to use for the {@link SwaggerProvider} object.
154       *
155       * @param value The new value for this setting.
156       * @return  This object.
157       */
158      public Builder messages(Supplier<Messages> value) {
159         messages = value;
160         return this;
161      }
162
163      /**
164       * Specifies a subclass of {@link SwaggerProvider} to create when the {@link #build()} method is called.
165       *
166       * @param value The new value for this setting.
167       *    <br>Can be <jk>null</jk> (defaults to {@link BasicSwaggerProvider}).
168       * @return  This object.
169       */
170      public Builder type(Class<? extends SwaggerProvider> value) {
171         implType = o(value).isPresent() ? value : BasicSwaggerProvider.class;
172         return this;
173      }
174
175      /**
176       * Returns the var resolver in this builder if it's been specified.
177       *
178       * @return The var resolver.
179       */
180      public Optional<VarResolver> varResolver() {
181         return o(varResolver).map(Supplier::get);
182      }
183
184      /**
185       * Specifies the variable resolver to use for the {@link SwaggerProvider} object.
186       *
187       * @param value The new value for this setting.
188       * @return  This object.
189       */
190      public Builder varResolver(Supplier<VarResolver> value) {
191         varResolver = value;
192         return this;
193      }
194
195      /**
196       * Specifies the default implementation class if not specified via {@link #type(Class)}.
197       *
198       * @return The default implementation class if not specified via {@link #type(Class)}.
199       */
200      protected Class<? extends SwaggerProvider> getDefaultType() { return BasicSwaggerProvider.class; }
201   }
202
203   /**
204    * Represents no SwaggerProvider.
205    *
206    * <p>
207    * Used on annotation to indicate that the value should be inherited from the parent class, and
208    * ultimately {@link BasicSwaggerProvider} if not specified at any level.
209    */
210   @SuppressWarnings({
211      "java:S9398" // Public annotation-default marker; moving breaks API.
212   })
213   public abstract class Void implements SwaggerProvider {}
214
215   /**
216    * Static creator.
217    *
218    * @param beanStore The bean store to use for creating beans.
219    * @return A new builder for this object.
220    */
221   static Builder create(BeanStore beanStore) {
222      return new Builder(beanStore);
223   }
224
225   /**
226    * Returns the Swagger associated with the specified {@link Rest}-annotated class.
227    *
228    * @param context The context of the {@link Rest}-annotated class.
229    * @param locale The request locale.
230    * @return A new {@link Swagger} DTO object.
231    * @throws Exception If an error occurred producing the Swagger.
232    */
233   @SuppressWarnings({
234      "java:S112" // throws Exception intentional - callback/lifecycle method
235   })
236   Swagger getSwagger(RestContext context, Locale locale) throws Exception;
237}