From 1ad7dcafaac59052e56c559f10e52b8e79719a19 Mon Sep 17 00:00:00 2001 From: Martin Ciglan Date: Fri, 24 Mar 2017 11:29:41 +0100 Subject: [PATCH] Bug 7603 Actions & RPCs - provide means for dealing with Actions, RPCs & routed RPCs from binding generator v2 point of view - examples given - review comments fixed TODO: JUnit tests Change-Id: Ie88f728a9854e247d99c2f4a154af9ac4ab70d86 Signed-off-by: Martin Ciglan --- .../generator/impl/AuxiliaryGenUtils.java | 6 + .../javav2/generator/impl/GenHelperUtil.java | 4 +- .../generator/impl/ModuleToGenType.java | 16 +- .../generator/impl/RpcActionGenHelper.java | 281 ++++++++++++++++++ .../action/examples/MyActionCallInput.java | 24 ++ .../action/examples/MyActionCallOutput.java | 25 ++ .../MyActionModuleMyActionCallAction.java | 43 +++ .../impl/action/examples/MyCont.java | 18 ++ .../action/examples/ListActionCallInput.java | 24 ++ .../action/examples/ListActionCallOutput.java | 25 ++ .../ListActionModuleListActionCall.java | 43 +++ .../impl/list/action/examples/MyList.java | 18 ++ .../impl/rpc/examples/MyCallInput.java | 24 ++ .../impl/rpc/examples/MyCallOutput.java | 25 ++ .../impl/rpc/examples/MyModuleMyCallRpc.java | 39 +++ .../resources/generator/my-rpc-module.yang | 21 ++ .../javav2/generator/util/BindingTypes.java | 49 ++- .../binding/javav2/generator/util/Types.java | 7 +- .../mdsal/binding/javav2/spec/base/Rpc.java | 2 +- 19 files changed, 672 insertions(+), 22 deletions(-) create mode 100644 binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/RpcActionGenHelper.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallInput.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallOutput.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionModuleMyActionCallAction.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyCont.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallInput.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallOutput.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionModuleListActionCall.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/MyList.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallInput.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallOutput.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyModuleMyCallRpc.java create mode 100644 binding2/mdsal-binding2-generator-impl/src/test/resources/generator/my-rpc-module.yang diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AuxiliaryGenUtils.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AuxiliaryGenUtils.java index d5d11c078c..334f09f2e9 100644 --- a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AuxiliaryGenUtils.java +++ b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AuxiliaryGenUtils.java @@ -8,6 +8,7 @@ package org.opendaylight.mdsal.binding.javav2.generator.impl; +import static com.google.common.base.Preconditions.checkArgument; import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets; import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.BOOLEAN; @@ -539,6 +540,11 @@ final class AuxiliaryGenUtils { return true; } + static void checkModuleAndModuleName(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); + checkArgument(module.getName() != null, "Module name cannot be NULL."); + } + @VisibleForTesting public static String replaceAllIllegalChars(final StringBuilder stringBuilder){ final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u"); diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java index b69161216c..2107c4230d 100644 --- a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java +++ b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java @@ -156,7 +156,7 @@ final class GenHelperUtil { * @param genCtx generated context * @return generated type builder with all implemented types */ - private static GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, + static GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, final GeneratedTypeBuilder builder, final Map genCtx) { for (final UsesNode usesNode : dataNodeContainer.getUses()) { final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath(), genCtx).toInstance(); @@ -463,7 +463,7 @@ final class GenHelperUtil { * * */ - private static GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode, + static GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode, final SchemaContext schemaContext, final String prefix, final boolean verboseClassComments, final Map> genTypeBuilders) { diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/ModuleToGenType.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/ModuleToGenType.java index 8c5e13ba4b..e8d1ae1804 100644 --- a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/ModuleToGenType.java +++ b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/ModuleToGenType.java @@ -46,9 +46,11 @@ final class ModuleToGenType { genCtx.put(module, new ModuleContext()); genCtx = allTypeDefinitionsToGenTypes(module, genCtx, typeProvider); + genCtx = actionsAndRPCMethodsToGenType(module, genCtx, schemaContext, verboseClassComments, + genTypeBuilders, typeProvider); genCtx = notificationsToGenType(module, genCtx, schemaContext, genTypeBuilders, verboseClassComments, typeProvider); - //TODO: call generate for other entities (groupings, rpcs, actions, identities) + //TODO: call generate for other entities (groupings, identities) if (!module.getChildNodes().isEmpty()) { final GeneratedTypeBuilder moduleType = GenHelperUtil.moduleToDataType(module, genCtx, verboseClassComments); @@ -95,6 +97,18 @@ final class ModuleToGenType { return genCtx; } + private static Map actionsAndRPCMethodsToGenType(final Module module, Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, + Map> genTypeBuilders, TypeProvider typeProvider) { + + genCtx = RpcActionGenHelper.rpcMethodsToGenType(module, genCtx, schemaContext, verboseClassComments, + genTypeBuilders, typeProvider); + genCtx = RpcActionGenHelper.actionMethodsToGenType(module, genCtx, schemaContext, verboseClassComments, + genTypeBuilders, typeProvider); + + return genCtx; + } + /** * Converts all notifications of the module to the list of * Type objects. In addition are to this list added containers diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/RpcActionGenHelper.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/RpcActionGenHelper.java new file mode 100644 index 0000000000..cfed2efeab --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/RpcActionGenHelper.java @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl; + +import static com.google.common.base.Preconditions.checkState; +import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.annotateDeprecatedIfNecessary; +import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.checkModuleAndModuleName; +import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createDescription; +import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.resolveListKeyTOBuilder; +import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.addImplementedInterfaceFromUses; +import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.addRawInterfaceDefinition; +import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.moduleTypeBuilder; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.ACTION; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.INPUT; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.INSTANCE_IDENTIFIER; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.INSTANTIABLE; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.KEYED_INSTANCE_IDENTIFIER; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.LIST_ACTION; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.OUTPUT; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.RPC; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.RPC_CALLBACK; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.TREE_NODE; +import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.augmentable; +import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.CLASS; +import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.VOID; +import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.parameterizedTypeFor; + +import com.google.common.annotations.Beta; +import com.google.common.base.Optional; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider; +import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil; +import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder; +import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder; +import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder; +import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.ActionDefinition; +import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.OperationDefinition; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; + +/** + * + * Util class used for generation of types for RPCs, routedRPCs and Actions (YANG 1.1 only) + * in Binding spec. v2. In case of routed RPC detected in input YANG, RPC is turned to Action. + * + */ +@Beta +public final class RpcActionGenHelper { + + private static final QName CONTEXT_REFERENCE = + QName.create("urn:opendaylight:yang:extension:yang-ext", "2013-07-09", "context-reference").intern(); + + private RpcActionGenHelper() { + throw new UnsupportedOperationException("Util class"); + } + + /** + * Let's find out what context we are talking about + * 1. routed RPC + * 2. global RPC + * + * In 1st case, we need Binding Generator behave like YANG 1.1 Action + * + * @param schemaNode RPC input node + * @return presence optional + */ + private static Optional getRoutingContext(final DataSchemaNode schemaNode) { + for (UnknownSchemaNode extension : schemaNode.getUnknownSchemaNodes()) { + if (CONTEXT_REFERENCE.equals(extension.getNodeType())) { + return Optional.fromNullable(extension.getQName()); + } + } + return Optional.absent(); + } + + /** + * Converts Yang 1.1 Actions to list of Type objects. + * @param module module from which is obtained set of all Action objects to + * iterate over them + * @param genCtx input, generated context + * @param verboseClassComments verbosity switch + * @return generated context + */ + static Map actionMethodsToGenType(final Module module, Map genCtx, + final SchemaContext schemaContext, final boolean verboseClassComments, Map> genTypeBuilders, TypeProvider typeProvider) { + + checkModuleAndModuleName(module); + final Collection potentials = module.getChildNodes(); + for (DataSchemaNode potential : potentials) { + if (potential instanceof ActionNodeContainer) { + final Set actions = ((ActionNodeContainer) potential).getActions(); + for (ActionDefinition action: actions) { + genCtx.get(module).addChildNodeType(potential, resolveOperation(potential, action, module, + schemaContext, verboseClassComments, genTypeBuilders, genCtx, typeProvider, true)); + } + } + } + return genCtx; + } + + /** + * Converts global RPCs inputs and outputs sub-statements of the module + * to the list of Type objects. In addition, containers + * and lists which belong to input or output are also part of returning list. + * Detected routed RPCs are turned to Yang 1.1 Actions + * + * @param module + * module from which is obtained set of all RPC objects to + * iterate over them + * @param genCtx input, generated context + * @param verboseClassComments verbosity switch + * + * @throws IllegalArgumentException + *
    + *
  • if the module is null
  • + *
  • if the name of module is null
  • + *
+ * @throws IllegalStateException + * if set of RPCs from module is null + * + * @return generated context + */ + static Map rpcMethodsToGenType(final Module module, Map genCtx, + final SchemaContext schemaContext, final boolean verboseClassComments, Map> genTypeBuilders, TypeProvider typeProvider) { + + checkModuleAndModuleName(module); + final Set rpcDefinitions = module.getRpcs(); + checkState(rpcDefinitions != null, "Set of RPCs from module " + module.getName() + " cannot be NULL."); + if (rpcDefinitions.isEmpty()) { + return genCtx; + } + + for (final RpcDefinition rpc : rpcDefinitions) { + DataSchemaNode parent = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext, rpc.getPath().getParent()); + //routedRPC? + if (getRoutingContext(parent).isPresent()) { + genCtx.get(module).addChildNodeType(parent, resolveOperation(parent, rpc, module, schemaContext, + verboseClassComments, genTypeBuilders, genCtx, typeProvider, true)); + } else { + //global RPC only + genCtx.get(module).addTopLevelNodeType(resolveOperation(parent, rpc, module, schemaContext, + verboseClassComments, genTypeBuilders, genCtx, typeProvider, false)); + + } + } + return genCtx; + } + + /** + * Converts RPC, Action or routed RPC into generated type + * @return generated type + */ + private static GeneratedTypeBuilder resolveOperation(final DataSchemaNode parent, final OperationDefinition operation, + final Module module, final SchemaContext schemaContext, final boolean verboseClassComments, + Map> genTypeBuilders, final Map genCtx, + TypeProvider typeProvider, final boolean isAction) { + + //operation name + final String operationName = operation.getQName().getLocalName(); + //concrete operation name + final StringBuilder sb = new StringBuilder(operationName).append('_'); + if (isAction) { + sb.append("Action"); + } else { + sb.append("Rpc"); + } + final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, sb.toString(), + verboseClassComments); + + final String basePackageName = interfaceBuilder.getPackageName(); + + interfaceBuilder.setDescription(createDescription(operation, interfaceBuilder.getFullyQualifiedName(), + schemaContext, verboseClassComments)); + final String operationComment = encodeAngleBrackets(operation.getDescription()); + final MethodSignatureBuilder operationMethod = interfaceBuilder.addMethod("invoke"); + + //input + final ContainerSchemaNode input = operation.getInput(); + final GeneratedTypeBuilder inType = resolveOperationNode(module, operation.getInput(), basePackageName, + schemaContext, operationName, verboseClassComments, typeProvider, genTypeBuilders, genCtx, true); + annotateDeprecatedIfNecessary(operation.getStatus(), inType); + genCtx.get(module).addChildNodeType(input, inType); + + //output + final ContainerSchemaNode output = operation.getOutput(); + final GeneratedTypeBuilder outType = resolveOperationNode(module, operation.getOutput(), basePackageName, + schemaContext, operationName, verboseClassComments, typeProvider, genTypeBuilders, genCtx, false); + annotateDeprecatedIfNecessary(operation.getStatus(), outType); + genCtx.get(module).addChildNodeType(output, outType); + + final GeneratedType inTypeInstance = inType.toInstance(); + operationMethod.addParameter(inTypeInstance, "input"); + + if (isAction) { + //action, routed RPC + String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, parent.getPath(), + BindingNamespaceType.Data); + GeneratedTypeBuilder parentType = addRawInterfaceDefinition(packageName, parent, schemaContext, + parent.getQName().getLocalName(), verboseClassComments, genTypeBuilders); + parentType.addImplementsType(TREE_NODE); + parentType.addImplementsType(augmentable(parentType)); + annotateDeprecatedIfNecessary(parent.getStatus(), parentType); + + GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, parentType, parentType, + ((ContainerSchemaNode) parent).getChildNodes(), genCtx, schemaContext, verboseClassComments, + genTypeBuilders, typeProvider); + + operationMethod.addParameter(parameterizedTypeFor(INSTANCE_IDENTIFIER, parentType), "ii"); + + if (parent instanceof ListSchemaNode) { + //ListAction + final GeneratedTOBuilder keyType = resolveListKeyTOBuilder(basePackageName, (ListSchemaNode) parent); + operationMethod.addParameter( + parameterizedTypeFor(KEYED_INSTANCE_IDENTIFIER, parentType, keyType), "kii"); + operationMethod.setReturnType(keyType); + interfaceBuilder.addImplementsType(parameterizedTypeFor(LIST_ACTION, parentType, inType, outType)); + } else { + //Action + operationMethod.addParameter(parameterizedTypeFor(INSTANCE_IDENTIFIER, parentType), "ii"); + interfaceBuilder.addImplementsType(parameterizedTypeFor(ACTION, parentType, inType, outType)); + } + } else { + //RPC + interfaceBuilder.addImplementsType(parameterizedTypeFor(RPC, inType, outType)); + } + + operationMethod.addParameter(parameterizedTypeFor(RPC_CALLBACK, outType), "callback"); + + operationMethod.setComment(operationComment); + operationMethod.setReturnType(VOID); + + return interfaceBuilder; + } + + private static GeneratedTypeBuilder resolveOperationNode(final Module module, final ContainerSchemaNode + operationNode, final String basePackageName, final SchemaContext schemaContext, final String + operationName, final boolean verboseClassComments, TypeProvider typeProvider, Map> genTypeBuilders, final Map genCtx, final boolean isInput) { + + final GeneratedTypeBuilder nodeType = addRawInterfaceDefinition(basePackageName, operationNode, schemaContext, + operationName, verboseClassComments, genTypeBuilders); + addImplementedInterfaceFromUses(operationNode, nodeType, genCtx); + nodeType.addImplementsType(TREE_NODE); + if (isInput) { + nodeType.addImplementsType(parameterizedTypeFor(INPUT, nodeType)); + } else { + nodeType.addImplementsType(parameterizedTypeFor(OUTPUT, nodeType)); + } + nodeType.addImplementsType(parameterizedTypeFor(INSTANTIABLE, nodeType)); + nodeType.addImplementsType(augmentable(nodeType)); + GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, nodeType, nodeType, operationNode.getChildNodes(), genCtx, + schemaContext, verboseClassComments, genTypeBuilders, typeProvider); + + final MethodSignatureBuilder nodeMethod = nodeType.addMethod("implementedInterface"); + nodeMethod.setReturnType(parameterizedTypeFor(CLASS, nodeType)); + nodeMethod.addAnnotation("", "Override"); + + return nodeType; + } +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallInput.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallInput.java new file mode 100644 index 0000000000..7613bc40b2 --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallInput.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Input; +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; + +/** + * action my-action-call input + */ +public interface MyActionCallInput extends Input, Instantiable, TreeNode { + + @Override + Class implementedInterface(); + + String getV1(); +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallOutput.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallOutput.java new file mode 100644 index 0000000000..8bd404d544 --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionCallOutput.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.Output; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; + +/** + * action my-action-call output + */ +public interface MyActionCallOutput extends Output, Instantiable, TreeNode { + + @Override + Class implementedInterface(); + + String getV2(); + +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionModuleMyActionCallAction.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionModuleMyActionCallAction.java new file mode 100644 index 0000000000..19b51e33aa --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyActionModuleMyActionCallAction.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Action; +import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.RpcCallback; + +/** + * It represents following YANG snippet: + * + * module my-action-module { + * + * container my-cont { + * action my-action-call { + * + * input { + * leaf v1 { + * type string; + * } + * } + * + * output { + * leaf v2 { + * type string + * } + * } + * + * } + * } + * } + */ +public interface MyActionModuleMyActionCallAction extends Action { + + @Override + void invoke(MyActionCallInput input, InstanceIdentifier ii, RpcCallback callback); +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyCont.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyCont.java new file mode 100644 index 0000000000..64d81e5ae2 --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/action/examples/MyCont.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable; + +/** + * container my-cont + */ +public interface MyCont extends TreeNode, Augmentable { +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallInput.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallInput.java new file mode 100644 index 0000000000..c8fea95d4a --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallInput.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.list.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Input; +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; + +/** + * action list-action-call input + */ +public interface ListActionCallInput extends Input, Instantiable, TreeNode { + + @Override + Class implementedInterface(); + + String getV1(); +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallOutput.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallOutput.java new file mode 100644 index 0000000000..4b6cc4f207 --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionCallOutput.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.list.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.Output; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; + +/** + * action list-action-call output + */ +public interface ListActionCallOutput extends Output, Instantiable, TreeNode { + + @Override + Class implementedInterface(); + + String getV2(); + +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionModuleListActionCall.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionModuleListActionCall.java new file mode 100644 index 0000000000..abf9239c5c --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/ListActionModuleListActionCall.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.list.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.KeyedInstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; +import org.opendaylight.mdsal.binding.javav2.spec.base.RpcCallback; + +/** + * It represents following YANG snippet: + * + * module list-action-module { + * + * list my-list { + * action list-action-call { + * + * input { + * leaf v1 { + * type string; + * } + * } + * + * output { + * leaf v2 { + * type string + * } + * } + * + * } + * } + * } + */ +public interface ListActionModuleListActionCall extends ListAction { + + @Override + void invoke(ListActionCallInput input, KeyedInstanceIdentifier kii, RpcCallback callback); +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/MyList.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/MyList.java new file mode 100644 index 0000000000..3775815a7a --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/list/action/examples/MyList.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.list.action.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable; + +/** + * list my-list + */ +public interface MyList extends TreeNode, Augmentable { +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallInput.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallInput.java new file mode 100644 index 0000000000..026fb84be8 --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallInput.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.rpc.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Input; +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; + +/** + * rpc my-call input + */ +public interface MyCallInput extends Input, Instantiable, TreeNode { + + @Override + Class implementedInterface(); + + String getV1(); +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallOutput.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallOutput.java new file mode 100644 index 0000000000..ce5d9f9afb --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyCallOutput.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.rpc.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.Output; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; + +/** + * rpc my-call output + */ +public interface MyCallOutput extends Output, Instantiable, TreeNode { + + @Override + Class implementedInterface(); + + String getV2(); + +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyModuleMyCallRpc.java b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyModuleMyCallRpc.java new file mode 100644 index 0000000000..69ef38a92e --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/java/org/opendaylight/mdsal/binding/javav2/generator/impl/rpc/examples/MyModuleMyCallRpc.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.mdsal.binding.javav2.generator.impl.rpc.examples; + +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.RpcCallback; + +/** + * It represents following YANG snippet: + * + * module my-module { + * + * rpc my-call { + * + * input { + * leaf v1 { + * type string; + * } + * } + * + * output { + * leaf v2 { + * type string + * } + * } + * } + * } + */ +public interface MyModuleMyCallRpc extends Rpc { + + @Override + void invoke(MyCallInput input, RpcCallback callback); +} diff --git a/binding2/mdsal-binding2-generator-impl/src/test/resources/generator/my-rpc-module.yang b/binding2/mdsal-binding2-generator-impl/src/test/resources/generator/my-rpc-module.yang new file mode 100644 index 0000000000..8c7b6c6a39 --- /dev/null +++ b/binding2/mdsal-binding2-generator-impl/src/test/resources/generator/my-rpc-module.yang @@ -0,0 +1,21 @@ +module my-rpc-module { + yang-version 1; + namespace "urn:my-rpc-module:simple:test"; + prefix my-rpc-module; + organization "yang-positive-smurfs"; + revision "2017-03-24"; + + rpc my-call { + input { + leaf v1 { + type string; + } + } + + output { + leaf v2 { + type string; + } + } + } +} \ No newline at end of file diff --git a/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/BindingTypes.java b/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/BindingTypes.java index 6716b513b3..d8aca39eb5 100644 --- a/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/BindingTypes.java +++ b/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/BindingTypes.java @@ -8,44 +8,63 @@ package org.opendaylight.mdsal.binding.javav2.generator.util; +import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.parameterizedTypeFor; +import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.typeForClass; + import javax.management.NotificationListener; import org.opendaylight.mdsal.binding.javav2.model.api.ConcreteType; import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType; import org.opendaylight.mdsal.binding.javav2.model.api.Type; -import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable; -import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentation; +import org.opendaylight.mdsal.binding.javav2.spec.base.Action; import org.opendaylight.mdsal.binding.javav2.spec.base.IdentifiableItem; +import org.opendaylight.mdsal.binding.javav2.spec.base.Input; import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.KeyedInstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; import org.opendaylight.mdsal.binding.javav2.spec.base.Notification; -import org.opendaylight.mdsal.binding.javav2.spec.structural.TreeChildNode; +import org.opendaylight.mdsal.binding.javav2.spec.base.Output; +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.RpcCallback; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeRoot; +import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable; +import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentation; +import org.opendaylight.mdsal.binding.javav2.spec.structural.TreeChildNode; import org.opendaylight.yangtools.concepts.Identifier; public final class BindingTypes { - public static final ConcreteType AUGMENTABLE = Types.typeForClass(Augmentable.class); - public static final ConcreteType AUGMENTATION = Types.typeForClass(Augmentation.class); - public static final ConcreteType TREE_NODE = Types.typeForClass(TreeNode.class); - public static final ConcreteType TREE_ROOT = Types.typeForClass(TreeRoot.class); - public static final ConcreteType IDENTIFIABLE_ITEM = Types.typeForClass(IdentifiableItem.class); - public static final ConcreteType IDENTIFIER = Types.typeForClass(Identifier.class); - public static final ConcreteType INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier.class); - public static final ConcreteType NOTIFICATION = Types.typeForClass(Notification.class); - public static final ConcreteType NOTIFICATION_LISTENER = Types.typeForClass(NotificationListener.class); + public static final ConcreteType ACTION = typeForClass(Action.class); + public static final ConcreteType AUGMENTABLE = typeForClass(Augmentable.class); + public static final ConcreteType AUGMENTATION = typeForClass(Augmentation.class); + public static final ConcreteType IDENTIFIABLE_ITEM = typeForClass(IdentifiableItem.class); + public static final ConcreteType IDENTIFIER = typeForClass(Identifier.class); + public static final ConcreteType INPUT = typeForClass(Input.class); + public static final ConcreteType INSTANCE_IDENTIFIER = typeForClass(InstanceIdentifier.class); + public static final ConcreteType INSTANTIABLE = typeForClass(Instantiable.class); + public static final ConcreteType KEYED_INSTANCE_IDENTIFIER = typeForClass(KeyedInstanceIdentifier.class); + public static final ConcreteType LIST_ACTION = typeForClass(ListAction.class); + public static final ConcreteType NOTIFICATION = typeForClass(Notification.class); + public static final ConcreteType NOTIFICATION_LISTENER = typeForClass(NotificationListener.class); + public static final ConcreteType OUTPUT = typeForClass(Output.class); + public static final ConcreteType RPC = typeForClass(Rpc.class); + public static final ConcreteType RPC_CALLBACK = typeForClass(RpcCallback.class); + public static final ConcreteType TREE_NODE = typeForClass(TreeNode.class); + public static final ConcreteType TREE_ROOT = typeForClass(TreeRoot.class); - private static final ConcreteType TREE_CHILD_NODE = Types.typeForClass(TreeChildNode.class); + private static final ConcreteType TREE_CHILD_NODE = typeForClass(TreeChildNode.class); private BindingTypes() { throw new UnsupportedOperationException("Utility class"); } public static ParameterizedType augmentable(Type t) { - return Types.parameterizedTypeFor(AUGMENTABLE, t); + return parameterizedTypeFor(AUGMENTABLE, t); } public static ParameterizedType treeChildNode(Type t) { - return Types.parameterizedTypeFor(TREE_CHILD_NODE, t); + return parameterizedTypeFor(TREE_CHILD_NODE, t); } } diff --git a/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/Types.java b/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/Types.java index 71552841b6..432c5653f1 100644 --- a/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/Types.java +++ b/binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/Types.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.mdsal.binding.javav2.model.api.BaseTypeWithRestrictions; import org.opendaylight.mdsal.binding.javav2.model.api.ConcreteType; @@ -29,7 +30,6 @@ import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType; import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions; import org.opendaylight.mdsal.binding.javav2.model.api.Type; import org.opendaylight.mdsal.binding.javav2.model.api.WildcardType; -import org.opendaylight.mdsal.binding.javav2.spec.base.RpcCallback; import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable; import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentation; import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint; @@ -43,7 +43,7 @@ public final class Types { new CacheLoader, ConcreteType>() { @Override - public ConcreteType load(final Class key) throws Exception { + public ConcreteType load(@Nonnull final Class key) throws Exception { return new ConcreteTypeImpl(key.getPackage().getName(), key.getSimpleName(), null); } }; @@ -52,9 +52,10 @@ public final class Types { CacheBuilder.newBuilder().weakKeys().build(TYPE_LOADER); public static final ConcreteType BOOLEAN = typeForClass(Boolean.class); - public static final ConcreteType RPC_CALLBACK = typeForClass(RpcCallback.class); + public static final ConcreteType CLASS = typeForClass(Class.class); public static final ConcreteType STRING = typeForClass(String.class); public static final ConcreteType VOID = typeForClass(Void.class); + public static final ConcreteType BYTE_ARRAY = primitiveType("byte[]", null); public static final ConcreteType CHAR_ARRAY = primitiveType("char[]", null); diff --git a/binding2/mdsal-binding2-spec/src/main/java/org/opendaylight/mdsal/binding/javav2/spec/base/Rpc.java b/binding2/mdsal-binding2-spec/src/main/java/org/opendaylight/mdsal/binding/javav2/spec/base/Rpc.java index f489842bff..08d7fb1520 100644 --- a/binding2/mdsal-binding2-spec/src/main/java/org/opendaylight/mdsal/binding/javav2/spec/base/Rpc.java +++ b/binding2/mdsal-binding2-spec/src/main/java/org/opendaylight/mdsal/binding/javav2/spec/base/Rpc.java @@ -11,7 +11,7 @@ package org.opendaylight.mdsal.binding.javav2.spec.base; /** * * The "rpc" statement is used to define an RPC operation. The "rpc" statement - * defines an rpc node in the schema tree. Under the rpc node, a schema node + * defines an RPC node in the schema tree. Under the RPC node, a schema node * with the name "input" and a schema node with the name "output" are also defined. * The nodes "input" and "output" are defined in the module’s namespace. * -- 2.36.6