Improve QNAME field definition 36/71836/8
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 24 Apr 2018 09:26:46 +0000 (11:26 +0200)
committerRobert Varga <nite@hq.sk>
Thu, 24 May 2018 09:58:08 +0000 (09:58 +0000)
The constant field that contains the QName corresponding to the
generated construct can rely on YangModuleInfo associated with
the generated module. Since that class already contains the module's
QName, we can lift it from there and use it to define the constant.

This has the benefit of not duplicating strings in classes, leading
to smaller footprint and improves startup time, as the strings do not
have to be parsed when the class is loaded.

JIRA: MDSAL-339
Change-Id: Ia7d336e3d386955f83648543b1e98f820ebbaf40
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
12 files changed:
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/YangModuleInfoTemplate.xtend
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/AugmentToUsesInAugmentCompilationTest.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/BaseCompilationTest.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/Bug5151Test.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CascadeUsesCompilationTest.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CompilationTest.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/NestedGroupingCompilationTest.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/TypedefCompilationTest.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingMapping.java

index ada941f0ea32e7695d27575a5fc5752ae3c9b845..9ae1749e1ca73660be2d3df520fbf97048334876 100644 (file)
@@ -30,6 +30,7 @@ import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findP
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
+import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
@@ -565,15 +566,16 @@ abstract class AbstractTypeGenerator {
         newType.setModuleName(module.getName());
         newType.setSchemaPath(identity.getPath());
 
-        qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, identity.getQName());
+        qnameConstant(newType, JavaTypeName.create(context.modulePackageName(), BindingMapping.MODULE_INFO_CLASS_NAME),
+            identity.getQName().getLocalName());
 
         context.addIdentityType(identity.getQName(), newType);
     }
 
