001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest.swagger;
014
015import static org.apache.juneau.internal.CollectionUtils.*;
016import java.util.*;
017import java.util.function.*;
018
019import org.apache.juneau.cp.*;
020import org.apache.juneau.dto.swagger.Swagger;
021import org.apache.juneau.http.response.*;
022import org.apache.juneau.jsonschema.*;
023import org.apache.juneau.rest.*;
024import org.apache.juneau.rest.annotation.*;
025import org.apache.juneau.svl.*;
026
027/**
028 * Interface for retrieving Swagger on a REST resource.
029 *
030 * <h5 class='section'>See Also:</h5><ul>
031 *    <li class='link'><a class="doclink" href="../../../../../index.html#jrs.Swagger">Swagger</a>
032 * </ul>
033 */
034public interface SwaggerProvider {
035
036   //-----------------------------------------------------------------------------------------------------------------
037   // Static
038   //-----------------------------------------------------------------------------------------------------------------
039
040   /**
041    * Represents no SwaggerProvider.
042    *
043    * <p>
044    * Used on annotation to indicate that the value should be inherited from the parent class, and
045    * ultimately {@link BasicSwaggerProvider} if not specified at any level.
046    */
047   public abstract class Void implements SwaggerProvider {}
048
049   /**
050    * Static creator.
051    *
052    * @param beanStore The bean store to use for creating beans.
053    * @return A new builder for this object.
054    */
055   static Builder create(BeanStore beanStore) {
056      return new Builder(beanStore);
057   }
058
059   //-----------------------------------------------------------------------------------------------------------------
060   // Builder
061   //-----------------------------------------------------------------------------------------------------------------
062
063   /**
064    * Builder class.
065    */
066   public class Builder {
067
068      final BeanStore beanStore;
069      Class<?> resourceClass;
070      Supplier<VarResolver> varResolver;
071      Supplier<JsonSchemaGenerator> jsonSchemaGenerator;
072      Supplier<Messages> messages;
073      Supplier<FileFinder> fileFinder;
074      BeanCreator<SwaggerProvider> creator;
075
076      /**
077       * Constructor.
078       *
079       * @param beanStore The bean store to use for creating beans.
080       */
081      protected Builder(BeanStore beanStore) {
082         this.beanStore = beanStore;
083         this.creator = beanStore.createBean(SwaggerProvider.class).type(BasicSwaggerProvider.class).builder(Builder.class, this);
084      }
085
086      /**
087       * Creates a new {@link SwaggerProvider} object from this builder.
088       *
089       * <p>
090       * Instantiates an instance of the {@link #type(Class) implementation class} or
091       * else {@link BasicSwaggerProvider} if implementation class was not specified.
092       *
093       * @return A new {@link SwaggerProvider} object.
094       */
095      public SwaggerProvider build() {
096         try {
097            return creator.run();
098         } catch (Exception e) {
099            throw new InternalServerError(e);
100         }
101      }
102
103      /**
104       * Returns the var resolver in this builder if it's been specified.
105       *
106       * @return The var resolver.
107       */
108      public Optional<VarResolver> varResolver() {
109         return optional(varResolver).map(Supplier::get);
110      }
111
112      /**
113       * Returns the JSON schema generator in this builder if it's been specified.
114       *
115       * @return The JSON schema generator.
116       */
117      public Optional<JsonSchemaGenerator> jsonSchemaGenerator() {
118         return optional(jsonSchemaGenerator).map(Supplier::get);
119      }
120
121      /**
122       * Returns the messages in this builder if it's been specified.
123       *
124       * @return The messages.
125       */
126      public Optional<Messages> messages() {
127         return optional(messages).map(Supplier::get);
128      }
129
130      /**
131       * Returns the file finder in this builder if it's been specified.
132       *
133       * @return The file finder.
134       */
135      public Optional<FileFinder> fileFinder() {
136         return optional(fileFinder).map(Supplier::get);
137      }
138
139      /**
140       * Specifies the default implementation class if not specified via {@link #type(Class)}.
141       *
142       * @return The default implementation class if not specified via {@link #type(Class)}.
143       */
144      protected Class<? extends SwaggerProvider> getDefaultType() {
145         return BasicSwaggerProvider.class;
146      }
147
148      /**
149       * Specifies a subclass of {@link SwaggerProvider} to create when the {@link #build()} method is called.
150       *
151       * @param value The new value for this setting.
152       * @return  This object.
153       */
154      public Builder type(Class<? extends SwaggerProvider> value) {
155         creator.type(value == null ? BasicSwaggerProvider.class : value);
156         return this;
157      }
158
159      /**
160       * Specifies the variable resolver to use for the {@link SwaggerProvider} object.
161       *
162       * @param value The new value for this setting.
163       * @return  This object.
164       */
165      public Builder varResolver(Supplier<VarResolver> value) {
166         varResolver = value;
167         return this;
168      }
169
170      /**
171       * Specifies the JSON-schema generator to use for the {@link SwaggerProvider} object.
172       *
173       * @param value The new value for this setting.
174       * @return  This object.
175       */
176      public Builder jsonSchemaGenerator(Supplier<JsonSchemaGenerator> value) {
177         jsonSchemaGenerator = value;
178         return this;
179      }
180
181      /**
182       * Specifies the messages to use for the {@link SwaggerProvider} object.
183       *
184       * @param value The new value for this setting.
185       * @return  This object.
186       */
187      public Builder messages(Supplier<Messages> value) {
188         messages = value;
189         return this;
190      }
191
192      /**
193       * Specifies the file-finder to use for the {@link SwaggerProvider} object.
194       *
195       * @param value The new value for this setting.
196       * @return  This object.
197       */
198      public Builder fileFinder(Supplier<FileFinder> value) {
199         fileFinder = value;
200         return this;
201      }
202
203      /**
204       * Specifies an already-instantiated bean for the {@link #build()} method too return.
205       *
206       * @param value The new value for this setting.
207       * @return  This object.
208       */
209      public Builder impl(SwaggerProvider value) {
210         creator.impl(value);
211         return this;
212      }
213   }
214
215   //-----------------------------------------------------------------------------------------------------------------
216   // Instance
217   //-----------------------------------------------------------------------------------------------------------------
218
219   /**
220    * Returns the Swagger associated with the specified {@link Rest}-annotated class.
221    *
222    * @param context The context of the {@link Rest}-annotated class.
223    * @param locale The request locale.
224    * @return A new {@link Swagger} DTO object.
225    * @throws Exception If an error occurred producing the Swagger.
226    */
227   Swagger getSwagger(RestContext context, Locale locale) throws Exception;
228
229}