Generate Rpc services 74/102574/10
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 5 Oct 2022 12:43:57 +0000 (14:43 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 12 Oct 2022 08:24:48 +0000 (10:24 +0200)
Introduce an Rpc concept similar to Action, except without a path.
Generate its specializations, allowing RPCs to be implemented and/or
invoked without their ModuleService aggregate.

JIRA: MDSAL-773
Change-Id: I5fec1ac5c81b908714965e71c3471b954b58d1f9
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
18 files changed:
binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractInvokableGenerator.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ActionGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InvokableRuntimeTypeBuilder.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractInvokableRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultActionRuntimeType.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultRpcRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/GeneratedTypesTest.java
binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal302Test.java
binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal500Test.java
binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal552Test.java
binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal666Test.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java
binding/mdsal-binding-model-ri/src/main/java/org/opendaylight/mdsal/binding/model/ri/BindingTypes.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingContract.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Rpc.java [new file with mode: 0644]

index e000547f16696173ace68e1b8b6967ff2bd0fba7..941b86c6c7b8069444cc57a51f509fb3147fe209 100644 (file)
@@ -207,7 +207,7 @@ public class InstanceIdentifierSerializeDeserializeTest extends AbstractBindingC
         final var ex = assertThrows(IncorrectNestingException.class,
             () -> codecContext.fromYangInstanceIdentifier(yiid));
         assertThat(ex.getMessage(), startsWith("Argument (urn:opendaylight:params:xml:ns:yang:md:sal:knock-knock"
-            + "?revision=2018-07-23)knock-knock is not valid child of "));
+            + "?revision=2018-07-23)knock-knock is not valid data tree child of "));
     }
 
     @Test
index 4f0f486d00444765001162bd8e986ffc9700692f..8ca6b4079a81a58a9a55685380a9ec5f86f8a644 100644 (file)
@@ -530,7 +530,9 @@ public abstract class AbstractCompositeGenerator<S extends EffectiveStatement<?,
                 tmp.add(this instanceof RpcGenerator ? new RpcOutputGenerator(output, this)
                     : new OutputGenerator(output, this));
             } else if (stmt instanceof RpcEffectiveStatement rpc) {
-                tmp.add(new RpcGenerator(rpc, this));
+                if (this instanceof ModuleGenerator module) {
+                    tmp.add(new RpcGenerator(rpc, module));
+                }
             } else if (stmt instanceof TypedefEffectiveStatement typedef) {
                 tmp.add(new TypedefGenerator(typedef, this));
             } else if (stmt instanceof AugmentEffectiveStatement augment) {
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractInvokableGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractInvokableGenerator.java
new file mode 100644 (file)
index 0000000..55313f5
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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.generator.impl.reactor;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
+import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
+
+abstract class AbstractInvokableGenerator<S extends SchemaTreeEffectiveStatement<?>, R extends CompositeRuntimeType>
+        extends CompositeSchemaTreeGenerator<S, R> {
+    private static final JavaTypeName FUNCTIONAL_INTERFACE_ANNOTATION = JavaTypeName.create(FunctionalInterface.class);
+
+    AbstractInvokableGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
+        super(statement, parent);
+    }
+
+    @Override
+    final void pushToInference(final SchemaInferenceStack dataTree) {
+        dataTree.enterSchemaTree(statement().argument());
+    }
+
+    @Override
+    final void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
+        // RPCs/Actions are a separate concept
+    }
+
+    @Override
+    final GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
+        final var builder = builderFactory.newGeneratedTypeBuilder(typeName());
+        builder.addImplementsType(implementedType(builderFactory,
+            getChild(this, InputEffectiveStatement.class).getOriginal().getGeneratedType(builderFactory),
+            getChild(this, OutputEffectiveStatement.class).getOriginal().getGeneratedType(builderFactory)));
+        builder.addAnnotation(FUNCTIONAL_INTERFACE_ANNOTATION);
+        defaultImplementedInterace(builder);
+
+        final var module = currentModule();
+        module.addQNameConstant(builder, statement().argument());
+
+        annotateDeprecatedIfNecessary(builder);
+        builderFactory.addCodegenInformation(module, statement(), builder);
+
+        return builder.build();
+    }
+
+    abstract @NonNull ParameterizedType implementedType(TypeBuilderFactory builderFactory, GeneratedType input,
+        GeneratedType output);
+}
index fad601d721afdaa2277edbd976d321fdc7bbd493..f64f319d91510de8a3c82a89ff36d403a0698cef 100644 (file)
@@ -7,40 +7,24 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
-import static com.google.common.base.Verify.verify;
-
 import java.util.List;
