Bug 1411 #1 BindingGeneratorImpl decomposition - Container schema nodes 72/51472/8
authorMartin Ciglan <mciglan@cisco.com>
Mon, 6 Feb 2017 15:24:16 +0000 (16:24 +0100)
committerMartin Ciglan <mciglan@cisco.com>
Tue, 21 Feb 2017 11:25:02 +0000 (11:25 +0000)
- resolve container schema nodes
from schema context to in-memory generated types
- able to deal with nested containers
- further decomposition done
- further util methods added
- review comments implemented

TODO: JUnit tests - Jakub Toth

Change-Id: Idd7b0140b03c1130c29488a377023cbdacb3ea50
Signed-off-by: Martin Ciglan <mciglan@cisco.com>
12 files changed:
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AugmentToGenType.java
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AuxiliaryGenUtils.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/BindingGeneratorImpl.java
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/ModuleToGenType.java
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/yang/types/TypeProviderImpl.java
binding2/mdsal-binding2-generator-impl/src/main/test/resources/generator/test-cont.yang [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/test/resources/generator/test.yang [new file with mode: 0644]
binding2/mdsal-binding2-generator-util/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/util/BindingGeneratorUtil.java
binding2/mdsal-binding2-maven-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/javav2/maven/api/gen/plugin/CodeGeneratorImpl.java
binding2/mdsal-binding2-util/pom.xml
binding2/mdsal-binding2-util/src/main/java/org/opendaylight/mdsal/binding/javav2/util/BindingMapping.java

index d6790ed8c3f96f212540b7e1af3366c409b8b267..f7735f6d63c40efb5329be85410f03b401c205ea 100644 (file)
@@ -356,7 +356,7 @@ final class AugmentToGenType {
         for (final DataSchemaNode caseNode : augmentedNodes) {
             if (caseNode != null) {
                 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName,
-                        caseNode.getPath());
+                        caseNode.getPath(), null);
                 final GeneratedTypeBuilder caseTypeBuilder = GenHelperUtil.addDefaultInterfaceDefinition(packageName,
                         caseNode, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders);
                 caseTypeBuilder.addImplementsType(targetType);
@@ -399,7 +399,7 @@ final class AugmentToGenType {
                 final Iterable<DataSchemaNode> childNodes = node.getChildNodes();
                 if (childNodes != null) {
                     GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType,
-                            childNodes);
+                            childNodes, genCtx, schemaContext, verboseClassComments, genTypeBuilders);
                 }
                 genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
                 genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, node);
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AuxiliaryGenUtils.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/AuxiliaryGenUtils.java
new file mode 100644 (file)
index 0000000..6670f21
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.javav2.generator.impl;
+
+import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
+import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.BOOLEAN;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import java.util.List;
+import java.util.Map;
+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.util.YangTextTemplate;
+import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
+import org.opendaylight.mdsal.binding.javav2.model.api.Constant;
+import org.opendaylight.mdsal.binding.javav2.model.api.Type;
+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.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+
+/**
+ * Auxiliary util class for {@link GenHelperUtil} class
+ */
+@Beta
+final class AuxiliaryGenUtils {
+
+    private static final Splitter BSDOT_SPLITTER = Splitter.on("\\.");
+    private static final char NEW_LINE = '\n';
+    private static final Pattern UNICODE_CHAR_PATTERN = Pattern.compile("\\\\+u");
+
+    /**
+     * Constant with the concrete name of identifier.
+     */
+    private static final String AUGMENT_IDENTIFIER_NAME = "augment-identifier";
+
+    /**
+     * Constant with the concrete name of namespace.
+     */
+    private static final String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext";
+
+    private AuxiliaryGenUtils() {
+        throw new UnsupportedOperationException("Util class");
+    }
+
+    static void annotateDeprecatedIfNecessary(final Status status, final GeneratedTypeBuilder builder) {
+        if (status == Status.DEPRECATED) {
+            builder.addAnnotation("", "Deprecated");
+        }
+    }
+
+    private static boolean hasBuilderClass(final SchemaNode schemaNode) {
+        if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode ||
+                schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition) {
+            return true;
+        }
+        return false;
+    }
+
+    static Constant qNameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
+                                  final QName name) {
+        return toBuilder.addConstant(Types.typeForClass(QName.class), constantName, name);
+    }
+
+    /**
+     * Created a method signature builder as part of
+     * <code>interfaceBuilder</code>.
+     *
+     * The method signature builder is created for the getter method of
+     * <code>schemaNodeName</code>. Also <code>comment</code> and
+     * <code>returnType</code> information are added to the builder.
+     *
+     * @param interfaceBuilder
+     *            generated type builder for which the getter method should be
+     *            created
+     * @param schemaNodeName
+     *            string with schema node name. The name will be the part of the
+     *            getter method name.
+     * @param comment
+     *            string with comment for the getter method
+     * @param returnType
+     *            type which represents the return type of the getter method
+     * @param status
+     *            status from yang file, for deprecated annotation
+     * @return method signature builder which represents the getter method of
+     *         <code>interfaceBuilder</code>
+     */
+    static MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder,
+                                                  final String schemaNodeName, final String comment, final Type returnType, final Status status) {
+
+        final MethodSignatureBuilder getMethod = interfaceBuilder
+                .addMethod(getterMethodName(schemaNodeName, returnType));
+        if (status == Status.DEPRECATED) {
+            getMethod.addAnnotation("", "Deprecated");
+        }
+        getMethod.setComment(encodeAngleBrackets(comment));
+        getMethod.setReturnType(returnType);
+        return getMethod;
+    }
+
+    /**
+     * Creates the name of the getter method name from <code>localName</code>.
+     *
+     * @param localName
+     *            string with the name of the getter method
+     * @param returnType
+     *            return type
+     * @return string with the name of the getter method for
+     *         <code>methodName</code> in JAVA method format
+     */
+    private static String getterMethodName(final String localName, final Type returnType) {
+        final StringBuilder method = new StringBuilder();
+        if (BOOLEAN.equals(returnType)) {
+            method.append("is");
+        } else {
+            method.append("get");
+        }
+        final String name = BindingMapping.toFirstUpper(BindingMapping.getPropertyName(localName));
+        method.append(name);
+        return method.toString();
+    }
+
+    static String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName,
+                                    final SchemaContext schemaContext, final boolean verboseClassComments) {
+        final StringBuilder sb = new StringBuilder();
+        final String nodeDescription = encodeAngleBrackets(schemaNode.getDescription());
+        final String formattedDescription = YangTextTemplate.formatToParagraph(nodeDescription, 0);
+
+        if (!Strings.isNullOrEmpty(formattedDescription)) {
+            sb.append(formattedDescription);
+            sb.append(NEW_LINE);
+        }
+
+        if (verboseClassComments) {
+            final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode);
+            final StringBuilder linkToBuilderClass = new StringBuilder();
+            final String[] namespace = Iterables.toArray(BSDOT_SPLITTER.split(fullyQualifiedName), String.class);
+            final String className = namespace[namespace.length - 1];
+
+            if (hasBuilderClass(schemaNode)) {
+                linkToBuilderClass.append(className);
+                linkToBuilderClass.append("Builder");
+            }
+
+            sb.append("<p>");
+            sb.append("This class represents the following YANG schema fragment defined in module <b>");
+            sb.append(module.getName());
+            sb.append("</b>");
+            sb.append(NEW_LINE);
+            sb.append("<pre>");
+            sb.append(NEW_LINE);
+            sb.append(encodeAngleBrackets(yangTemplateForNode.render(schemaNode).body()));
+            sb.append("</pre>");
+            sb.append(NEW_LINE);
+            sb.append("The schema path to identify an instance is");
+            sb.append(NEW_LINE);
+            sb.append("<i>");
+            sb.append(YangTextTemplate.formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot()));
+            sb.append("</i>");
+            sb.append(NEW_LINE);
+
+            if (hasBuilderClass(schemaNode)) {
+                sb.append(NEW_LINE);
+                sb.append("<p>To create instances of this class use " + "{@link " + linkToBuilderClass + "}.");
+                sb.append(NEW_LINE);
+                sb.append("@see ");
+                sb.append(linkToBuilderClass);
+                sb.append(NEW_LINE);
+                if (schemaNode instanceof ListSchemaNode) {
+                    final List<QName> keyDef = ((ListSchemaNode)schemaNode).getKeyDefinition();
+                    if (keyDef != null && !keyDef.isEmpty()) {
+                        sb.append("@see ");
+                        sb.append(className);
+                        sb.append("Key");
+                    }
+                    sb.append(NEW_LINE);
+                }
+            }
+        }
+
+        return replaceAllIllegalChars(sb);
+    }
+
+    static String createDescription(final Module module, final boolean verboseClassComments) {
+        final StringBuilder sb = new StringBuilder();
+        final String moduleDescription = encodeAngleBrackets(module.getDescription());
+        final String formattedDescription = YangTextTemplate.formatToParagraph(moduleDescription, 0);
+
+        if (!Strings.isNullOrEmpty(formattedDescription)) {
+            sb.append(formattedDescription);
+            sb.append(NEW_LINE);
+        }
+
+        if (verboseClassComments) {
+            sb.append("<p>");
+            sb.append("This class represents the following YANG schema fragment defined in module <b>");
+            sb.append(module.getName());
+            sb.append("</b>");
+            sb.append(NEW_LINE);
+            sb.append("<pre>");
+            sb.append(NEW_LINE);
+            sb.append(encodeAngleBrackets(yangTemplateForModule.render(module).body()));
+            sb.append("</pre>");
+        }
+
+        return replaceAllIllegalChars(sb);
+    }
+
+    /**
+     * Returns first unique name for the augment generated type builder. The
+     * generated type builder name for augment consists from name of augmented
+     * node and serial number of its augmentation.
+     *
+     * @param builders
+     *            map of builders which were created in the package to which the
+     *            augmentation belongs
+     * @param genTypeName
+     *            string with name of augmented node
+     * @return string with unique name for augmentation builder
+     */
+    static String augGenTypeName(final Map<String, GeneratedTypeBuilder> builders, final String genTypeName) {
+        int index = 1;
+        if (builders != null) {
+            while (builders.containsKey(genTypeName + index)) {
+                index = index + 1;
+            }
+        }
+        return genTypeName + index;
+    }
+
+    /**
+     * @param unknownSchemaNodes unknows schema nodes
+     * @return nodeParameter of UnknownSchemaNode
+     */
+    static String getAugmentIdentifier(final List<UnknownSchemaNode> unknownSchemaNodes) {
+        for (final UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) {
+            final QName nodeType = unknownSchemaNode.getNodeType();
+            if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.getLocalName())
+                    && YANG_EXT_NAMESPACE.equals(nodeType.getNamespace().toString())) {
+                return unknownSchemaNode.getNodeParameter();
+            }
+        }
+        return null;
+    }
+
+    @VisibleForTesting
+    public static String replaceAllIllegalChars(final StringBuilder stringBuilder){
+        final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");
+        return ret.isEmpty() ? "" : ret;
+    }
+}
index 3cd16f81989c9bf40d12b4e8b5a92a87b06861e4..219af4be954c0c10aa7971daac70948592d20669 100644 (file)
@@ -43,6 +43,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * (in JAVA class/interface name format). Inner value represents instance of
      * builder for schema node specified in key part.
      */
