Split out JavaFileTemplate 79/68979/3
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 1 Mar 2018 23:23:38 +0000 (00:23 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 2 Mar 2018 00:19:06 +0000 (01:19 +0100)
This is a useful piece with a bit of logic. Separate it out into
Java, where maintenance is easier. This forces us to define operations
on import map, which is always good.

Change-Id: Idf279352c57a96112b235f700ec7e910bf886461
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
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/BuilderTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java [new file with mode: 0644]
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/UnionTemplate.xtend

index 832a436cbd9893db3a08a547408abdf4017eb10c..c02a2d29609d225fbece5b12d02096474d7a0c62 100644 (file)
@@ -14,19 +14,13 @@ import com.google.common.base.Splitter
 import com.google.common.collect.Iterables
 import java.util.Arrays
 import java.util.Collection
-import java.util.HashMap
 import java.util.List
-import java.util.Map
 import java.util.StringTokenizer
 import java.util.regex.Pattern
-import org.opendaylight.mdsal.binding.model.api.ConcreteType
 import org.opendaylight.mdsal.binding.model.api.Constant
 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
-import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
 import org.opendaylight.mdsal.binding.model.api.GeneratedType
 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.YangSourceDefinition.Single
 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Multiple
@@ -39,10 +33,7 @@ import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 import org.opendaylight.yangtools.yang.model.api.SchemaNode
 
-abstract class BaseTemplate {
-    protected val Map<String, String> importMap = new HashMap()
-    protected val GeneratedType type;
-
+abstract class BaseTemplate extends JavaFileTemplate {
     private static final char NEW_LINE = '\n'
     private static val AMP_MATCHER = CharMatcher.is('&')
     private static val NL_MATCHER = CharMatcher.is(NEW_LINE)
@@ -51,47 +42,20 @@ abstract class BaseTemplate {
     private static val NL_SPLITTER = Splitter.on(NL_MATCHER)
     private static val TAIL_COMMENT_PATTERN = Pattern.compile("*/", Pattern.LITERAL);
 
-    new(GeneratedType _type) {
-        if (_type === null) {
-            throw new IllegalArgumentException("Generated type reference cannot be NULL!")
-        }
-        this.type = _type;
+    new(GeneratedType type) {
+        super(type)
     }
 
-    def packageDefinition() '''package «type.packageName»;'''
-
     final public def generate() {
         val _body = body()
         '''
-            «packageDefinition»
-            «imports»
+            package «type.packageName»;
+            «generateImportBlock»
 
             «_body»
         '''.toString
     }
 
-    protected def imports() '''
-        «FOR entry : importMap.entrySet»
-            «IF !hasSamePackage(entry.value) && !isLocalInnerClass(entry.value)»
-                import «entry.value».«entry.key»;
-            «ENDIF»
-        «ENDFOR»
-    '''
-
-    /**
-     * Checks if packages of generated type and imported type is the same
-     *
-     * @param importedTypePackageName the package name of imported type
-     * @return true if the packages are the same false otherwise
-     */
-    final private def boolean hasSamePackage(String importedTypePackageName) {
-        return type.packageName.equals(importedTypePackageName);
-    }
-
-    def isLocalInnerClass(String importedTypePackageName) {
-        return type.fullyQualifiedName.equals(importedTypePackageName);
-    }
-
     protected abstract def CharSequence body();
 
     // Helper patterns
@@ -152,15 +116,6 @@ abstract class BaseTemplate {
         }
     '''
 
-    final protected def importedName(Type intype) {
-        GeneratorUtil.putTypeIntoImports(type, intype, importMap);
-        GeneratorUtil.getExplicitType(type, intype, importMap)
-    }
-
-    final protected def importedName(Class<?> cls) {
-        importedName(Types.typeForClass(cls))
-    }
-
     /**
      * Template method which generates method parameters with their types from <code>parameters</code>.
      *
@@ -450,16 +405,6 @@ abstract class BaseTemplate {
         «ENDIF»
     '''
 
-    def getRestrictions(Type type) {
-        var Restrictions restrictions = null
-        if (type instanceof ConcreteType) {
-            restrictions = type.restrictions
-        } else if (type instanceof GeneratedTransferObject) {
-            restrictions = type.restrictions
-        }
-        return restrictions
-    }
-
     /**
      * Template method which generates method parameters with their types from <code>parameters</code>.
      *
@@ -475,20 +420,6 @@ abstract class BaseTemplate {
         ENDIF
     »'''
 
-    def protected GeneratedProperty findProperty(GeneratedTransferObject gto, String name) {
-        val props = gto.properties
-        for (prop : props) {
-            if (prop.name.equals(name)) {
-                return prop
-            }
-        }
-        val GeneratedTransferObject parent = gto.superType
-        if (parent !== null) {
-            return findProperty(parent, name)
-        }
-        return null
-    }
-
     def protected emitConstant(Constant c) '''
         «IF c.value instanceof QName»
             «val qname = c.value as QName»
index 6113ce93342421af70ff204664a11964858d7947..4f5049915c3dcd856066e1bd182f99c63f194815 100644 (file)
@@ -80,7 +80,7 @@ class BuilderTemplate extends BaseTemplate {
     new(GeneratedType genType) {
         super(genType)
         this.properties = propertiesFromMethods(createMethods)
-        importMap.put(Builder.simpleName, Builder.package.name)
+        addImport(Builder.simpleName, Builder.package.name)
     }
 
     /**
index e732521c94466390419b8a56b9e2643f086efdf6..28f8adaee3c3e2c50f0983510bf5aad23f4cc47d 100644 (file)
@@ -126,11 +126,11 @@ class InterfaceTemplate extends BaseTemplate {
                     «IF innerClass.unionType»
                         «val unionTemplate = new UnionTemplate(innerClass)»
                         «unionTemplate.generateAsInnerClass»
-                        «this.importMap.putAll(unionTemplate.importMap
+                        «addImports(unionTemplate
                     «ELSE»
                         «val classTemplate = new ClassTemplate(innerClass)»
                         «classTemplate.generateAsInnerClass»
-                        «this.importMap.putAll(classTemplate.importMap
+                        «addImports(classTemplate
                     «ENDIF»
 
                 «ENDIF»
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
new file mode 100644 (file)
index 0000000..b0d3c31
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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.mdsal.binding.java.api.generator;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding.model.api.ConcreteType;
+import org.opendaylight.mdsal.binding.model.api.GeneratedProperty;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.Restrictions;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.util.Types;
+
+/**
+ * Base Java file template. Contains a non-null type and imports which the generated code refers to.
+ */
+class JavaFileTemplate {
+    // Hidden to well-define operations
+    private final Map<String, String> importMap = new HashMap<>();
+
+    protected final GeneratedType type;
+
+    JavaFileTemplate(final GeneratedType type) {
+        this.type = requireNonNull(type);
+    }
+
+    final GeneratedProperty findProperty(final GeneratedTransferObject gto, final String name) {
+        final Optional<GeneratedProperty> optProp = gto.getProperties().stream()
+                .filter(prop -> prop.getName().equals(name)).findFirst();
+        if (optProp.isPresent()) {
+            return optProp.get();
+        }
+
+        final GeneratedTransferObject parent = gto.getSuperType();
+        return parent != null ? findProperty(parent, name) : null;
+    }
+
+    static final Restrictions getRestrictions(final Type type) {
+        if (type instanceof ConcreteType) {
+            return ((ConcreteType)type).getRestrictions();
+        }
+        if (type instanceof GeneratedTransferObject) {
+            return ((GeneratedTransferObject)type).getRestrictions();
+        }
+        return null;
+    }
+
+    final String generateImportBlock() {
+        return importMap.entrySet().stream()
+                .filter(e -> isDefaultVisible(e.getValue()))
+                .sorted((e1, e2) -> {
+                    final int cmp = e1.getValue().compareTo(e2.getValue());
+                    return cmp != 0 ? cmp : e1.getKey().compareTo(e2.getKey());
+                })
+                .map(e -> "import " + e.getValue() + "." + e.getKey() + ";\n")
+                .collect(Collectors.joining());
+    }
+
+    final String importedName(final Type intype) {
+        GeneratorUtil.putTypeIntoImports(type, intype, importMap);
+        return GeneratorUtil.getExplicitType(type, intype, importMap);
+    }
+
+    final String importedName(final Class<?> cls) {
+        return importedName(Types.typeForClass(cls));
+    }
+
+    final void addImport(final String className, final String packageName) {
+        importMap.put(className, packageName);
+    }
+
+    final void addImports(final JavaFileTemplate from) {
+        importMap.putAll(from.importMap);
+    }
+
+    // Exposed for BuilderTemplate
+    boolean isLocalInnerClass(final String importedTypePackageName) {
+        return type.getFullyQualifiedName().equals(importedTypePackageName);
+    }
+
+    private boolean isDefaultVisible(final String prefix) {
+        return !hasSamePackage(prefix) || !isLocalInnerClass(prefix);
+    }
+
+    /**
+     * Checks if packages of generated type and imported type is the same
+     *
+     * @param importedTypePackageName the package name of imported type
+     * @return true if the packages are the same false otherwise
+     */
+    private boolean hasSamePackage(final String importedTypePackageName) {
+        return type.getPackageName().equals(importedTypePackageName);
+    }
+}
index fa718d366e4dc4de951903e5ef5d990ce5bd539b..3c7444e52791bfffd526a5981ee42d5173cff3eb 100644 (file)
@@ -29,8 +29,8 @@ class UnionTemplate extends ClassTemplate {
      */
     new(GeneratedTransferObject genType) {
         super(genType)
-        if(isBaseEncodingImportRequired) {
-            this.importMap.put("BaseEncoding","com.google.common.io")
+        if (isBaseEncodingImportRequired) {
+            addImport("BaseEncoding","com.google.common.io")
         }
     }