1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.bean.openapi3;
18
19 import static org.apache.juneau.commons.utils.AssertionUtils.*;
20 import static org.apache.juneau.commons.utils.CollectionUtils.*;
21 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
22 import static org.apache.juneau.commons.utils.Utils.*;
23 import static org.apache.juneau.internal.ConverterUtils.*;
24
25 import java.util.*;
26
27 import org.apache.juneau.commons.collections.*;
28 import org.apache.juneau.json.*;
29 import org.apache.juneau.objecttools.*;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public class OpenApi extends OpenApiElement {
79
80
81 public static final OpenApi NULL = new OpenApi();
82
83 private static final Comparator<String> PATH_COMPARATOR = (o1, o2) -> o1.replace('{', '@').compareTo(o2.replace('{', '@'));
84
85 private String openapi = "3.0.0";
86 private Info info;
87 private List<Server> servers = list();
88 private Map<String,PathItem> paths;
89 private Components components;
90 private List<SecurityRequirement> security = list();
91 private List<Tag> tags = list();
92 private ExternalDocumentation externalDocs;
93
94
95
96
97 public OpenApi() {}
98
99
100
101
102
103
104 public OpenApi(OpenApi copyFrom) {
105 super(copyFrom);
106 this.openapi = copyFrom.openapi;
107 this.info = copyFrom.info;
108 if (nn(copyFrom.servers))
109 this.servers.addAll(copyOf(copyFrom.servers, Server::copy));
110 this.paths = copyOf(copyFrom.paths);
111 this.components = copyFrom.components;
112 if (nn(copyFrom.security))
113 this.security.addAll(copyOf(copyFrom.security, SecurityRequirement::copy));
114 if (nn(copyFrom.tags))
115 this.tags.addAll(copyOf(copyFrom.tags, Tag::copy));
116 this.externalDocs = copyFrom.externalDocs;
117 }
118
119
120
121
122
123
124
125
126 public OpenApi addPath(String path, PathItem pathItem) {
127 assertArgNotNull("path", path);
128 assertArgNotNull("pathItem", pathItem);
129 if (paths == null)
130 paths = new TreeMap<>(PATH_COMPARATOR);
131 getPaths().put(path, pathItem);
132 return this;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 public OpenApi addSecurity(Collection<SecurityRequirement> values) {
147 security = listb(SecurityRequirement.class).sparse().addAny(security, values).build();
148 return this;
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162 public OpenApi addSecurity(SecurityRequirement...values) {
163 security = listb(SecurityRequirement.class).sparse().addAll(security).addAny((Object)values).build();
164 return this;
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178 public OpenApi addServers(Collection<Server> values) {
179 if (nn(values))
180 servers.addAll(values);
181 return this;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195 public OpenApi addServers(Server...values) {
196 if (nn(values))
197 for (var v : values)
198 if (nn(v))
199 servers.add(v);
200 return this;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214 public OpenApi addTags(Collection<Tag> values) {
215 if (nn(values))
216 tags.addAll(values);
217 return this;
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231 public OpenApi addTags(Tag...values) {
232 if (nn(values))
233 for (var v : values)
234 if (nn(v))
235 tags.add(v);
236 return this;
237 }
238
239
240
241
242
243
244 public OpenApi copy() {
245 return new OpenApi(this);
246 }
247
248
249
250
251
252
253
254
255 public <T> T findRef(String ref, Class<T> c) {
256 assertArgNotNullOrBlank("ref", ref);
257 assertArgNotNull("c", c);
258 if (! ref.startsWith("#/"))
259 throw rex("Unsupported reference: ''{0}''", ref);
260 try {
261 return new ObjectRest(this).get(ref.substring(1), c);
262 } catch (Exception e) {
263 throw bex(e, c, "Reference ''{0}'' could not be converted to type ''{1}''.", ref, cn(c));
264 }
265 }
266
267 @Override
268 public <T> T get(String property, Class<T> type) {
269 assertArgNotNull("property", property);
270 return switch (property) {
271 case "openapi" -> toType(getOpenapi(), type);
272 case "info" -> toType(getInfo(), type);
273 case "servers" -> toType(getServers(), type);
274 case "paths" -> toType(getPaths(), type);
275 case "components" -> toType(getComponents(), type);
276 case "security" -> toType(getSecurity(), type);
277 case "tags" -> toType(getTags(), type);
278 case "externalDocs" -> toType(getExternalDocs(), type);
279 default -> super.get(property, type);
280 };
281 }
282
283
284
285
286
287
288 public Components getComponents() { return components; }
289
290
291
292
293
294
295 public ExternalDocumentation getExternalDocs() { return externalDocs; }
296
297
298
299
300
301
302 public Info getInfo() { return info; }
303
304
305
306
307
308
309 public String getOpenapi() { return openapi; }
310
311
312
313
314
315
316 public Map<String,PathItem> getPaths() { return paths; }
317
318
319
320
321
322
323 public List<SecurityRequirement> getSecurity() { return nullIfEmpty(security); }
324
325
326
327
328
329
330 public List<Server> getServers() { return nullIfEmpty(servers); }
331
332
333
334
335
336
337 public List<Tag> getTags() { return nullIfEmpty(tags); }
338
339 @Override
340 public Set<String> keySet() {
341
342 var s = setb(String.class)
343 .addIf(nn(components), "components")
344 .addIf(nn(externalDocs), "externalDocs")
345 .addIf(nn(info), "info")
346 .addIf(nn(openapi), "openapi")
347 .addIf(nn(paths), "paths")
348 .addIf(ne(security), "security")
349 .addIf(ne(servers), "servers")
350 .addIf(ne(tags), "tags")
351 .build();
352
353 return new MultiSet<>(s, super.keySet());
354 }
355
356 @Override
357 public OpenApi set(String property, Object value) {
358 assertArgNotNull("property", property);
359 return switch (property) {
360 case "components" -> setComponents(toType(value, Components.class));
361 case "externalDocs" -> setExternalDocs(toType(value, ExternalDocumentation.class));
362 case "info" -> setInfo(toType(value, Info.class));
363 case "openapi" -> setOpenapi(s(value));
364 case "paths" -> setPaths(toMapBuilder(value, String.class, PathItem.class).sparse().build());
365 case "security" -> setSecurity(listb(SecurityRequirement.class).addAny(value).sparse().build());
366 case "servers" -> setServers(listb(Server.class).addAny(value).sparse().build());
367 case "tags" -> setTags(listb(Tag.class).addAny(value).sparse().build());
368 default -> {
369 super.set(property, value);
370 yield this;
371 }
372 };
373 }
374
375
376
377
378
379
380
381 public OpenApi setComponents(Components value) {
382 components = value;
383 return this;
384 }
385
386
387
388
389
390
391
392 public OpenApi setExternalDocs(ExternalDocumentation value) {
393 externalDocs = value;
394 return this;
395 }
396
397
398
399
400
401
402
403 public OpenApi setInfo(Info value) {
404 info = value;
405 return this;
406 }
407
408
409
410
411
412
413
414 public OpenApi setOpenapi(String value) {
415 openapi = value;
416 return this;
417 }
418
419
420
421
422
423
424
425 public OpenApi setPaths(Map<String,PathItem> value) {
426 this.paths = toMapBuilder(value, String.class, PathItem.class).sparse().sorted(PATH_COMPARATOR).build();
427 return this;
428 }
429
430
431
432
433
434
435
436 public OpenApi setSecurity(List<SecurityRequirement> value) {
437 security.clear();
438 if (nn(value))
439 security.addAll(value);
440 return this;
441 }
442
443
444
445
446
447
448
449 public OpenApi setServers(List<Server> value) {
450 servers.clear();
451 if (nn(value))
452 servers.addAll(value);
453 return this;
454 }
455
456
457
458
459
460
461
462 public OpenApi setTags(List<Tag> value) {
463 tags.clear();
464 if (nn(value))
465 tags.addAll(value);
466 return this;
467 }
468
469
470
471
472
473
474
475
476
477
478
479
480 public OpenApi setTags(Tag...value) {
481 setTags(listb(Tag.class).add(value).sparse().build());
482 return this;
483 }
484
485 @Override
486 public OpenApi strict() {
487 super.strict();
488 return this;
489 }
490
491 @Override
492 public OpenApi strict(Object value) {
493 super.strict(value);
494 return this;
495 }
496
497 @Override
498 public String toString() {
499 return JsonSerializer.DEFAULT.toString(this);
500 }
501 }