+    //TODO: convert it to local variable eventually
     private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders = new HashMap<>();
 
     private Map<Module, ModuleContext> genCtx = new HashMap<>();
@@ -52,12 +53,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
      */
     private TypeProvider typeProvider;
 
-    /**
-     * Holds reference to schema context to resolve data of augmented element
-     * when creating augmentation builder
-     */
-    private SchemaContext schemaContext;
-
     /**
      * Creates a new binding generator v2.
      *
@@ -83,7 +78,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
     public List<Type> generateTypes(SchemaContext context) {
         Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL.");
         Preconditions.checkState(context.getModules() != null, "Schema Context does not contain defined modules.");
-        schemaContext = context;
         typeProvider = new TypeProviderImpl(context);
         final Set<Module> modules = context.getModules();
         return generateTypes(context, modules);
@@ -95,17 +89,18 @@ public class BindingGeneratorImpl implements BindingGenerator {
         Preconditions.checkState(context.getModules() != null, "Schema Context does not contain defined modules.");
         Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL.");
 
-        schemaContext = context;
         typeProvider = new TypeProviderImpl(context);
         final Module[] modulesArray = new Module[context.getModules().size()];
         context.getModules().toArray(modulesArray);
         final List<Module> contextModules = ModuleDependencySort.sort(modulesArray);
+        genTypeBuilders = new HashMap<>();
 
         for (final Module contextModule : contextModules) {
-            genCtx = ModuleToGenType.generate(contextModule, context, typeProvider, verboseClassComments);
+            genCtx = ModuleToGenType.generate(contextModule, genTypeBuilders, context, typeProvider,
+                    verboseClassComments);
         }
         for (final Module contextModule : contextModules) {
-            genCtx = AugmentToGenType.generate(contextModule, schemaContext, genCtx,
+            genCtx = AugmentToGenType.generate(contextModule, context, genCtx,
                     genTypeBuilders, verboseClassComments);
         }
 
index b0ef6d381994bae56d90f31c9d7ce3f8eaa46144..28aef1cc07c2fb9189e6581abd36bfa8378e1fc6 100644 (file)
@@ -8,29 +8,29 @@
 
 package org.opendaylight.mdsal.binding.javav2.generator.impl;
 
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.annotateDeprecatedIfNecessary;
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.augGenTypeName;
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.constructGetter;
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createDescription;
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.getAugmentIdentifier;
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.qNameConstant;
+import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
+
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterables;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 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.util.YangTextTemplate;
-import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
-import org.opendaylight.mdsal.binding.javav2.model.api.Constant;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
 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.spec.base.TreeNode;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
 import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable;
 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -39,38 +39,19 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 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.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 
 /**
- * Helper util class used for generation of types in binding spec v2.
+ * Helper util class used for generation of types in Binding spec v2.
  */
 @Beta
 final class GenHelperUtil {
 
-    private static final Pattern UNICODE_CHAR_PATTERN = Pattern.compile("\\\\+u");
-    private static final Splitter BSDOT_SPLITTER = Splitter.on("\\.");
-    private static final char NEW_LINE = '\n';
-
-    /**
-     * Constant with the concrete name of identifier.
-     */
-    private static final String AUGMENT_IDENTIFIER_NAME = "augment-identifier";
-
-    /**
-     * Constant with the concrete name of namespace.
-     */
-    private static final String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext";
-
     private GenHelperUtil() {
         throw new UnsupportedOperationException("Util class");
     }
@@ -115,7 +96,8 @@ final class GenHelperUtil {
      * @throws IllegalArgumentException
      *             if <code>module</code> is null
      */
-    static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean verboseClassComments) {
+    private static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean
+            verboseClassComments) {
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
         final String packageName = BindingMapping.getRootPackageName(module);
         final String moduleName = BindingMapping.getClassName(module.getName()) + postfix;
@@ -142,21 +124,18 @@ final class GenHelperUtil {
      * @param builder
      *            builder to which are added implemented types according to
      *            <code>dataNodeContainer</code>
-     * @param genCtx
+     * @param genCtx generated context
      * @return generated type builder with all implemented types
      */
     private static GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer,
                           final GeneratedTypeBuilder builder, Map<Module, ModuleContext> genCtx) {
         for (final UsesNode usesNode : dataNodeContainer.getUses()) {
-            if (usesNode.getGroupingPath() != null) {
-                final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath(), genCtx).toInstance();
-                if (genType == null) {
-                    throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "
-                            + builder.getName());
-                }
-
-                builder.addImplementsType(genType);
+            final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath(), genCtx).toInstance();
+            if (genType == null) {
+                throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "
+                    + builder.getName());
             }
+            builder.addImplementsType(genType);
         }
         return builder;
     }
