Bug 1411-4: MDSAL Binding2 Generator Impl 89/45089/1
authorMartin Ciglan <mciglan@cisco.com>
Thu, 16 Jun 2016 12:27:11 +0000 (14:27 +0200)
committerRobert Varga <nite@hq.sk>
Fri, 2 Sep 2016 15:14:00 +0000 (15:14 +0000)
- BindingGeneratorImpl decomposition proposal
- introduction for Twirl templates for Yang Snippets generation
- rather more templates, less logic, more content
- JUnit test - to be finished
- added several twirl templates for YANG
- review comments fixed
- apply https://git.opendaylight.org/gerrit/#/c/44939/ for spec v2

Change-Id: I79cb7e9c0d41c23408949dd5d4d40d572cc86652
Signed-off-by: Martin Ciglan <mciglan@cisco.com>
Signed-off-by: Filip Gregor <fgregor@cisco.com>
(cherry picked from commit a5e2366bfdf89f9b859b0a7ecfe4bdf4b4cc423e)

29 files changed:
binding2/mdsal-binding2-generator-impl/pom.xml
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/AugmentToGenType.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/BindingGeneratorImpl.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/GenHelperUtil.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/GeneratedClassLoadingStrategy.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/ModuleContext.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/ModuleToGenType.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/util/YangTextTemplate.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/yang/types/TypeProviderImpl.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/test/java/org/opendaylight/mdsal/binding2/TestUtils.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/test/java/org/opendaylight/mdsal/binding2/YangTemplateTest.java [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/test/resources/yang-template/yang-template-import.yang [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/test/resources/yang-template/yang-template-test.yang [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForModule.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForNode.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForNodes.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteAugments.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteDataSchemaNode.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteDataSchemaNodes.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteExtension.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteFeature.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteGroupingDef.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteGroupingDefs.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteIdentity.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteNotification.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteRPC.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUnknownSchemaNode.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUnknownSchemaNodes.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUsesNodes.scala.txt [new file with mode: 0644]

index 71ed8e5cd28243b5d65f24dcda723b6f3c011b4e..9a98a75c18e676233cef2e135d5a7b0a4966f764 100644 (file)
                 </executions>
             </plugin>
 
-            <!-- Scala -> compile Scala files, in this example generated from Twirl -->
+            <!-- Scala -> compile Scala files generated from Twirl -->
             <plugin>
                 <groupId>net.alchim31.maven</groupId>
                 <artifactId>scala-maven-plugin</artifactId>
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/AugmentToGenType.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/AugmentToGenType.java
new file mode 100644 (file)
index 0000000..6b6e4fa
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2016 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.binding2.generator.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static org.opendaylight.mdsal.binding2.generator.impl.GenHelperUtil.findCaseByPath;
+import static org.opendaylight.mdsal.binding2.generator.impl.GenHelperUtil.findChildNodeByPath;
+import static org.opendaylight.mdsal.binding2.generator.impl.GenHelperUtil.processUsesAugments;
+import static org.opendaylight.mdsal.binding2.generator.impl.GenHelperUtil.resolveDataSchemaNodes;
+import static org.opendaylight.mdsal.binding2.generator.util.Binding2GeneratorUtil.packageNameForAugmentedGeneratedType;
+import static org.opendaylight.mdsal.binding2.generator.util.Binding2GeneratorUtil.packageNameForGeneratedType;
+import static org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.getRootPackageName;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.mdsal.binding2.generator.util.ReferencedTypeImpl;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+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.UsesNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+
+@Beta
+final class AugmentToGenType {
+
+    private AugmentToGenType() {
+        throw new UnsupportedOperationException("Utility class");
+    }
+
+    /**
+     * Comparator based on augment target path.
+     */
+    private static final Comparator<AugmentationSchema> AUGMENT_COMP = (o1, o2) -> {
+        final Iterator<QName> thisIt = o1.getTargetPath().getPathFromRoot().iterator();
+        final Iterator<QName> otherIt = o2.getTargetPath().getPathFromRoot().iterator();
+
+        while (thisIt.hasNext()) {
+            if (!otherIt.hasNext()) {
+                return 1;
+            }
+
+            final int comp = thisIt.next().compareTo(otherIt.next());
+            if (comp != 0) {
+                return comp;
+            }
+        }
+
+        return otherIt.hasNext() ? -1 : 0;
+    };
+
+    /**
+     * Converts all <b>augmentation</b> of the module to the list
+     * <code>Type</code> objects.
+     *
+     * @param module
+     *            module from which is obtained list of all augmentation objects
+     *            to iterate over them
+     * @param schemaContext
+     * @param genCtx
+     * @param genTypeBuilders
+     *
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if the module is null</li>
+     *             <li>if the name of module is null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if set of augmentations from module is null
+     */
+    static Map<Module, ModuleContext> generate(final Module module, final SchemaContext schemaContext, Map<Module,
+            ModuleContext> genCtx, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+            final boolean verboseClassComments) {
+
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkArgument(module.getName() != null, "Module name cannot be NULL.");
+        checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
+
+        final String basePackageName = getRootPackageName(module);
+        final List<AugmentationSchema> augmentations = resolveAugmentations(module);
+        for (final AugmentationSchema augment : augmentations) {
+            genCtx = augmentationToGenTypes(basePackageName, augment, module, schemaContext, verboseClassComments,
+                    genCtx, genTypeBuilders);
+        }
+        return genCtx;
+    }
+
+    /**
+     * Returns list of <code>AugmentationSchema</code> objects. The objects are
+     * sorted according to the length of their target path from the shortest to
+     * the longest.
+     *
+     * @param module
+     *            module from which is obtained list of all augmentation objects
+     * @return list of sorted <code>AugmentationSchema</code> objects obtained
+     *         from <code>module</code>
+     * @throws IllegalArgumentException
+     *             if module is null
+     * @throws IllegalStateException
+     *             if set of module augmentations is null
+     */
+    private static List<AugmentationSchema> resolveAugmentations(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
+
+        final Set<AugmentationSchema> augmentations = module.getAugmentations();
+        final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
+        Collections.sort(sortedAugmentations, AUGMENT_COMP);
+
+        return sortedAugmentations;
+    }
+
+    /**
+     * Converts <code>augSchema</code> to list of <code>Type</code> which
+     * contains generated type for augmentation. In addition there are also
+     * generated types for all containers, list and choices which are child of
+     * <code>augSchema</code> node or a generated types for cases are added if
+     * augmented node is choice.
+     *
+     * @param augmentPackageName
+     *            string with the name of the package to which the augmentation
+     *            belongs
+     * @param augSchema
+     *            AugmentationSchema which is contains data about augmentation
+     *            (target path, childs...)
+     * @param module
+     *            current module
+     * @param schemaContext
+     * @param genCtx
+     * @param genTypeBuilders
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>augmentPackageName</code> equals null</li>
+     *             <li>if <code>augSchema</code> equals null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if augment target path is null
+     * @return
+     */
+    private static Map<Module, ModuleContext> augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema,
+            final Module module, final SchemaContext schemaContext, final boolean verboseClassComments,
+            Map<Module, ModuleContext> genCtx, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+
+        Map<Module, ModuleContext> generatedCtx;
+        checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
+        checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
+        checkState(augSchema.getTargetPath() != null,
+                "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+
+        generatedCtx = processUsesAugments(schemaContext, augSchema, module, genCtx, genTypeBuilders, verboseClassComments);
+        final SchemaPath targetPath = augSchema.getTargetPath();
+        SchemaNode targetSchemaNode;
+
+        targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
+        if (targetSchemaNode instanceof DataSchemaNode && ((DataSchemaNode) targetSchemaNode).isAddedByUses()) {
+            if (targetSchemaNode instanceof DerivableSchemaNode) {
+                targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull();
+            }
+            if (targetSchemaNode == null) {
+                throw new IllegalStateException("Failed to find target node from grouping in augmentation " + augSchema
+                        + " in module " + module.getName());
+            }
+        }
+        if (targetSchemaNode == null) {
+            throw new IllegalArgumentException("augment target not found: " + targetPath);
+        }
+
+        GeneratedTypeBuilder targetTypeBuilder = findChildNodeByPath(targetSchemaNode.getPath(), generatedCtx);
+        if (targetTypeBuilder == null) {
+            targetTypeBuilder = findCaseByPath(targetSchemaNode.getPath(), generatedCtx);
+        }
+        if (targetTypeBuilder == null) {
+            throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
+        }
+
+        if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
+            final String packageName = augmentPackageName;
+            final Type targetType = new ReferencedTypeImpl(targetTypeBuilder.getPackageName(),
+                    targetTypeBuilder.getName());
+            generatedCtx = GenHelperUtil.addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName, targetType,
+                    augSchema, genTypeBuilders, generatedCtx);
+            return generatedCtx;
+
+        } else {
+            generatedCtx = generateTypesFromAugmentedChoiceCases(schemaContext, module, augmentPackageName,
+                    targetTypeBuilder.toInstance(), (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(),
+                    null, generatedCtx, verboseClassComments, genTypeBuilders);
+            return generatedCtx;
+        }
+    }
+
+    public static Map<Module, ModuleContext> usesAugmentationToGenTypes(final SchemaContext schemaContext, final String
+                        augmentPackageName, final AugmentationSchema augSchema, final Module module, final UsesNode usesNode, final DataNodeContainer
+                        usesNodeParent, Map<Module, ModuleContext> genCtx,
+                        Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+                        final boolean verboseClassComments) {
+
+        Map<Module, ModuleContext> generatedCtx;
+        checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
+        checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
+        checkState(augSchema.getTargetPath() != null,
+                "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+
+        generatedCtx = processUsesAugments(schemaContext, augSchema, module, genCtx, genTypeBuilders, verboseClassComments);
+        final SchemaPath targetPath = augSchema.getTargetPath();
+        final SchemaNode targetSchemaNode = findOriginalTargetFromGrouping(schemaContext, targetPath, usesNode);
+        if (targetSchemaNode == null) {
+            throw new IllegalArgumentException("augment target not found: " + targetPath);
+        }
+
+        GeneratedTypeBuilder targetTypeBuilder = findChildNodeByPath(targetSchemaNode.getPath(), generatedCtx);
+        if (targetTypeBuilder == null) {
+            targetTypeBuilder = findCaseByPath(targetSchemaNode.getPath(), generatedCtx);
+        }
+        if (targetTypeBuilder == null) {
+            throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
+        }
+
+        if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
+            String packageName = augmentPackageName;
+            if (usesNodeParent instanceof SchemaNode) {
+                packageName = packageNameForAugmentedGeneratedType(augmentPackageName, ((SchemaNode) usesNodeParent).getPath());
+            }
+            generatedCtx = GenHelperUtil.addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
+                    targetTypeBuilder.toInstance(), augSchema, genTypeBuilders, generatedCtx);
+            return generatedCtx;
+        } else {
+            generatedCtx = generateTypesFromAugmentedChoiceCases(schemaContext, module, augmentPackageName,
+                    targetTypeBuilder.toInstance(), (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(),
+                    usesNodeParent, generatedCtx, verboseClassComments, genTypeBuilders);
+            return generatedCtx;
+        }
+    }
+
+    /**
+     * Convenient method to find node added by uses statement.
+     * @param schemaContext
+     * @param targetPath
+     *            node path
+     * @param parentUsesNode
+     *            parent of uses node
+     * @return node from its original location in grouping
+     */
+    private static DataSchemaNode findOriginalTargetFromGrouping(final SchemaContext schemaContext, final SchemaPath targetPath,
+                                          final UsesNode parentUsesNode) {
+        final SchemaNode targetGrouping = SchemaContextUtil.findNodeInSchemaContext(schemaContext, parentUsesNode
+                .getGroupingPath()
+                .getPathFromRoot());
+        if (!(targetGrouping instanceof GroupingDefinition)) {
+            throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
+        }
+
+        final GroupingDefinition grouping = (GroupingDefinition) targetGrouping;
+        SchemaNode result = grouping;
+        for (final QName node : targetPath.getPathFromRoot()) {
+            if (result instanceof DataNodeContainer) {
+                final QName resultNode = QName.create(result.getQName().getModule(), node.getLocalName());
+                result = ((DataNodeContainer) result).getDataChildByName(resultNode);
+            } else if (result instanceof ChoiceSchemaNode) {
+                result = ((ChoiceSchemaNode) result).getCaseNodeByName(node.getLocalName());
+            }
+        }
+        if (result == null) {
+            return null;
+        }
+
+        if (result instanceof DerivableSchemaNode) {
+            DerivableSchemaNode castedResult = (DerivableSchemaNode) result;
+            Optional<? extends SchemaNode> originalNode = castedResult
+                    .getOriginal();
+            if (castedResult.isAddedByUses() && originalNode.isPresent()) {
+                result = originalNode.get();
+            }
+        }
+
+        if (result instanceof DataSchemaNode) {
+            DataSchemaNode resultDataSchemaNode = (DataSchemaNode) result;
+            if (resultDataSchemaNode.isAddedByUses()) {
+                // The original node is required, but we have only the copy of
+                // the original node.
+                // Maybe this indicates a bug in Yang parser.
+                throw new IllegalStateException(
+                        "Failed to generate code for augment in "
+                                + parentUsesNode);
+            } else {
+                return resultDataSchemaNode;
+            }
+        } else {
+            throw new IllegalStateException(
+                    "Target node of uses-augment statement must be DataSchemaNode. Failed to generate code for augment in "
+                            + parentUsesNode);
+        }
+    }
+
+    /**
+     * Generates list of generated types for all the cases of a choice which are
+     * added to the choice through the augment.
+     *
+     * @param schemaContext
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string contains name of package to which augment belongs. If
+     *            an augmented choice is from an other package (pcg1) than an
+     *            augmenting choice (pcg2) then case's of the augmenting choice
+     *            will belong to pcg2.
+     * @param targetType
+     *            Type which represents target choice
+     * @param targetNode
+     *            node which represents target choice
+     * @param augmentedNodes
+     *            set of choice case nodes for which is checked if are/aren't
+     *            added to choice through augmentation
+     * @return list of generated types which represents augmented cases of
+     *         choice <code>refChoiceType</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>basePackageName</code> is null</li>
+     *             <li>if <code>targetType</code> is null</li>
+     *             <li>if <code>augmentedNodes</code> is null</li>
+     *             </ul>
+     */
+    private static Map<Module, ModuleContext> generateTypesFromAugmentedChoiceCases(final SchemaContext schemaContext, final Module module,
+                          final String basePackageName, final Type targetType, final ChoiceSchemaNode targetNode,
+                          final Iterable<DataSchemaNode> augmentedNodes, final DataNodeContainer usesNodeParent,
+                          Map<Module, ModuleContext> genCtx, final boolean verboseClassComments,
+                          Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
+        checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
+        checkArgument(targetType != null, "Referenced Choice Type cannot be NULL.");
+        checkArgument(augmentedNodes != null, "Set of Choice Case Nodes cannot be NULL.");
+
+        for (final DataSchemaNode caseNode : augmentedNodes) {
+            if (caseNode != null) {
+                final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
+                final GeneratedTypeBuilder caseTypeBuilder = GenHelperUtil.addDefaultInterfaceDefinition(packageName,
+                        caseNode, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders);
+                caseTypeBuilder.addImplementsType(targetType);
+
+                SchemaNode parent;
+                final SchemaPath nodeSp = targetNode.getPath();
+                parent = findDataSchemaNode(schemaContext, nodeSp.getParent());
+
+                GeneratedTypeBuilder childOfType = null;
+                if (parent instanceof Module) {
+                    childOfType = genCtx.get(parent).getModuleNode();
+                } else if (parent instanceof ChoiceCaseNode) {
+                    childOfType = findCaseByPath(parent.getPath(), genCtx);
+                } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
+                    childOfType = findChildNodeByPath(parent.getPath(), genCtx);
+                } else if (parent instanceof GroupingDefinition) {
+                    childOfType = GenHelperUtil.findGroupingByPath(parent.getPath(), genCtx);
+                }
+
+                if (childOfType == null) {
+                    throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
+                }
+
+                ChoiceCaseNode node = null;
+                final String caseLocalName = caseNode.getQName().getLocalName();
+                if (caseNode instanceof ChoiceCaseNode) {
+                    node = (ChoiceCaseNode) caseNode;
+                } else if (targetNode.getCaseNodeByName(caseLocalName) == null) {
+                    final String targetNodeLocalName = targetNode.getQName().getLocalName();
+                    for (DataSchemaNode dataSchemaNode : usesNodeParent.getChildNodes()) {
+                        if (dataSchemaNode instanceof ChoiceSchemaNode && targetNodeLocalName.equals(dataSchemaNode.getQName
+                                ().getLocalName())) {
+                            node = ((ChoiceSchemaNode) dataSchemaNode).getCaseNodeByName(caseLocalName);
+                            break;
+                        }
+                    }
+                } else {
+                    node = targetNode.getCaseNodeByName(caseLocalName);
+                }
+                final Iterable<DataSchemaNode> childNodes = node.getChildNodes();
+                if (childNodes != null) {
+                    resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
+                }
+                genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
+                genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, node);
+            }
+        }
+        return genCtx;
+    }
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/BindingGeneratorImpl.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/BindingGeneratorImpl.java
new file mode 100644 (file)
index 0000000..bad95da
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016 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.binding2.generator.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.annotations.Beta;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.mdsal.binding2.generator.api.BindingGenerator;
+import org.opendaylight.mdsal.binding2.generator.spi.TypeProvider;
+import org.opendaylight.mdsal.binding2.generator.yang.types.TypeProviderImpl;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
+
+/**
+ * Main class for Binding generator v2. Provides transformation of Schema Context to
+ * generated transfer objects. Process is accompanied with Twirl templates to generate
+ * particular Javadoc for related YANG elements.
+ */
+@Beta
+public class BindingGeneratorImpl implements BindingGenerator {
+
+    /**
+     * When set to true, generated classes will include Javadoc comments
+     * which are useful for users.
+     */
+    private final boolean verboseClassComments;
+
+    /**
+     * Outer key represents the package name. Outer value represents map of all
+     * builders in the same package. Inner key represents the schema node name
+     * (in JAVA class/interface name format). Inner value represents instance of
+     * builder for schema node specified in key part.
+     */
+    private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders = new HashMap<>();
+
+    private Map<Module, ModuleContext> genCtx = new HashMap<>();
+
+    /**
+     * Creates a new binding generator v2.
+     *
+     * @param verboseClassComments generate verbose comments
+     */
+    public BindingGeneratorImpl(final boolean verboseClassComments) {
+        this.verboseClassComments = verboseClassComments;
+    }
+
+    /**
+     * Provide methods for converting YANG types to JAVA types.
+     */
+    private TypeProvider typeProvider;
+
+    /**
+     * Holds reference to schema context to resolve data of augmented element
+     * when creating augmentation builder
+     */
+    private SchemaContext schemaContext;
+
+    /**
+     * Resolves generated types from <code>context</code> schema nodes of all
+     * modules.
+     *
+     * Generated types are created for modules, groupings, types, containers,
+     * lists, choices, augments, rpcs, notification, identities.
+     *
+     * @param context
+     *            schema context which contains data about all schema nodes
+     *            saved in modules
+     * @return list of types (usually <code>GeneratedType</code>
+     *         <code>GeneratedTransferObject</code>which are generated from
+     *         <code>context</code> data.
+     * @throws IllegalArgumentException
+     *             if arg <code>context</code> is null
+     * @throws IllegalStateException
+     *             if <code>context</code> contain no modules
+     */
+    @Override
+    public List<Type> generateTypes(SchemaContext context) {
+        checkArgument(context != null, "Schema Context reference cannot be NULL.");
+        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);
+    }
+
+    @Override
+    public List<Type> generateTypes(SchemaContext context, Set<Module> modules) {
+        checkArgument(context != null, "Schema Context reference cannot be NULL.");
+        checkState(context.getModules() != null, "Schema Context does not contain defined modules.");
+        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);
+
+        for (final Module contextModule : contextModules) {
+            genCtx = ModuleToGenType.generate(contextModule, context, typeProvider, verboseClassComments);
+        }
+        for (final Module contextModule : contextModules) {
+            genCtx = AugmentToGenType.generate(contextModule, schemaContext, genCtx,
+                    genTypeBuilders, verboseClassComments);
+        }
+
+        final List<Type> filteredGenTypes = new ArrayList<>();
+        for (final Module m : modules) {
+            final ModuleContext ctx = checkNotNull(genCtx.get(m), "Module context not found for module %s", m);
+            filteredGenTypes.addAll(ctx.getGeneratedTypes());
+            final Set<Type> additionalTypes = ((TypeProviderImpl) typeProvider).getAdditionalTypes().get(m);
+            if (additionalTypes != null) {
+                filteredGenTypes.addAll(additionalTypes);
+            }
+        }
+
+        return filteredGenTypes;
+    }
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/GenHelperUtil.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/GenHelperUtil.java
new file mode 100644 (file)
index 0000000..3951410
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2016 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.binding2.generator.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.opendaylight.mdsal.binding2.generator.impl.AugmentToGenType.usesAugmentationToGenTypes;
+import static org.opendaylight.mdsal.binding2.generator.util.BindingTypes.TREE_ROOT;
+import static org.opendaylight.mdsal.binding2.generator.util.BindingTypes.augmentable;
+import static org.opendaylight.mdsal.binding2.generator.util.Types.typeForClass;
+
+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.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import org.opendaylight.mdsal.binding2.generator.impl.util.YangTextTemplate;
+import org.opendaylight.mdsal.binding2.generator.util.Binding2GeneratorUtil;
+import org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping;
+import org.opendaylight.mdsal.binding2.generator.util.BindingTypes;
+import org.opendaylight.mdsal.binding2.generator.util.Types;
+import org.opendaylight.mdsal.binding2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.mdsal.binding2.model.api.Constant;
+import org.opendaylight.mdsal.binding2.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding2.txt.yangTemplateForModule;
+import org.opendaylight.mdsal.binding2.txt.yangTemplateForNode;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+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.
+ */
+@Beta
+final class GenHelperUtil {
+
+    private GenHelperUtil() {
+        throw new UnsupportedOperationException("Util class");
+    }
+
+    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";
+
+
+    /**
+     * Create GeneratedTypeBuilder object from module argument.
+     *
+     * @param module
+     *            Module object from which builder will be created
+     * @param genCtx
+     * @param verboseClassComments
+     *
+     * @return <code>GeneratedTypeBuilder</code> which is internal
+     *         representation of the module
+     * @throws IllegalArgumentException
+     *             if module is null
+     */
+    static GeneratedTypeBuilder moduleToDataType(final Module module, Map<Module, ModuleContext> genCtx, final boolean verboseClassComments) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+
+        final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data", verboseClassComments);
+        addImplementedInterfaceFromUses(module, moduleDataTypeBuilder, genCtx);
+        moduleDataTypeBuilder.addImplementsType(TREE_ROOT);
+        moduleDataTypeBuilder.addComment(module.getDescription());
+        moduleDataTypeBuilder.setDescription(createDescription(module, verboseClassComments));
+        moduleDataTypeBuilder.setReference(module.getReference());
+        return moduleDataTypeBuilder;
+    }
+
+    /**
+     * Generates type builder for <code>module</code>.
+     *
+     * @param module
+     *            Module which is source of package name for generated type
+     *            builder
+     * @param postfix
+     *            string which is added to the module class name representation
+     *            as suffix
+     * @param verboseClassComments
+     * @return instance of GeneratedTypeBuilder which represents
+     *         <code>module</code>.
+     * @throws IllegalArgumentException
+     *             if <code>module</code> is null
+     */
+    static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean verboseClassComments) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        final String packageName = Binding2Mapping.getRootPackageName(module);
+        final String moduleName = Binding2Mapping.getClassName(module.getName()) + postfix;
+
+        final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName);
+        moduleBuilder.setDescription(createDescription(module, verboseClassComments));
+        moduleBuilder.setReference(module.getReference());
+        moduleBuilder.setModuleName(moduleName);
+
+        return moduleBuilder;
+    }
+
+    /**
+     * Adds the implemented types to type builder.
+     *
+     * The method passes through the list of <i>uses</i> in
+     * {@code dataNodeContainer}. For every <i>use</i> is obtained corresponding
+     * generated type from all groupings
+     * allGroupings} which is added as <i>implements type</i> to
+     * <code>builder</code>
+     *
+     * @param dataNodeContainer
+     *            element which contains the list of used YANG groupings
+     * @param builder
+     *            builder to which are added implemented types according to
+     *            <code>dataNodeContainer</code>
+     * @param genCtx
+     * @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);
+            }
+        }
+        return builder;
+    }
+
+     static GeneratedTypeBuilder findGroupingByPath(final SchemaPath path, Map<Module, ModuleContext> genCtx) {
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getGrouping(path);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+     }
+
+    private static String createDescription(final Module module, final boolean verboseClassComments) {
+        final StringBuilder sb = new StringBuilder();
+        final String moduleDescription = Binding2GeneratorUtil.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(Binding2GeneratorUtil.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.
+     *
+     * The subnodes aren't mapped to the methods if they are part of grouping or
+     * augment (in this case are already part of them).
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string contains the module package name
+     * @param parent
+     *            generated type builder which represents any node. The subnodes
+     *            of this node are added to the <code>typeBuilder</code> as
+     *            methods. The subnode can be of type leaf, leaf-list, list,
+     *            container, choice.
+     * @param childOf
+     *            parent type
+     * @param schemaNodes
+     *            set of data schema nodes which are the children of the node
+     *            for which <code>typeBuilder</code> was created
+     * @return generated type builder which is the same builder as input
+     *         parameter. The getter methods (representing child nodes) could be
+     *         added to it.
+     */
+    static GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName,
+                          final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final Iterable<DataSchemaNode> schemaNodes) {
+        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);
+                }
+            }
+        }
+        return parent;
+    }
+
+    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) {
+        final String basePackageName = Binding2Mapping.getRootPackageName(module);
+        for (final UsesNode usesNode : node.getUses()) {
+            for (final AugmentationSchema augment : usesNode.getAugmentations()) {
+                genCtx = usesAugmentationToGenTypes(schemaContext, basePackageName, augment, module, usesNode,
+                        node, genCtx, genTypeBuilders, verboseClassComments);
+                genCtx = processUsesAugments(schemaContext, augment, module, genCtx, genTypeBuilders, verboseClassComments);
+            }
+        }
+        return genCtx;
+    }
+
+    static GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path, Map<Module, ModuleContext> genCtx) {
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getChildNode(path);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    static GeneratedTypeBuilder findCaseByPath(final SchemaPath path, Map<Module, ModuleContext> genCtx) {
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getCase(path);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a generated type builder for an augmentation.
+     *
+     * The name of the type builder is equal to the name of augmented node with
+     * serial number as suffix.
+     *
+     * @param module
+     *            current module
+     * @param augmentPackageName
+     *            string with contains the package name to which the augment
+     *            belongs
+     * @param basePackageName
+     *            string with the package name to which the augmented node
+     *            belongs
+     * @param targetTypeRef
+     *            target type
+     * @param augSchema
+     *            augmentation schema which contains data about the child nodes
+     *            and uses of augment
+     * @return generated type builder for augment in genCtx
+     */
+    static Map<Module, ModuleContext> addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName,
+                final String basePackageName, final Type targetTypeRef, final AugmentationSchema augSchema,
+                Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, Map<Module, ModuleContext> genCtx) {
+
+        Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
+        if (augmentBuilders == null) {
+            augmentBuilders = new HashMap<>();
+            genTypeBuilders.put(augmentPackageName, augmentBuilders);
+        }
+        final String augIdentifier = getAugmentIdentifier(augSchema.getUnknownSchemaNodes());
+
+        String augTypeName;
+        if (augIdentifier != null) {
+            augTypeName = Binding2Mapping.getClassName(augIdentifier);
+        } else {
+            augTypeName = augGenTypeName(augmentBuilders, targetTypeRef.getName());
+        }
+
+        GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
+
+        augTypeBuilder.addImplementsType(BindingTypes.TREE_NODE);
+        augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
+        annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder);
+        augTypeBuilder = addImplementedInterfaceFromUses(augSchema, augTypeBuilder, genCtx);
+
+        augTypeBuilder = augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema
+                .getChildNodes());
+        augmentBuilders.put(augTypeName, augTypeBuilder);
+
+        if(!augSchema.getChildNodes().isEmpty()) {
+            genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
+
+        }
+        genCtx.get(module).addAugmentType(augTypeBuilder);
+        return genCtx;
+    }
+
+    /**
+     * Adds the methods to <code>typeBuilder</code> what represents subnodes of
+     * node for which <code>typeBuilder</code> was created.
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string contains the module package name
+     * @param typeBuilder
+     *            generated type builder which represents any node. The subnodes
+     *            of this node are added to the <code>typeBuilder</code> as
+     *            methods. The subnode can be of type leaf, leaf-list, list,
+     *            container, choice.
+     * @param childOf
+     *            parent type
+     * @param schemaNodes
+     *            set of data schema nodes which are the children of the node
+     *            for which <code>typeBuilder</code> was created
+     * @return generated type builder which is the same object as the input
+     *         parameter <code>typeBuilder</code>. The getter method could be
+     *         added to it.
+     */
+    private static GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName,
+                                                        final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf,
+                                                        final Iterable<DataSchemaNode> schemaNodes) {
+        if ((schemaNodes != null) && (typeBuilder != null)) {
+            for (final DataSchemaNode schemaNode : schemaNodes) {
+                if (!schemaNode.isAugmenting()) {
+                    //TODO: design decomposition and implement it
+                    //addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
+                }
+            }
+        }
+        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>.
+     *
+     * The new builder always implements
+     * {@link org.opendaylight.mdsal.binding2.spec.TreeNode TreeNode}.<br>
+     * If <code>schemaNode</code> is instance of GroupingDefinition it also
+     * implements {@link org.opendaylight.mdsal.binding2.spec.Augmentable
+     * Augmentable}.<br>
+     * If <code>schemaNode</code> is instance of
+     * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+     * DataNodeContainer} it can also implement nodes which are specified in
+     * <i>uses</i>.
+     *
+     * @param packageName
+     *            string with the name of the package to which
+     *            <code>schemaNode</code> belongs.
+     * @param schemaNode
+     *            schema node for which is created generated type builder
+     * @param parent
+     *            parent type (can be null)
+     * @param schemaContext
+     * @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) {
+            it.addImplementsType(BindingTypes.TREE_NODE);
+        } else {
+            it.addImplementsType(BindingTypes.treeChildNode(parent));
+        }
+        if (!(schemaNode instanceof GroupingDefinition)) {
+            it.addImplementsType(augmentable(it));
+        }
+
+        if (schemaNode instanceof DataNodeContainer) {
+            //TODO: design decomposition and implement it
+            //groupingsToGenTypes(module, ((DataNodeContainer) schemaNode).getGroupings());
+            it = addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it, genCtx);
+        }
+
+        return it;
+    }
+
+    /**
+     * Returns reference to generated type builder for specified
+     * <code>schemaNode</code> with <code>packageName</code>.
+     *
+     * Firstly the generated type builder is searched in
+     * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
+     * found it is created and added to <code>genTypeBuilders</code>.
+     *
+     * @param packageName
+     *            string with the package name to which returning generated type
+     *            builder belongs
+     * @param schemaNode
+     *            schema node which provide data about the schema node name
+     * @param schemaContext
+     * @param prefix
+     *            return type name prefix
+     * @return generated type builder for <code>schemaNode</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>schemaNode</code> is null</li>
+     *             <li>if <code>packageName</code> is null</li>
+     *             <li>if QName of schema node is null</li>
+     *             <li>if schemaNode name is null</li>
+     *             </ul>
+     *
+     */
+    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) {
+        checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
+        checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL.");
+        checkArgument(schemaNode.getQName() != null, "QName for Data Schema Node cannot be NULL.");
+        final String schemaNodeName = schemaNode.getQName().getLocalName();
+        checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL.");
+
+        String genTypeName;
+        if (prefix == null) {
+            genTypeName = Binding2Mapping.getClassName(schemaNodeName);
+        } else {
+            genTypeName = prefix + Binding2Mapping.getClassName(schemaNodeName);
+        }
+
+        final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
+        final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode);
+        qNameConstant(newType, Binding2Mapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
+        newType.addComment(schemaNode.getDescription());
+        newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName(), schemaContext, verboseClassComments));
+        newType.setReference(schemaNode.getReference());
+        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);
+            genTypeBuilders.put(packageName, builders);
+        } else {
+            final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
+            if (!builders.containsKey(genTypeName)) {
+                builders.put(genTypeName, newType);
+            }
+        }
+        return newType;
+
+    }
+
+    private static Constant qNameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
+                                          final QName name) {
+        return toBuilder.addConstant(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 = Binding2GeneratorUtil.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(Binding2GeneratorUtil.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);
+    }
+
+    private 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;
+    }
+
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/GeneratedClassLoadingStrategy.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/GeneratedClassLoadingStrategy.java
new file mode 100644 (file)
index 0000000..ca32561
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 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.binding2.generator.impl;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding2.generator.api.ClassLoadingStrategy;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+
+@Beta
+public abstract class GeneratedClassLoadingStrategy implements ClassLoadingStrategy {
+
+    @Override
+    public Class<?> loadClass(Type type) throws ClassNotFoundException {
+        return loadClass(type.getFullyQualifiedName());
+    }
+
+    @Override
+    public abstract Class<?> loadClass(String fqcn) throws ClassNotFoundException;
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/ModuleContext.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/ModuleContext.java
new file mode 100644 (file)
index 0000000..f162968
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2013 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.binding2.generator.impl;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.EnumBuilder;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+/**
+ * This class holds information about generated entities in context of YANG module
+ */
+@Beta
+final class ModuleContext {
+    private GeneratedTypeBuilder moduleNode;
+    private final List<GeneratedTOBuilder> genTOs = new ArrayList<>();
+    private final Map<SchemaPath, Type> typedefs = new HashMap<>();
+    private final Map<SchemaPath, GeneratedTypeBuilder> childNodes = new HashMap<>();
+    private final Map<SchemaPath, GeneratedTypeBuilder> groupings = new HashMap<>();
+    private final Map<SchemaPath, GeneratedTypeBuilder> cases = new HashMap<>();
+    private final Map<QName,GeneratedTOBuilder> identities = new HashMap<>();
+    private final Set<GeneratedTypeBuilder> topLevelNodes = new HashSet<>();
+    private final List<GeneratedTypeBuilder> augmentations = new ArrayList<>();
+    private final BiMap<Type,AugmentationSchema> typeToAugmentation = HashBiMap.create();
+    private final Map<Type,Object> typeToSchema = new HashMap<>();
+    private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
+    private final BiMap<Type,ChoiceCaseNode> caseTypeToSchema = HashBiMap.create();
+    private final Map<SchemaPath, Type> innerTypes = new HashMap<>();
+
+    List<Type> getGeneratedTypes() {
+        List<Type> result = new ArrayList<>();
+
+        if (moduleNode != null) {
+            result.add(moduleNode.toInstance());
+        }
+
+        result.addAll(genTOs.stream().map(GeneratedTOBuilder::toInstance).collect(Collectors.toList()));
+        result.addAll(typedefs.values().stream().filter(b -> b != null).collect(Collectors.toList()));
+        result.addAll(childNodes.values().stream().map(GeneratedTypeBuilder::toInstance).collect(Collectors.toList()));
+        result.addAll(groupings.values().stream().map(GeneratedTypeBuilder::toInstance).collect(Collectors.toList()));
+        result.addAll(cases.values().stream().map(GeneratedTypeBuilder::toInstance).collect(Collectors.toList()));
+        result.addAll(identities.values().stream().map(GeneratedTOBuilder::toInstance).collect(Collectors.toList()));
+        result.addAll(topLevelNodes.stream().map(GeneratedTypeBuilder::toInstance).collect(Collectors.toList()));
+        result.addAll(augmentations.stream().map(GeneratedTypeBuilder::toInstance).collect(Collectors.toList()));
+
+        return ImmutableList.copyOf(result);
+    }
+
+    public Multimap<Type, Type> getChoiceToCases() {
+        return Multimaps.unmodifiableMultimap(choiceToCases);
+    }
+
+    public GeneratedTypeBuilder getModuleNode() {
+        return moduleNode;
+    }
+
+    public GeneratedTypeBuilder getChildNode(final SchemaPath p) {
+        return childNodes.get(p);
+    }
+
+    public GeneratedTypeBuilder getGrouping(final SchemaPath p) {
+        return groupings.get(p);
+    }
+
+    public GeneratedTypeBuilder getCase(final SchemaPath p) {
+        return cases.get(p);
+    }
+
+    public void addModuleNode(final GeneratedTypeBuilder moduleNode) {
+        this.moduleNode = moduleNode;
+    }
+
+    public void addGeneratedTOBuilder(final GeneratedTOBuilder b) {
+        genTOs.add(b);
+    }
+
+    public void addChildNodeType(final SchemaNode p, final GeneratedTypeBuilder b) {
+        childNodes.put(p.getPath(), b);
+        typeToSchema.put(b,p);
+    }
+
+    public void addGroupingType(final SchemaPath p, final GeneratedTypeBuilder b) {
+        groupings.put(p, b);
+    }
+
+    public void addTypedefType(final SchemaPath p, final Type t) {
+        typedefs.put(p, t);
+    }
+
+    public void addCaseType(final SchemaPath p, final GeneratedTypeBuilder b) {
+        cases.put(p, b);
+    }
+
+    public void addIdentityType(final QName name,final GeneratedTOBuilder b) {
+        identities.put(name,b);
+    }
+
+    public void addTopLevelNodeType(final GeneratedTypeBuilder b) {
+        topLevelNodes.add(b);
+    }
+
+    public void addAugmentType(final GeneratedTypeBuilder b) {
+        augmentations.add(b);
+    }
+
+    public Map<SchemaPath, Type> getTypedefs() {
+        return typedefs;
+    }
+
+    public Map<SchemaPath, GeneratedTypeBuilder> getChildNodes() {
+        return Collections.unmodifiableMap(childNodes);
+    }
+
+    public Map<SchemaPath, GeneratedTypeBuilder> getGroupings() {
+        return Collections.unmodifiableMap(groupings);
+    }
+
+    public Map<SchemaPath, GeneratedTypeBuilder> getCases() {
+        return Collections.unmodifiableMap(cases);
+    }
+
+    public Map<QName,GeneratedTOBuilder> getIdentities() {
+        return Collections.unmodifiableMap(identities);
+    }
+
+    public Set<GeneratedTypeBuilder> getTopLevelNodes() {
+        return Collections.unmodifiableSet(topLevelNodes);
+    }
+
+    public List<GeneratedTypeBuilder> getAugmentations() {
+        return Collections.unmodifiableList(augmentations);
+    }
+
+    public BiMap<Type, AugmentationSchema> getTypeToAugmentation() {
+        return Maps.unmodifiableBiMap(typeToAugmentation);
+    }
+
+    public void addTypeToAugmentation(final GeneratedTypeBuilder builder, final AugmentationSchema schema) {
+        typeToAugmentation.put(builder, schema);
+        typeToSchema.put(builder, schema);
+    }
+
+    public void addChoiceToCaseMapping(final Type choiceType, final Type caseType, final ChoiceCaseNode schema) {
+        choiceToCases.put(choiceType, caseType);
+        caseTypeToSchema.put(caseType, schema);
+        typeToSchema.put(caseType, schema);
+    }
+
+    public BiMap<Type, ChoiceCaseNode> getCaseTypeToSchemas() {
+        return Maps.unmodifiableBiMap(caseTypeToSchema);
+    }
+
+    /**
+     *
+     * Returns mapping of type to its schema.
+     *
+     * Valid values are only instances of {@link DataSchemaNode} or {@link AugmentationSchema}
+     *
+     * @return Mapping from type to corresponding schema
+     */
+    public Map<Type, Object> getTypeToSchema() {
+        return Collections.unmodifiableMap(typeToSchema);
+    }
+
+    protected void addTypeToSchema(Type type, TypeDefinition<?> typedef) {
+        typeToSchema.put(type, typedef);
+    }
+
+    /**
+     * Adds mapping between schema path and inner enum.
+     *
+     * @param path
+     * @param enumBuilder
+     */
+    void addInnerTypedefType(SchemaPath path, EnumBuilder enumBuilder) {
+        innerTypes.put(path, enumBuilder);
+    }
+
+    public Type getInnerType(SchemaPath path) {
+        return innerTypes.get(path);
+    }
+
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/ModuleToGenType.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/ModuleToGenType.java
new file mode 100644 (file)
index 0000000..5ef8f39
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 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.binding2.generator.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.annotations.Beta;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.mdsal.binding2.generator.spi.TypeProvider;
+import org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping;
+import org.opendaylight.mdsal.binding2.generator.yang.types.TypeProviderImpl;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+import org.opendaylight.mdsal.binding2.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
+
+@Beta
+final class ModuleToGenType {
+
+    private 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<>();
+
+        genCtx.put(module, new ModuleContext());
+        genCtx = allTypeDefinitionsToGenTypes(module, genCtx, typeProvider);
+
+        //TODO: call generate for other entities (groupings, rpcs, identities, notifications)
+
+        if (!module.getChildNodes().isEmpty()) {
+            final GeneratedTypeBuilder moduleType = GenHelperUtil.moduleToDataType(module, genCtx, verboseClassComments);
+            genCtx.get(module).addModuleNode(moduleType);
+            final String basePackageName = Binding2Mapping.getRootPackageName(module);
+            GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, moduleType, moduleType, module
+                    .getChildNodes());
+        }
+
+        return genCtx;
+    }
+
+    /**
+     * Converts all extended type definitions of module to the list of
+     * <code>Type</code> objects.
+     *
+     * @param module
+     *            module from which is obtained set of type definitions
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if module is null</li>
+     *             <li>if name of module is null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if set of type definitions from module is null
+     */
+    private static Map<Module, ModuleContext> allTypeDefinitionsToGenTypes(final Module module, Map<Module, ModuleContext> genCtx,
+                                                     TypeProvider typeProvider) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkArgument(module.getName() != null, "Module name cannot be NULL.");
+        final DataNodeIterator it = new DataNodeIterator(module);
+        final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
+        checkState(typeDefinitions != null, "Type Definitions for module Â«module.name» cannot be NULL.");
+
+        typeDefinitions.stream().filter(typedef -> typedef != null).forEach(typedef -> {
+            final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef,
+                    typedef);
+            if (type != null) {
+                final ModuleContext ctx = genCtx.get(module);
+                ctx.addTypedefType(typedef.getPath(), type);
+                ctx.addTypeToSchema(type, typedef);
+            }
+        });
+        return genCtx;
+    }
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/util/YangTextTemplate.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/impl/util/YangTextTemplate.java
new file mode 100644 (file)
index 0000000..f59e5a0
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2016 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.binding2.generator.impl.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.CharMatcher;
+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.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+import org.opendaylight.mdsal.binding2.generator.util.Types;
+import org.opendaylight.mdsal.binding2.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding2.model.api.ParameterizedType;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+import org.opendaylight.mdsal.binding2.model.api.WildcardType;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * Util class
+ */
+@Beta
+public final class YangTextTemplate {
+    private static final CharMatcher NEWLINE_OR_TAB = CharMatcher.anyOf("\n\t");
+    private static final String DOT = ".";
+    private static final String COMMA = ",";
+    private static final char NEW_LINE = '\n';
+    private static final CharMatcher NL_MATCHER = CharMatcher.is(NEW_LINE);
+    private static final CharMatcher AMP_MATCHER = CharMatcher.is('&');
+    private static final Splitter NL_SPLITTER = Splitter.on(NL_MATCHER);
+    private static final CharMatcher TAB_MATCHER = CharMatcher.is('\t');
+    private static final Pattern SPACES_PATTERN = Pattern.compile(" +");
+
+    private YangTextTemplate() {
+        throw new UnsupportedOperationException("Util class");
+    }
+
+    public static String formatSchemaPath(final String moduleName, final Iterable<QName> schemaPath) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(moduleName);
+
+        QName currentElement = Iterables.getFirst(schemaPath, null);
+        for (QName pathElement : schemaPath) {
+            sb.append('/');
+            if (!currentElement.getNamespace().equals(pathElement.getNamespace())) {
+                currentElement = pathElement;
+                sb.append(pathElement);
+            } else {
+                sb.append(pathElement.getLocalName());
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Used in #yangtemplateformodule.scala.txt for formating revision description
+     *
+     * @param text Content of tag description
+     * @param nextLineIndent Number of spaces from left side default is 12
+     * @return formatted description
+     */
+    public static String formatToParagraph(final String text, final int nextLineIndent) {
+        if (Strings.isNullOrEmpty(text)) {
+            return "";
+        }
+        boolean isFirstElementOnNewLineEmptyChar = false;
+        final StringBuilder sb = new StringBuilder();
+        final StringBuilder lineBuilder = new StringBuilder();
+        final String lineIndent = Strings.repeat(" ", nextLineIndent);
+        final String textToFormat = NEWLINE_OR_TAB.removeFrom(text);
+        final String formattedText = textToFormat.replaceAll(" +", " ");
+        final StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
+
+        while (tokenizer.hasMoreElements()) {
+            final String nextElement = tokenizer.nextElement().toString();
+
+            if (lineBuilder.length() + nextElement.length() > 80) {
+                // Trim trailing whitespace
+                for (int i = lineBuilder.length() - 1; i >= 0 && lineBuilder.charAt(i) != ' '; --i) {
+                    lineBuilder.setLength(i);
+                }
+                // Trim leading whitespace
+                while (lineBuilder.charAt(0) == ' ') {
+                    lineBuilder.deleteCharAt(0);
+                }
+                sb.append(lineBuilder).append('\n');
+                lineBuilder.setLength(0);
+
+                if (nextLineIndent > 0) {
+                    sb.append(lineIndent);
+                }
+
+                if (" ".equals(nextElement)) {
+                    isFirstElementOnNewLineEmptyChar = true;
+                }
+            }
+            if (isFirstElementOnNewLineEmptyChar) {
+                isFirstElementOnNewLineEmptyChar = false;
+            } else {
+                lineBuilder.append(nextElement);
+            }
+        }
+        return sb.append(lineBuilder).append('\n').toString();
+    }
+
+    /**
+     * Used in all yangtemplates for formating augmentation target
+     *
+     * @param schemaPath path to augmented node
+     * @return path in string format
+     */
+    public static String formatToAugmentPath(final Iterable<QName> schemaPath) {
+        final StringBuilder sb = new StringBuilder();
+        for (QName pathElement : schemaPath) {
+            sb.append("\\(")
+            .append(pathElement.getNamespace())
+            .append(')')
+            .append(pathElement.getLocalName());
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Evaluates if it is necessary to add the package name for type to the map of imports for parentGenType
+     * If it is so the package name is saved to the map imports.
+     *
+     * @param parentGenType generated type for which is the map of necessary imports build
+     * @param type JAVA type for which is the necessary of the package import evaluated
+     * @param imports map of the imports for parentGenType
+     */
+    public static void putTypeIntoImports(final GeneratedType parentGenType, final Type type,
+        final Map<String, String> imports) {
+        checkArgument(parentGenType != null, "Parent Generated Type parameter MUST be specified and cannot be NULL!");
+        checkArgument(type != null, "Type parameter MUST be specified and cannot be NULL!");
+        checkArgument(parentGenType.getPackageName() != null,
+                "Parent Generated Type cannot have Package Name referenced as NULL!");
+
+        final String typeName = Preconditions.checkNotNull(type.getName());
+        final String typePackageName = Preconditions.checkNotNull(type.getPackageName());
+        final String parentTypeName = Preconditions.checkNotNull(parentGenType.getName());
+        if (typeName.equals(parentTypeName) || typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
+            return;
+        }
+        if (!imports.containsKey(typeName)) {
+            imports.put(typeName, typePackageName);
+        }
+        if (type instanceof ParameterizedType) {
+            final ParameterizedType paramType = (ParameterizedType) type;
+            final Type[] params = paramType.getActualTypeArguments();
+            if (params != null) {
+                for (Type param : params) {
+                    putTypeIntoImports(parentGenType, param, imports);
+                }
+            }
+        }
+    }
+
+    /**
+     * Builds the string which contains either the full path to the type (package name with type) or only type name
+     * if the package is among imports.
+     *
+     * @param parentGenType generated type which contains type
+     * @param type JAVA type for which is the string with type info generated
+     * @param imports map of necessary imports for parentGenType
+     * @return string with type name for type in the full format or in the short format
+     */
+    public static String getExplicitType(final GeneratedType parentGenType, final Type type,
+        final Map<String, String> imports) {
+        checkArgument(type != null, "Type parameter MUST be specified and cannot be NULL!");
+        checkArgument(imports != null, "Imports Map cannot be NULL!");
+
+        final String typePackageName = Preconditions.checkNotNull(type.getPackageName());
+        final String typeName = Preconditions.checkNotNull(type.getName());
+        final String importedPackageName = imports.get(typeName);
+        final StringBuilder builder;
+        if (typePackageName.equals(importedPackageName)) {
+            builder = new StringBuilder(typeName);
+            addActualTypeParameters(builder, type, parentGenType, imports);
+            if (builder.toString().equals("Void")) {
+                return "void";
+            }
+        } else {
+            builder = new StringBuilder();
+            if (!typePackageName.isEmpty()) {
+                builder.append(typePackageName + DOT + typeName);
+            } else {
+                builder.append(type.getName());
+            }
+            if (type.equals(Types.voidType())) {
+                return "void";
+            }
+            addActualTypeParameters(builder, type, parentGenType, imports);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Adds actual type parameters from type to builder if type is ParametrizedType.
+     *
+     * @param builder string builder which contains type name
+     * @param type JAVA Type for which is the string with type info generated
+     * @param parentGenType generated type which contains type
+     * @param imports map of necessary imports for parentGenType
+     * @return adds actual type parameters to builder
+     */
+    private static StringBuilder addActualTypeParameters(final StringBuilder builder, final Type type,
+        final GeneratedType parentGenType, final Map<String, String> imports) {
+        if (type instanceof ParameterizedType) {
+            final ParameterizedType pType = (ParameterizedType) type;
+            final Type[] pTypes = pType.getActualTypeArguments();
+            builder.append("<");
+            builder.append(getParameters(parentGenType, pTypes, imports));
+            builder.append(">");
+        }
+        return builder;
+    }
+
+    /**
+     * Generates the string with all actual type parameters from
+     *
+     * @param parentGenType generated type for which is the JAVA code generated
+     * @param pTypes array of Type instances = actual type parameters
+     * @param availableImports map of imports for parentGenType
+     * @return string with all actual type parameters from pTypes
+     */
+    private static String getParameters(final GeneratedType parentGenType, final Type[] pTypes,
+        final Map<String, String> availableImports) {
+        if (pTypes == null || pTypes.length == 0) {
+            return "?";
+        }
+        final StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < pTypes.length; i++) {
+            final Type t = pTypes[i];
+
+            String separator = COMMA;
+            if (i == (pTypes.length - 1)) {
+                separator = "";
+            }
+
+            String wildcardParam = "";
+            if (t.equals(Types.voidType())) {
+                builder.append("java.lang.Void")
+                .append(separator);
+                continue;
+            } else {
+
+                if (t instanceof WildcardType) {
+                    wildcardParam = "? extends ";
+                }
+
+                builder.append(wildcardParam)
+                .append(getExplicitType(parentGenType, t, availableImports) + separator);
+            }
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Wraps text as documentation
+     *
+     * @param text text for wrapping
+     * @return wrapped text
+     */
+    public static String wrapToDocumentation(String text) {
+        if (text.isEmpty()) {
+            return "";
+        }
+        final StringBuilder sb = new StringBuilder("/**");
+        sb.append(NEW_LINE);
+        Iterable<String> lineSplitText = NL_SPLITTER.split(text);
+        for (final String t : lineSplitText) {
+            sb.append(" *");
+            if (t.isEmpty()) {
+                sb.append(" ");
+                sb.append(t);
+            }
+            sb.append(NEW_LINE);
+        }
+        sb.append(" */");
+        return sb.toString();
+    }
+
+    public static String encodeJavadocSymbols(String description) {
+        if (description == null || description.isEmpty()) {
+            return description;
+        }
+        String ret = description.replace("*/", "&#42;&#47;");
+        return AMP_MATCHER.replaceFrom(ret, "&amp;");
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/yang/types/TypeProviderImpl.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding2/generator/yang/types/TypeProviderImpl.java
new file mode 100644 (file)
index 0000000..6a90b5d
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016 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.binding2.generator.yang.types;
+
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.mdsal.binding2.generator.spi.TypeProvider;
+import org.opendaylight.mdsal.binding2.model.api.Restrictions;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+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.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Beta
+public final class TypeProviderImpl implements TypeProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TypeProviderImpl.class);
+
+    /**
+     * Contains the schema data red from YANG files.
+     */
+    private final SchemaContext schemaContext;
+
+    /**
+     * Map<moduleName, Map<moduleDate, Map<typeName, type>>>
+     */
+    private final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
+
+    private final Map<Module, Set<Type>> additionalTypes;
+    /**
+     * Creates new instance of class <code>TypeProviderImpl</code>.
+     *
+     * @param schemaContext
+     *            contains the schema data red from YANG files
+     * @throws IllegalArgumentException
+     *             if <code>schemaContext</code> equal null.
+     */
+    public TypeProviderImpl(final SchemaContext schemaContext) {
+        this.schemaContext = schemaContext;
+        this.genTypeDefsContextMap = new HashMap<>();
+        this.additionalTypes = new HashMap<>();
+    }
+
+    @Override
+    public Type javaTypeForSchemaDefinitionType(TypeDefinition<?> type, SchemaNode parentNode) {
+        return null;
+    }
+
+    @Override
+    public Type javaTypeForSchemaDefinitionType(TypeDefinition<?> type, SchemaNode parentNode, Restrictions restrictions) {
+        return null;
+    }
+
+    @Override
+    public String getTypeDefaultConstruction(LeafSchemaNode node) {
+        return null;
+    }
+
+    @Override
+    public String getConstructorPropertyName(SchemaNode node) {
+        return null;
+    }
+
+    @Override
+    public String getParamNameFromType(TypeDefinition<?> type) {
+        return null;
+    }
+
+    /**
+     * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
+     *
+     * @param typeDefinition
+     *            type definition which should be converted to JAVA
+     *            <code>Type</code>
+     * @return JAVA <code>Type</code> which represents
+     *         <code>typeDefinition</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>typeDefinition</code> equal null</li>
+     *             <li>if Q name of <code>typeDefinition</code></li>
+     *             <li>if name of <code>typeDefinition</code></li>
+     *             </ul>
+     */
+    public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
+        Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
+        if (typeDefinition.getQName() == null) {
+            throw new IllegalArgumentException(
+                    "Type Definition cannot have non specified QName (QName cannot be NULL!)");
+        }
+        Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
+                "Type Definitions Local Name cannot be NULL!");
+
+        final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
+        if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
+            final Module module = findParentModule(schemaContext, parentNode);
+
+            if (module != null) {
+                final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
+                final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
+                if (genTOs != null) {
+                    return genTOs.get(typeDefinition.getQName().getLocalName());
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets base type definition for <code>extendTypeDef</code>. The method is
+     * recursively called until non <code>ExtendedType</code> type is found.
+     *
+     * @param extendTypeDef
+     *            type definition for which is the base type definition sought
+     * @return type definition which is base type for <code>extendTypeDef</code>
+     * @throws IllegalArgumentException
+     *             if <code>extendTypeDef</code> equal null
+     */
+    private static TypeDefinition<?> baseTypeDefForExtendedType(final TypeDefinition<?> extendTypeDef) {
+        Preconditions.checkArgument(extendTypeDef != null, "Type Definition reference cannot be NULL!");
+
+        TypeDefinition<?> ret = extendTypeDef;
+        while (ret.getBaseType() != null) {
+            ret = ret.getBaseType();
+        }
+
+        return ret;
+    }
+
+    public Map<Module, Set<Type>> getAdditionalTypes() {
+        return additionalTypes;
+    }
+
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/test/java/org/opendaylight/mdsal/binding2/TestUtils.java b/binding2/mdsal-binding2-generator-impl/src/main/test/java/org/opendaylight/mdsal/binding2/TestUtils.java
new file mode 100644 (file)
index 0000000..bd3c545
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 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.binding2;
+
+import com.google.common.annotations.Beta;
+import java.io.File;
+import java.net.URI;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Beta
+public final class TestUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TestUtils.class);
+
+    private TestUtils() {
+        throw new UnsupportedOperationException("Utility class");
+    }
+
+    public static Set<Module> loadModules(final URI resourceDirectory)
+            throws SourceException, ReactorException {
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
+                .newBuild();
+        File[] files = new File(resourceDirectory).listFiles();
+
+        for (File file : files) {
+            if (file.getName().endsWith(".yang")) {
+                addSources(reactor, new YangStatementSourceImpl(file.getPath(), true));
+            } else {
+                LOG.info("Ignoring non-yang file {}", file);
+            }
+        }
+
+        EffectiveSchemaContext ctx = reactor.buildEffective();
+        return ctx.getModules();
+    }
+
+    private static void addSources(final CrossSourceStatementReactor.BuildAction reactor,
+        final YangStatementSourceImpl... sources) {
+        for (YangStatementSourceImpl source : sources) {
+            reactor.addSource(source);
+        }
+    }
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/test/java/org/opendaylight/mdsal/binding2/YangTemplateTest.java b/binding2/mdsal-binding2-generator-impl/src/main/test/java/org/opendaylight/mdsal/binding2/YangTemplateTest.java
new file mode 100644 (file)
index 0000000..e473f01
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 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.binding2;
+
+import com.google.common.annotations.Beta;
+import java.net.URISyntaxException;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding2.txt.yangTemplateForModule;
+import org.opendaylight.mdsal.binding2.txt.yangTemplateForNode;
+import org.opendaylight.mdsal.binding2.txt.yangTemplateForNodes;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+
+@Beta
+public class YangTemplateTest {
+
+    private Set<Module> modules;
+
+    @Before
+    public void setup() throws URISyntaxException, ReactorException {
+        modules = TestUtils.loadModules(getClass().getResource("/yang-template").toURI());
+    }
+
+    @Test
+    public void printYangSnippetForModule() {
+        for (Module module : modules) {
+            /**
+             * We should be able to call Scala render method from Binding Generator implementation
+             * for 3 different inputs:
+             * 1. single SchemaNode
+             * 2. set of SchemaNode
+             * 3. whole Module
+             */
+            final String moduleBody = yangTemplateForModule.render(module).body();
+            //FIXME: don't do it this way, only for very first attempt to show results
+            System.out.println("module ".concat(module.getName()).concat(":").concat(moduleBody));
+
+            //TODO: finish following sections
+            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+                final String nodeBody = yangTemplateForNode.render(dataSchemaNode).body();
+            }
+
+            final String rpcsBody = yangTemplateForNodes.render(module.getRpcs()).body();
+            final String notificationsBody = yangTemplateForNodes.render(module.getNotifications()).body();
+
+            //////////
+        }
+
+    }
+}
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/test/resources/yang-template/yang-template-import.yang b/binding2/mdsal-binding2-generator-impl/src/main/test/resources/yang-template/yang-template-import.yang
new file mode 100644 (file)
index 0000000..191446e
--- /dev/null
@@ -0,0 +1,13 @@
+module yang-template-import {
+    yang-version 1;
+    namespace "org.opendaylight.yang.template";
+    prefix "yti";
+
+    revision 2016-06-23 {
+        description "Simple yang missing deviation statement";
+    }
+
+    leaf yti-leaf {
+        type string;
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/test/resources/yang-template/yang-template-test.yang b/binding2/mdsal-binding2-generator-impl/src/main/test/resources/yang-template/yang-template-test.yang
new file mode 100644 (file)
index 0000000..5353239
--- /dev/null
@@ -0,0 +1,118 @@
+module yang-template-test {
+    yang-version 1;
+    namespace "org.opendaylight.yang.template";
+    prefix "ytemp";
+
+    revision 2016-01-01 {
+        description "Simple yang missing deviation statement";
+    }
+
+    import yang-template-import { prefix yti; revision-date 2016-06-23; }
+
+    typedef simple-typedef {
+        type string;
+        default "simple-typedef";
+    }
+
+    container simple-container {
+    }
+
+    leaf simple-leaf {
+        type string;
+    }
+
+    leaf-list simple-leaf-list  {
+        type string;
+    }
+
+    leaf-list simple-leaf-list-userordered  {
+        ordered-by user;
+        type string;
+    }
+
+    list simple-list  {
+    key "simple-list-leaf-1";
+    unique "simple-list-leaf-2";
+        leaf simple-list-leaf-1 {
+            type string;
+        }
+        leaf simple-list-leaf-2 {
+            type string;
+        }
+    }
+
+    list simple-list-userordered  {
+    ordered-by user;
+    key "simple-list-userordered-leaf-1";
+    unique "simple-list-userordered-leaf-2";
+        leaf simple-list-userordered-leaf-1 {
+            type string;
+        }
+        leaf simple-list-userordered-leaf-2 {
+            type string;
+        }
+    }
+
+    choice simple-choice {
+        case simple-case-1 {
+            leaf simple-case-1-leaf {
+                type string;
+            }
+        }
+        case simple-case-2 {
+            leaf simple-case-2-leaf {
+                type string;
+            }
+        }
+    }
+
+    anyxml simple-anyxml;
+
+    grouping simple-grouping {
+        leaf simple-grouping-leaf {
+            description "simple-grouping-leaf description";
+            type string;
+        }
+    }
+
+    container simple-container-uses {
+        uses simple-grouping {
+            refine simple-grouping-leaf {
+                description "refined simple-grouping-leaf description";
+            }
+        }
+    }
+
+    rpc simple-rpc {
+        input {
+            leaf rpc-input-leaf {
+                type string;
+            }
+        }
+    }
+
+    notification simple-notification {
+        leaf notification-leaf {
+            type string;
+        }
+    }
+
+    augment "/simple-container-uses" {
+        leaf augment-leaf {
+            type string;
+        }
+    }
+
+    identity simple-identity {
+        description "simple-identity";
+    }
+
+    extension simple-extension {
+        description "simple-extension";
+        argument "simple-extension-argument";
+    }
+
+    feature simple-feature {
+        description "simple-feature definex if device has some feature... hdd";
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForModule.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForModule.scala.txt
new file mode 100644 (file)
index 0000000..2517fbb
--- /dev/null
@@ -0,0 +1,112 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.mdsal.binding2.generator.impl.util.YangTextTemplate
+@import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil
+@import org.opendaylight.yangtools.yang.model.api.Module
+
+@(module: Module)
+@if(module != null) {
+    @generateYangSnippet(module)
+}
+
+@generateYangSnippet(module: Module) = {
+    module @{module.getName()} {
+        yang-version @module.getYangVersion();
+        namespace "@module.getNamespace().toString()";
+        prefix "@module.getPrefix()";
+
+        @if(module.getImports() != null && !module.getImports().isEmpty()) {
+            @for(moduleImport <- module.getImports()) {
+                @if(moduleImport != null && !moduleImport.getModuleName()) {
+                    import @{moduleImport.getModuleName()} { prefix "@{moduleImport.getPrefix()}"; }
+                }
+            }
+        }
+        @if(module.getRevision() != null) {
+            revision @{SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision())} {
+                description "@{YangTextTemplate.formatToParagraph(module.getDescription(), 12)}";
+            }
+        }
+        @if(module.getChildNodes() != null) {
+            @yangTemplateWriteDataSchemaNodes(module.getChildNodes())
+        }
+        @if(module.getGroupings() != null && !module.getGroupings().isEmpty()) {
+            @yangTemplateWriteGroupingDefs(module.getGroupings())
+        }
+        @if(module.getAugmentations() != null && !module.getAugmentations().isEmpty()) {
+            @yangTemplateWriteAugments(module.getAugmentations())
+        }
+        @if(module.getDeviations() != null && !module.getDeviations().isEmpty()) {
+            @for(deviation <- module.getDeviations()) {
+                @if(deviation != null) {
+                    deviation @{deviation.getTargetPath()} {
+                        @if(deviation.getReference() != null && !deviation.getReference().isEmpty()) {
+                            reference "@{deviation.getReference()}";
+                        }
+                        @for(deviation <- deviation.getDeviates()) {
+                            @if(deviation != null && deviation.getDeviateType() != null ) {
+                                deviation @{deviation.getDeviateType().name()};
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        @if(module.getExtensionSchemaNodes() != null && !module.getExtensionSchemaNodes().isEmpty()) {
+            @for(extension <- module.getExtensionSchemaNodes()) {
+                @if(extension != null) {
+                    @yangTemplateWriteExtension(extension)
+                }
+            }
+        }
+        @if(module.getFeatures() != null && !module.getFeatures().isEmpty()) {
+            @for(feature <- module.getFeatures()) {
+                @if(feature != null) {
+                    @yangTemplateWriteFeature(feature)
+                }
+            }
+        }
+        @if(module.getIdentities() != null && !module.getIdentities().isEmpty()) {
+            @for(identity <- module.getIdentities()) {
+                @if(identity != null) {
+                    @yangTemplateWriteIdentity(identity)
+                }
+            }
+        }
+        @if(module.getNotifications() != null && !module.getNotifications().isEmpty()) {
+            @for(notification <- module.getNotifications()) {
+                @if(notification != null) {
+                    @yangTemplateWriteNotification(notification)
+                }
+            }
+        }
+        @if(module.getRpcs() != null && !module.getRpcs().isEmpty()) {
+            @for(rpc <- module.getRpcs()) {
+                @if(rpc != null) {
+                    @yangTemplateWriteRPC(rpc)
+                }
+            }
+        }
+        @if(module.getUnknownSchemaNodes() != null && !module.getUnknownSchemaNodes().isEmpty()) {
+            @yangTemplateWriteUnknownSchemaNodes(module.getUnknownSchemaNodes())
+        }
+        @if(module.getUses() != null && !module.getUses().isEmpty()) {
+            @yangTemplateWriteUsesNodes(module.getUses())
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForNode.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForNode.scala.txt
new file mode 100644 (file)
index 0000000..805f223
--- /dev/null
@@ -0,0 +1,79 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
+@import org.opendaylight.yangtools.yang.model.api.FeatureDefinition
+@import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+@import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
+@import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+@import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+@import org.opendaylight.yangtools.yang.model.api.SchemaNode
+@import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+@import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.Status
+@import org.opendaylight.yangtools.yang.model.api.`type`.EnumTypeDefinition
+@import org.opendaylight.yangtools.yang.model.api.`type`.EnumTypeDefinition.EnumPair
+
+@(node: SchemaNode)
+@if(node != null) {
+    @generateYangSnippet(node)
+}
+
+@generateYangSnippet(node: SchemaNode) = {
+    @if(node.isInstanceOf[DataSchemaNode]) {
+        @yangTemplateWriteDataSchemaNode(node.asInstanceOf[DataSchemaNode])
+    }
+    @if(node.isInstanceOf[EnumTypeDefinition.EnumPair]) {
+        enum @{node.asInstanceOf[EnumTypeDefinition.EnumPair].getName()} {
+            @if(node.asInstanceOf[EnumTypeDefinition.EnumPair].getValue() != null) {
+                value @{node.asInstanceOf[EnumTypeDefinition.EnumPair].getValue()};
+            } else {
+            ;
+            }
+        }
+    }
+    @if(node.isInstanceOf[ExtensionDefinition]) {
+        @yangTemplateWriteExtension(node.asInstanceOf[ExtensionDefinition])
+    }
+    @if(node.isInstanceOf[FeatureDefinition]) {
+        @yangTemplateWriteFeature(node.asInstanceOf[FeatureDefinition])
+    }
+    @if(node.isInstanceOf[GroupingDefinition]) {
+        @yangTemplateWriteGroupingDef(node.asInstanceOf[GroupingDefinition])
+    }
+    @if(node.isInstanceOf[IdentitySchemaNode]) {
+        @yangTemplateWriteIdentity(node.asInstanceOf[IdentitySchemaNode])
+    }
+    @if(node.isInstanceOf[NotificationDefinition]) {
+        @yangTemplateWriteNotification(node.asInstanceOf[NotificationDefinition])
+    }
+    @if(node.isInstanceOf[RpcDefinition]) {
+        @yangTemplateWriteRPC(node.asInstanceOf[RpcDefinition])
+    }
+    @if(node.isInstanceOf[TypeDefinition[_]]) {
+    type @{node.asInstanceOf[TypeDefinition[_]].getQName().getLocalName()}
+        @if(node.asInstanceOf[TypeDefinition[_]].getStatus() != Status.CURRENT) {
+            status @{node.asInstanceOf[TypeDefinition[_]].getStatus()};
+        } else {
+        ;
+        }
+    }
+    @if(node.isInstanceOf[UnknownSchemaNode]) {
+        @yangTemplateWriteUnknownSchemaNode(node.asInstanceOf[UnknownSchemaNode])
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForNodes.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateForNodes.scala.txt
new file mode 100644 (file)
index 0000000..3d4da7c
--- /dev/null
@@ -0,0 +1,32 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+@import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+@import org.opendaylight.yangtools.yang.model.api.SchemaNode
+
+@(nodes: Set[_ <: SchemaNode])
+@if(nodes != null) {
+    @for(node <- nodes) {
+        @if(node.isInstanceOf[NotificationDefinition]) {
+                @yangTemplateWriteNotification(node.asInstanceOf[NotificationDefinition])
+        }
+        @if(node.isInstanceOf[RpcDefinition]) {
+                @yangTemplateWriteRPC(node.asInstanceOf[RpcDefinition])
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteAugments.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteAugments.scala.txt
new file mode 100644 (file)
index 0000000..4820c13
--- /dev/null
@@ -0,0 +1,45 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.mdsal.binding2.generator.impl.util.YangTextTemplate
+@import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
+
+@(augments: Set[_ <: AugmentationSchema])
+@for(augment <- augments) {
+    @if(augment != null) {
+        augment @{YangTextTemplate.formatToAugmentPath(augment.getTargetPath().getPathFromRoot())} {
+            @if(augment.getWhenCondition() != null && !augment.getWhenCondition().toString().isEmpty()) {
+                when "@augment.getWhenCondition().toString()";
+            }
+            @if(augment.getDescription() != null && !augment.getDescription().isEmpty()) {
+                description "@augment.getDescription().toString()";
+            }
+            @if(augment.getReference() != null && !augment.getReference().isEmpty()) {
+                reference "@augment.getReference().toString()";
+            }
+            @if(augment.getStatus() != null) {
+                status "@augment.getStatus()";
+            }
+            @if(augment.getChildNodes() != null && !augment.getChildNodes().isEmpty()) {
+                @yangTemplateWriteDataSchemaNodes(augment.getChildNodes())
+            }
+            @if(augment.getUses() != null && !augment.getUses().isEmpty()) {
+                @yangTemplateWriteUsesNodes(augment.getUses())
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteDataSchemaNode.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteDataSchemaNode.scala.txt
new file mode 100644 (file)
index 0000000..a68bf99
--- /dev/null
@@ -0,0 +1,131 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+@import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.SchemaNode
+@import org.opendaylight.yangtools.yang.model.api.Status
+@import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
+
+@(dataSchemaNode: DataSchemaNode)
+@if(dataSchemaNode.isInstanceOf[ContainerSchemaNode]) {
+    @writeContSchemaNode(dataSchemaNode.asInstanceOf[ContainerSchemaNode])
+}
+@if(dataSchemaNode.isInstanceOf[AnyXmlSchemaNode]) {
+    anyxml @{dataSchemaNode.asInstanceOf[AnyXmlSchemaNode].getQName().getLocalName()}
+    @if(dataSchemaNode.asInstanceOf[AnyXmlSchemaNode].getStatus() != Status.CURRENT) {
+        ;
+    } else {
+        {
+            status @{dataSchemaNode.asInstanceOf[AnyXmlSchemaNode].getStatus()};
+        }
+    }
+}
+@if(dataSchemaNode.isInstanceOf[LeafSchemaNode]) {
+    leaf @{dataSchemaNode.asInstanceOf[LeafSchemaNode].getQName().getLocalName()} {
+        type @{dataSchemaNode.asInstanceOf[LeafSchemaNode].getType().getQName().getLocalName()};
+    }
+    @if(dataSchemaNode.asInstanceOf[LeafSchemaNode].getStatus() != Status.CURRENT) {
+        status @{dataSchemaNode.asInstanceOf[LeafSchemaNode].getStatus()};
+    }
+}
+@if(dataSchemaNode.isInstanceOf[LeafListSchemaNode]) {
+    leaf-list @{dataSchemaNode.asInstanceOf[LeafListSchemaNode].getQName().getLocalName()} {
+        type @{dataSchemaNode.asInstanceOf[LeafListSchemaNode].getType().getQName().getLocalName()};
+    }
+    @if(dataSchemaNode.asInstanceOf[LeafListSchemaNode].getStatus() != Status.CURRENT) {
+        status @{dataSchemaNode.asInstanceOf[LeafListSchemaNode].getStatus()};
+    }
+}
+@if(dataSchemaNode.isInstanceOf[ChoiceCaseNode]) {
+    case @{dataSchemaNode.asInstanceOf[ChoiceCaseNode].getQName().getLocalName()} {
+        @for(childNode <- dataSchemaNode.asInstanceOf[ChoiceCaseNode].getChildNodes()) {
+            @yangTemplateWriteDataSchemaNode(childNode)
+        }
+    }
+    @if(dataSchemaNode.asInstanceOf[ChoiceCaseNode].getStatus() != Status.CURRENT) {
+        status @{dataSchemaNode.asInstanceOf[ChoiceCaseNode].getStatus()};
+    }
+}
+@if(dataSchemaNode.isInstanceOf[ChoiceSchemaNode]) {
+    choice @{dataSchemaNode.asInstanceOf[ChoiceSchemaNode].getQName().getLocalName()} {
+        @for(childNode <- dataSchemaNode.asInstanceOf[ChoiceSchemaNode].getCases()) {
+            @yangTemplateWriteDataSchemaNode(childNode)
+        }
+    }
+    @if(dataSchemaNode.asInstanceOf[ChoiceSchemaNode].getStatus() != Status.CURRENT) {
+        status @{dataSchemaNode.asInstanceOf[ChoiceSchemaNode].getStatus()};
+    }
+}
+@if(dataSchemaNode.isInstanceOf[ListSchemaNode]) {
+    @writeListSchemaNode(dataSchemaNode.asInstanceOf[ListSchemaNode])
+}
+
+@writeContSchemaNode(container: ContainerSchemaNode) = {
+    container @{container.getQName().getLocalName()} {
+        @if(container.getChildNodes() != null && !container.getChildNodes().isEmpty()) {
+            @yangTemplateWriteDataSchemaNodes(container.getChildNodes())
+        }
+        @if(container.getAvailableAugmentations() != null && !container.getAvailableAugmentations().isEmpty()) {
+            @yangTemplateWriteAugments(container.getAvailableAugmentations())
+        }
+        @if(container.getGroupings() != null && !container.getGroupings().isEmpty()) {
+            @yangTemplateWriteGroupingDefs(container.getGroupings())
+        }
+        @if(container.getUses() != null && !container.getUses().isEmpty()) {
+            @yangTemplateWriteUsesNodes(container.getUses())
+        }
+        @if(container.getStatus() != Status.CURRENT) {
+            status @{container.getStatus()};
+        }
+        @if(container.getUnknownSchemaNodes() != null && !container.getUnknownSchemaNodes().isEmpty()) {
+            @yangTemplateWriteUnknownSchemaNodes(container.getUnknownSchemaNodes())
+        }
+    }
+}
+
+@writeListSchemaNode(list: ListSchemaNode) = {
+    list @{list.getQName().getLocalName()} {
+        key "@for(listKey <- list.getKeyDefinition()) {
+            @{listKey.getLocalName()}
+        }"
+        @if(list.getChildNodes() != null && !list.getChildNodes().isEmpty()) {
+            @yangTemplateWriteDataSchemaNodes(list.getChildNodes())
+        }
+        @if(list.getAvailableAugmentations() != null && !list.getAvailableAugmentations().isEmpty()) {
+            @yangTemplateWriteAugments(list.getAvailableAugmentations())
+        }
+        @if(list.getGroupings() != null && !list.getGroupings().isEmpty()) {
+            @yangTemplateWriteGroupingDefs(list.getGroupings())
+        }
+        @if(list.getUses() != null && !list.getUses().isEmpty()) {
+            @yangTemplateWriteUsesNodes(list.getUses())
+        }
+        @if(list.getStatus() != Status.CURRENT) {
+            status @{list.getStatus()};
+        }
+        @if(list.getUnknownSchemaNodes() != null && !list.getUnknownSchemaNodes().isEmpty()) {
+            @yangTemplateWriteUnknownSchemaNodes(list.getUnknownSchemaNodes())
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteDataSchemaNodes.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteDataSchemaNodes.scala.txt
new file mode 100644 (file)
index 0000000..40e7ac3
--- /dev/null
@@ -0,0 +1,23 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+
+@(dataSchemaNodes: Collection[_ <: DataSchemaNode])
+@for(dataSchemaNode <- dataSchemaNodes) {
+    @yangTemplateWriteDataSchemaNode(dataSchemaNode)
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteExtension.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteExtension.scala.txt
new file mode 100644 (file)
index 0000000..e637052
--- /dev/null
@@ -0,0 +1,34 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
+
+@(extension: ExtensionDefinition)
+extension @{extension.getQName().getLocalName()} {
+    @if(extension.getDescription() != null && !extension.getDescription().isEmpty()) {
+        description "@{extension.getDescription()}";
+    }
+    @if(extension.getArgument() != null && !extension.getArgument().isEmpty()) {
+        argument "@{extension.getArgument()}";
+    }
+    @if(extension.getReference() != null && !extension.getReference().isEmpty()) {
+        reference "@{extension.getReference()}";
+    }
+    @if(extension.getStatus() != null) {
+        status @{extension.getStatus()};
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteFeature.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteFeature.scala.txt
new file mode 100644 (file)
index 0000000..e81e358
--- /dev/null
@@ -0,0 +1,31 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.FeatureDefinition
+
+@(feature: FeatureDefinition)
+feature @{feature.getQName().getLocalName()} {
+    @if(feature.getDescription() != null && !feature.getDescription().isEmpty()) {
+        description "@{feature.getDescription()}";
+    }
+    @if(feature.getReference() != null && !feature.getReference().isEmpty()) {
+        reference "@{feature.getReference()}";
+    }
+    @if(feature.getStatus() != null) {
+        status @{feature.getStatus()};
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteGroupingDef.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteGroupingDef.scala.txt
new file mode 100644 (file)
index 0000000..5b1a562
--- /dev/null
@@ -0,0 +1,35 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+@import org.opendaylight.yangtools.yang.model.api.Status
+
+@(groupingDef: GroupingDefinition)
+grouping @{groupingDef.getQName().getLocalName()} {
+    @if(groupingDef.getGroupings() != null && !groupingDef.getGroupings().isEmpty()) {
+        @yangTemplateWriteGroupingDefs(groupingDef.getGroupings())
+    }
+    @if(groupingDef.getChildNodes() != null && !groupingDef.getChildNodes().isEmpty()) {
+        @yangTemplateWriteDataSchemaNodes(groupingDef.getChildNodes())
+    }
+    @if(groupingDef.getStatus() != Status.CURRENT) {
+        status @{groupingDef.getStatus()};
+    }
+    @if(groupingDef.getUnknownSchemaNodes() != null && !groupingDef.getUnknownSchemaNodes().isEmpty()) {
+        @yangTemplateWriteUnknownSchemaNodes(groupingDef.getUnknownSchemaNodes())
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteGroupingDefs.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteGroupingDefs.scala.txt
new file mode 100644 (file)
index 0000000..533b654
--- /dev/null
@@ -0,0 +1,25 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+
+@(groupingDefs: Set[_ <: GroupingDefinition])
+@for(groupingDef <- groupingDefs) {
+    @if(groupingDef != null) {
+        @yangTemplateWriteGroupingDef(groupingDef)
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteIdentity.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteIdentity.scala.txt
new file mode 100644 (file)
index 0000000..a72bf08
--- /dev/null
@@ -0,0 +1,40 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
+
+@(identity: IdentitySchemaNode)
+identity @{identity.getQName().getLocalName()} {
+    @if(identity.getBaseIdentity() != null) {
+        base "(@writeIdentityNs(identity.getBaseIdentity()))@{identity.getBaseIdentity()}";
+    }
+    @if(identity.getDescription() != null && !identity.getDescription().isEmpty()) {
+        description "@{identity.getDescription()}";
+    }
+    @if(identity.getReference() != null && !identity.getReference().isEmpty()) {
+        reference "@{identity.getReference()}";
+    }
+    @if(identity.getStatus() != null) {
+        status @{identity.getStatus()};
+    }
+}
+
+@writeIdentityNs(identity: IdentitySchemaNode) = {
+    @if(identity.getQName().getNamespace() != null) {
+        @{identity.getQName().getNamespace()}:
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteNotification.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteNotification.scala.txt
new file mode 100644 (file)
index 0000000..610103e
--- /dev/null
@@ -0,0 +1,44 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+@import org.opendaylight.yangtools.yang.model.api.Status
+
+@(notification: NotificationDefinition)
+notification @{notification.getQName().getLocalName()} {
+    @if(notification.getDescription() != null && !notification.getDescription().isEmpty()) {
+        description "@{notification.getDescription()}";
+    }
+    @if(notification.getChildNodes() != null && !notification.getChildNodes().isEmpty()) {
+        @yangTemplateWriteDataSchemaNodes(notification.getChildNodes())
+    }
+    @if(notification.getAvailableAugmentations() != null && !notification.getAvailableAugmentations().isEmpty()) {
+        @yangTemplateWriteAugments(notification.getAvailableAugmentations())
+    }
+    @if(notification.getGroupings() != null && !notification.getGroupings().isEmpty()) {
+        @yangTemplateWriteGroupingDefs(notification.getGroupings())
+    }
+    @if(notification.getUses() != null && !notification.getUses().isEmpty()) {
+        @yangTemplateWriteUsesNodes(notification.getUses())
+    }
+    @if(notification.getReference() != null && !notification.getReference().isEmpty()) {
+        reference "@{notification.getReference()}";
+    }
+    @if(notification.getStatus() != Status.CURRENT) {
+        status @{notification.getStatus()};
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteRPC.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteRPC.scala.txt
new file mode 100644 (file)
index 0000000..2436b72
--- /dev/null
@@ -0,0 +1,49 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+@import org.opendaylight.yangtools.yang.model.api.Status
+
+@(rpc: RpcDefinition)
+rpc @{rpc.getQName().getLocalName()} {
+    @if(rpc.getDescription() != null && !rpc.getDescription().isEmpty()) {
+        "@{rpc.getDescription()}";
+    }
+    @if(rpc.getGroupings() != null && !rpc.getGroupings().isEmpty()) {
+        @yangTemplateWriteGroupingDefs(rpc.getGroupings())
+    }
+    @if(rpc.getInput() != null) {
+        input {
+            @if(rpc.getInput().getChildNodes != null && !rpc.getInput().getChildNodes().isEmpty()) {
+                @yangTemplateWriteDataSchemaNodes(rpc.getInput().getChildNodes)
+            }
+        }
+    }
+    @if(rpc.getOutput() != null) {
+        output {
+            @if(rpc.getOutput().getChildNodes != null && !rpc.getOutput().getChildNodes().isEmpty()) {
+                @yangTemplateWriteDataSchemaNodes(rpc.getOutput().getChildNodes)
+            }
+        }
+    }
+    @if(rpc.getReference() != null && !rpc.getReference().isEmpty()) {
+        reference "@{rpc.getReference()}";
+    }
+    @if(rpc.getStatus() != Status.CURRENT) {
+        status @{rpc.getStatus()};
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUnknownSchemaNode.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUnknownSchemaNode.scala.txt
new file mode 100644 (file)
index 0000000..11a2de8
--- /dev/null
@@ -0,0 +1,24 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
+
+@(unknownSchemaNode: UnknownSchemaNode)
+@if(unknownSchemaNode != null) {
+    test
+    @* to do *@
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUnknownSchemaNodes.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUnknownSchemaNodes.scala.txt
new file mode 100644 (file)
index 0000000..852cdd1
--- /dev/null
@@ -0,0 +1,25 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
+
+@(unknownSchemaNodes: List[_ <: UnknownSchemaNode])
+@for(unknownSchemaNode <- unknownSchemaNodes) {
+    @if(unknownSchemaNode != null) {
+        @yangTemplateWriteUnknownSchemaNode(unknownSchemaNode)
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUsesNodes.scala.txt b/binding2/mdsal-binding2-generator-impl/src/main/twirl/org/opendaylight/mdsal/binding2/yangTemplateWriteUsesNodes.scala.txt
new file mode 100644 (file)
index 0000000..3c9396e
--- /dev/null
@@ -0,0 +1,41 @@
+@*
+ * Copyright (c) 2016 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
+ *@
+
+@**********************************************************
+* Twirl YangTemplate for generating yang snippets.        *
+* Twirl is transformed to Scala and compiled. Then,       *
+* it can be called from Java with particular input        *
+* parameters to render desired output code.               *
+*                                                         *
+* Note: we should introduce our own format instead of txt *
+***********************************************************@
+
+@import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+@import org.opendaylight.yangtools.yang.model.api.UsesNode
+
+@(usesNodes: Set[_ <: UsesNode])
+@if(usesNodes != null) {
+    @for(usesNode <- usesNodes) {
+        @if(usesNode != null) {
+            uses @{usesNode.getGroupingPath().getLastComponent().getLocalName()}
+            @if(usesNode.getRefines().isEmpty()) {
+                ;
+            } else {
+                {
+                @for(path <- usesNode.getRefines().keySet()) {
+                    refine @{path.getLastComponent()} {
+                    @if(usesNode.getRefines().get(path).isInstanceOf[DataSchemaNode]) {
+                            @yangTemplateWriteDataSchemaNode(usesNode.getRefines().get(path).asInstanceOf[DataSchemaNode])
+                        }
+                    }
+                }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file