Removed “processModule” method from DefinitionGenerator class.
This method is invoked only when a specific single model is requested
directly and generated POST request had an incorrect payload.
Fixed “addRootPostLink” method to correct POST payload containing
the first container/list child.
Adapted affected unit tests.
JIRA: NETCONF-1179
Change-Id: Ic10280770cfceedc2c9c5099cdbdab14cdc28ad6
Signed-off-by: Oleksandr Zharov <oleksandr.zharov@pantheon.tech>
Signed-off-by: Ivan Hrasko <ivan.hrasko@pantheon.tech>
private static void addRootPostLink(final Module module, final String deviceName,
final List<Parameter> pathParams, final String resourcePath, final Map<String, Path> paths) {
- if (containsListOrContainer(module.getChildNodes())) {
+ final var childNode = getListOrContainerChildNode(module);
+ if (childNode != null) {
final String moduleName = module.getName();
- final String name = moduleName + MODULE_NAME_SUFFIX;
paths.put(resourcePath, new Path.Builder()
- .post(buildPost(null, null, name, "", moduleName, deviceName,
+ .post(buildPost(childNode, null, moduleName, "", moduleName, deviceName,
module.getDescription().orElse(""), pathParams))
.build());
}
* @throws IOException if I/O operation fails
*/
private static Map<String, Schema> convertToSchemas(final Module module, final EffectiveModelContext schemaContext,
- final Map<String, Schema> definitions, final DefinitionNames definitionNames,
- final boolean isForSingleModule) throws IOException {
+ final Map<String, Schema> definitions, final DefinitionNames definitionNames) throws IOException {
processContainersAndLists(module, definitions, definitionNames, schemaContext);
processRPCs(module, definitions, definitionNames, schemaContext);
- if (isForSingleModule) {
- processModule(module, definitions, definitionNames, schemaContext);
- }
-
return definitions;
}
if (isForSingleModule) {
definitionNames.addUnlinkedName(module.getName() + MODULE_NAME_SUFFIX);
}
- return convertToSchemas(module, schemaContext, definitions, definitionNames, isForSingleModule);
- }
-
- private static void processModule(final Module module, final Map<String, Schema> definitions,
- final DefinitionNames definitionNames, final EffectiveModelContext schemaContext) {
- final Map<String, Property> properties = new HashMap<>();
- final List<String> required = new ArrayList<>();
- final String moduleName = module.getName();
- final String definitionName = moduleName + MODULE_NAME_SUFFIX;
- final SchemaInferenceStack stack = SchemaInferenceStack.of(schemaContext);
- for (final DataSchemaNode node : module.getChildNodes()) {
- stack.enterSchemaTree(node.getQName());
- final String localName = node.getQName().getLocalName();
- if (node.isConfiguration()) {
- if (node instanceof ContainerSchemaNode || node instanceof ListSchemaNode) {
- if (isSchemaNodeMandatory(node)) {
- required.add(localName);
- }
- for (final DataSchemaNode childNode : ((DataNodeContainer) node).getChildNodes()) {
- final Property.Builder childNodeProperty = new Property.Builder();
-
- final String ref = COMPONENTS_PREFIX
- + moduleName
- + "_" + localName
- + definitionNames.getDiscriminator(node);
-
- if (node instanceof ListSchemaNode) {
- childNodeProperty.type(ARRAY_TYPE);
- final Property items = new Property.Builder().ref(ref).build();
- childNodeProperty.items(items);
- childNodeProperty.description(childNode.getDescription().orElse(""));
- childNodeProperty.title(localName);
- } else {
- /*
- Description can't be added, because nothing allowed alongside $ref.
- allOf is not an option, because ServiceNow can't parse it.
- */
- childNodeProperty.ref(ref);
- }
- //add module name prefix to property name, when ServiceNow can process colons
- properties.put(localName, childNodeProperty.build());
- }
- } else if (node instanceof LeafSchemaNode) {
- /*
- Add module name prefix to property name, when ServiceNow can process colons(second parameter
- of processLeafNode).
- */
- final Property leafNode = processLeafNode((LeafSchemaNode) node, localName, required, stack,
- module.getNamespace());
- properties.put(localName, leafNode);
- }
- }
- stack.exit();
- }
- final Schema.Builder definitionBuilder = new Schema.Builder()
- .title(definitionName)
- .type(OBJECT_TYPE)
- .properties(properties)
- .description(module.getDescription().orElse(""))
- .required(required.size() > 0 ? required : null);
-
- definitions.put(definitionName, definitionBuilder.build());
+ return convertToSchemas(module, schemaContext, definitions, definitionNames);
}
private static boolean isSchemaNodeMandatory(final DataSchemaNode node) {
// Hidden on purpose
}
- public static Operation buildPost(final DataSchemaNode childNode, final String parentName, final String nodeName,
- final String discriminator, final String moduleName, final @NonNull String deviceName,
- final String description, final List<Parameter> pathParams) {
+ public static Operation buildPost(final @NonNull DataSchemaNode childNode, final String parentName,
+ final String nodeName, final String discriminator, final String moduleName,
+ final @NonNull String deviceName, final String description, final List<Parameter> pathParams) {
final var summary = SUMMARY_TEMPLATE.formatted(HttpMethod.POST, deviceName, moduleName, nodeName);
final List<String> tags = List.of(deviceName + " " + moduleName);
final List<Parameter> parameters = new ArrayList<>(pathParams);
if (parentName != null) {
nameElements.add(parentName);
}
- if (childNode != null && childNode.isConfiguration()) {
+ if (childNode.isConfiguration()) {
final String childNodeName = childNode.getQName().getLocalName();
nameElements.add(nodeName);
nameElements.add(childNodeName + discriminator);
assertNotNull(schemas);
// correct number of schemas generated
- assertEquals(3, schemas.size());
+ assertEquals(2, schemas.size());
final var makeToast = schemas.get("toaster_make-toast_input").properties().get("toasterToastType");
assertEquals("wheat-bread", makeToast.defaultValue().toString());
private static final String CONFIG_ROOT_CONTAINER = "mandatory-test_root-container";
private static final String CONFIG_MANDATORY_CONTAINER = "mandatory-test_root-container_mandatory-container";
private static final String CONFIG_MANDATORY_LIST = "mandatory-test_root-container_mandatory-list";
- private static final String MANDATORY_TEST_MODULE = "mandatory-test_module";
private static final String CONTAINER = "container";
private static final String LIST = "list";
verifyRequiredField(schemas.get(CONFIG_MANDATORY_LIST), reqMandatoryListElements);
containersWithRequired.add(CONFIG_MANDATORY_LIST);
- final var testModuleMandatoryArray = List.of("root-container", "root-mandatory-list");
- verifyRequiredField(schemas.get(MANDATORY_TEST_MODULE), testModuleMandatoryArray);
- containersWithRequired.add(MANDATORY_TEST_MODULE);
-
verifyThatOthersNodeDoesNotHaveRequiredField(containersWithRequired, schemas);
}
// Test `components/schemas` objects
final var definitions = doc.components().schemas();
- assertEquals(2, definitions.size());
+ assertEquals(1, definitions.size());
assertTrue(definitions.containsKey("my-yang_data"));
- assertTrue(definitions.containsKey("my-yang_module"));
}
@Test
// Test `components/schemas` objects
final var definitions = doc.components().schemas();
- assertEquals(11, definitions.size());
+ assertEquals(10, definitions.size());
}
/**
assertEquals("urn:ietf:params:xml:ns:yang:test:action:types", namespace);
}
- /**
- * Test JSON and XML references for request operation.
- */
- private static void verifyPostDataRequestRef(final Operation operation, final String expectedJsonRef,
- final String expectedXmlRef) {
- final Map<String, MediaTypeObject> postContent;
- if (operation.requestBody() != null) {
- postContent = operation.requestBody().content();
- } else {
- postContent = operation.responses().get("200").content();
- }
- assertNotNull(postContent);
- final var postJsonRef = postContent.get("application/json").schema().ref();
- assertNotNull(postJsonRef);
- assertEquals(expectedJsonRef, postJsonRef);
- final var postXmlRef = postContent.get("application/xml").schema().ref();
- assertNotNull(postXmlRef);
- assertEquals(expectedXmlRef, postXmlRef);
- }
-
private static void verifyRequestRef(final Operation operation, final String expectedRef, final String nodeType) {
final Map<String, MediaTypeObject> postContent;
if (operation.requestBody() != null) {
],
"parameters": [],
"requestBody": {
- "description": "toaster_module",
+ "description": "toaster",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/toaster_module"
+ "properties":{
+ "toaster":{
+ "$ref":"#/components/schemas/toaster_toaster",
+ "type":"object"
+ }
+ }
}
},
"application/xml": {
"schema": {
- "$ref": "#/components/schemas/toaster_module"
+ "$ref": "#/components/schemas/toaster_toaster"
}
}
}
}
},
"description": "YANG version of the TOASTER-MIB.\n\nNote:\nIn example payload, you can see only the first data node child of the resource to be created, following the\nguidelines of RFC 8040, which allows us to create only one resource in POST request.\n",
- "summary": "POST - Controller - toaster - toaster_module"
+ "summary": "POST - Controller - toaster - toaster"
}
},
"/rests/operations/toaster:cancel-toast": {
"title": "toaster_make-toast_input",
"type": "object"
},
- "toaster_module": {
- "properties": {
- "toaster": {
- "$ref": "#/components/schemas/toaster_toaster"
- }
- },
- "description": "YANG version of the TOASTER-MIB.",
- "title": "toaster_module",
- "type": "object"
- },
"toaster_restock-toaster_input": {
"properties": {
"amountOfBreadToStock": {
],
"parameters": [],
"requestBody": {
- "description": "toaster_module",
+ "description": "toaster",
"content": {
"application/xml": {
"schema": {
- "$ref": "#/components/schemas/toaster_module"
+ "$ref": "#/components/schemas/toaster_toaster"
}
},
"application/json": {
"schema": {
- "$ref": "#/components/schemas/toaster_module"
+ "properties":{
+ "toaster":{
+ "$ref":"#/components/schemas/toaster_toaster",
+ "type":"object"
+ }
+ }
}
}
}
}
},
"description": "YANG version of the TOASTER-MIB.\n\nNote:\nIn example payload, you can see only the first data node child of the resource to be created, following the\nguidelines of RFC 8040, which allows us to create only one resource in POST request.\n",
- "summary": "POST - 123 - toaster - toaster_module"
+ "summary": "POST - 123 - toaster - toaster"
}
}
},
"title": "toaster_make-toast_input",
"type": "object"
},
- "toaster_module": {
- "properties": {
- "toaster": {
- "$ref": "#/components/schemas/toaster_toaster"
- }
- },
- "description": "YANG version of the TOASTER-MIB.",
- "title": "toaster_module",
- "type": "object"
- },
"toaster_restock-toaster_input": {
"properties": {
"amountOfBreadToStock": {