@@ -171,37 +150,6 @@ final class GenHelperUtil {
         return null;
      }
 
-    private static String createDescription(final Module module, final boolean verboseClassComments) {
-        final StringBuilder sb = new StringBuilder();
-        final String moduleDescription = BindingGeneratorUtil.encodeAngleBrackets(module.getDescription());
-        final String formattedDescription = YangTextTemplate.formatToParagraph(moduleDescription, 0);
-
-        if (!Strings.isNullOrEmpty(formattedDescription)) {
-            sb.append(formattedDescription);
-            sb.append(NEW_LINE);
-        }
-
-        if (verboseClassComments) {
-            sb.append("<p>");
-            sb.append("This class represents the following YANG schema fragment defined in module <b>");
-            sb.append(module.getName());
-            sb.append("</b>");
-            sb.append(NEW_LINE);
-            sb.append("<pre>");
-            sb.append(NEW_LINE);
-            sb.append(BindingGeneratorUtil.encodeAngleBrackets(yangTemplateForModule.render(module).body()));
-            sb.append("</pre>");
-        }
-
-        return replaceAllIllegalChars(sb);
-    }
-
-    @VisibleForTesting
-    public static String replaceAllIllegalChars(final StringBuilder stringBuilder){
-        final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");
-        return ret.isEmpty() ? "" : ret;
-    }
-
     /**
      * Adds the methods to <code>typeBuilder</code> which represent subnodes of
      * node for which <code>typeBuilder</code> was created.
@@ -228,18 +176,29 @@ final class GenHelperUtil {
      *         added to it.
      */
     static GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName,
