From: Vladyslav Marchenko Date: Thu, 22 Oct 2020 12:51:40 +0000 (+0300) Subject: Propagate notification status to generated listener methods X-Git-Tag: v7.0.2~47 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=99459c3a8270ef41ff6c95f88f2db7bc1b278269;p=mdsal.git Propagate notification status to generated listener methods When we are generating listener interface for notifications: - deprecated notification methods are marked as @deprecated; - obsolete notification methods are marked as @deprecated and additionally are "default no-op" (so that users are not forced to implement them); JIRA: MDSAL-554 Change-Id: I298b4dff44bd74715d9e1ebac277ac4d7918ffe6 Signed-off-by: Vladyslav Marchenko Signed-off-by: Robert Varga --- 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 afed7fe272..96c880171d 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 @@ -124,6 +124,7 @@ import org.opendaylight.yangtools.yang.model.api.OutputSchemaNode; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.Status; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; @@ -630,9 +631,16 @@ abstract class AbstractTypeGenerator { resolveDataSchemaNodes(context, notificationInterface, notificationInterface, notification.getChildNodes(), false); - addComment(listenerInterface.addMethod("on" + notificationInterface.getName()) + final MethodSignatureBuilder notificationMethod = + listenerInterface.addMethod("on" + notificationInterface.getName()) .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification") - .setReturnType(primitiveVoidType()), notification); + .setReturnType(primitiveVoidType()); + + annotateDeprecatedIfNecessary(notification, notificationMethod); + if (notification.getStatus().equals(Status.OBSOLETE)) { + notificationMethod.setDefault(true); + } + addComment(notificationMethod, notification); } } diff --git a/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal554Test.java b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal554Test.java new file mode 100644 index 0000000000..632c155ed9 --- /dev/null +++ b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal554Test.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020 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; + +import static org.junit.Assert.assertEquals; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.junit.Test; +import org.opendaylight.mdsal.binding.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.model.api.JavaTypeName; +import org.opendaylight.mdsal.binding.model.api.MethodSignature; +import org.opendaylight.mdsal.binding.model.api.Type; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class Mdsal554Test { + @Test + public void builderTemplateGenerateListenerMethodsTest() { + final EffectiveModelContext context = YangParserTestUtils.parseYangResource("/mdsal554.yang"); + + final Set toGenModules = new HashSet<>(); + for (final Module module : context.getModules()) { + toGenModules.add(module); + } + + final List genTypes = DefaultBindingGenerator.generateFor(context, toGenModules); + + final GeneratedType type = (GeneratedType) genTypes.get(3); + + final List methods = type.getMethodDefinitions(); + + assertEquals(3, methods.size()); + assertEquals(methods.get(0).getName(), "onDeprecatedNotification"); + assertEquals(methods.get(0).isDefault(), false); + assertEquals(methods.get(0).getAnnotations().size(), 1); + assertEquals(methods.get(0).getAnnotations().get(0).getIdentifier(), JavaTypeName.create(Deprecated.class)); + assertEquals(methods.get(0).getAnnotations().get(0).getParameters().size(), 0); + + assertEquals(methods.get(1).getName(), "onObsoleteNotification"); + assertEquals(methods.get(1).isDefault(), true); + assertEquals(methods.get(1).getAnnotations().size(), 1); + assertEquals(methods.get(1).getAnnotations().get(0).getIdentifier(), JavaTypeName.create(Deprecated.class)); + assertEquals(methods.get(1).getAnnotations().get(0).getParameters().size(), 1); + assertEquals(methods.get(1).getAnnotations().get(0).getParameters().get(0).getName(), "forRemoval"); + assertEquals(methods.get(1).getAnnotations().get(0).getParameters().get(0).getValue(), "true"); + + assertEquals(methods.get(2).getName(), "onTestNotification"); + assertEquals(methods.get(2).isDefault(), false); + assertEquals(methods.get(2).getAnnotations().size(), 0); + } +} diff --git a/binding/mdsal-binding-generator-impl/src/test/resources/mdsal554.yang b/binding/mdsal-binding-generator-impl/src/test/resources/mdsal554.yang new file mode 100644 index 0000000000..427e1cdbcf --- /dev/null +++ b/binding/mdsal-binding-generator-impl/src/test/resources/mdsal554.yang @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 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 + */ +module test-listener { + yang-version 1; + namespace "urn:opendaylight:test-listener"; + prefix "t"; + + revision "2020-10-22" { + } + + notification deprecated-notification { + description "Just a testing deprecated notification."; + status deprecated; + } + + notification obsolete-notification { + description "Just a testing obsolete notification."; + status obsolete; + } + + notification test-notification { + description "Just a testing notification."; + } +} diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend index ed6bcea2c1..24ea00a019 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend @@ -32,7 +32,6 @@ import org.opendaylight.mdsal.binding.model.api.JavaTypeName import org.opendaylight.mdsal.binding.model.api.MethodSignature import org.opendaylight.mdsal.binding.model.api.Restrictions import org.opendaylight.mdsal.binding.model.api.Type -import org.opendaylight.mdsal.binding.model.api.TypeMember import org.opendaylight.mdsal.binding.model.api.TypeMemberComment import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Single import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Multiple diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend index ac67e96555..903b99fdd2 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend @@ -31,7 +31,6 @@ import org.opendaylight.mdsal.binding.model.api.MethodSignature import org.opendaylight.mdsal.binding.model.api.Type import org.opendaylight.mdsal.binding.model.util.Types import org.opendaylight.mdsal.binding.model.util.TypeConstants -import org.opendaylight.mdsal.binding.model.api.TypeMember /** * Template for generating JAVA interfaces. @@ -190,6 +189,10 @@ class InterfaceTemplate extends BaseTemplate { } else { switch method.name { case DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME : generateDefaultImplementedInterface + default : + if (VOID == method.returnType.identifier) { + generateNoopVoidInterfaceMethod(method) + } } } } @@ -208,6 +211,14 @@ class InterfaceTemplate extends BaseTemplate { «method.returnType.importedName» «method.name»(«method.parameters.generateParameters»); ''' + def private generateNoopVoidInterfaceMethod(MethodSignature method) ''' + «method.comment.asJavadoc» + «method.annotations.generateAnnotations» + default «VOID.importedName» «method.name»(«method.parameters.generateParameters») { + // No-op + } + ''' + def private static accessorJavadoc(MethodSignature method, String orString) { val reference = method.comment?.referenceDescription val propReturn = method.propertyNameFromGetter + ", or " + orString + " if it is not present." diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java index ec891f2625..d86bbfe66e 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java @@ -67,9 +67,13 @@ class JavaFileTemplate { */ static final @NonNull JavaTypeName OVERRIDE = JavaTypeName.create(Override.class); /** - * {@code java.lang.SuppressWarnings} as a JavaTypeName. + * {@code java.lang.void} as a JavaTypeName. */ static final @NonNull JavaTypeName SUPPRESS_WARNINGS = JavaTypeName.create(SuppressWarnings.class); + /** + * {@code java.lang.SuppressWarnings} as a JavaTypeName. + */ + static final @NonNull JavaTypeName VOID = JavaTypeName.create(void.class); /** * {@code java.util.Arrays} as a JavaTypeName. diff --git a/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceGeneratorTest.java b/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceGeneratorTest.java index 4afa251185..93ff329568 100644 --- a/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceGeneratorTest.java +++ b/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceGeneratorTest.java @@ -8,14 +8,134 @@ package org.opendaylight.mdsal.binding.java.api.generator; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; import org.junit.Test; +import org.opendaylight.mdsal.binding.model.api.AnnotationType; +import org.opendaylight.mdsal.binding.model.api.GeneratedType; +import org.opendaylight.mdsal.binding.model.api.JavaTypeName; +import org.opendaylight.mdsal.binding.model.api.MethodSignature; import org.opendaylight.mdsal.binding.model.api.Type; +import org.opendaylight.mdsal.binding.model.util.Types; public class InterfaceGeneratorTest { + private static final String TEST = "test"; + private static final JavaTypeName TYPE_NAME = JavaTypeName.create(TEST, TEST); + @Test - public void basicTest() throws Exception { + public void basicTest() { assertEquals("", new InterfaceGenerator().generate(mock(Type.class))); } + + @Test + public void builderTemplateListenerMethodTest() { + final MethodSignature methSign = mockMethSign("on" + TEST); + final GeneratedType genType = mockGenType(methSign); + + String expected = String.join(System.lineSeparator(), + "package test;", + "", + "public interface test", + "{", + "", + "", + "", + "", + " void ontest();", + "", + "}", + "", + "" + ); + assertEquals(expected, new InterfaceGenerator().generate(genType)); + } + + @Test + public void builderTemplateDeprecatedListenerMethodTest() { + final MethodSignature methSign = mockMethSign("on" + TEST); + addMethodStatus(methSign, JavaTypeName.create(Deprecated.class)); + final GeneratedType genType = mockGenType(methSign); + + String expected = String.join(System.lineSeparator(), + "package test;", + "import java.lang.Deprecated;", + "", + "public interface test", + "{", + "", + "", + "", + "", + " @Deprecated", + " void ontest();", + "", + "}", + "", + "" + ); + assertEquals(expected, new InterfaceGenerator().generate(genType)); + } + + @Test + public void builderTemplateGenerateObsoleteListenerMethodTest() { + final MethodSignature methSign = mockMethSign("on" + TEST); + addMethodStatus(methSign, JavaTypeName.create(Deprecated.class)); + doReturn(true).when(methSign).isDefault(); + final GeneratedType genType = mockGenType(methSign); + + String expected = String.join(System.lineSeparator(), + "package test;", + "import java.lang.Deprecated;", + "", + "public interface test", + "{", + "", + "", + "", + "", + " @Deprecated", + " default void ontest() {", + " // No-op", + " }", + "", + "}", + "", + "" + ); + assertEquals(expected, new InterfaceGenerator().generate(genType)); + } + + private static GeneratedType mockGenType(final MethodSignature methSign) { + final GeneratedType genType = spy(GeneratedType.class); + doReturn(TYPE_NAME).when(genType).getIdentifier(); + doReturn(TEST).when(genType).getName(); + doReturn(TEST).when(genType).getPackageName(); + final List listMethodSign = new ArrayList<>(); + listMethodSign.add(methSign); + doReturn(listMethodSign).when(genType).getMethodDefinitions(); + + final List impls = new ArrayList<>(); + doReturn(impls).when(genType).getImplements(); + return genType; + } + + private static MethodSignature mockMethSign(final String methodeName) { + final MethodSignature methSign = mock(MethodSignature.class); + doReturn(methodeName).when(methSign).getName(); + final Type methType = Types.typeForClass(void.class); + doReturn(methType).when(methSign).getReturnType(); + doReturn(MethodSignature.ValueMechanics.NORMAL).when(methSign).getMechanics(); + return methSign; + } + + private static void addMethodStatus(MethodSignature methSign, JavaTypeName annotationJavaType) { + final AnnotationType annotationType = mock(AnnotationType.class); + doReturn(annotationJavaType).when(annotationType).getIdentifier(); + doReturn(ImmutableList.of(annotationType)).when(methSign).getAnnotations(); + } } \ No newline at end of file