From 21a7a7dcf9cee6f66cae97753d431e97866cd00d Mon Sep 17 00:00:00 2001 From: Jie Han Date: Mon, 15 Jan 2018 08:48:04 +0800 Subject: [PATCH] Binding2 - Add yang and tests - fix resolve action in generator - add yang and tests Change-Id: I81d100f5deb071a8f0f3b9a9a76c36be0051d652 Signed-off-by: Jie Han --- .../impl/operation/ActionServiceAdapter.java | 4 +- ...ingDOMOperationProviderServiceAdapter.java | 4 +- .../impl/operation/RpcServiceAdapter.java | 97 ++++--- .../BindingDOMOperationAdapterTest.java | 261 ++++++++++++++++++ .../impl/BindingToNormalizedNodeCodec.java | 6 + .../generator/impl/RpcActionGenHelper.java | 13 +- .../test/test-operation-service.yang | 76 +++++ .../src/main/yang/test-operation-service.yang | 76 +++++ 8 files changed, 478 insertions(+), 59 deletions(-) create mode 100644 binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationAdapterTest.java create mode 100644 binding2/mdsal-binding2-java-api-generator/src/test/resources/test/test-operation-service.yang create mode 100644 binding2/mdsal-binding2-test-model/src/main/yang/test-operation-service.yang diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/ActionServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/ActionServiceAdapter.java index 7b82d4a73b..426be662c7 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/ActionServiceAdapter.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/ActionServiceAdapter.java @@ -94,7 +94,7 @@ class ActionServiceAdapter implements InvocationHandler { } break; case "invoke": - if (args.length == 2) { + if (args.length == 3) { final Input input = (Input) requireNonNull(args[0]); final InstanceIdentifier path = (InstanceIdentifier) requireNonNull(args[1]); final RpcCallback callback = (RpcCallback) requireNonNull(args[2]); @@ -146,7 +146,7 @@ class ActionServiceAdapter implements InvocationHandler { }, MoreExecutors.directExecutor()); } } - break; + return 0; default: break; } diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java index 4b2f2f0e96..52f4b07e7e 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java @@ -167,7 +167,7 @@ public class BindingDOMOperationProviderServiceAdapter implements RpcActionProvi public void onFailure(Throwable error) { bindingResult.set(RpcResultBuilder.failed().withError(ErrorType.APPLICATION, - error.getMessage()).build()); + error.getMessage(), error).build()); } }) ); @@ -198,7 +198,7 @@ public class BindingDOMOperationProviderServiceAdapter implements RpcActionProvi public void onFailure(Throwable error) { bindingResult.set(RpcResultBuilder.failed().withError(ErrorType.APPLICATION, - error.getMessage()).build()); + error.getMessage(), error).build()); } }) ); diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java index c30d2c8ebb..3495ee850d 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java @@ -7,9 +7,11 @@ */ package org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation; +import static java.util.Objects.requireNonNull; + import com.google.common.annotations.Beta; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; @@ -18,16 +20,18 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collection; -import java.util.Map.Entry; import java.util.Optional; import org.opendaylight.mdsal.binding.javav2.dom.adapter.extractor.ContextReferenceExtractor; import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec; import org.opendaylight.mdsal.binding.javav2.dom.codec.serialized.LazySerializedContainerNode; import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; +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.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.dom.api.DOMRpcResult; import org.opendaylight.mdsal.dom.api.DOMRpcService; @@ -43,14 +47,13 @@ import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; -import org.opendaylight.yangtools.yang.model.api.OperationDefinition; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaPath; @Beta class RpcServiceAdapter implements InvocationHandler { - private final ImmutableMap rpcNames; + private final RpcInvocationStrategy strategy; private final Class> type; private final BindingToNormalizedNodeCodec codec; private final DOMRpcService delegate; @@ -61,20 +64,22 @@ class RpcServiceAdapter implements InvocationHandler { this.type = Preconditions.checkNotNull(type); this.codec = Preconditions.checkNotNull(codec); this.delegate = Preconditions.checkNotNull(domService); - final ImmutableMap.Builder rpcBuilder = ImmutableMap.builder(); - for (final Entry rpc : codec.getRPCMethodToSchema(type).entrySet()) { - rpcBuilder.put(rpc.getKey(), createStrategy(rpc.getKey(), (RpcDefinition) rpc.getValue())); - } - rpcNames = rpcBuilder.build(); + strategy = createStrategy(type); proxy = (Rpc) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, this); } - private RpcInvocationStrategy createStrategy(final Method method, final RpcDefinition schema) { - final RpcRoutingStrategy strategy = RpcRoutingStrategy.from(schema); - if (strategy.isContextBasedRouted()) { - return new RoutedStrategy(schema.getPath(), method, strategy.getLeaf()); + private RpcInvocationStrategy createStrategy(final Class> rpcInterface) { + final RpcDefinition rpc = codec.getRpcDefinition(rpcInterface); + final RpcRoutingStrategy domStrategy = RpcRoutingStrategy.from(rpc); + if (domStrategy.isContextBasedRouted()) { + try { + return new RoutedStrategy(rpc.getPath(), + rpcInterface.getMethod("invoke", Input.class, RpcCallback.class), domStrategy.getLeaf()); + } catch (final NoSuchMethodException e) { + throw new IllegalStateException("Can not find 'invoke' method", e); + } } - return new NonRoutedStrategy(schema.getPath()); + return new NonRoutedStrategy(rpc.getPath()); } Rpc getProxy() { @@ -84,49 +89,41 @@ class RpcServiceAdapter implements InvocationHandler { @Override @SuppressWarnings("checkstyle:hiddenField") public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { - - final RpcInvocationStrategy rpc = rpcNames.get(method); - if (rpc != null) { - if (method.getParameterTypes().length == 0) { - return rpc.invokeEmpty(); - } - if (args.length != 1) { - throw new IllegalArgumentException("Input must be provided."); - } - return rpc.invoke((TreeNode) args[0]); - } - - if (isObjectMethod(method)) { - return callObjectMethod(proxy, method, args); - } - throw new UnsupportedOperationException("Method " + method.toString() + "is unsupported."); - } - - private static boolean isObjectMethod(final Method method) { - switch (method.getName()) { - case "toString": - return method.getReturnType().equals(String.class) && method.getParameterTypes().length == 0; - case "hashCode": - return method.getReturnType().equals(int.class) && method.getParameterTypes().length == 0; - case "equals": - return method.getReturnType().equals(boolean.class) && method.getParameterTypes().length == 1 - && method.getParameterTypes()[0] == Object.class; - default: - return false; - } - } - - private Object callObjectMethod(final Object self, final Method method, final Object[] args) { switch (method.getName()) { case "toString": return type.getName() + "$Adapter{delegate=" + delegate.toString() + "}"; case "hashCode": - return System.identityHashCode(self); + return System.identityHashCode(proxy); case "equals": - return self == args[0]; + return proxy == args[0]; + case "invoke": + if (args.length == 2) { + final Input input = (Input) requireNonNull(args[0]); + final RpcCallback callback = (RpcCallback) requireNonNull(args[1]); + ListenableFuture> future = strategy.invoke((TreeNode) input); + Futures.addCallback(future, new FutureCallback>() { + + @Override + public void onSuccess(final RpcResult result) { + if (result.getErrors().isEmpty()) { + callback.onSuccess((Output) result.getResult()); + } else { + result.getErrors().forEach(e -> callback.onFailure(e.getCause())); + } + } + + @Override + public void onFailure(final Throwable throwable) { + callback.onFailure(throwable); + } + }, MoreExecutors.directExecutor()); + } + return 0; default: - return null; + break; } + + throw new UnsupportedOperationException("Method " + method.toString() + "is unsupported."); } private abstract class RpcInvocationStrategy { diff --git a/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationAdapterTest.java b/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationAdapterTest.java new file mode 100644 index 0000000000..f6490fe45c --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationAdapterTest.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2018 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.dom.adapter.impl.operation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.ImmutableSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.mdsal.binding.javav2.api.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.test.BindingBrokerTestFactory; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.test.BindingTestContext; +import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.RpcCallback; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException; +import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.TestOperationServiceInContAction; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.TestOperationServiceMyRpcRpc; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.data.MyCont; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.data.my_cont.in_cont.InContInput; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.data.my_cont.in_cont.InContOutput; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.data.my_rpc.MyRpcInput; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.data.my_rpc.MyRpcOutput; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.dto.my_cont.in_cont.InContInputBuilder; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.dto.my_cont.in_cont.InContOutputBuilder; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.dto.my_rpc.MyRpcInputBuilder; +import org.opendaylight.mdsal.gen.javav2.urn.test.operation.rev170621.dto.my_rpc.MyRpcOutputBuilder; +import org.opendaylight.yangtools.concepts.ObjectRegistration; + + +public class BindingDOMOperationAdapterTest { + private static final MyRpcOutput RPC_OUTPUT = new MyRpcOutputBuilder().setRpcOutputLeaf("rpc_output_leaf").build(); + private static final InContOutput ACTION_OUTPUT = + new InContOutputBuilder().setOutputLeaf("action_output_leaf").build(); + private BindingDOMOperationProviderServiceAdapter adapter; + private BindingDOMOperationServiceAdapter serviceAdapter; + + @Before + public void setUp() throws Exception { + final BindingBrokerTestFactory testFactory = new BindingBrokerTestFactory(); + testFactory.setExecutor(Executors.newCachedThreadPool()); + + final BindingTestContext testContext = testFactory.getTestContext(); + testContext.start(); + + this.adapter = new BindingDOMOperationProviderServiceAdapter(testContext.getDomRpcRegistry(), + testContext.getDomActionRegistry(), testContext.getCodec()); + + this.serviceAdapter = new BindingDOMOperationServiceAdapter(testContext.getDomRpcInvoker(), + testContext.getDomActionService(), testContext.getCodec()); + } + + @Test + public void actionTest() throws Exception { + final CountDownLatch invokeLatch = new CountDownLatch(1); + final ObjectRegistration registration = adapter.registerActionImplementation( + TestOperationServiceInContAction.class, new TestActionImpl(), LogicalDatastoreType.OPERATIONAL, + ImmutableSet.of( + DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(MyCont.class)))); + assertNotNull(registration); + + final TestOperationServiceInContAction action = + serviceAdapter.getActionService(TestOperationServiceInContAction.class); + assertNotNull(action); + + action.invoke(new InContInputBuilder().setInputLeaf("in").build(), + InstanceIdentifier.create(MyCont.class), + new RpcCallback() { + @Override + public void onSuccess(InContOutput output) { + assertEquals(ACTION_OUTPUT, output); + invokeLatch.countDown(); + } + + @Override + public void onFailure(Throwable cause) { + assertNotNull(cause); + } + }); + assertEquals("Invoke complete", true, invokeLatch.await(5, TimeUnit.SECONDS)); + } + + @Test + public void actionFailedTest() throws Exception { + + final CountDownLatch invokeLatch = new CountDownLatch(1); + + final ObjectRegistration registration = adapter.registerActionImplementation( + TestOperationServiceInContAction.class, new TestActionFailedImpl(), LogicalDatastoreType.OPERATIONAL, + ImmutableSet.of(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, + InstanceIdentifier.create(MyCont.class)))); + assertNotNull(registration); + + final TestOperationServiceInContAction action = + serviceAdapter.getActionService(TestOperationServiceInContAction.class); + assertNotNull(action); + + action.invoke(new InContInputBuilder().setInputLeaf("in").build(), + InstanceIdentifier.create(MyCont.class), + new RpcCallback() { + @Override + public void onSuccess(InContOutput output) { + + } + + @Override + public void onFailure(Throwable cause) { + assertTrue(cause instanceof RuntimeException); + assertEquals(cause.getMessage(), "TestActionFailedImpl invoke failed."); + invokeLatch.countDown(); + } + }); + assertEquals("Invoke complete", true, invokeLatch.await(5, TimeUnit.SECONDS)); + } + + @Test + public void actionNotAvaliableTest() throws Exception { + + final CountDownLatch invokeLatch = new CountDownLatch(1); + + final TestOperationServiceInContAction action = + serviceAdapter.getActionService(TestOperationServiceInContAction.class); + assertNotNull(action); + + action.invoke(new InContInputBuilder().setInputLeaf("in").build(), + InstanceIdentifier.create(MyCont.class), + new RpcCallback() { + @Override + public void onSuccess(InContOutput output) { + + } + + @Override + public void onFailure(Throwable cause) { + assertTrue(cause instanceof DOMActionNotAvailableException); + invokeLatch.countDown(); + } + }); + assertEquals("Invoke complete", true, invokeLatch.await(5, TimeUnit.SECONDS)); + } + + @Test + public void rpcTest() throws Exception { + final CountDownLatch invokeLatch = new CountDownLatch(1); + + assertNotNull(adapter.registerRpcImplementation(TestOperationServiceMyRpcRpc.class, + new TestRpcImpl())); + final TestOperationServiceMyRpcRpc rpc = + serviceAdapter.getRpcService(TestOperationServiceMyRpcRpc.class); + assertNotNull(rpc); + + rpc.invoke(new MyRpcInputBuilder().setRpcInputLeaf("123").build(), + new RpcCallback() { + @Override + public void onSuccess(MyRpcOutput output) { + assertEquals(RPC_OUTPUT, output); + invokeLatch.countDown(); + } + + @Override + public void onFailure(Throwable cause) { + } + }); + assertEquals("Invoke complete", true, invokeLatch.await(5, TimeUnit.SECONDS)); + } + + @Test + public void rpcFailedTest() throws Exception { + + final CountDownLatch invokeLatch = new CountDownLatch(1); + + assertNotNull(adapter.registerRpcImplementation(TestOperationServiceMyRpcRpc.class, + new TestRpcFailedImpl())); + final TestOperationServiceMyRpcRpc rpc = + serviceAdapter.getRpcService(TestOperationServiceMyRpcRpc.class); + assertNotNull(rpc); + + rpc.invoke(new MyRpcInputBuilder().setRpcInputLeaf("123").build(), + new RpcCallback() { + @Override + public void onSuccess(MyRpcOutput output) { + + } + + @Override + public void onFailure(Throwable cause) { + assertTrue(cause instanceof RuntimeException); + assertEquals(cause.getMessage(), "TestRpcFailedImpl invoke failed."); + invokeLatch.countDown(); + } + }); + assertEquals("Invoke complete", true, invokeLatch.await(5, TimeUnit.SECONDS)); + } + + @Test + public void rpcNotAvaliableTest() throws Exception { + final CountDownLatch invokeLatch = new CountDownLatch(1); + + final TestOperationServiceMyRpcRpc rpc = + serviceAdapter.getRpcService(TestOperationServiceMyRpcRpc.class); + assertNotNull(rpc); + + rpc.invoke(new MyRpcInputBuilder().setRpcInputLeaf("123").build(), + new RpcCallback() { + @Override + public void onSuccess(MyRpcOutput output) { + + } + + @Override + public void onFailure(Throwable cause) { + assertTrue(cause instanceof DOMRpcImplementationNotAvailableException); + invokeLatch.countDown(); + } + }); + assertEquals("Invoke complete", true, invokeLatch.await(5, TimeUnit.SECONDS)); + } + + private class TestRpcImpl implements TestOperationServiceMyRpcRpc { + + @Override + public void invoke(MyRpcInput input, RpcCallback callback) { + callback.onSuccess(RPC_OUTPUT); + } + } + + private class TestRpcFailedImpl implements TestOperationServiceMyRpcRpc { + + @Override + public void invoke(MyRpcInput input, RpcCallback callback) { + callback.onFailure(new RuntimeException("TestRpcFailedImpl invoke failed.")); + } + } + + private class TestActionImpl implements TestOperationServiceInContAction { + + @Override + public void invoke(InContInput input, InstanceIdentifier ii, RpcCallback callback) { + callback.onSuccess(ACTION_OUTPUT); + } + } + + private class TestActionFailedImpl implements TestOperationServiceInContAction { + + @Override + public void invoke(InContInput input, InstanceIdentifier ii, RpcCallback callback) { + callback.onFailure(new RuntimeException("TestActionFailedImpl invoke failed.")); + } + } +} \ No newline at end of file diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java index 2c7cccdbde..9268cc9d0b 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java @@ -365,6 +365,12 @@ public final class BindingToNormalizedNodeCodec return schema.getPath(); } + public RpcDefinition getRpcDefinition(final Class> type) { + final RpcDefinition schema = runtimeContext.getRpcDefinition(type); + checkArgument(schema != null, "Failed to find schema for %s", type); + return schema; + } + /** * Resolve method with definition of specific RPC as binding object. * 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 index 8e0ecb1d26..66260fb8fb 100644 --- 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 @@ -250,6 +250,7 @@ final class RpcActionGenHelper { if (isAction) { requireNonNull(parent, "Parent must be specified for action."); + //action GeneratedTypeBuilder parentType = genCtx.get(module).getChildNode(parent.getPath()); checkState(parentType != null, "Parent generated type for " + parent + " data schema node must have been generated already"); @@ -259,18 +260,20 @@ final class RpcActionGenHelper { //ListAction GeneratedTransferObject keyType = null; for (MethodSignatureBuilder method : parentType.getMethodDefinitions()) { - if (method.getName().equals("getKey")) { + if (method.getName().equals("getIdentifier")) { keyType = (GeneratedTransferObject) method.toInstance(parentType).getReturnType(); } } - operationMethod.addParameter( - parameterizedTypeFor(KEYED_INSTANCE_IDENTIFIER, parentType, keyType), "kii"); - interfaceBuilder.addImplementsType(parameterizedTypeFor(LIST_ACTION, parentType, inType, outType)); + operationMethod.addParameter(parameterizedTypeFor(KEYED_INSTANCE_IDENTIFIER, parentType, keyType), + "kii"); + interfaceBuilder.addImplementsType(parameterizedTypeFor(LIST_ACTION, parentType, keyType, inType, + outType)); } else { //Action operationMethod.addParameter(parameterizedTypeFor(INSTANCE_IDENTIFIER, parentType), "ii"); - interfaceBuilder.addImplementsType(parameterizedTypeFor(ACTION, parentType, inType, outType)); + interfaceBuilder.addImplementsType(parameterizedTypeFor(ACTION, parentType, + parameterizedTypeFor(INSTANCE_IDENTIFIER, parentType) ,inType, outType)); } } else { //RPC diff --git a/binding2/mdsal-binding2-java-api-generator/src/test/resources/test/test-operation-service.yang b/binding2/mdsal-binding2-java-api-generator/src/test/resources/test/test-operation-service.yang new file mode 100644 index 0000000000..49a03cac79 --- /dev/null +++ b/binding2/mdsal-binding2-java-api-generator/src/test/resources/test/test-operation-service.yang @@ -0,0 +1,76 @@ +module test-operation-service { + yang-version 1.1; + namespace "urn:test:operation"; + prefix "operation"; + + revision "2017-06-21" { + description + "Initial revision"; + } + + container my-cont { + action in-cont { + input { + leaf input-leaf { + type string; + } + } + + output { + leaf output-leaf { + type string; + } + } + } + + action in-cont2 { + input { + leaf input-leaf { + type string; + } + } + + output { + leaf output-leaf { + type string; + } + } + } + } + + list my-list { + key "name"; + + leaf name { + type string; + } + + action in-list { + input { + leaf input-list-leaf { + type string; + } + } + + output { + leaf output-list-leaf { + type string; + } + } + } + } + + rpc my-rpc { + input { + leaf rpc-input-leaf { + type string; + } + } + + output { + leaf rpc-output-leaf { + type string; + } + } + } +} diff --git a/binding2/mdsal-binding2-test-model/src/main/yang/test-operation-service.yang b/binding2/mdsal-binding2-test-model/src/main/yang/test-operation-service.yang new file mode 100644 index 0000000000..49a03cac79 --- /dev/null +++ b/binding2/mdsal-binding2-test-model/src/main/yang/test-operation-service.yang @@ -0,0 +1,76 @@ +module test-operation-service { + yang-version 1.1; + namespace "urn:test:operation"; + prefix "operation"; + + revision "2017-06-21" { + description + "Initial revision"; + } + + container my-cont { + action in-cont { + input { + leaf input-leaf { + type string; + } + } + + output { + leaf output-leaf { + type string; + } + } + } + + action in-cont2 { + input { + leaf input-leaf { + type string; + } + } + + output { + leaf output-leaf { + type string; + } + } + } + } + + list my-list { + key "name"; + + leaf name { + type string; + } + + action in-list { + input { + leaf input-list-leaf { + type string; + } + } + + output { + leaf output-list-leaf { + type string; + } + } + } + } + + rpc my-rpc { + input { + leaf rpc-input-leaf { + type string; + } + } + + output { + leaf rpc-output-leaf { + type string; + } + } + } +} -- 2.36.6