-                          final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final Iterable<DataSchemaNode> schemaNodes) {
+                          final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf,
+                          final Iterable<DataSchemaNode> schemaNodes, Map<Module, ModuleContext> genCtx,
+                          final SchemaContext schemaContext, final boolean verboseClassComments,
+                          Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+
         if (schemaNodes != null && parent != null) {
             for (final DataSchemaNode schemaNode : schemaNodes) {
                 if (!schemaNode.isAugmenting() && !schemaNode.isAddedByUses()) {
-                    //TODO: design decomposition and implement it
-                    //addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module);
+                    addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module, genCtx,
+                            schemaContext, verboseClassComments, genTypeBuilders);
                 }
             }
         }
         return parent;
     }
 
+    static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode
+            schemaNode, final Module module, Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext,
+                                                              final boolean verboseClassComments, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+        return addDefaultInterfaceDefinition(packageName, schemaNode, null, module, genCtx, schemaContext,
+                verboseClassComments, genTypeBuilders);
+    }
+
     static Map<Module, ModuleContext> processUsesAugments(final SchemaContext schemaContext, final
                         DataNodeContainer node, final Module module, Map<Module, ModuleContext> genCtx,  Map<String,
                         Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments) {
@@ -369,50 +328,6 @@ final class GenHelperUtil {
         return typeBuilder;
     }
 
-    /**
-     * @param unknownSchemaNodes
-     * @return nodeParameter of UnknownSchemaNode
-     */
-    private static String getAugmentIdentifier(final List<UnknownSchemaNode> unknownSchemaNodes) {
-        for (final UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) {
-            final QName nodeType = unknownSchemaNode.getNodeType();
-            if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.getLocalName())
-                    && YANG_EXT_NAMESPACE.equals(nodeType.getNamespace().toString())) {
-                return unknownSchemaNode.getNodeParameter();
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns first unique name for the augment generated type builder. The
-     * generated type builder name for augment consists from name of augmented
-     * node and serial number of its augmentation.
-     *
-     * @param builders
-     *            map of builders which were created in the package to which the
-     *            augmentation belongs
-     * @param genTypeName
-     *            string with name of augmented node
-     * @return string with unique name for augmentation builder
-     */
-    private static String augGenTypeName(final Map<String, GeneratedTypeBuilder> builders, final String genTypeName) {
-        int index = 1;
-        if (builders != null) {
-            while (builders.containsKey(genTypeName + index)) {
-                index = index + 1;
-            }
-        }
-        return genTypeName + index;
-    }
-
-    static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode
-            schemaNode, final Module module, Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext,
-            final boolean verboseClassComments, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
-        return addDefaultInterfaceDefinition(packageName, schemaNode, null, module, genCtx, schemaContext,
-                verboseClassComments, genTypeBuilders);
-    }
-
     /**
      * Instantiates generated type builder with <code>packageName</code> and
      * <code>schemaNode</code>.
@@ -434,12 +349,13 @@ final class GenHelperUtil {
      *            schema node for which is created generated type builder
      * @param parent
      *            parent type (can be null)
-     * @param schemaContext
+     * @param schemaContext schema context
      * @return generated type builder <code>schemaNode</code>
      */
     private static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode
             schemaNode, final Type parent, final Module module, Map<Module, ModuleContext> genCtx,
             final SchemaContext schemaContext, final boolean verboseClassComments, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+
         GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, schemaContext, "",
                 verboseClassComments, genTypeBuilders);
         if (parent == null) {
@@ -489,9 +405,9 @@ final class GenHelperUtil {
     private static GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
                        final SchemaContext schemaContext, final String prefix, final boolean verboseClassComments,
                        Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+
         Preconditions.checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
         Preconditions.checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL.");
-        Preconditions.checkArgument(schemaNode.getQName() != null, "QName for Data Schema Node cannot be NULL.");
         final String schemaNodeName = schemaNode.getQName().getLocalName();
         Preconditions.checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL.");
 
@@ -511,7 +427,6 @@ final class GenHelperUtil {
         newType.setSchemaPath((List<QName>) schemaNode.getPath().getPathFromRoot());
         newType.setModuleName(module.getName());
 
-        //FIXME: update genTypeBuilders for callers
         if (!genTypeBuilders.containsKey(packageName)) {
             final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
             builders.put(genTypeName, newType);
@@ -526,84 +441,59 @@ final class GenHelperUtil {
 
     }
 
-    private static Constant qNameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
-                                          final QName name) {
-        return toBuilder.addConstant(Types.typeForClass(QName.class), constantName, name);
-    }
-
-    private static String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName,
-                             final SchemaContext schemaContext, final boolean verboseClassComments) {
-        final StringBuilder sb = new StringBuilder();
-        final String nodeDescription = BindingGeneratorUtil.encodeAngleBrackets(schemaNode.getDescription());
-        final String formattedDescription = YangTextTemplate.formatToParagraph(nodeDescription, 0);
-
-        if (!Strings.isNullOrEmpty(formattedDescription)) {
-            sb.append(formattedDescription);
-            sb.append(NEW_LINE);
-        }
-
-        if (verboseClassComments) {
-            final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode);
-            final StringBuilder linkToBuilderClass = new StringBuilder();
-            final String[] namespace = Iterables.toArray(BSDOT_SPLITTER.split(fullyQualifiedName), String.class);
-            final String className = namespace[namespace.length - 1];
-
-            if (hasBuilderClass(schemaNode)) {
-                linkToBuilderClass.append(className);
-                linkToBuilderClass.append("Builder");
-            }
-
-            sb.append("<p>");
-            sb.append("This class represents the following YANG schema fragment defined in module <b>");
-            sb.append(module.getName());
-            sb.append("</b>");
-            sb.append(NEW_LINE);
-            sb.append("<pre>");
-            sb.append(NEW_LINE);
-            sb.append(BindingGeneratorUtil.encodeAngleBrackets(yangTemplateForNode.render(schemaNode).body()));
-            sb.append("</pre>");
-            sb.append(NEW_LINE);
-            sb.append("The schema path to identify an instance is");
-            sb.append(NEW_LINE);
-            sb.append("<i>");
-            sb.append(YangTextTemplate.formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot()));
-            sb.append("</i>");
-            sb.append(NEW_LINE);
-
-            if (hasBuilderClass(schemaNode)) {
-                sb.append(NEW_LINE);
-                sb.append("<p>To create instances of this class use " + "{@link " + linkToBuilderClass + "}.");
-                sb.append(NEW_LINE);
-                sb.append("@see ");
-                sb.append(linkToBuilderClass);
-                sb.append(NEW_LINE);
-                if (schemaNode instanceof ListSchemaNode) {
-                    final List<QName> keyDef = ((ListSchemaNode)schemaNode).getKeyDefinition();
-                    if (keyDef != null && !keyDef.isEmpty()) {
-                        sb.append("@see ");
-                        sb.append(className);
-                        sb.append("Key");
-                    }
-                    sb.append(NEW_LINE);
-                }
+    private static void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node,
+        final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module,
+        Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean verboseClassComments,
+        Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+        //TODO: implement rest of schema nodes GTO building
+        if (node != null && typeBuilder != null) {
+            if (node instanceof ContainerSchemaNode) {
+                containerToGenType(module, basePackageName, typeBuilder, childOf, (ContainerSchemaNode) node,
+                        schemaContext, verboseClassComments, genCtx, genTypeBuilders);
             }
         }
 
-        return replaceAllIllegalChars(sb);
     }
 
-    private static void annotateDeprecatedIfNecessary(final Status status, final GeneratedTypeBuilder builder) {
-        if (status == Status.DEPRECATED) {
-            builder.addAnnotation("", "Deprecated");
+    private static void containerToGenType(final Module module, final String basePackageName,
+        final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node,
+        final SchemaContext schemaContext, final boolean verboseClassComments, Map<Module, ModuleContext> genCtx,
+        Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+
+        final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node,
+                schemaContext, verboseClassComments, genCtx, genTypeBuilders);
+        if (genType != null) {
+            constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType, node.getStatus());
+            resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes(), genCtx,
+                    schemaContext, verboseClassComments, genTypeBuilders);
         }
     }
 
-    private static boolean hasBuilderClass(final SchemaNode schemaNode) {
-        if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode ||
-                schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition) {
-            return true;
+    private static GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName,
+        final GeneratedTypeBuilder childOf, final DataSchemaNode node, final SchemaContext schemaContext,
+        final boolean verboseClassComments, Map<Module, ModuleContext> genCtx, Map<String, Map<String,
+        GeneratedTypeBuilder>> genTypeBuilders) {
+
+        if (node.isAugmenting() || node.isAddedByUses()) {
+            return null;
+        }
+        final String packageName = packageNameForGeneratedType(basePackageName, node.getPath(), BindingNamespaceType.Data);
+        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module,
+                genCtx, schemaContext, verboseClassComments, genTypeBuilders);
+        genType.addComment(node.getDescription());
+        annotateDeprecatedIfNecessary(node.getStatus(), genType);
+        genType.setDescription(createDescription(node, genType.getFullyQualifiedName(), schemaContext, verboseClassComments));
+        genType.setModuleName(module.getName());
+        genType.setReference(node.getReference());
+        genType.setSchemaPath((List) node.getPath().getPathFromRoot());
+        if (node instanceof DataNodeContainer) {
+            genCtx.get(module).addChildNodeType(node, genType);
+            //TODO: implement groupings to GTO building first
+            // groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings());
+            processUsesAugments(schemaContext, (DataNodeContainer) node, module, genCtx, genTypeBuilders,
+                    verboseClassComments);
         }
-        return false;
+        return genType;
     }
 
 }
