Use YangSnippetCleaner in implemetation + test with yangs
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / AuxiliaryGenUtils.java
index c5977ae4801b84fb03307f2bb369a274f5c31303..e30c25bbb5a40a427f04aea3b70387cc116b38c9 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.mdsal.binding.javav2.generator.impl;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.BOOLEAN;
 
@@ -18,17 +19,20 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 import org.opendaylight.mdsal.binding.javav2.generator.impl.txt.yangTemplateForModule;
 import org.opendaylight.mdsal.binding.javav2.generator.impl.txt.yangTemplateForNode;
+import org.opendaylight.mdsal.binding.javav2.generator.impl.txt.yangTemplateForNodes;
 import org.opendaylight.mdsal.binding.javav2.generator.impl.util.YangTextTemplate;
 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
-import org.opendaylight.mdsal.binding.javav2.generator.util.NonJavaCharsConverter;
+import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
+import org.opendaylight.mdsal.binding.javav2.generator.util.YangSnippetCleaner;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
@@ -40,7 +44,7 @@ import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOB
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder;
-import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -155,10 +159,9 @@ final class AuxiliaryGenUtils {
         } else {
             method.append("get");
         }
-        final String name = BindingMapping.toFirstUpper(NonJavaCharsConverter.convertIdentifier(BindingMapping.getPropertyName
-                (localName), JavaIdentifier.METHOD));
-        method.append(name);
-        return method.toString();
+        // underscore used as separator for distinction of method parts in convertIdentifier()
+        method.append('_').append(localName);
+        return JavaIdentifierNormalizer.normalizeSpecificIdentifier(method.toString(), JavaIdentifier.METHOD);
     }
 
     static String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName,
@@ -190,7 +193,8 @@ final class AuxiliaryGenUtils {
             sb.append(NEW_LINE);
             sb.append("<pre>");
             sb.append(NEW_LINE);
-            sb.append(encodeAngleBrackets(yangTemplateForNode.render(schemaNode).body()));
+            String formedYang = YangSnippetCleaner.clean(yangTemplateForNode.render(schemaNode, module).body());
+            sb.append(encodeAngleBrackets(formedYang));
             sb.append("</pre>");
             sb.append(NEW_LINE);
             sb.append("The schema path to identify an instance is");
@@ -240,13 +244,44 @@ final class AuxiliaryGenUtils {
             sb.append(NEW_LINE);
             sb.append("<pre>");
             sb.append(NEW_LINE);
-            sb.append(encodeAngleBrackets(yangTemplateForModule.render(module).body()));
+            String formedYang = YangSnippetCleaner.clean(yangTemplateForModule.render(module).body());
+            sb.append(encodeAngleBrackets(formedYang));
             sb.append("</pre>");
         }
 
         return replaceAllIllegalChars(sb);
     }
 
