2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.sal.rest.doc.impl;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.CONTENT_KEY;
16 import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.REF_KEY;
17 import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.REQUEST_BODY_KEY;
18 import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.RESPONSES_KEY;
19 import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.SCHEMA_KEY;
20 import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.getAppropriateModelPrefix;
22 import com.fasterxml.jackson.databind.JsonNode;
23 import com.fasterxml.jackson.databind.node.ObjectNode;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.Sets;
26 import java.util.ArrayList;
27 import java.util.HashSet;
28 import java.util.List;
30 import java.util.stream.Collectors;
31 import java.util.stream.StreamSupport;
32 import org.junit.Test;
33 import org.opendaylight.netconf.sal.rest.doc.swagger.OpenApiObject;
34 import org.opendaylight.netconf.sal.rest.doc.swagger.SwaggerObject;
36 public final class ApiDocGeneratorRFC8040Test extends AbstractApiDocTest {
37 private static final String NAME = "toaster2";
38 private static final String MY_YANG = "my-yang";
39 private static final String MY_YANG_REVISION = "2022-10-06";
40 private static final String REVISION_DATE = "2009-11-20";
41 private static final String NAME_2 = "toaster";
42 private static final String REVISION_DATE_2 = "2009-11-20";
43 private static final String PATH_PARAMS_TEST_MODULE = "path-params-test";
44 private static final String MANDATORY_TEST = "mandatory-test";
45 private static final String CONFIG_ROOT_CONTAINER = "mandatory-test_config_root-container";
46 private static final String ROOT_CONTAINER = "mandatory-test_root-container";
47 private static final String CONFIG_MANDATORY_CONTAINER = "mandatory-test_root-container_config_mandatory-container";
48 private static final String MANDATORY_CONTAINER = "mandatory-test_root-container_mandatory-container";
49 private static final String CONFIG_MANDATORY_LIST = "mandatory-test_root-container_config_mandatory-list";
50 private static final String CONFIG_MANDATORY_LIST_POST = "mandatory-test_root-container_config_mandatory-list_post";
51 private static final String MANDATORY_LIST = "mandatory-test_root-container_mandatory-list";
52 private static final String MANDATORY_TEST_MODULE = "mandatory-test_config_module";
53 private static final String CHOICE_TEST_MODULE = "choice-test";
54 private static final String PROPERTIES = "properties";
55 private static final String CONTAINER = "container";
56 private static final String LIST = "list";
58 private final ApiDocGeneratorRFC8040 generator = new ApiDocGeneratorRFC8040(SCHEMA_SERVICE);
61 * Test that paths are generated according to the model.
64 public void testPaths() {
65 final SwaggerObject doc = (SwaggerObject) generator.getApiDeclaration(NAME, REVISION_DATE, URI_INFO,
66 ApiDocServiceImpl.OAversion.V2_0);
68 assertEquals(List.of("/rests/data",
69 "/rests/data/toaster2:toaster",
70 "/rests/data/toaster2:toaster/toasterSlot={slotId}",
71 "/rests/data/toaster2:toaster/toasterSlot={slotId}/toaster-augmented:slotInfo",
72 "/rests/data/toaster2:lst",
73 "/rests/data/toaster2:lst/cont1",
74 "/rests/data/toaster2:lst/cont1/cont11",
75 "/rests/data/toaster2:lst/cont1/lst11",
76 "/rests/data/toaster2:lst/lst1={key1},{key2}",
77 "/rests/operations/toaster2:make-toast",
78 "/rests/operations/toaster2:cancel-toast",
79 "/rests/operations/toaster2:restock-toaster"),
80 ImmutableList.copyOf(doc.getPaths().fieldNames()));
84 * Test that generated configuration paths allow to use operations: get, put, delete and post.
87 public void testConfigPaths() {
88 final List<String> configPaths = List.of("/rests/data/toaster2:lst",
89 "/rests/data/toaster2:lst/cont1",
90 "/rests/data/toaster2:lst/cont1/cont11",
91 "/rests/data/toaster2:lst/cont1/lst11",
92 "/rests/data/toaster2:lst/lst1={key1},{key2}");
94 final SwaggerObject doc = (SwaggerObject) generator.getApiDeclaration(NAME, REVISION_DATE, URI_INFO,
95 ApiDocServiceImpl.OAversion.V2_0);
97 for (final String path : configPaths) {
98 final JsonNode node = doc.getPaths().get(path);
99 assertFalse(node.path("get").isMissingNode());
100 assertFalse(node.path("put").isMissingNode());
101 assertFalse(node.path("delete").isMissingNode());
102 assertFalse(node.path("post").isMissingNode());
107 * Test that generated document contains the following definitions.
110 public void testDefinitions() {
111 final SwaggerObject doc = (SwaggerObject) generator.getApiDeclaration(NAME, REVISION_DATE, URI_INFO,
112 ApiDocServiceImpl.OAversion.V2_0);
114 final ObjectNode definitions = doc.getDefinitions();
115 assertNotNull(definitions);
117 final JsonNode configLstTop = definitions.get("toaster2_config_lst_TOP");
118 assertNotNull(configLstTop);
119 DocGenTestHelper.containsReferences(configLstTop, "toaster2:lst", "#/definitions/toaster2_config_lst");
121 final JsonNode configLst = definitions.get("toaster2_config_lst");
122 assertNotNull(configLst);
123 DocGenTestHelper.containsReferences(configLst, "lst1", "#/definitions/toaster2_lst_config_lst1");
124 DocGenTestHelper.containsReferences(configLst, "cont1", "#/definitions/toaster2_lst_config_cont1");
126 final JsonNode configLst1Top = definitions.get("toaster2_lst_config_lst1_TOP");
127 assertNotNull(configLst1Top);
128 DocGenTestHelper.containsReferences(configLst1Top, "toaster2:lst1", "#/definitions/toaster2_lst_config_lst1");
130 final JsonNode configLst1 = definitions.get("toaster2_lst_config_lst1");
131 assertNotNull(configLst1);
133 final JsonNode configCont1Top = definitions.get("toaster2_lst_config_cont1_TOP");
134 assertNotNull(configCont1Top);
135 DocGenTestHelper.containsReferences(configCont1Top, "toaster2:cont1",
136 "#/definitions/toaster2_lst_config_cont1");
138 final JsonNode configCont1 = definitions.get("toaster2_lst_config_cont1");
139 assertNotNull(configCont1);
140 DocGenTestHelper.containsReferences(configCont1, "cont11", "#/definitions/toaster2_lst_cont1_config_cont11");
141 DocGenTestHelper.containsReferences(configCont1, "lst11", "#/definitions/toaster2_lst_cont1_config_lst11");
143 final JsonNode configCont11Top = definitions.get("toaster2_lst_cont1_config_cont11_TOP");
144 assertNotNull(configCont11Top);
145 DocGenTestHelper.containsReferences(configCont11Top, "toaster2:cont11",
146 "#/definitions/toaster2_lst_cont1_config_cont11");
148 final JsonNode configCont11 = definitions.get("toaster2_lst_cont1_config_cont11");
149 assertNotNull(configCont11);
151 final JsonNode configLst11Top = definitions.get("toaster2_lst_cont1_config_lst11_TOP");
152 assertNotNull(configLst11Top);
153 DocGenTestHelper.containsReferences(configLst11Top, "toaster2:lst11",
154 "#/definitions/toaster2_lst_cont1_config_lst11");
156 final JsonNode configLst11 = definitions.get("toaster2_lst_cont1_config_lst11");
157 assertNotNull(configLst11);
161 * Test that generated document contains RPC definition for "make-toast" with correct input.
164 public void testRPC() {
165 final SwaggerObject doc = (SwaggerObject) generator.getApiDeclaration(NAME_2, REVISION_DATE_2, URI_INFO,
166 ApiDocServiceImpl.OAversion.V2_0);
169 final ObjectNode definitions = doc.getDefinitions();
170 final JsonNode inputTop = definitions.get("toaster_make-toast_input_TOP");
171 assertNotNull(inputTop);
172 final String testString = "{\"toaster:input\":{\"$ref\":\"#/definitions/toaster_make-toast_input\"}}";
173 assertEquals(testString, inputTop.get("properties").toString());
174 final JsonNode input = definitions.get("toaster_make-toast_input");
175 final JsonNode properties = input.get("properties");
176 assertTrue(properties.has("toasterDoneness"));
177 assertTrue(properties.has("toasterToastType"));
181 public void testMandatory() {
182 final var doc = (OpenApiObject) generator.getApiDeclaration(MANDATORY_TEST, null, URI_INFO,
183 ApiDocServiceImpl.OAversion.V3_0);
185 final var definitions = doc.getComponents().getSchemas();
186 final var containersWithRequired = new ArrayList<String>();
188 final var reqRootContainerElements = Set.of("mandatory-root-leaf", "mandatory-container",
189 "mandatory-first-choice", "mandatory-list");
190 verifyRequiredField(definitions.get(CONFIG_ROOT_CONTAINER), reqRootContainerElements);
191 containersWithRequired.add(CONFIG_ROOT_CONTAINER);
192 verifyRequiredField(definitions.get(ROOT_CONTAINER), reqRootContainerElements);
193 containersWithRequired.add(ROOT_CONTAINER);
195 final var reqMandatoryContainerElements = Set.of("mandatory-leaf", "leaf-list-with-min-elements");
196 verifyRequiredField(definitions.get(CONFIG_MANDATORY_CONTAINER), reqMandatoryContainerElements);
197 containersWithRequired.add(CONFIG_MANDATORY_CONTAINER);
198 verifyRequiredField(definitions.get(MANDATORY_CONTAINER), reqMandatoryContainerElements);
199 containersWithRequired.add(MANDATORY_CONTAINER);
201 final var reqMandatoryListElements = Set.of("mandatory-list-field");
202 verifyRequiredField(definitions.get(CONFIG_MANDATORY_LIST), reqMandatoryListElements);
203 containersWithRequired.add(CONFIG_MANDATORY_LIST);
204 verifyRequiredField(definitions.get(MANDATORY_LIST), reqMandatoryListElements);
205 containersWithRequired.add(MANDATORY_LIST);
207 final var testModuleMandatoryArray = Set.of("root-container", "root-mandatory-list");
208 verifyRequiredField(definitions.get(MANDATORY_TEST_MODULE), testModuleMandatoryArray);
209 containersWithRequired.add(MANDATORY_TEST_MODULE);
211 verifyThatPropertyDoesNotHaveRequired(containersWithRequired, definitions);
215 * Test that request parameters are correctly numbered.
218 * It means we should have name and name1, etc. when we have the same parameter in path multiple times.
221 public void testParametersNumbering() {
222 final var doc = (OpenApiObject) generator.getApiDeclaration(PATH_PARAMS_TEST_MODULE, null, URI_INFO,
223 ApiDocServiceImpl.OAversion.V3_0);
225 var pathToList1 = "/rests/data/path-params-test:cont/list1={name}";
226 assertTrue(doc.getPaths().has(pathToList1));
227 assertEquals(List.of("name"), getPathParameters(doc.getPaths(), pathToList1));
229 var pathToList2 = "/rests/data/path-params-test:cont/list1={name}/list2={name1}";
230 assertTrue(doc.getPaths().has(pathToList2));
231 assertEquals(List.of("name", "name1"), getPathParameters(doc.getPaths(), pathToList2));
233 var pathToList3 = "/rests/data/path-params-test:cont/list3={name}";
234 assertTrue(doc.getPaths().has(pathToList3));
235 assertEquals(List.of("name"), getPathParameters(doc.getPaths(), pathToList3));
237 var pathToList4 = "/rests/data/path-params-test:cont/list1={name}/list4={name1}";
238 assertTrue(doc.getPaths().has(pathToList4));
239 assertEquals(List.of("name", "name1"), getPathParameters(doc.getPaths(), pathToList4));
241 var pathToList5 = "/rests/data/path-params-test:cont/list1={name}/cont2";
242 assertTrue(doc.getPaths().has(pathToList4));
243 assertEquals(List.of("name"), getPathParameters(doc.getPaths(), pathToList5));
246 private static void verifyThatPropertyDoesNotHaveRequired(final List<String> expected,
247 final ObjectNode definitions) {
248 final var fields = definitions.fields();
249 while (fields.hasNext()) {
250 final var next = fields.next();
251 final var nodeName = next.getKey();
252 final var jsonNode = next.getValue();
253 if (expected.contains(nodeName)) {
256 assertNull("Json node " + nodeName + " should not have 'required' field in body",
257 jsonNode.get("required"));
261 private static void verifyRequiredField(final JsonNode rootContainer, final Set<String> expected) {
262 assertNotNull(rootContainer);
263 final var required = rootContainer.get("required");
264 assertNotNull(required);
265 assertTrue(required.isArray());
266 final var actualContainerArray = StreamSupport.stream(required.spliterator(), false)
267 .map(JsonNode::textValue)
268 .collect(Collectors.toSet());
269 assertEquals(expected, actualContainerArray);
273 * Test that request for actions is correct and has parameters.
276 public void testActionPathsParams() {
277 final var doc = (OpenApiObject) generator.getApiDeclaration("action-types", null, URI_INFO,
278 ApiDocServiceImpl.OAversion.V3_0);
280 final var pathWithParameters = "/rests/operations/action-types:list={name}/list-action";
281 assertTrue(doc.getPaths().has(pathWithParameters));
282 assertEquals(List.of("name"), getPathParameters(doc.getPaths(), pathWithParameters));
284 final var pathWithoutParameters = "/rests/operations/action-types:multi-container/inner-container/action";
285 assertTrue(doc.getPaths().has(pathWithoutParameters));
286 assertEquals(List.of(), getPathParameters(doc.getPaths(), pathWithoutParameters));
290 public void testChoice() {
291 final var doc = (SwaggerObject) generator.getApiDeclaration(CHOICE_TEST_MODULE, null, URI_INFO,
292 ApiDocServiceImpl.OAversion.V2_0);
295 final var definitions = doc.getDefinitions();
296 JsonNode firstContainer = definitions.get("choice-test_first-container");
297 assertEquals("default-value",
298 firstContainer.get(PROPERTIES).get("leaf-default").get("default").asText());
299 assertFalse(firstContainer.get(PROPERTIES).has("leaf-non-default"));
301 JsonNode secondContainer = definitions.get("choice-test_second-container");
302 assertTrue(secondContainer.get(PROPERTIES).has("leaf-first-case"));
303 assertFalse(secondContainer.get(PROPERTIES).has("leaf-second-case"));
307 public void testSimpleOpenApiObjects() {
308 final var doc = (OpenApiObject) generator.getApiDeclaration(MY_YANG, MY_YANG_REVISION, URI_INFO,
309 ApiDocServiceImpl.OAversion.V3_0);
310 assertEquals(List.of("/rests/data", "/rests/data/my-yang:data"),
311 ImmutableList.copyOf(doc.getPaths().fieldNames()));
313 final var JsonNodeMyYangData = doc.getPaths().get("/rests/data/my-yang:data");
314 verifyRequestRef(JsonNodeMyYangData.path("post"),
315 "#/components/schemas/my-yang_config_data",
316 "#/components/schemas/my-yang_config_data");
317 verifyRequestRef(JsonNodeMyYangData.path("put"), "#/components/schemas/my-yang_config_data_TOP",
318 "#/components/schemas/my-yang_config_data");
319 verifyRequestRef(JsonNodeMyYangData.path("get"), "#/components/schemas/my-yang_data_TOP",
320 "#/components/schemas/my-yang_data");
322 // Test `components/schemas` objects
323 final var definitions = doc.getComponents().getSchemas();
324 assertEquals(5, definitions.size());
325 assertTrue(definitions.has("my-yang_config_data"));
326 assertTrue(definitions.has("my-yang_config_data_TOP"));
327 assertTrue(definitions.has("my-yang_data"));
328 assertTrue(definitions.has("my-yang_data_TOP"));
329 assertTrue(definitions.has("my-yang_config_module"));
333 public void testToaster2OpenApiObjects() {
334 final var doc = (OpenApiObject) generator.getApiDeclaration(NAME, REVISION_DATE, URI_INFO,
335 ApiDocServiceImpl.OAversion.V3_0);
336 final var jsonNodeToaster = doc.getPaths().get("/rests/data/toaster2:toaster");
337 verifyPostRequestRef(jsonNodeToaster.path("post"),
338 "#/components/schemas/toaster2_toaster_config_toasterSlot",
339 "#/components/schemas/toaster2_toaster_config_toasterSlot", LIST);
340 verifyRequestRef(jsonNodeToaster.path("put"), "#/components/schemas/toaster2_config_toaster_TOP",
341 "#/components/schemas/toaster2_config_toaster");
342 verifyRequestRef(jsonNodeToaster.path("get"), "#/components/schemas/toaster2_toaster_TOP",
343 "#/components/schemas/toaster2_toaster");
345 final var jsonNodeToasterSlot = doc.getPaths().get("/rests/data/toaster2:toaster/toasterSlot={slotId}");
346 verifyPostRequestRef(jsonNodeToasterSlot.path("post"),
347 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo",
348 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo", CONTAINER);
349 verifyRequestRef(jsonNodeToasterSlot.path("put"),
350 "#/components/schemas/toaster2_toaster_config_toasterSlot_TOP",
351 "#/components/schemas/toaster2_toaster_config_toasterSlot");
352 verifyRequestRef(jsonNodeToasterSlot.path("get"), "#/components/schemas/toaster2_toaster_toasterSlot_TOP",
353 "#/components/schemas/toaster2_toaster_toasterSlot");
355 final var jsonNodeSlotInfo = doc.getPaths().get(
356 "/rests/data/toaster2:toaster/toasterSlot={slotId}/toaster-augmented:slotInfo");
357 verifyRequestRef(jsonNodeSlotInfo.path("post"),
358 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo",
359 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo");
360 verifyRequestRef(jsonNodeSlotInfo.path("put"),
361 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo_TOP",
362 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo");
363 verifyRequestRef(jsonNodeSlotInfo.path("get"), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo_TOP",
364 "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo");
366 final var jsonNodeLst = doc.getPaths().get("/rests/data/toaster2:lst");
367 verifyPostRequestRef(jsonNodeLst.path("post"), "#/components/schemas/toaster2_lst_config_cont1",
368 "#/components/schemas/toaster2_lst_config_cont1", CONTAINER);
369 verifyRequestRef(jsonNodeLst.path("put"), "#/components/schemas/toaster2_config_lst_TOP",
370 "#/components/schemas/toaster2_config_lst");
371 verifyRequestRef(jsonNodeLst.path("get"), "#/components/schemas/toaster2_lst_TOP",
372 "#/components/schemas/toaster2_lst");
374 final var jsonNodeLst1 = doc.getPaths().get("/rests/data/toaster2:lst/lst1={key1},{key2}");
375 verifyRequestRef(jsonNodeLst1.path("post"), "#/components/schemas/toaster2_lst_config_lst1",
376 "#/components/schemas/toaster2_lst_config_lst1");
377 verifyRequestRef(jsonNodeLst1.path("put"), "#/components/schemas/toaster2_lst_config_lst1_TOP",
378 "#/components/schemas/toaster2_lst_config_lst1");
379 verifyRequestRef(jsonNodeLst1.path("get"), "#/components/schemas/toaster2_lst_lst1_TOP",
380 "#/components/schemas/toaster2_lst_lst1");
382 final var jsonNodeMakeToast = doc.getPaths().get("/rests/operations/toaster2:make-toast");
383 assertTrue(jsonNodeMakeToast.path("get").isMissingNode());
384 verifyRequestRef(jsonNodeMakeToast.path("post"), "#/components/schemas/toaster2_make-toast_input_TOP",
385 "#/components/schemas/toaster2_make-toast_input");
387 final var jsonNodeCancelToast = doc.getPaths().get("/rests/operations/toaster2:cancel-toast");
388 assertTrue(jsonNodeCancelToast.path("get").isMissingNode());
389 // Test RPC with empty input
390 final var postContent = jsonNodeCancelToast.path("post").get("requestBody").get("content");
391 final var jsonSchema = postContent.get("application/json").get("schema");
392 assertNull(jsonSchema.get("$ref"));
393 assertEquals(2, jsonSchema.size());
394 final var xmlSchema = postContent.get("application/xml").get("schema");
395 assertNull(xmlSchema.get("$ref"));
396 assertEquals(2, xmlSchema.size());
397 // Test `components/schemas` objects
398 final var definitions = doc.getComponents().getSchemas();
399 assertEquals(44, definitions.size());
403 * Test that reference to schema in each path is valid (all referenced schemas exist).
406 public void testRootPostSchemaReference() {
407 final var document = (OpenApiObject) generator.getApiDeclaration(NAME, REVISION_DATE, URI_INFO,
408 ApiDocServiceImpl.OAversion.V3_0);
409 assertNotNull(document);
410 final var expectedSchema = "toaster2_config_module";
411 // verify schema reference itself
412 verifyRequestRef(document.getPaths().path("/rests/data").path("post"),
413 getAppropriateModelPrefix(ApiDocServiceImpl.OAversion.V3_0) + expectedSchema,
414 getAppropriateModelPrefix(ApiDocServiceImpl.OAversion.V3_0) + expectedSchema);
415 // verify existence of the schemas being referenced
416 assertTrue("The expected referenced schema (" + expectedSchema + ") is not created",
417 document.getComponents().getSchemas().has(expectedSchema));
421 * Test that reference to schema in each path is valid (all referenced schemas exist).
424 public void testSchemasExistenceSingleModule() {
425 final var document = (OpenApiObject) generator.getApiDeclaration(NAME, REVISION_DATE, URI_INFO,
426 ApiDocServiceImpl.OAversion.V3_0);
427 assertNotNull(document);
428 final var referencedSchemas = new HashSet<String>();
429 for (final var elements = document.getPaths().elements(); elements.hasNext(); ) {
430 final var path = elements.next();
431 referencedSchemas.addAll(extractSchemaRefFromPath(path, ApiDocServiceImpl.OAversion.V3_0));
433 final var schemaNamesIterator = document.getComponents().getSchemas().fieldNames();
434 final var schemaNames = Sets.newHashSet(schemaNamesIterator);
435 for (final var ref : referencedSchemas) {
436 assertTrue("Referenced schema " + ref + " does not exist", schemaNames.contains(ref));
441 * Test JSON and XML references for request operation.
443 private static void verifyRequestRef(final JsonNode path, final String expectedJsonRef,
444 final String expectedXmlRef) {
445 final JsonNode postContent;
446 if (path.get("requestBody") != null) {
447 postContent = path.get("requestBody").get("content");
449 postContent = path.get("responses").get("200").get("content");
451 assertNotNull(postContent);
452 final var postJsonRef = postContent.get("application/json").get("schema").get("$ref");
453 assertNotNull(postJsonRef);
454 assertEquals(expectedJsonRef, postJsonRef.textValue());
455 final var postXmlRef = postContent.get("application/xml").get("schema").get("$ref");
456 assertNotNull(postXmlRef);
457 assertEquals(expectedXmlRef, postXmlRef.textValue());
460 private static void verifyPostRequestRef(final JsonNode path, final String expectedJsonRef,
461 final String expectedXmlRef, String nodeType) {
462 final JsonNode postContent;
463 if (path.get("requestBody") != null) {
464 postContent = path.get("requestBody").get("content");
466 postContent = path.get("responses").get("200").get("content");
468 assertNotNull(postContent);
469 final String postJsonRef;
470 if (nodeType.equals(CONTAINER)) {
471 postJsonRef = postContent.path("application/json").path("schema").path("properties").elements().next()
472 .path("$ref").textValue();
474 postJsonRef = postContent.path("application/json").path("schema").path("properties").elements().next()
475 .path("items").path("$ref").textValue();
477 assertEquals(expectedJsonRef, postJsonRef);
478 final var postXmlRef = postContent.get("application/xml").get("schema").get("$ref");
479 assertNotNull(postXmlRef);
480 assertEquals(expectedXmlRef, postXmlRef.textValue());
483 private static Set<String> extractSchemaRefFromPath(final JsonNode path,
484 final ApiDocServiceImpl.OAversion oaversion) {
485 if (path == null || path.isMissingNode()) {
488 final var references = new HashSet<String>();
489 final var get = path.path("get");
490 if (!get.isMissingNode()) {
492 schemaRefFromContent(get.path(RESPONSES_KEY).path("200").path(CONTENT_KEY), oaversion));
494 final var post = path.path("post");
495 if (!post.isMissingNode()) {
496 references.addAll(schemaRefFromContent(post.path(REQUEST_BODY_KEY).path(CONTENT_KEY), oaversion));
498 final var put = path.path("put");
499 if (!put.isMissingNode()) {
500 references.addAll(schemaRefFromContent(put.path(REQUEST_BODY_KEY).path(CONTENT_KEY), oaversion));
502 final var patch = path.path("patch");
503 if (!patch.isMissingNode()) {
504 references.addAll(schemaRefFromContent(patch.path(REQUEST_BODY_KEY).path(CONTENT_KEY), oaversion));
509 private static Set<String> schemaRefFromContent(final JsonNode content,
510 final ApiDocServiceImpl.OAversion oaversion) {
511 final HashSet<String> refs = new HashSet<>();
512 content.fieldNames().forEachRemaining(mediaType -> {
513 final JsonNode ref = content.path(mediaType).path(SCHEMA_KEY).path(REF_KEY);
514 if (ref != null && !ref.isMissingNode()) {
515 refs.add(ref.asText().replaceFirst(getAppropriateModelPrefix(oaversion), ""));