index 91034d86ead0b1a2ad5c79f9a5bbf7b3a78cdd0d..d7a3707eaa4f522121be3bebb8d8db13357f9a00 100644 (file)
@@ -30,10 +30,10 @@ final class ModuleToGenType {
         throw new UnsupportedOperationException("Utility class");
     }
 
-    static Map<Module, ModuleContext> generate(final Module module, final SchemaContext schemaContext,
-                                               TypeProvider typeProvider, final boolean verboseClassComments) {
-        Map<Module, ModuleContext> genCtx = new HashMap<>();
+    static Map<Module, ModuleContext> generate(final Module module, Map<String, Map<String, GeneratedTypeBuilder>>
+            genTypeBuilders, final SchemaContext schemaContext, TypeProvider typeProvider, final boolean verboseClassComments) {
 
+        Map<Module, ModuleContext> genCtx = new HashMap<>();
         genCtx.put(module, new ModuleContext());
         genCtx = allTypeDefinitionsToGenTypes(module, genCtx, typeProvider);
 
@@ -44,7 +44,7 @@ final class ModuleToGenType {
             genCtx.get(module).addModuleNode(moduleType);
             final String basePackageName = BindingMapping.getRootPackageName(module);
             GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, moduleType, moduleType, module
-                    .getChildNodes());
+                    .getChildNodes(), genCtx, schemaContext, verboseClassComments, genTypeBuilders);
         }
 
         return genCtx;