+    static String createDescription(final Set<? extends SchemaNode> schemaNodes, final Module module, final
+            boolean verboseClassComments) {
+        final StringBuilder sb = new StringBuilder();
+
+        if (!isNullOrEmpty(schemaNodes)) {
+            final SchemaNode node = schemaNodes.iterator().next();
+
+            if (node instanceof RpcDefinition) {
+                sb.append("Interface for implementing the following YANG RPCs defined in module <b>" + module.getName() + "</b>");
+            } else if (node instanceof NotificationDefinition) {
+                sb.append("Interface for receiving the following YANG notifications defined in module <b>" + module.getName() + "</b>");
+            }
+        }
+        sb.append(NEW_LINE);
+
+        if (verboseClassComments) {
+            sb.append("<pre>");
+            sb.append(NEW_LINE);
+            sb.append(encodeAngleBrackets(yangTemplateForNodes.render(schemaNodes, module).body()));
+            sb.append("</pre>");
+            sb.append(NEW_LINE);
+        }
+
+        return replaceAllIllegalChars(sb);
+    }
+
+    private static boolean isNullOrEmpty(final Collection<?> list) {
+        return list == null || list.isEmpty();
+    }
+
     /**
      * Returns first unique name for the augment generated type builder. The
      * generated type builder name for augment consists from name of augmented
@@ -306,12 +341,11 @@ final class AuxiliaryGenUtils {
     static EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final QName enumName,
         final Map<Module, ModuleContext> genCtx, final GeneratedTypeBuilder typeBuilder, final Module module) {
         if (enumTypeDef != null && typeBuilder != null && enumTypeDef.getQName().getLocalName() != null) {
-            final String enumerationName = BindingMapping.getClassName(enumName);
-            final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
+            final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumName.getLocalName());
             final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription());
             enumBuilder.setDescription(enumTypedefDescription);
             enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
-            ModuleContext ctx = genCtx.get(module);
+            final ModuleContext ctx = genCtx.get(module);
             ctx.addInnerTypedefType(enumTypeDef.getPath(), enumBuilder);
             return enumBuilder;
         }
@@ -343,7 +377,7 @@ final class AuxiliaryGenUtils {
     static GeneratedTOBuilder addTOToTypeBuilder(final TypeDefinition<?> typeDef, final GeneratedTypeBuilder
             typeBuilder, final DataSchemaNode leaf, final Module parentModule, final TypeProvider typeProvider,
             final SchemaContext schemaContext) {
-        final String classNameFromLeaf = BindingMapping.getClassName(leaf.getQName());
+        final String classNameFromLeaf = leaf.getQName().getLocalName();
         final List<GeneratedTOBuilder> genTOBuilders = new ArrayList<>();
         final String packageName = typeBuilder.getFullyQualifiedName();
         if (typeDef instanceof UnionTypeDefinition) {
@@ -381,6 +415,7 @@ final class AuxiliaryGenUtils {
 
     }
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     static Type createReturnTypeForUnion(final GeneratedTOBuilder genTOBuilder, final TypeDefinition<?> typeDef,
             final GeneratedTypeBuilder typeBuilder, final Module parentModule, final TypeProvider typeProvider) {
         final GeneratedTOBuilderImpl returnType = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
@@ -443,6 +478,76 @@ final class AuxiliaryGenUtils {
         return false;
     }
 
+    /**
+     * Generates for the <code>list</code> which contains any list keys special
+     * generated TO builder.
+     *
+     * @param packageName
+     *            string with package name to which the list belongs
+     * @param list
+     *            schema node of list
+     * @return generated TO builder which represents the keys of the
+     *         <code>list</code> or empty TO builder if <code>list</code> is null or list of
+     *         key definitions is null or empty.
+     */
+    static GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list) {
+        GeneratedTOBuilder genTOBuilder = null;
+        if ((list.getKeyDefinition() != null) && (!list.getKeyDefinition().isEmpty())) {
+            // underscore used as separator for distinction of class name parts
+            final String genTOName =
+                    new StringBuilder(list.getQName().getLocalName()).append('_').append(BindingNamespaceType.Key)
+                            .toString();
+            genTOBuilder =
+                    new GeneratedTOBuilderImpl(new StringBuilder(packageName).append(".wrapper").toString(), genTOName);
+        }
+        return genTOBuilder;
+    }
+
+    /**
+     * Converts <code>leaf</code> schema node to property of generated TO
+     * builder.
+     *
+     * @param toBuilder
+     *            generated TO builder to which is <code>leaf</code> added as
+     *            property
+     * @param leaf
+     *            leaf schema node which is added to <code>toBuilder</code> as
+     *            property
+     * @param returnType
+     *            property type
+     * @param isReadOnly
+     *            boolean value which says if leaf property is|isn't read only
+     * @return boolean value
+     *         <ul>
+     *         <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
+     *         name equals null or if leaf is added by <i>uses</i>.</li>
+     *         <li>true - other cases</li>
+     *         </ul>
+     */
+    static boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,
+        final Type returnType, final boolean isReadOnly) {
+
+        if (returnType == null) {
+            return false;
+        }
+        final String leafName = leaf.getQName().getLocalName();
+        final String leafDesc = encodeAngleBrackets(leaf.getDescription());
+        final GeneratedPropertyBuilder propBuilder =
+                toBuilder.addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(leafName, JavaIdentifier.METHOD));
+        propBuilder.setReadOnly(isReadOnly);
+        propBuilder.setReturnType(returnType);
+        propBuilder.setComment(leafDesc);
+        toBuilder.addEqualsIdentity(propBuilder);
+        toBuilder.addHashIdentity(propBuilder);
+        toBuilder.addToStringProperty(propBuilder);
+        return true;
+    }
+
+    static void checkModuleAndModuleName(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkArgument(module.getName() != null, "Module name cannot be NULL.");
+    }
+
     @VisibleForTesting
     public static String replaceAllIllegalChars(final StringBuilder stringBuilder){
         final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");