From b950bb23c4552155e89c20708b2d85c05aba7d24 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Fri, 27 Jul 2018 03:10:33 +0200 Subject: [PATCH] Fix actions in keyed lists When we encounter a keyed list we end up generating an action for the key, not for the list, which leads to a compilation error. Change-Id: Iad9a5b449778704a3209d43011060f4a7942b9a6 Signed-off-by: Robert Varga --- .../binding/api/ActionProviderService.java | 16 ++++++----- .../mdsal/binding/api/ActionService.java | 15 ++++++----- .../dom/adapter/ActionServiceAdapter.java | 7 +++-- .../generator/impl/AbstractTypeGenerator.java | 12 +++++---- .../binding/generator/impl/ActionsTest.java | 2 +- .../src/test/resources/actions.yang | 20 +++++++++++++- .../binding/model/util/BindingTypes.java | 19 ++++++++++++- .../src/main/yang/actions.yang | 18 +++++++++++++ .../yangtools/yang/binding/Action.java | 4 +-- .../yang/binding/KeyedListAction.java | 27 +++++++++++++++++++ 10 files changed, 112 insertions(+), 28 deletions(-) create mode 100644 binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedListAction.java diff --git a/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionProviderService.java b/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionProviderService.java index 6de0801def..3f4e737fd1 100644 --- a/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionProviderService.java +++ b/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionProviderService.java @@ -15,6 +15,7 @@ import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.yangtools.concepts.ObjectRegistration; import org.opendaylight.yangtools.yang.binding.Action; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; /** * Registration interface used by {@code action} implementations. Each action is defined in a YANG model, @@ -40,17 +41,18 @@ public interface ActionProviderService extends BindingService { * @throws IllegalArgumentException if any of the {@code validNodes} does not match {@code datastore} * @throws UnsupportedOperationException if this service cannot handle requested datastore */ - , S extends T> ObjectRegistration registerImplementation( - Class actionInterface, S implementation, LogicalDatastoreType datastore, - Set> validNodes); + , T extends Action, S extends T> + ObjectRegistration registerImplementation(Class actionInterface, S implementation, + LogicalDatastoreType datastore, Set> validNodes); - default , S extends T> ObjectRegistration registerImplementation( - final Class actionInterface, final S implementation, final LogicalDatastoreType datastore) { + default , T extends Action, S extends T> + ObjectRegistration registerImplementation(final Class actionInterface, final S implementation, + final LogicalDatastoreType datastore) { return registerImplementation(actionInterface, implementation, datastore, ImmutableSet.of()); } - default , S extends T> ObjectRegistration registerImplementation( - final Class actionInterface, final S implementation) { + default , T extends Action, S extends T> + ObjectRegistration registerImplementation(final Class actionInterface, final S implementation) { return registerImplementation(actionInterface, implementation, LogicalDatastoreType.OPERATIONAL); } } diff --git a/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionService.java b/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionService.java index 7b272ba101..6642c34e6e 100644 --- a/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionService.java +++ b/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionService.java @@ -56,22 +56,23 @@ public interface ActionService extends BindingService { > T getActionHandle(Class actionInterface, Set> validNodes); - default > T getActionHandle(final Class actionInterface) { + default , T extends Action> T getActionHandle( + final Class actionInterface) { return getActionHandle(actionInterface, ImmutableSet.of()); } - default > T getActionHandle(final Class actionInterface, - final LogicalDatastoreType dataStore, final InstanceIdentifier path) { + default , T extends Action> T getActionHandle( + final Class actionInterface, final LogicalDatastoreType dataStore, final P path) { return getActionHandle(actionInterface, ImmutableSet.of(DataTreeIdentifier.create(dataStore, path))); } - default > T getActionHandle(final Class actionInterface, - final InstanceIdentifier path) { + default , T extends Action> T getActionHandle( + final Class actionInterface, final P path) { return getActionHandle(actionInterface, LogicalDatastoreType.OPERATIONAL, path); } - default > T getActionHandle(final Class actionInterface, - @SuppressWarnings("unchecked") final DataTreeIdentifier... nodes) { + default , T extends Action> T getActionHandle( + final Class actionInterface, @SuppressWarnings("unchecked") final DataTreeIdentifier... nodes) { return getActionHandle(actionInterface, ImmutableSet.copyOf(nodes)); } } diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/ActionServiceAdapter.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/ActionServiceAdapter.java index 04c74e630e..513db38d2b 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/ActionServiceAdapter.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/ActionServiceAdapter.java @@ -35,8 +35,8 @@ final class ActionServiceAdapter extends AbstractBindingLoadingAdapter>, ActionAdapter> implements ActionService { private static final class ConstrainedAction implements Delegator>, - Action { - private final Action delegate; + Action, RpcInput, RpcOutput> { + private final Action, RpcInput, RpcOutput> delegate; private final Set> nodes; ConstrainedAction(final Action delegate, final Set> nodes) { @@ -45,8 +45,7 @@ final class ActionServiceAdapter } @Override - public FluentFuture> invoke(final InstanceIdentifier path, - final RpcInput input) { + public FluentFuture> invoke(final InstanceIdentifier path, final RpcInput input) { checkState(nodes.contains(path), "Cannot service %s", path); return delegate.invoke(path, input); } diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java index 907eba6d20..a70b7cf959 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java @@ -29,6 +29,7 @@ import static org.opendaylight.mdsal.binding.model.util.BindingTypes.childOf; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.choiceIn; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifiable; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifier; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.keyedListAction; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.rpcResult; import static org.opendaylight.mdsal.binding.model.util.Types.BOOLEAN; import static org.opendaylight.mdsal.binding.model.util.Types.listTypeFor; @@ -285,7 +286,7 @@ abstract class AbstractTypeGenerator { if (genType != null) { constructGetter(parent, genType, node); resolveDataSchemaNodes(context, genType, genType, node.getChildNodes()); - actionsToGenType(context, genType, node); + actionsToGenType(context, genType, node, null); } } @@ -303,8 +304,8 @@ abstract class AbstractTypeGenerator { genTOBuilder.addImplementsType(identifierMarker); genType.addImplementsType(identifiableMarker); - actionsToGenType(context, genTOBuilder, node); } + actionsToGenType(context, genType, node, genTOBuilder); for (final DataSchemaNode schemaNode : node.getChildNodes()) { if (!schemaNode.isAugmenting()) { @@ -404,7 +405,7 @@ abstract class AbstractTypeGenerator { } private void actionsToGenType(final ModuleContext context, - final Type parent, final T parentSchema) { + final Type parent, final T parentSchema, final Type keyType) { for (final ActionDefinition action : parentSchema.getActions()) { final GeneratedType input; final GeneratedType output; @@ -429,7 +430,8 @@ abstract class AbstractTypeGenerator { BindingMapping.MODULE_INFO_CLASS_NAME), qname.getLocalName()); annotateDeprecatedIfNecessary(action.getStatus(), builder); - builder.addImplementsType(action(parent, input, output)); + builder.addImplementsType(keyType != null ? keyedListAction(parent, keyType, input, output) + : action(parent, input, output)); addCodegenInformation(builder, context.module(), action); context.addChildNodeType(action, builder); @@ -669,7 +671,7 @@ abstract class AbstractTypeGenerator { resolveDataSchemaNodes(context, genType, genType, grouping.getChildNodes()); groupingsToGenTypes(context, grouping.getGroupings()); processUsesAugments(grouping, context); - actionsToGenType(context, genType, grouping); + actionsToGenType(context, genType, grouping, null); } } diff --git a/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ActionsTest.java b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ActionsTest.java index fd1ffda7b6..3dfd3cfe6e 100644 --- a/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ActionsTest.java +++ b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/ActionsTest.java @@ -23,6 +23,6 @@ public class ActionsTest { List generateTypes = new BindingGeneratorImpl().generateTypes(context); assertNotNull(generateTypes); - assertEquals(13, generateTypes.size()); + assertEquals(21, generateTypes.size()); } } diff --git a/binding/mdsal-binding-generator-impl/src/test/resources/actions.yang b/binding/mdsal-binding-generator-impl/src/test/resources/actions.yang index 4ea4a546dc..171b8cb5ed 100644 --- a/binding/mdsal-binding-generator-impl/src/test/resources/actions.yang +++ b/binding/mdsal-binding-generator-impl/src/test/resources/actions.yang @@ -5,7 +5,17 @@ module actions { container cont { action foo { - + + } + } + + list lst { + key key; + leaf key { + type string; + } + action foo { + } } @@ -23,6 +33,14 @@ module actions { uses grp; } + list grplst { + key key; + leaf key { + type string; + } + uses grp; + } + container othercont { uses other; } diff --git a/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/BindingTypes.java b/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/BindingTypes.java index 5afd0cdcb6..117276462d 100644 --- a/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/BindingTypes.java +++ b/binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/BindingTypes.java @@ -27,6 +27,7 @@ import org.opendaylight.yangtools.yang.binding.DataRoot; import org.opendaylight.yangtools.yang.binding.Identifiable; import org.opendaylight.yangtools.yang.binding.Identifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedListAction; import org.opendaylight.yangtools.yang.binding.Notification; import org.opendaylight.yangtools.yang.binding.NotificationListener; import org.opendaylight.yangtools.yang.binding.RpcInput; @@ -64,6 +65,7 @@ public final class BindingTypes { private static final ConcreteType ACTION = typeForClass(Action.class); private static final ConcreteType CHILD_OF = typeForClass(ChildOf.class); private static final ConcreteType CHOICE_IN = typeForClass(ChoiceIn.class); + private static final ConcreteType KEYED_LIST_ACTION = typeForClass(KeyedListAction.class); private static final ConcreteType RPC_RESULT = typeForClass(RpcResult.class); private BindingTypes() { @@ -80,7 +82,22 @@ public final class BindingTypes { * @throws NullPointerException if any argument is is null */ public static ParameterizedType action(final Type parent, final Type input, final Type output) { - return parameterizedTypeFor(ACTION, parent, input, output); + return parameterizedTypeFor(ACTION, instanceIdentifier(parent), input, output); + } + + /** + * Type specializing {@link KeyedListAction} for a particular type. + * + * @param parent Type of parent defining the action + * @param keyType Type of parent's key + * @param input Type input type + * @param output Type output type + * @return A parameterized type corresponding to {@code KeyedListAction} + * @throws NullPointerException if any argument is is null + */ + public static ParameterizedType keyedListAction(final Type parent, final Type keyType, final Type input, + final Type output) { + return parameterizedTypeFor(KEYED_LIST_ACTION, keyType, parent, input, output); } /** diff --git a/binding/mdsal-binding-test-model/src/main/yang/actions.yang b/binding/mdsal-binding-test-model/src/main/yang/actions.yang index 32210d9fb2..5f2eff6431 100644 --- a/binding/mdsal-binding-test-model/src/main/yang/actions.yang +++ b/binding/mdsal-binding-test-model/src/main/yang/actions.yang @@ -13,6 +13,16 @@ module actions { } } + list lst { + key key; + leaf key { + type string; + } + action foo { + + } + } + grouping grp { action bar { output { @@ -31,6 +41,14 @@ module actions { uses grp; } + list grplst { + key key; + leaf key { + type string; + } + uses grp; + } + container othercont { uses other; } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Action.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Action.java index 0b60c9c835..e77d65800b 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Action.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Action.java @@ -20,7 +20,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult; */ @Beta @FunctionalInterface -public interface Action

{ +public interface Action

, I extends RpcInput, O extends RpcOutput> { /** * Invoke the action. * @@ -30,5 +30,5 @@ public interface Action

> invoke(@NonNull InstanceIdentifier

path, @NonNull I input); + @NonNull FluentFuture<@NonNull RpcResult<@NonNull O>> invoke(@NonNull P path, @NonNull I input); } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedListAction.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedListAction.java new file mode 100644 index 0000000000..f7c31d0f21 --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedListAction.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018 Pantheon Technologies, 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.annotations.Beta; +import com.google.common.util.concurrent.FluentFuture; +import javax.annotation.CheckReturnValue; +import org.opendaylight.yangtools.yang.common.RpcResult; + +/** + * Interface extended by all interfaces generated for a YANG {@code action} instantiated in keyed lists. + * + * @author Robert Varga + */ +@Beta +@FunctionalInterface +public interface KeyedListAction, T extends DataObject & Identifiable, + I extends RpcInput, O extends RpcOutput> extends Action, I, O> { + @Override + @CheckReturnValue + FluentFuture> invoke(KeyedInstanceIdentifier path, I input); +} -- 2.36.6