index dc0d46a3071f50aa2244a06859da0c836ccbfd2b..7d339795c377b37b7955c2b830f4b217b2605ad7 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
@@ -39,7 +40,17 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     private final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
 
+
+    /**
+     * Map which maps schema paths to JAVA <code>Type</code>.
+     */
+    private final Map<SchemaPath, Type> referencedTypes;
+
+    /**
+     * Map for additional types e.g unions
+     */
     private final Map<Module, Set<Type>> additionalTypes;
+
     /**
      * Creates new instance of class <code>TypeProviderImpl</code>.
      *
@@ -51,6 +62,7 @@ public final class TypeProviderImpl implements TypeProvider {
     public TypeProviderImpl(final SchemaContext schemaContext) {
         this.schemaContext = schemaContext;
         this.genTypeDefsContextMap = new HashMap<>();
+        this.referencedTypes = new HashMap<>();
         this.additionalTypes = new HashMap<>();
     }
 
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/test/resources/generator/test-cont.yang b/binding2/mdsal-binding2-generator-impl/src/main/test/resources/generator/test-cont.yang
new file mode 100644 (file)
index 0000000..85163be
--- /dev/null
@@ -0,0 +1,13 @@
+module test-cont {
+    yang-version 1;
+
+    namespace "urn:test:simple:test:cont";
+    prefix test-cont;
+    organization "test.cont.org";
+    revision "2017-02-17";
+
+    container my-cont {
+        container my-inner-cont {
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/test/resources/generator/test.yang b/binding2/mdsal-binding2-generator-impl/src/main/test/resources/generator/test.yang
new file mode 100644 (file)
index 0000000..763e254
--- /dev/null
@@ -0,0 +1,11 @@
+module test {
+    yang-version 1;
+
+    namespace "urn:test:simple:test";
+    prefix test;
+    organization "test.org";
+    revision "2017-02-06";
+
+    container my-cont {
+    }
+}
\ No newline at end of file
index 23a1ab1723b1ef5be956a0d15cf524c817e9c603..54f67cecdb19642e4bd53e25199a6fa97d597f38 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.CharMatcher;
 import com.google.common.collect.Iterables;
 import java.util.Iterator;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -51,15 +52,24 @@ public final class BindingGeneratorUtil {
      * @return string with valid JAVA package name
      * @throws NullPointerException if any of the arguments are null
      */