-
-    private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
-            final QName name) {
-        return toBuilder.addConstant(typeForClass(QName.class), constantName, name);
+    private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder,
+            final JavaTypeName yangModuleInfo, final String localName) {
+        return toBuilder.addConstant(typeForClass(QName.class), BindingMapping.QNAME_STATIC_FIELD_NAME,
+            new SimpleImmutableEntry<>(yangModuleInfo, localName));
     }
 
     /**
@@ -1663,7 +1665,8 @@ abstract class AbstractTypeGenerator {
         // FIXME: Validation of name conflict
         final GeneratedTypeBuilder newType = typeProvider.newGeneratedTypeBuilder(identifier);
         final Module module = findParentModule(schemaContext, schemaNode);
-        qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
+        qnameConstant(newType, JavaTypeName.create(BindingMapping.getRootPackageName(module.getQNameModule()),
+            BindingMapping.MODULE_INFO_CLASS_NAME), schemaNode.getQName().getLocalName());
 
         addCodegenInformation(newType, module, schemaNode);
         newType.setSchemaPath(schemaNode.getPath());
index e40dbfa5069acbfbbdca2c92575308fcc9c96cd4..0b9d7fb5638fe119d64666721d7b6de7fa3a9640 100644 (file)
@@ -15,6 +15,7 @@ import com.google.common.base.Splitter
 import com.google.common.collect.Iterables
 import java.util.Collection
 import java.util.List
+import java.util.Map.Entry
 import java.util.StringTokenizer
 import java.util.regex.Pattern
 import org.opendaylight.mdsal.binding.model.api.ConcreteType
@@ -22,6 +23,7 @@ import org.opendaylight.mdsal.binding.model.api.Constant
 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
 import org.opendaylight.mdsal.binding.model.api.GeneratedType
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
+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
@@ -29,6 +31,7 @@ import org.opendaylight.mdsal.binding.model.api.TypeMember
 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Single
 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Multiple
 import org.opendaylight.mdsal.binding.model.util.Types
+import org.opendaylight.yangtools.yang.binding.BindingMapping
 import org.opendaylight.yangtools.yang.binding.CodeHelpers
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
@@ -433,11 +436,9 @@ abstract class BaseTemplate extends JavaFileTemplate {
     »'''
 
     def protected emitConstant(Constant c) '''
-        «IF c.value instanceof QName»
-            «val qname = c.value as QName»
-            «val rev = qname.revision»
-            public static final «c.type.importedName» «c.name» = «QName.importedName».create("«qname.namespace.toString
-                »", «IF rev.isPresent»"«rev.get»", «ENDIF»"«qname.localName»").intern();
+        «IF BindingMapping.QNAME_STATIC_FIELD_NAME.equals(c.name)»
+            «val entry = c.value as Entry<JavaTypeName, String>»
+            public static final «c.type.importedName» «c.name» = «entry.key.importedName».«BindingMapping.MODULE_INFO_QNAMEOF_METHOD_NAME»("«entry.value»");
         «ELSE»
             public static final «c.type.importedName» «c.name» = «c.value»;
         «ENDIF»
index f8aeba321c4ab282c171940648669303511ff239..02b1150bc074059c2aeee3bb2b96132a404e8745 100644 (file)
@@ -68,6 +68,10 @@ class JavaFileTemplate {
         return importedName(Types.typeForClass(cls));
     }
 
+    final String importedName(final JavaTypeName intype) {
+        return javaType.getReferenceString(intype);
+    }
+
     final void addImport(final Class<?> cls) {
         javaType.getReferenceString(JavaTypeName.create(cls));
     }
index b4db903b0e973caa1ac2d0c58c6a003ba951fa7e..62e2342d13cc7c3b81d0abbbf7b354e6bd529844 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.mdsal.binding.java.api.generator
 
 import static org.opendaylight.yangtools.yang.binding.BindingMapping.MODEL_BINDING_PROVIDER_CLASS_NAME
 import static org.opendaylight.yangtools.yang.binding.BindingMapping.MODULE_INFO_CLASS_NAME
+import static org.opendaylight.yangtools.yang.binding.BindingMapping.MODULE_INFO_QNAMEOF_METHOD_NAME
 import static extension org.opendaylight.yangtools.yang.binding.BindingMapping.getClassName
 import static extension org.opendaylight.yangtools.yang.binding.BindingMapping.getRootPackageName
 
@@ -35,6 +36,11 @@ import org.opendaylight.yangtools.yang.common.Revision
 import org.opendaylight.yangtools.yang.model.api.Module
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 
+/**
+ * Template for {@link YangModuleInfo} implementation for a particular module. Aside from fulfilling that contract,
+ * this class provides a static {@code createQName(String)} method, which is used by co-generated code to initialize
+ * QNAME constants.
+ */
 class YangModuleInfoTemplate {
 
     val Module module
@@ -60,17 +66,20 @@ class YangModuleInfoTemplate {
     def String generate() {
         val body = '''
             public final class «MODULE_INFO_CLASS_NAME» extends «ResourceYangModuleInfo.importedName» {
-
+                «val rev = module.revision»
+                private static final «QName.importedName» NAME = «QName.importedName».create("«module.namespace.toString»", «IF rev.present»"«rev.get.toString»", «ENDIF»"«module.name»").intern();
                 private static final «YangModuleInfo.importedName» INSTANCE = new «MODULE_INFO_CLASS_NAME»();
 
-                «val rev = module.revision»
-                private final «QName.importedName» name = QName.create("«module.namespace.toString»", «IF rev.present»"«rev.get.toString»", «ENDIF»"«module.name»").intern();
                 private final «Set.importedName»<«YangModuleInfo.importedName»> importedModules;
 
                 public static «YangModuleInfo.importedName» getInstance() {
                     return INSTANCE;
                 }
 
+                public static «QName.importedName» «MODULE_INFO_QNAMEOF_METHOD_NAME»(final «String.importedName» localName) {
+                    return «QName.importedName».create(NAME, localName).intern();
+                }
+
                 «classBody(module, MODULE_INFO_CLASS_NAME)»
             }
         '''
@@ -134,7 +143,7 @@ class YangModuleInfoTemplate {
 
         @Override
         public «QName.importedName» getName() {
-            return name;
+            return NAME;
         }
 
         @Override
@@ -261,11 +270,11 @@ class YangModuleInfoTemplate {
         «FOR submodule : module.submodules»
             «val className = submodule.name.className»
             private static final class «className»Info extends «ResourceYangModuleInfo.importedName» {
-
+                «val rev = submodule.revision»
+                private final «QName.importedName» NAME = «QName.importedName».create("«
+                    submodule.namespace.toString»", «IF rev.present»"«rev.get.toString»", «ENDIF»"«submodule.name»").intern();
                 private static final «YangModuleInfo.importedName» INSTANCE = new «className»Info();
 
-                «val rev = submodule.revision»
-                private final «QName.importedName» name = QName.create("«submodule.namespace.toString»", «IF rev.present»"«rev.get.toString»", «ENDIF» "«submodule.name»").intern();
                 private final «Set.importedName»<YangModuleInfo> importedModules;
 
                 public static «YangModuleInfo.importedName» getInstance() {
index 9420ea6e39ef4e6120ffb546aea9def3029eec10..ad9cae49a684246ec726d870ef6bedce43140529 100644 (file)
@@ -26,14 +26,14 @@ public class AugmentToUsesInAugmentCompilationTest extends BaseCompilationTest {
 
         // Test if all sources are generated from 'module foo'
         File fooParent = new File(sourcesOutputDir, CompilationTestUtils.NS_FOO);
-        CompilationTestUtils.assertFilesCount(fooParent, 4);
+        CompilationTestUtils.assertFilesCount(fooParent, 5);
         assertTrue(new File(fooParent, "IgpLinkAttributes.java").exists());
         assertTrue(new File(fooParent, "Link1.java").exists());
         assertTrue(new File(fooParent, "Link1Builder.java").exists());
 
         // Test if all sources are generated from 'module bar'
         File barParent = new File(sourcesOutputDir, CompilationTestUtils.NS_BAR);
-        CompilationTestUtils.assertFilesCount(barParent, 7);
+        CompilationTestUtils.assertFilesCount(barParent, 8);
         assertTrue(new File(barParent, "BarData.java").exists());
         assertTrue(new File(barParent, "NetworkTopology.java").exists());
         assertTrue(new File(barParent, "NetworkTopologyBuilder.java").exists());
@@ -56,7 +56,7 @@ public class AugmentToUsesInAugmentCompilationTest extends BaseCompilationTest {
 
         // Test if all sources are generated from 'module baz'
         File bazParent = new File(sourcesOutputDir, CompilationTestUtils.NS_BAZ);
-        CompilationTestUtils.assertFilesCount(bazParent, 4);
+        CompilationTestUtils.assertFilesCount(bazParent, 5);
         assertTrue(new File(bazParent, "IgpLinkAttributes1.java").exists());
         assertTrue(new File(bazParent, "IgpLinkAttributes1Builder.java").exists());
         assertTrue(new File(bazParent, "LinkAttributes.java").exists());
index cf0c28e6832eb048eb8dc4b659df25637fbbd324..4f9704f689fbf451ed10dbeaa60325ea05228eb7 100644 (file)
@@ -10,17 +10,23 @@ package org.opendaylight.mdsal.binding.java.api.generator.test;
 import static org.junit.Assert.assertTrue;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.common.io.Files;
 import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.opendaylight.mdsal.binding.generator.api.BindingGenerator;
 import org.opendaylight.mdsal.binding.generator.impl.BindingGeneratorImpl;
 import org.opendaylight.mdsal.binding.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.mdsal.binding.java.api.generator.YangModuleInfoTemplate;
 import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
@@ -50,5 +56,16 @@ public abstract class BaseCompilationTest {
         Collections.sort(types, (o1, o2) -> o2.getName().compareTo(o1.getName()));
         final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
         generator.generateToFile(sourcesOutputDir);
+
+        // Also generate YangModuleInfo
+        for (Module module : context.getModules()) {
+            final YangModuleInfoTemplate template = new YangModuleInfoTemplate(module, context,
+                mod -> Optional.of("fake/" + mod.getName()));
+
+            final File file = new File(GeneratorJavaFile.packageToDirectory(sourcesOutputDir,
+                BindingMapping.getRootPackageName(module.getQNameModule())),
+                BindingMapping.MODULE_INFO_CLASS_NAME + ".java");
+            Files.asCharSink(file, StandardCharsets.UTF_8).write(template.generate());
+        }
     }
 }
index f43415b0d3cf3d62b8bf0e297ade4723e9244f81..fc9b8279630b144d702c3f41640c15454ab61f51 100644 (file)
@@ -36,7 +36,7 @@ public class Bug5151Test extends BaseCompilationTest {
         CompilationTestUtils.testCompilation(sourcesOutputDir, compiledOutputDir);
 
         final Map<String, File> generatedFiles = getFiles(sourcesOutputDir);
-        assertEquals(3, generatedFiles.size());
+        assertEquals(4, generatedFiles.size());
 
         final File fooContainerFile = generatedFiles.get("FooContainer.java");
         assertNotNull(fooContainerFile);
index 533bfdec16b5ad92116611805140a859b0e12bcf..2186d8c2b797afcfdb415e8f5940dc81f9bd4c91 100644 (file)
@@ -37,7 +37,7 @@ public class CascadeUsesCompilationTest extends BaseCompilationTest {
 
         // Test if all sources are generated from module foo
         File parent = new File(sourcesOutputDir, NS_FOO);
-        assertFilesCount(parent, 5);
+        assertFilesCount(parent, 6);
         File fooData = new File(parent, "FooData.java");
         File foo_gr1 = new File(parent, "FooGr1.java");
         File nodes = new File(parent, "Nodes.java");
@@ -49,7 +49,7 @@ public class CascadeUsesCompilationTest extends BaseCompilationTest {
 
         // Test if all sources are generated from module bar
         parent = new File(sourcesOutputDir, NS_BAR);
-        assertFilesCount(parent, 2);
+        assertFilesCount(parent, 3);
         File barGr1 = new File(parent, "BarGr1.java");
         File barGr2 = new File(parent, "BarGr2.java");
         assertTrue(barGr1.exists());
@@ -57,7 +57,7 @@ public class CascadeUsesCompilationTest extends BaseCompilationTest {
 
         // Test if all sources are generated from module baz
         parent = new File(sourcesOutputDir, NS_BAZ);
-        assertFilesCount(parent, 1);
+        assertFilesCount(parent, 2);
         File bazGr1 = new File(parent, "BazGr1.java");
         assertTrue(bazGr1.exists());
 
index 3ede285aba6dca0a1f3864b1143cd035e0144389..6dd0fcef59a8a27df2973cf009abbc4059db45ba 100644 (file)
@@ -73,7 +73,7 @@ public class CompilationTest extends BaseCompilationTest {
         assertTrue(linksBuilder.exists());
         assertTrue(linksKey.exists());
         assertTrue(testData.exists());
-        CompilationTestUtils.assertFilesCount(parent, 6);
+        CompilationTestUtils.assertFilesCount(parent, 7);
 
         parent = new File(sourcesOutputDir, CompilationTestUtils.NS_TEST + CompilationTestUtils.FS + "links");
         final File level = new File(parent, "Level.java");
@@ -138,7 +138,7 @@ public class CompilationTest extends BaseCompilationTest {
         assertTrue(new File(parent, "OpenObject.java").exists());
         assertTrue(new File(parent, "ExplicitRouteObject.java").exists());
         assertTrue(new File(parent, "PathKeySubobject.java").exists());
-        CompilationTestUtils.assertFilesCount(parent, 9);
+        CompilationTestUtils.assertFilesCount(parent, 10);
 
         parent = new File(parent, "object");
         assertTrue(new File(parent, "Nodes.java").exists());
@@ -196,7 +196,7 @@ public class CompilationTest extends BaseCompilationTest {
         assertTrue(new File(parent, "BasicExplicitRouteSubobjects.java").exists());
         assertTrue(new File(parent, "ExplicitRouteSubobjects.java").exists());
         assertTrue(new File(parent, "RouteSubobjects.java").exists());
-        CompilationTestUtils.assertFilesCount(parent, 5);
+        CompilationTestUtils.assertFilesCount(parent, 6);
 
         parent = new File(parent, "route");
         CompilationTestUtils.assertFilesCount(parent, 1);
@@ -243,7 +243,7 @@ public class CompilationTest extends BaseCompilationTest {
         assertTrue(pathAttributes.exists());
         assertTrue(update.exists());
         assertTrue(updateBuilder.exists());
-        CompilationTestUtils.assertFilesCount(parent, 6);
+        CompilationTestUtils.assertFilesCount(parent, 7);
 
         parent = new File(sourcesOutputDir, CompilationTestUtils.NS_FOO + CompilationTestUtils.FS + "path");
         CompilationTestUtils.assertFilesCount(parent, 1);
@@ -269,7 +269,7 @@ public class CompilationTest extends BaseCompilationTest {
         assertTrue(destination.exists());
         assertTrue(pathAttributes1.exists());
         assertTrue(pathAttributes1Builder.exists());
-        CompilationTestUtils.assertFilesCount(parent, 5);
+        CompilationTestUtils.assertFilesCount(parent, 6);
 
         parent = new File(sourcesOutputDir, CompilationTestUtils.NS_BAR + CompilationTestUtils.FS + "destination");
         CompilationTestUtils.assertFilesCount(parent, 2);
@@ -309,7 +309,7 @@ public class CompilationTest extends BaseCompilationTest {
 
         // Test if all sources were generated from 'module baz'
         parent = new File(sourcesOutputDir, CompilationTestUtils.NS_BAZ);
-        CompilationTestUtils.assertFilesCount(parent, 2);
+        CompilationTestUtils.assertFilesCount(parent, 3);
         final File linkstateDestination = new File(parent, "LinkstateDestination.java");
         assertTrue(linkstateDestination.exists());
 
@@ -376,7 +376,7 @@ public class CompilationTest extends BaseCompilationTest {
         assertTrue(new File(parent, "NodesBuilder.java").exists());
         assertTrue(new File(parent, "Alg.java").exists());
         assertTrue(new File(parent, "NodesIdUnionBuilder.java").exists());
-        CompilationTestUtils.assertFilesCount(parent, 5);
+        CompilationTestUtils.assertFilesCount(parent, 6);
 
         // Test if sources are compilable
         CompilationTestUtils.testCompilation(sourcesOutputDir, compiledOutputDir);
@@ -437,13 +437,13 @@ public class CompilationTest extends BaseCompilationTest {
 
         // Test if all sources are generated
         final File fooParent = new File(sourcesOutputDir, CompilationTestUtils.NS_FOO);
-        CompilationTestUtils.assertFilesCount(fooParent, 3);
+        CompilationTestUtils.assertFilesCount(fooParent, 4);
         assertTrue(new File(fooParent, "FooData.java").exists());
         assertTrue(new File(fooParent, "Nodes.java").exists());
         assertTrue(new File(fooParent, "NodesBuilder.java").exists());
 
         final File barParent = new File(sourcesOutputDir, CompilationTestUtils.NS_BAR);
-        CompilationTestUtils.assertFilesCount(barParent, 1);
+        CompilationTestUtils.assertFilesCount(barParent, 2);
         assertTrue(new File(barParent, "IdentityClass.java").exists());
 
         // Test if sources are compilable
index 9d6b66720956a3fb51e2176ba26964470d4e5d9e..5d732f7d2e0d83ffb7cf073c882aad6eb5d0e877 100644 (file)
@@ -42,7 +42,7 @@ public class NestedGroupingCompilationTest extends BaseCompilationTest {
         assertTrue(fooBuilder.exists());
         assertTrue(testData.exists());
         assertTrue(fooDir.exists());
-        assertFilesCount(parent, 4);
+        assertFilesCount(parent, 5);
 
         parent = new File(parent, "foo");
         File bar = new File(parent, "Bar.java");
index fd3af51eee897d2419379122fa161de429ddc2cf..54ee2210aa909bbcdc4494e7a2edc8c71019e80d 100644 (file)
@@ -63,7 +63,7 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         assertTrue(unionExt2.exists());
         assertTrue(unionExt3.exists());
         assertTrue(unionExt4.exists());
-        CompilationTestUtils.assertFilesCount(parent, 33);
+        CompilationTestUtils.assertFilesCount(parent, 34);
 
         // Test if sources are compilable
         CompilationTestUtils.testCompilation(sourcesOutputDir, compiledOutputDir);
index 919d76530663e999ac239ec50ac50deca4f2af4a..7461ec8b428e05efca2c784436f538036f98e32a 100644 (file)
@@ -56,6 +56,7 @@ public final class BindingMapping {
     private static final Splitter DOT_SPLITTER = Splitter.on('.');
 
     public static final String MODULE_INFO_CLASS_NAME = "$YangModuleInfoImpl";
+    public static final String MODULE_INFO_QNAMEOF_METHOD_NAME = "qnameOf";
     public static final String MODEL_BINDING_PROVIDER_CLASS_NAME = "$YangModelBindingProvider";
 
     public static final String RPC_INPUT_SUFFIX = "Input";