-import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultActionRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
 import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
-import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
 import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code action} statement.
  */
-final class ActionGenerator extends CompositeSchemaTreeGenerator<ActionEffectiveStatement, ActionRuntimeType> {
-    private static final JavaTypeName FUNCTIONAL_INTERFACE_ANNOTATION = JavaTypeName.create(FunctionalInterface.class);
-
+final class ActionGenerator extends AbstractInvokableGenerator<ActionEffectiveStatement, ActionRuntimeType> {
     ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
-    @Override
-    void pushToInference(final SchemaInferenceStack dataTree) {
-        dataTree.enterSchemaTree(statement().getIdentifier());
-    }
-
     @Override
     ClassPlacement classPlacement() {
         // We do not generate Actions for groupings as they are inexact, and do not capture an actual instantiation --
@@ -50,54 +34,26 @@ final class ActionGenerator extends CompositeSchemaTreeGenerator<ActionEffective
     }
 
     @Override
-    GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
-        final GeneratedTypeBuilder builder = builderFactory.newGeneratedTypeBuilder(typeName());
-        builder.addImplementsType(implementedType(builderFactory));
-        builder.addAnnotation(FUNCTIONAL_INTERFACE_ANNOTATION);
-        defaultImplementedInterace(builder);
-
-        final ModuleGenerator module = currentModule();
-        module.addQNameConstant(builder, statement().argument());
-
-//        addGetterMethods(builder, builderFactory);
-
-        annotateDeprecatedIfNecessary(builder);
-        builderFactory.addCodegenInformation(module, statement(), builder);
-
-        return builder.build();
-    }
-
-    private @NonNull Type implementedType(final TypeBuilderFactory builderFactory) {
-        final GeneratedType input = getChild(this, InputEffectiveStatement.class).getOriginal()
-            .getGeneratedType(builderFactory);
-        final GeneratedType output = getChild(this, OutputEffectiveStatement.class).getOriginal()
-            .getGeneratedType(builderFactory);
-
-        final AbstractCompositeGenerator<?, ?> parent = getParent();
-        if (parent instanceof ListGenerator) {
-            final KeyGenerator keyGen = ((ListGenerator) parent).keyGenerator();
+    ParameterizedType implementedType(final TypeBuilderFactory builderFactory, final GeneratedType input,
+            final GeneratedType output) {
+        final var parent = getParent();
+        final var parentType = Type.of(parent.typeName());
+        if (parent instanceof ListGenerator list) {
+            final var keyGen = list.keyGenerator();
             if (keyGen != null) {
-                return BindingTypes.keyedListAction(Type.of(parent.typeName()), keyGen.getGeneratedType(builderFactory),
-                    input, output);
+                return BindingTypes.keyedListAction(parentType, keyGen.getGeneratedType(builderFactory), input, output);
             }
         }
-
-        return BindingTypes.action(Type.of(parent.typeName()), input, output);
-    }
-
-    @Override
-    void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
-        // actions are a separate concept
+        return BindingTypes.action(parentType, input, output);
     }
 
     @Override
     CompositeRuntimeTypeBuilder<ActionEffectiveStatement, ActionRuntimeType> createBuilder(
             final ActionEffectiveStatement statement) {
-        return new CompositeRuntimeTypeBuilder<>(statement) {
+        return new InvokableRuntimeTypeBuilder<>(statement) {
             @Override
             ActionRuntimeType build(final GeneratedType generatedType, final ActionEffectiveStatement statement,
-                    final List<RuntimeType> childTypes, final List<AugmentRuntimeType> augmentTypes) {
-                verify(augmentTypes.isEmpty(), "Unexpected augments %s", augmentTypes);
+                    final List<RuntimeType> childTypes) {
                 return new DefaultActionRuntimeType(generatedType, statement, childTypes);
             }
         };
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InvokableRuntimeTypeBuilder.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InvokableRuntimeTypeBuilder.java
new file mode 100644 (file)
index 0000000..f36d292
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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.generator.impl.reactor;
+
+import static com.google.common.base.Verify.verify;
+
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract class InvokableRuntimeTypeBuilder<S extends EffectiveStatement<?, ?>, R extends CompositeRuntimeType>
+        extends CompositeRuntimeTypeBuilder<S, R> {
+    InvokableRuntimeTypeBuilder(final S statement) {
+        super(statement);
+    }
+
+    @Override
+    final R build(final GeneratedType type, final S statement, final List<RuntimeType> children,
+            final List<AugmentRuntimeType> augments) {
+        verify(augments.isEmpty(), "Unexpected augments %s", augments);
+        return build(type, statement, children);
+    }
+
+    abstract @NonNull R build(GeneratedType type, S statement, List<RuntimeType> children);
+}
index e0ae6b4151ad12c8985f6256539a8c464a798930..af0b38cb6867775378f053790304d4334c8bdbc5 100644 (file)
@@ -7,46 +7,44 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultRpcRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
+import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
 import org.opendaylight.mdsal.binding.runtime.api.RpcRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code rpc} statement.
  */
 // FIXME: hide this once we have RpcRuntimeType
-public final class RpcGenerator extends CompositeSchemaTreeGenerator<RpcEffectiveStatement, RpcRuntimeType> {
-    RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+public final class RpcGenerator extends AbstractInvokableGenerator<RpcEffectiveStatement, RpcRuntimeType> {
+    RpcGenerator(final RpcEffectiveStatement statement, final ModuleGenerator parent) {
         super(statement, parent);
     }
 
     @Override
-    void pushToInference(final SchemaInferenceStack dataTree) {
-        dataTree.enterSchemaTree(statement().argument());
-    }
-
-    @Override
-    // FIXME: switch to the same thing we are using for 'action'
     ClassPlacement classPlacement() {
-        return ClassPlacement.PHANTOM;
-    }
-
-    @Override
-    GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
-        throw new UnsupportedOperationException();
+        return ClassPlacement.TOP_LEVEL;
     }
 
     @Override
-    void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
-        // RPCs are a separate concept
+    ParameterizedType implementedType(final TypeBuilderFactory builderFactory, final GeneratedType input,
+            final GeneratedType output) {
+        return BindingTypes.rpc(input, output);
     }
 
     @Override
     CompositeRuntimeTypeBuilder<RpcEffectiveStatement, RpcRuntimeType> createBuilder(
             final RpcEffectiveStatement statement) {
-        // RPCs do not have a dedicated interface
-        throw new UnsupportedOperationException("Should never be called");
+        return new InvokableRuntimeTypeBuilder<>(statement) {
+            @Override
+            RpcRuntimeType build(final GeneratedType generatedType, final RpcEffectiveStatement statement,
+                    final List<RuntimeType> childTypes) {
+                return new DefaultRpcRuntimeType(generatedType, statement, childTypes);
+            }
+        };
     }
 }
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractInvokableRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractInvokableRuntimeType.java
new file mode 100644 (file)
index 0000000..f198438
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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.generator.impl.rt;
+
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InvokableRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract sealed class AbstractInvokableRuntimeType<S extends EffectiveStatement<?, ?>>
+        extends AbstractCompositeRuntimeType<S> implements InvokableRuntimeType
+        permits DefaultActionRuntimeType, DefaultRpcRuntimeType {
+    private final @NonNull InputRuntimeType input;
+    private final @NonNull OutputRuntimeType output;
+
+    AbstractInvokableRuntimeType(final GeneratedType bindingType, final S statement, final List<RuntimeType> children) {
+        super(bindingType, statement, children);
+        input = child(children, InputRuntimeType.class);
+        output = child(children, OutputRuntimeType.class);
+    }
+
+    @Override
+    public final InputRuntimeType input() {
+        return input;
+    }
+
+    @Override
+    public final OutputRuntimeType output() {
+        return output;
+    }
+
+    private static <T extends RuntimeType> @NonNull T child(final List<RuntimeType> list, final Class<T> clazz) {
+        return list.stream().filter(clazz::isInstance).map(clazz::cast).findFirst().orElseThrow();
+    }
+}
index 32aff37f7e8062b2bec1e8f935e27750ba8a0037..7a0ab85bd659400e7464eee04f3ad858a3f58995 100644 (file)
@@ -9,38 +9,16 @@ package org.opendaylight.mdsal.binding.generator.impl.rt;
 
 import com.google.common.annotations.Beta;
 import java.util.List;
-import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
 
 @Beta
-public final class DefaultActionRuntimeType extends AbstractCompositeRuntimeType<ActionEffectiveStatement>
+public final class DefaultActionRuntimeType extends AbstractInvokableRuntimeType<ActionEffectiveStatement>
         implements ActionRuntimeType {
-    private final @NonNull InputRuntimeType input;
-    private final @NonNull OutputRuntimeType output;
-
     public DefaultActionRuntimeType(final GeneratedType bindingType, final ActionEffectiveStatement statement,
             final List<RuntimeType> children) {
         super(bindingType, statement, children);
-        input = child(children, InputRuntimeType.class);
-        output = child(children, OutputRuntimeType.class);
-    }
-
-    @Override
-    public InputRuntimeType input() {
-        return input;
-    }
-
-    @Override
-    public OutputRuntimeType output() {
-        return output;
-    }
-
-    private static <T extends RuntimeType> @NonNull T child(final List<RuntimeType> list, final Class<T> clazz) {
-        return list.stream().filter(clazz::isInstance).map(clazz::cast).findFirst().orElseThrow();
     }
 }
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultRpcRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultRpcRuntimeType.java
new file mode 100644 (file)
index 0000000..82cc561
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.RpcRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
+
+@Beta
+public final class DefaultRpcRuntimeType extends AbstractInvokableRuntimeType<RpcEffectiveStatement>
+        implements RpcRuntimeType {
+    public DefaultRpcRuntimeType(final GeneratedType bindingType, final RpcEffectiveStatement statement,
+            final List<RuntimeType> children) {
+        super(bindingType, statement, children);
+    }
+}
index 7969ca1f82724d4c156bae2cf1d27d78335bc13e..c59fba10ae58160464814d0410ce182fd2c5ad30 100644 (file)
@@ -222,7 +222,7 @@ public class GeneratedTypesTest {
         String getListChildContainerMethodReturnTypeName = "";
 
         for (final GeneratedType genType : genTypes) {
-            if (!(genType instanceof GeneratedTransferObject)) {
+            if (!(genType instanceof GeneratedTransferObject genTO)) {
                 if (genType.getName().equals("ListParentContainer")) {
                     listParentContainerMethodsCount = genType.getMethodDefinitions().size();
                 } else if (genType.getName().equals("SimpleList")) {
@@ -260,7 +260,6 @@ public class GeneratedTypesTest {
                     listChildContainerMethodsCount = genType.getMethodDefinitions().size();
                 }
             } else {
-                final GeneratedTransferObject genTO = (GeneratedTransferObject) genType;
                 final List<GeneratedProperty> properties = genTO.getProperties();
                 final List<GeneratedProperty> hashProps = genTO.getHashCodeIdentifiers();
                 final List<GeneratedProperty> equalProps = genTO.getEqualsIdentifiers();
@@ -318,25 +317,21 @@ public class GeneratedTypesTest {
         int innerListKeyPropertyCount = 0;
 
         for (final GeneratedType type : genTypes) {
-            if (!(type instanceof GeneratedTransferObject)) {
+            if (!(type instanceof GeneratedTransferObject genTO)) {
                 genTypesCount++;
-            } else {
-                final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
-
-                if (genTO.getName().equals("CompositeKeyListKey")) {
-                    compositeKeyListKeyCount++;
-                    final List<GeneratedProperty> properties = genTO.getProperties();
-                    for (final GeneratedProperty prop : properties) {
-                        if (prop.getName().equals("key1") || prop.getName().equals("key2")) {
-                            compositeKeyListKeyPropertyCount++;
-                        }
+            } else if (genTO.getName().equals("CompositeKeyListKey")) {
+                compositeKeyListKeyCount++;
+                final List<GeneratedProperty> properties = genTO.getProperties();
+                for (final GeneratedProperty prop : properties) {
+                    if (prop.getName().equals("key1") || prop.getName().equals("key2")) {
+                        compositeKeyListKeyPropertyCount++;
                     }
-                    genTOsCount++;
-                } else if (genTO.getName().equals("InnerListKey")) {
-                    final List<GeneratedProperty> properties = genTO.getProperties();
-                    innerListKeyPropertyCount = properties.size();
-                    genTOsCount++;
                 }
+                genTOsCount++;
+            } else if (genTO.getName().equals("InnerListKey")) {
+                final List<GeneratedProperty> properties = genTO.getProperties();
+                innerListKeyPropertyCount = properties.size();
+                genTOsCount++;
             }
         }
         assertEquals(1, compositeKeyListKeyCount);
@@ -374,6 +369,6 @@ public class GeneratedTypesTest {
     public void testAugmentRpcInput() {
         final List<GeneratedType> genTypes = DefaultBindingGenerator.generateFor(YangParserTestUtils.parseYangResource(
             "/augment-rpc-input.yang"));
-        assertEquals(6, genTypes.size());
+        assertEquals(7, genTypes.size());
     }
 }
index 34f2ecfadf62742219e0c5daed843153239dc26e..79339ff003754b22f178307c101b9fc1926c068f 100644 (file)
@@ -10,17 +10,14 @@ package org.opendaylight.mdsal.binding.generator.impl;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
-import java.util.List;
 import org.junit.Test;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
 public class Mdsal302Test {
     @Test
     public void testRpcUsesAugment() {
-        List<GeneratedType> generateTypes = DefaultBindingGenerator.generateFor(YangParserTestUtils.parseYangResource(
-            "/mdsal302.yang"));
-        assertNotNull(generateTypes);
-        assertEquals(15, generateTypes.size());
+        final var types = DefaultBindingGenerator.generateFor(YangParserTestUtils.parseYangResource("/mdsal302.yang"));
+        assertNotNull(types);
+        assertEquals(16, types.size());
     }
 }
index 39d4c13e8e4eda0670e87072623b59dc2bb3e04b..ee83c8cfa0fe53f95b690682cf6da628d09a8b0c 100644 (file)
@@ -22,9 +22,9 @@ public class Mdsal500Test {
         final List<GeneratedType> types = DefaultBindingGenerator.generateFor(
                 YangParserTestUtils.parseYangResource("/mdsal500.yang"));
         assertNotNull(types);
-        assertEquals(4, types.size());
+        assertEquals(5, types.size());
 
-        final GeneratedType rpcService = types.get(3);
+        final GeneratedType rpcService = types.get(4);
         assertEquals("Mdsal500Service", rpcService.getName());
         final List<MethodSignature> methods = rpcService.getMethodDefinitions();
         assertEquals(1, methods.size());
index 710ce16cd2c4e2730d334824d679328c1f95d62e..3e19020df2152adf579b77dcc270818a88849a9c 100644 (file)
@@ -30,7 +30,7 @@ public class Mdsal552Test {
         final List<GeneratedType> types = DefaultBindingGenerator.generateFor(
                 YangParserTestUtils.parseYangResource("/mdsal552.yang"));
         assertNotNull(types);
-        assertEquals(5, types.size());
+        assertEquals(6, types.size());
 
         final GeneratedType baz = types.stream()
                 .filter(type -> BAZ.equals(type.getIdentifier()))
index a75d1e79721f5edfa94b6da5dd2a3e39540f5550..9f0ff562e3ea7465fc8f11633455aa07e3c146d4 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.mdsal.binding.generator.impl;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import java.util.Optional;
 import java.util.stream.Collectors;
 import org.junit.Test;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
@@ -28,13 +27,13 @@ public class Mdsal666Test {
         final var generatedNames = DefaultBindingGenerator.generateFor(
             YangParserTestUtils.parseYangResource("/mdsal666.yang")).stream().map(GeneratedType::getIdentifier)
             .collect(Collectors.toUnmodifiableList());
-        assertEquals(10, generatedNames.size());
+        assertEquals(11, generatedNames.size());
 
-        // Reserved for future use
-        assertEquals(Optional.empty(), generatedNames.stream().filter(FOO::equals).findAny());
-        // Grouping is relocated for 'rpc foo' ...
-        assertTrue(generatedNames.stream().filter(FOO_GRP::equals).findAny().isPresent());
+        // 'rpc foo' ...
+        assertTrue(generatedNames.stream().anyMatch(FOO::equals));
+        // ... grouping is relocated for 'rpc foo' ...
+        assertTrue(generatedNames.stream().anyMatch(FOO_GRP::equals));
         // .. and 'action baz'
-        assertTrue(generatedNames.stream().filter(BAZ_GRP::equals).findAny().isPresent());
+        assertTrue(generatedNames.stream().anyMatch(BAZ_GRP::equals));
     }
 }
index d161cbedf11822e04908976f1a8991cca682d03c..65b4907909187012ae673f418049bb6a0ad6ed27 100644 (file)
@@ -57,7 +57,6 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@@ -517,7 +516,7 @@ class JavaFileTemplate {
 
     private static boolean hasBuilderClass(final SchemaNode schemaNode) {
         return schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode
-                || schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition;
+                || schemaNode instanceof NotificationDefinition;
     }
 
     private static boolean isSameProperty(final String getterName1, final String getterName2) {
index b09d898d1b7fd3c856d128f0468b06646512eb31..d32bf1c674a181d41a023ba291bd35fa3a4cdf67 100644 (file)
@@ -40,6 +40,7 @@ import org.opendaylight.yangtools.yang.binding.KeyedListNotification;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
 import org.opendaylight.yangtools.yang.binding.OpaqueObject;
+import org.opendaylight.yangtools.yang.binding.Rpc;
 import org.opendaylight.yangtools.yang.binding.RpcInput;
 import org.opendaylight.yangtools.yang.binding.RpcOutput;
 import org.opendaylight.yangtools.yang.binding.RpcService;
@@ -88,6 +89,7 @@ public final class BindingTypes {
     private static final ConcreteType KEYED_LIST_NOTIFICATION = typeForClass(KeyedListNotification.class);
     private static final ConcreteType NOTIFICATION = typeForClass(Notification.class);
     private static final ConcreteType OPAQUE_OBJECT = typeForClass(OpaqueObject.class);
+    private static final ConcreteType RPC = typeForClass(Rpc.class);
     private static final ConcreteType RPC_RESULT = typeForClass(RpcResult.class);
     private static final ConcreteType YANG_FEATURE = typeForClass(YangFeature.class);
 
@@ -260,6 +262,18 @@ public final class BindingTypes {
         return parameterizedTypeFor(OPAQUE_OBJECT, type);
     }
 
+    /**
+     * Type specializing {@link Rpc} for a particular type.
+     *
+     * @param input Type input type
+     * @param output Type output type
+     * @return A parameterized type corresponding to {@code Rpc<Input, Output>}
+     * @throws NullPointerException if any argument is {@code null}
+     */
+    public static @NonNull ParameterizedType rpc(final Type input, final Type output) {
+        return parameterizedTypeFor(RPC, input, output);
+    }
+
     /**
      * Type specializing {@link RpcResult} for a particular type.
      *
index 76a9a2709c4c057298cb0dbb9f898f4a275e1f25..a805fc11c498342f079cc85b1d38a98cebc2d9d7 100644 (file)
@@ -18,7 +18,7 @@ import org.eclipse.jdt.annotation.NonNull;
 @Beta
 // FIXME: evaluate integrating with BindingObject
 public sealed interface BindingContract<T extends BindingContract<T>>
-        permits Action, BaseIdentity, DataContainer, YangFeature {
+        permits Action, BaseIdentity, DataContainer, Rpc, YangFeature {
     /**
      * Return the interface implemented by this object. This method differs from {@link Object#getClass()} in that it
      * returns the interface contract, not a concrete implementation class.
diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Rpc.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Rpc.java
new file mode 100644 (file)
index 0000000..937014e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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.yangtools.yang.binding;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import edu.umd.cs.findbugs.annotations.CheckReturnValue;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Interface extended by all interfaces generated for a YANG {@code rpc}.
+ */
+public non-sealed interface Rpc<I extends RpcInput, O extends RpcOutput> extends BindingContract<Rpc<I, O>> {
+    /**
+     * Invoke the RPC.
+     *
+     * @param input Input argument
+     * @return Future result of invocation
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @CheckReturnValue
+    @NonNull ListenableFuture<@NonNull RpcResult<@NonNull O>> invoke(@NonNull I input);
+}