-    public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
+    public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath, final
+        BindingNamespaceType namespaceType) {
+
         final Iterable<QName> pathTowardsRoot = schemaPath.getPathTowardsRoot();
         final Iterable<QName> pathFromRoot = schemaPath.getPathFromRoot();
         final int size = Iterables.size(pathTowardsRoot) - 1;
         if (size <= 0) {
+            if (namespaceType != null) {
+                final StringBuilder sb = new StringBuilder();
+                sb.append(basePackageName)
+                  .append('.')
+                  .append(namespaceType.getPackagePrefix());
+                return sb.toString();
+            }
             return basePackageName;
         }
 
-        return generateNormalizedPackageName(basePackageName, pathFromRoot, size);
+        return generateNormalizedPackageName(basePackageName, pathFromRoot, size, namespaceType);
     }
 
     /**
@@ -90,19 +100,22 @@ public final class BindingGeneratorUtil {
             return basePackageName;
         }
 
-        return generateNormalizedPackageName(basePackageName, pathFromRoot, size);
+        return generateNormalizedPackageName(basePackageName, pathFromRoot, size, null);
     }
 
-
-    private static String generateNormalizedPackageName(final String base, final Iterable<QName> path, final int size) {
+    private static String generateNormalizedPackageName(final String base, final Iterable<QName> path, final int
+            size, BindingNamespaceType namespaceType) {
         final StringBuilder builder = new StringBuilder(base);
+        if (namespaceType != null) {
+            builder.append('.').append(namespaceType.getPackagePrefix());
+        }
         final Iterator<QName> iterator = path.iterator();
         for (int i = 0; i < size; ++i) {
             builder.append('.');
             String nodeLocalName = iterator.next().getLocalName();
-            //FIXME: colon or dash in identifier?
             builder.append(nodeLocalName);
         }
+
         return BindingMapping.normalizePackageName(builder.toString());
     }
 
index a881b82fecaecf7f595d64b81a9949ab09974948..bffcbb011f003c5536bcb016339c8cf4a4a98460 100644 (file)
@@ -18,6 +18,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.maven.project.MavenProject;
+import org.opendaylight.mdsal.binding.javav2.generator.api.BindingGenerator;
+import org.opendaylight.mdsal.binding.javav2.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.mdsal.binding.javav2.model.api.Type;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
@@ -55,6 +58,9 @@ public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContext
     @Override
     public Collection<File> generateSources(SchemaContext context, File outputBaseDir, Set<Module> currentModules) throws IOException {
 
+        final BindingGenerator bindingGenerator = new BindingGeneratorImpl(true);
+        final List<Type> types = bindingGenerator.generateTypes(context, currentModules);
+
         List<File> result = new ArrayList<>();
         return result;
     }
index d58e80334a0847c4716b22c43eddb62f84cbebab..b732d7e2ebe1fe125ccdf3e419d6ae981589f072 100644 (file)
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.mdsal</groupId>
+                <artifactId>mdsal-artifacts</artifactId>
+                <version>2.2.0-SNAPSHOT</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-model-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding2-spec</artifactId>
+        </dependency>
     </dependencies>
 
     <!--
index e451014a3aac127b68fed1d9fc866868d569331b..217eff14d2b4a7a8773809eae6e6e38d089aad8e 100644 (file)
@@ -19,7 +19,7 @@ import java.text.SimpleDateFormat;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import org.opendaylight.yangtools.concepts.SemVer;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
 /**
@@ -36,7 +36,11 @@ public final class BindingMapping {
             "true", "try", "void", "volatile", "while");
 
     public static final String QNAME_STATIC_FIELD_NAME = "QNAME";
-    public static final String PACKAGE_PREFIX = "org.opendaylight.yang.gen.v2";
+
+    /**
+     * Package prefix for Binding v2 generated Java code structures
+     */
+    public static final String PACKAGE_PREFIX = "org.opendaylight.mdsal.gen.javav2";
 
     private static final Splitter DOT_SPLITTER = Splitter.on('.');
     private static final Interner<String> PACKAGE_INTERNER = Interners.newWeakInterner();
