1
18
19 package org.springdoc.core;
20
21 import java.net.URL;
22 import java.util.Comparator;
23 import java.util.HashSet;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Set;
29 import java.util.TreeMap;
30 import java.util.stream.Collectors;
31
32 import org.apache.commons.lang3.StringUtils;
33
34 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
35 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
36 import org.springframework.boot.context.properties.ConfigurationProperties;
37 import org.springframework.context.annotation.Configuration;
38 import org.springframework.util.CollectionUtils;
39
40 import static org.springdoc.core.Constants.GROUP_NAME_NOT_NULL;
41 import static org.springdoc.core.Constants.SPRINGDOC_SWAGGER_UI_ENABLED;
42 import static org.springdoc.core.Constants.SWAGGER_UI_OAUTH_REDIRECT_URL;
43 import static org.springframework.util.AntPathMatcher.DEFAULT_PATH_SEPARATOR;
44
45
50 @Configuration
51 @ConfigurationProperties(prefix = "springdoc.swagger-ui")
52 @ConditionalOnProperty(name = SPRINGDOC_SWAGGER_UI_ENABLED, matchIfMissing = true)
53 @ConditionalOnBean(SpringDocConfiguration.class)
54 public class SwaggerUiConfigProperties {
55
56 public static final String CONFIG_URL_PROPERTY = "configUrl";
57 public static final String LAYOUT_PROPERTY = "layout";
58 public static final String FILTER_PROPERTY = "filter";
59
62 private String path = Constants.DEFAULT_SWAGGER_UI_PATH;
63
64
67 private String layout;
68
69
72 private String configUrl;
73
74
77 private String validatorUrl;
78
79
83 private String filter;
84
85
88 private String operationsSorter;
89
90
93 private String tagsSorter;
94
95
100 private Boolean deepLinking;
101
102
105 private Boolean displayOperationId;
106
107
110 private Integer defaultModelsExpandDepth;
111
112
115 private Integer defaultModelExpandDepth;
116
117
120 private String defaultModelRendering;
121
122
125 private Boolean displayRequestDuration;
126
127
130 private String docExpansion;
131
132
135 private Integer maxDisplayedTags;
136
137
140 private Boolean showExtensions;
141
142
145 private Boolean showCommonExtensions;
146
147
150 private List<String> supportedSubmitMethods;
151
152
155 private String oauth2RedirectUrl = SWAGGER_UI_OAUTH_REDIRECT_URL;
156
157 private String url;
158
159 private Set<SwaggerUrl> urls = new HashSet<>();
160
161 private Direction groupsOrder = Direction.ASC;
162
163 public void addGroup(String group) {
164 SwaggerUrl swaggerUrl = new SwaggerUrl(group);
165 urls.add(swaggerUrl);
166 }
167
168 public Set<SwaggerUrl> getUrls() {
169 return this.urls;
170 }
171
172 public void setUrls(Set<SwaggerUrl> urls) {
173 this.urls = urls;
174 }
175
176 public void addUrl(String url) {
177 this.urls.forEach(elt ->
178 {
179 if (StringUtils.isBlank(elt.url))
180 elt.setUrl(url + DEFAULT_PATH_SEPARATOR + elt.getName());
181 }
182 );
183 }
184
185 public Map<String, Object> getConfigParameters() {
186 final Map<String, Object> params = new TreeMap<>();
187
188 params.put("validatorUrl", validatorUrl != null ? validatorUrl : "");
189 SpringDocPropertiesUtils.put(CONFIG_URL_PROPERTY, configUrl, params);
190 SpringDocPropertiesUtils.put("deepLinking", this.deepLinking, params);
191 SpringDocPropertiesUtils.put("displayOperationId", displayOperationId, params);
192 SpringDocPropertiesUtils.put("defaultModelsExpandDepth", defaultModelsExpandDepth, params);
193 SpringDocPropertiesUtils.put("defaultModelExpandDepth", defaultModelExpandDepth, params);
194 SpringDocPropertiesUtils.put("defaultModelRendering", defaultModelRendering, params);
195 SpringDocPropertiesUtils.put("displayRequestDuration", displayRequestDuration, params);
196 SpringDocPropertiesUtils.put("docExpansion", docExpansion, params);
197 SpringDocPropertiesUtils.put("maxDisplayedTags", maxDisplayedTags, params);
198 SpringDocPropertiesUtils.put("showExtensions", showExtensions, params);
199 SpringDocPropertiesUtils.put("showCommonExtensions", showCommonExtensions, params);
200 SpringDocPropertiesUtils.put("operationsSorter", operationsSorter, params);
201 SpringDocPropertiesUtils.put("tagsSorter", tagsSorter, params);
202 if (!CollectionUtils.isEmpty(supportedSubmitMethods))
203 SpringDocPropertiesUtils.put("supportedSubmitMethods", supportedSubmitMethods.toString(), params);
204 SpringDocPropertiesUtils.put("oauth2RedirectUrl", oauth2RedirectUrl, params);
205 SpringDocPropertiesUtils.put("url", url, params);
206 put("urls", urls, params);
207 return params;
208 }
209
210 public String getValidatorUrl() {
211 return validatorUrl;
212 }
213
214 public void setValidatorUrl(String validatorUrl) {
215 this.validatorUrl = validatorUrl;
216 }
217
218 public String getPath() {
219 return path;
220 }
221
222 public void setPath(String path) {
223 this.path = path;
224 }
225
226 public String getLayout() {
227 return layout;
228 }
229
230 public void setLayout(String layout) {
231 this.layout = layout;
232 }
233
234 public String getConfigUrl() {
235 return configUrl;
236 }
237
238 public void setConfigUrl(String configUrl) {
239 this.configUrl = configUrl;
240 }
241
242 public String getFilter() {
243 return filter;
244 }
245
246 public void setFilter(String filter) {
247 this.filter = filter;
248 }
249
250 public String getOperationsSorter() {
251 return operationsSorter;
252 }
253
254 public void setOperationsSorter(String operationsSorter) {
255 this.operationsSorter = operationsSorter;
256 }
257
258 public String getTagsSorter() {
259 return tagsSorter;
260 }
261
262 public void setTagsSorter(String tagsSorter) {
263 this.tagsSorter = tagsSorter;
264 }
265
266 public Boolean getDeepLinking() {
267 return deepLinking;
268 }
269
270 public void setDeepLinking(Boolean deepLinking) {
271 this.deepLinking = deepLinking;
272 }
273
274 public Boolean getDisplayOperationId() {
275 return displayOperationId;
276 }
277
278 public void setDisplayOperationId(Boolean displayOperationId) {
279 this.displayOperationId = displayOperationId;
280 }
281
282 public Integer getDefaultModelsExpandDepth() {
283 return defaultModelsExpandDepth;
284 }
285
286 public void setDefaultModelsExpandDepth(Integer defaultModelsExpandDepth) {
287 this.defaultModelsExpandDepth = defaultModelsExpandDepth;
288 }
289
290 public Integer getDefaultModelExpandDepth() {
291 return defaultModelExpandDepth;
292 }
293
294 public void setDefaultModelExpandDepth(Integer defaultModelExpandDepth) {
295 this.defaultModelExpandDepth = defaultModelExpandDepth;
296 }
297
298 public String getDefaultModelRendering() {
299 return defaultModelRendering;
300 }
301
302 public void setDefaultModelRendering(String defaultModelRendering) {
303 this.defaultModelRendering = defaultModelRendering;
304 }
305
306 public Boolean getDisplayRequestDuration() {
307 return displayRequestDuration;
308 }
309
310 public void setDisplayRequestDuration(Boolean displayRequestDuration) {
311 this.displayRequestDuration = displayRequestDuration;
312 }
313
314 public String getDocExpansion() {
315 return docExpansion;
316 }
317
318 public void setDocExpansion(String docExpansion) {
319 this.docExpansion = docExpansion;
320 }
321
322 public Integer getMaxDisplayedTags() {
323 return maxDisplayedTags;
324 }
325
326 public void setMaxDisplayedTags(Integer maxDisplayedTags) {
327 this.maxDisplayedTags = maxDisplayedTags;
328 }
329
330 public Boolean getShowExtensions() {
331 return showExtensions;
332 }
333
334 public void setShowExtensions(Boolean showExtensions) {
335 this.showExtensions = showExtensions;
336 }
337
338 public Boolean getShowCommonExtensions() {
339 return showCommonExtensions;
340 }
341
342 public void setShowCommonExtensions(Boolean showCommonExtensions) {
343 this.showCommonExtensions = showCommonExtensions;
344 }
345
346 public List<String> getSupportedSubmitMethods() {
347 return supportedSubmitMethods;
348 }
349
350 public void setSupportedSubmitMethods(List<String> supportedSubmitMethods) {
351 this.supportedSubmitMethods = supportedSubmitMethods;
352 }
353
354 public String getOauth2RedirectUrl() {
355 return oauth2RedirectUrl;
356 }
357
358 public void setOauth2RedirectUrl(String oauth2RedirectUrl) {
359 this.oauth2RedirectUrl = oauth2RedirectUrl;
360 }
361
362 public String getUrl() {
363 return url;
364 }
365
366 public void setUrl(String url) {
367 this.url = url;
368 }
369
370 public boolean isValidUrl(String url) {
371 try {
372 new URL(url).toURI();
373 return true;
374 }
375 catch (Exception e) {
376 return false;
377 }
378 }
379
380 private void put(String urls, Set<SwaggerUrl> swaggerUrls, Map<String, Object> params) {
381 Comparator<SwaggerUrl> swaggerUrlComparator;
382 if (groupsOrder.isAscending())
383 swaggerUrlComparator = Comparator.comparing(SwaggerUrl::getName);
384 else
385 swaggerUrlComparator = (h1, h2) -> h2.getName().compareTo(h1.getName());
386
387 swaggerUrls = swaggerUrls.stream().sorted(swaggerUrlComparator).filter(elt -> StringUtils.isNotEmpty(elt.getUrl())).collect(Collectors.toCollection(LinkedHashSet::new));
388 if (!CollectionUtils.isEmpty(swaggerUrls)) {
389 params.put(urls, swaggerUrls);
390 }
391 }
392
393 public Direction getGroupsOrder() {
394 return groupsOrder;
395 }
396
397 public void setGroupsOrder(Direction groupsOrder) {
398 this.groupsOrder = groupsOrder;
399 }
400
401 enum Direction {
402 ASC,
403 DESC;
404
405 public boolean isAscending() {
406 return this.equals(ASC);
407 }
408 }
409
410 static class SwaggerUrl {
411 private String url;
412
413 private String name;
414
415 public SwaggerUrl() {
416 }
417
418 public SwaggerUrl(String group, String url) {
419 Objects.requireNonNull(group, GROUP_NAME_NOT_NULL);
420 this.url = url;
421 this.name = group;
422 }
423
424 public SwaggerUrl(String group) {
425 Objects.requireNonNull(group, GROUP_NAME_NOT_NULL);
426 this.name = group;
427 }
428
429 public String getUrl() {
430 return url;
431 }
432
433 public void setUrl(String url) {
434 this.url = url;
435 }
436
437 public String getName() {
438 return name;
439 }
440
441 public void setName(String name) {
442 this.name = name;
443 }
444
445 @Override
446 public boolean equals(Object o) {
447 if (this == o) return true;
448 if (o == null || getClass() != o.getClass()) return false;
449 SwaggerUrl that = (SwaggerUrl) o;
450 return name.equals(that.name);
451 }
452
453 @Override
454 public int hashCode() {
455 return Objects.hash(name);
456 }
457
458 @Override
459 public String toString() {
460 final StringBuilder sb = new StringBuilder("SwaggerUrl{");
461 sb.append("url='").append(url).append('\'');
462 sb.append(", name='").append(name).append('\'');
463 sb.append('}');
464 return sb.toString();
465 }
466 }
467 }