@@ -105,16 +109,30 @@ public final class BindingMapping {
             packageNameBuilder.append('.');
         }
 
-        final SemVer semVer = module.getSemanticVersion();
-        if (semVer != null) {
-            packageNameBuilder.append(semVer.toString());
-        } else {
-            packageNameBuilder.append("rev");
-            packageNameBuilder.append(PACKAGE_DATE_FORMAT.get().format(module.getRevision()));
-        }
-        return normalizePackageName(packageNameBuilder.toString());
+        //TODO: per yangtools dev, semantic version not used yet
+//        final SemVer semVer = module.getSemanticVersion();
+//        if (semVer != null) {
+//            packageNameBuilder.append(semVer.toString());
+//        } else {
+//            packageNameBuilder.append("rev");
+//            packageNameBuilder.append(PACKAGE_DATE_FORMAT.get().format(module.getRevision()));
+//        }
+
+        packageNameBuilder.append("rev");
+        packageNameBuilder.append(PACKAGE_DATE_FORMAT.get().format(module.getRevision()));
+
+        //seems to be duplicate call, because normalizing is run again on full packagename + localName
+        //return normalizePackageName(packageNameBuilder.toString(), null);
+        return packageNameBuilder.toString();
     }
 
+    /**
+     * This method normalizes input package name to become valid package identifier
+     * and appends Binding v2 specific namespace type
+     *
+     * @param packageName package name
+     * @return normalized package name
+     */
     public static String normalizePackageName(final String packageName) {
         if (packageName == null) {
             return null;
@@ -130,10 +148,15 @@ public final class BindingMapping {
                 builder.append('.');
             }
 
-            //FIXME: don't use underscore in v2
+            //TODO: incorporate use of PackageNameNormalizer (impl in progress)
+            //TODO: to not to worry about various characters in identifiers,
+            //TODO: relying on https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html
+
+            //FIXME: delete this custom check when naming convention patch above is merged
             if (Character.isDigit(p.charAt(0)) || BindingMapping.JAVA_RESERVED_WORDS.contains(p)) {
                 builder.append('_');
             }
+
             builder.append(p);
         }
 
@@ -141,6 +164,11 @@ public final class BindingMapping {
         return PACKAGE_INTERNER.intern(builder.toString());
     }
 
+    /**
+     * Prepares valid Java class name
+     * @param localName
+     * @return class name
+     */
     public static String getClassName(final String localName) {
         Preconditions.checkArgument(localName != null, "Name should not be null.");
         return toFirstUpper(toCamelCase(localName));
@@ -193,6 +221,44 @@ public final class BindingMapping {
         return s.substring(0, 1).toUpperCase() + s.substring(1);
     }
 
+    /**
+     * Prepares Java property name for method getter code generation
+     * @param yangIdentifier given YANG element local name
+     * @return property name
+     */
+    public static String getPropertyName(final String yangIdentifier) {
+        final String potential = toFirstLower(toCamelCase(yangIdentifier));
+        if ("class".equals(potential)) {
+            return "xmlClass";
+        }
+        return potential;
+    }
+
+    /**
+     * Returns the {@link String} {@code s} with an
+     * {@link Character#isLowerCase(char) lower case} first character. This
+     * function is null-safe.
+     *
+     * @param s
+     *            the string that should get an lower case first character. May
+     *            be <code>null</code>.
+     * @return the {@link String} {@code s} with an lower case first character
+     *         or <code>null</code> if the input {@link String} {@code s} was
+     *         <code>null</code>.
+     */
+    private static String toFirstLower(final String s) {
+        if (s == null || s.length() == 0) {
+            return s;
+        }
+        if (Character.isLowerCase(s.charAt(0))) {
+            return s;
+        }
+        if (s.length() == 1) {
+            return s.toLowerCase();
+        }
+        return s.substring(0, 1).toLowerCase() + s.substring(1);
+    }
+
     //TODO: further implementation of static util methods...
 
 }