Bug 6856: Rpc definition should implicitly define input/ouput
[mdsal.git] / binding / mdsal-binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / BindingGeneratorImpl.java
index 83f5bb92b8a9f25a9f4450639ad2ef6142dd158c..c485d01a87306170cc51a496354898ad4d2e1957 100644 (file)
@@ -11,6 +11,7 @@ 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 static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.computeDefaultSUID;
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForAugmentedGeneratedType;
 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_OBJECT;
@@ -26,6 +27,7 @@ import static org.opendaylight.yangtools.binding.generator.util.Types.typeForCla
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -36,6 +38,7 @@ import com.google.common.collect.Sets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -93,18 +96,19 @@ 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.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.BaseTypes;
 import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
-import org.opendaylight.yangtools.yang.model.util.UnionType;
-import org.opendaylight.yangtools.yang.parser.builder.util.Comparators;
+import org.opendaylight.yangtools.yang.model.util.type.CompatUtils;
 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -115,6 +119,27 @@ public class BindingGeneratorImpl implements BindingGenerator {
     private static final Splitter BSDOT_SPLITTER = Splitter.on("\\.");
     private static final char NEW_LINE = '\n';
 
+    /**
+     * 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;
+    };
+
     /**
      * Constant with the concrete name of identifier.
      */
@@ -310,6 +335,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
         final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module);
         genType.addComment(node.getDescription());
+        annotateDeprecatedIfNecessary(node.getStatus(), genType);
         genType.setDescription(createDescription(node, genType.getFullyQualifiedName()));
         genType.setModuleName(module.getName());
         genType.setReference(node.getReference());
@@ -326,7 +352,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node) {
         final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node);
         if (genType != null) {
-            constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType);
+            constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType, node.getStatus());
             resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes());
         }
     }
@@ -335,7 +361,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
             final GeneratedTypeBuilder childOf, final ListSchemaNode node) {
         final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node);
         if (genType != null) {
-            constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), Types.listTypeFor(genType));
+            constructGetter(parent, node.getQName().getLocalName(), node.getDescription(),
+                    Types.listTypeFor(genType), node.getStatus());
 
             final List<String> listKeys = listKeys(node);
             final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
@@ -421,7 +448,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         final Set<AugmentationSchema> augmentations = module.getAugmentations();
         final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
-        Collections.sort(sortedAugmentations, Comparators.AUGMENT_COMP);
+        Collections.sort(sortedAugmentations, AUGMENT_COMP);
 
         return sortedAugmentations;
     }
@@ -476,22 +503,25 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
         final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service");
         interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));
-        interfaceBuilder.setDescription(createDescription(rpcDefinitions, module.getName(), module.getModuleSourcePath()));
+        interfaceBuilder.setDescription(createDescription(rpcDefinitions, module.getName()));
 
         for (final RpcDefinition rpc : rpcDefinitions) {
             if (rpc != null) {
                 final String rpcName = BindingMapping.getClassName(rpc.getQName());
                 final String rpcMethodName = BindingMapping.getPropertyName(rpcName);
-                final String rpcComment = rpc.getDescription();
+                final String rpcComment = encodeAngleBrackets(rpc.getDescription());
                 final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);
                 final ContainerSchemaNode input = rpc.getInput();
                 final ContainerSchemaNode output = rpc.getOutput();
 
-                if (input != null) {
+                //in case of implicit RPC input (StatementSource.CONTEXT),
+                // stay compatible (no input argument generated)
+                if (input != null && isExplicitStatement(input)) {
                     final GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName);
                     addImplementedInterfaceFromUses(input, inType);
                     inType.addImplementsType(DATA_OBJECT);
                     inType.addImplementsType(augmentable(inType));
+                    annotateDeprecatedIfNecessary(rpc.getStatus(), inType);
                     resolveDataSchemaNodes(module, basePackageName, inType, inType, input.getChildNodes());
                     genCtx.get(module).addChildNodeType(input, inType);
                     final GeneratedType inTypeInstance = inType.toInstance();
@@ -499,11 +529,14 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 }
 
                 Type outTypeInstance = VOID;
-                if (output != null) {
+                //in case of implicit RPC output (StatementSource.CONTEXT),
+                //stay compatible (Future<RpcResult<Void>> return type generated)
+                if (output != null && isExplicitStatement(output)) {
                     final GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName);
                     addImplementedInterfaceFromUses(output, outType);
                     outType.addImplementsType(DATA_OBJECT);
                     outType.addImplementsType(augmentable(outType));
+                    annotateDeprecatedIfNecessary(rpc.getStatus(), outType);
                     resolveDataSchemaNodes(module, basePackageName, outType, outType, output.getChildNodes());
                     genCtx.get(module).addChildNodeType(output, outType);
                     outTypeInstance = outType.toInstance();
@@ -518,6 +551,11 @@ public class BindingGeneratorImpl implements BindingGenerator {
         genCtx.get(module).addTopLevelNodeType(interfaceBuilder);
     }
 
+    private static boolean isExplicitStatement(ContainerSchemaNode node) {
+        return node instanceof EffectiveStatement
+                && ((EffectiveStatement) node).getDeclared().getStatementSource() == StatementSource.DECLARATION;
+    }
+
     /**
      * Converts all <b>notifications</b> of the module to the list of
      * <code>Type</code> objects. In addition are to this list added containers
@@ -555,6 +593,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
                 final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName,
                         notification, null, module);
+                annotateDeprecatedIfNecessary(notification.getStatus(), notificationInterface);
                 notificationInterface.addImplementsType(NOTIFICATION);
                 genCtx.get(module).addChildNodeType(notification, notificationInterface);
 
@@ -564,10 +603,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
                 listenerInterface.addMethod("on" + notificationInterface.getName())
                 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification")
-                .setComment(notification.getDescription()).setReturnType(Types.VOID);
+                .setComment(encodeAngleBrackets(notification.getDescription())).setReturnType(Types.VOID);
             }
         }
-        listenerInterface.setDescription(createDescription(notifications, module.getName(), module.getModuleSourcePath()));
+        listenerInterface.setDescription(createDescription(notifications, module.getName()));
 
         genCtx.get(module).addTopLevelNodeType(listenerInterface);
     }
@@ -693,6 +732,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
     private void groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module module) {
         final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath());
         final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping, module);
+        annotateDeprecatedIfNecessary(grouping.getStatus(), genType);
         genCtx.get(module).addGroupingType(grouping.getPath(), genType);
         resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.getChildNodes());
         groupingsToGenTypes(module, grouping.getGroupings());
@@ -724,7 +764,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 && (enumTypeDef.getQName().getLocalName() != null)) {
             final String enumerationName = BindingMapping.getClassName(enumName);
             final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
-            enumBuilder.setDescription(enumTypeDef.getDescription());
+            final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription());
+            enumBuilder.setDescription(enumTypedefDescription);
             enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
             ModuleContext ctx = genCtx.get(module);
             ctx.addInnerTypedefType(enumTypeDef.getPath(), enumBuilder);
@@ -825,7 +866,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         } else {
             generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(),
-                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes());
+                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(), null);
         }
     }
 
@@ -860,7 +901,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     augSchema);
         } else {
             generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(),
-                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes());
+                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(), usesNodeParent);
         }
     }
 
@@ -883,10 +924,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final GroupingDefinition grouping = (GroupingDefinition) targetGrouping;
         SchemaNode result = grouping;
         for (final QName node : targetPath.getPathFromRoot()) {
-            // finding by local name is valid, grouping cannot contain nodes
-            // with same name and different namespace
             if (result instanceof DataNodeContainer) {
-                result = ((DataNodeContainer) result).getDataChildByName(node.getLocalName());
+                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());
             }
@@ -964,13 +1004,13 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         augTypeBuilder.addImplementsType(DATA_OBJECT);
         augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
+        annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder);
         addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
 
         augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.getChildNodes());
         augmentBuilders.put(augTypeName, augTypeBuilder);
 
-        if(!augSchema.getChildNodes().isEmpty()) {
-            genCtx.get(module).addTargetToAugmentation(targetTypeRef, augTypeBuilder);
+        if (!augSchema.getChildNodes().isEmpty()) {
             genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
 
         }
@@ -1157,9 +1197,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
         if (!choiceNode.isAddedByUses()) {
             final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());
             final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
-            constructGetter(parent, choiceNode.getQName().getLocalName(), choiceNode.getDescription(),
-                    choiceTypeBuilder);
+            constructGetter(parent, choiceNode.getQName().getLocalName(),
+                    choiceNode.getDescription(), choiceTypeBuilder, choiceNode.getStatus());
             choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class));
+            annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder);
             genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder);
             generateTypesFromChoiceCases(module, basePackageName, choiceTypeBuilder.toInstance(), choiceNode);
         }
@@ -1208,6 +1249,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
                 caseTypeBuilder.addImplementsType(refChoiceType);
+                annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder);
                 genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
                 genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
                 final Iterable<DataSchemaNode> caseChildNodes = caseNode.getChildNodes();
@@ -1280,7 +1322,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             </ul>
      */
     private void generateTypesFromAugmentedChoiceCases(final Module module, final String basePackageName,
-            final Type targetType, final ChoiceSchemaNode targetNode, final Iterable<DataSchemaNode> augmentedNodes) {
+            final Type targetType, final ChoiceSchemaNode targetNode, final Iterable<DataSchemaNode> augmentedNodes,
+            final DataNodeContainer usesNodeParent) {
         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.");
@@ -1311,10 +1354,20 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 }
 
                 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(caseNode.getQName().getLocalName());
+                    node = targetNode.getCaseNodeByName(caseLocalName);
                 }
                 final Iterable<DataSchemaNode> childNodes = node.getChildNodes();
                 if (childNodes != null) {
@@ -1326,6 +1379,20 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }
     }
 
+    private static boolean isInnerType(final LeafSchemaNode leaf, final TypeDefinition<?> type) {
+        // New parser with encapsulated type
+        if (leaf.getPath().equals(type.getPath())) {
+            return true;
+        }
+
+        // Embedded type definition with new parser. Also takes care of the old parser with bits
+        if (leaf.getPath().equals(type.getPath().getParent())) {
+            return true;
+        }
+
+        return false;
+    }
+
     /**
      * Converts <code>leaf</code> to the getter method which is added to
      * <code>typeBuilder</code>.
@@ -1355,34 +1422,38 @@ public class BindingGeneratorImpl implements BindingGenerator {
             return null;
         }
 
-        Type returnType = null;
         final Module parentModule = findParentModule(schemaContext, leaf);
+        Type returnType = null;
 
-        // FIXME: cascade assumes that ExtendedType does not resolve into any of the TypeDefinitions and
-        //        will pass on to the default case. That default case will be also taken for base types.
-        //        There is another twist here, which is the fact that the new parser will wrap the type
-        //        if we have redefined the default value -- which is not something that was done before.
-
-        final TypeDefinition<?> typeDef = leaf.getType();
-        if (typeDef instanceof EnumTypeDefinition) {
-            returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
-            final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
-            final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(),
-                typeBuilder, module);
-
-            if (enumBuilder != null) {
-                returnType = enumBuilder.toInstance(typeBuilder);
-            }
-            ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
-        } else if (typeDef instanceof UnionTypeDefinition) {
-            GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
-            if (genTOBuilder != null) {
-                returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
-            }
-        } else if (typeDef instanceof BitsTypeDefinition) {
-            GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
-            if (genTOBuilder != null) {
-                returnType = genTOBuilder.toInstance();
+        final TypeDefinition<?> typeDef = CompatUtils.compatLeafType(leaf);
+        if (isInnerType(leaf, typeDef)) {
+            if (typeDef instanceof EnumTypeDefinition) {
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
+                final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
+                final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(),
+                    typeBuilder, module);
+                if (enumBuilder != null) {
+                    returnType = enumBuilder.toInstance(typeBuilder);
+                }
+                ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
+            } else if (typeDef instanceof UnionTypeDefinition) {
+                GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
+                if (genTOBuilder != null) {
+                    returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
+                }
+            } else if (typeDef instanceof BitsTypeDefinition) {
+                GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
+                if (genTOBuilder != null) {
+                    returnType = genTOBuilder.toInstance();
+                }
+            } else {
+                // It is constrained version of already declared type (inner declared type exists,
+                // onlyfor special cases (Enum, Union, Bits), which were already checked.
+                // In order to get proper class we need to look up closest derived type
+                // and apply restrictions from leaf type
+                final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
+                        restrictions);
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
@@ -1393,16 +1464,26 @@ public class BindingGeneratorImpl implements BindingGenerator {
             return null;
         }
 
+        if (typeDef instanceof EnumTypeDefinition) {
+            ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
+        }
+
         String leafDesc = leaf.getDescription();
         if (leafDesc == null) {
             leafDesc = "";
         }
 
-        final MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
+        final MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType, leaf.getStatus());
         processContextRefExtension(leaf, getter, parentModule);
         return returnType;
     }
 
+    private static TypeDefinition<?> getBaseOrDeclaredType(final TypeDefinition<?> typeDef) {
+        // Returns DerivedType in case of new parser.
+        final TypeDefinition<?> baseType = typeDef.getBaseType();
+        return (baseType != null && baseType.getBaseType() != null) ? baseType : typeDef;
+    }
+
     private void processContextRefExtension(final LeafSchemaNode leaf, final MethodSignatureBuilder getter,
             final Module module) {
         for (final UnknownSchemaNode node : leaf.getUnknownSchemaNodes()) {
@@ -1471,7 +1552,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 leafDesc = "";
             }
             Type returnType = null;
-            final TypeDefinition<?> typeDef = leaf.getType();
+            final TypeDefinition<?> typeDef = CompatUtils.compatLeafType(leaf);
             if (typeDef instanceof UnionTypeDefinition) {
                 // GeneratedType for this type definition should be already
                 // created
@@ -1480,7 +1561,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                         qname.getRevision());
                 final ModuleContext mc = genCtx.get(unionModule);
                 returnType = mc.getTypedefs().get(typeDef.getPath());
-            } else if (typeDef instanceof EnumTypeDefinition && BaseTypes.ENUMERATION_QNAME.equals(typeDef.getQName())) {
+            } else if (typeDef instanceof EnumTypeDefinition && typeDef.getBaseType() == null) {
                 // Annonymous enumeration (already generated, since it is inherited via uses).
                 LeafSchemaNode originalLeaf = (LeafSchemaNode) SchemaNodeUtils.getRootOriginalIfPossible(leaf);
                 QName qname = originalLeaf.getQName();
@@ -1522,7 +1603,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             return false;
         }
         final String leafName = leaf.getQName().getLocalName();
-        final String leafDesc = leaf.getDescription();
+        final String leafDesc = encodeAngleBrackets(leaf.getDescription());
         final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(BindingMapping.getPropertyName(leafName));
         propBuilder.setReadOnly(isReadOnly);
         propBuilder.setReturnType(returnType);
@@ -1552,48 +1633,56 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *         </ul>
      */
     private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node, final Module module) {
-        if ((node != null) && (typeBuilder != null)) {
-            final QName nodeName = node.getQName();
-
-            if (nodeName != null && !node.isAddedByUses()) {
-                final TypeDefinition<?> typeDef = node.getType();
-                final Module parentModule = findParentModule(schemaContext, node);
-
-                Type returnType = null;
-                if (typeDef instanceof EnumTypeDefinition) {
-                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node);
-                    final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
-                    final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName,
-                            typeBuilder,module);
-                    returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());
-                    ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType);
-                } else if (typeDef instanceof UnionType) {
-                    final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
-                    if (genTOBuilder != null) {
-                        returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
-                    }
-                } else if (typeDef instanceof BitsTypeDefinition) {
-                    final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
-                    returnType = genTOBuilder.toInstance();
-                } else {
-                    final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
-                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions);
-                }
+        if (node == null || typeBuilder == null || node.isAddedByUses()) {
+            return false;
+        }
+
+        final QName nodeName = node.getQName();
+        if (nodeName == null) {
+            return false;
+        }
+
+        final TypeDefinition<?> typeDef = node.getType();
+        final Module parentModule = findParentModule(schemaContext, node);
 
-                final ParameterizedType listType = Types.listTypeFor(returnType);
-                constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription(), listType);
-                return true;
+        Type returnType = null;
+        if (typeDef.getBaseType() == null) {
+            if (typeDef instanceof EnumTypeDefinition) {
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node);
+                final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
+                final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName,
+                    typeBuilder,module);
+                returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());
+                ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType);
+            } else if (typeDef instanceof UnionTypeDefinition) {
+                final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
+                if (genTOBuilder != null) {
+                    returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
+                }
+            } else if (typeDef instanceof BitsTypeDefinition) {
+                final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
+                returnType = genTOBuilder.toInstance();
+            } else {
+                final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions);
             }
+        } else {
+            final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+            returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions);
         }
-        return false;
+
+        final ParameterizedType listType = Types.listTypeFor(returnType);
+        constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription(), listType, node.getStatus());
+        return true;
     }
 
     private Type createReturnTypeForUnion(final GeneratedTOBuilder genTOBuilder, final TypeDefinition<?> typeDef,
             final GeneratedTypeBuilder typeBuilder, final Module parentModule) {
         final GeneratedTOBuilderImpl returnType = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
                 genTOBuilder.getName());
+        final String typedefDescription = encodeAngleBrackets(typeDef.getDescription());
 
-        returnType.setDescription(typeDef.getDescription());
+        returnType.setDescription(typedefDescription);
         returnType.setReference(typeDef.getReference());
         returnType.setSchemaPath(typeDef.getPath().getPathFromRoot());
         returnType.setModuleName(parentModule.getName());
@@ -1803,14 +1892,19 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *            string with comment for the getter method
      * @param returnType
      *            type which represents the return type of the getter method
+     * @param status
+     *            status from yang file, for deprecated annotation
      * @return method signature builder which represents the getter method of
      *         <code>interfaceBuilder</code>
      */
     private static MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder,
-            final String schemaNodeName, final String comment, final Type returnType) {
+            final String schemaNodeName, final String comment, final Type returnType, final Status status) {
         final MethodSignatureBuilder getMethod = interfaceBuilder
                 .addMethod(getterMethodName(schemaNodeName, returnType));
-        getMethod.setComment(comment);
+        if (status == Status.DEPRECATED) {
+            getMethod.addAnnotation("", "Deprecated");
+        }
+        getMethod.setComment(encodeAngleBrackets(comment));
         getMethod.setReturnType(returnType);
         return getMethod;
     }
@@ -1875,7 +1969,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         if (genTOBuilder != null) {
             final GeneratedTransferObject genTO = genTOBuilder.toInstance();
-            constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO);
+            constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO, Status.CURRENT);
             genCtx.get(module).addGeneratedTOBuilder(genTOBuilder);
         }
     }
@@ -1926,10 +2020,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
     /**
      * Builds generated TO builders for <code>typeDef</code> of type
-     * {@link org.opendaylight.yangtools.yang.model.util.UnionType UnionType} or
-     * {@link org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
-     * BitsTypeDefinition} which are also added to <code>typeBuilder</code> as
-     * enclosing transfer object.
+     * {@link UnionTypeDefinition} or {@link BitsTypeDefinition} which are
+     * also added to <code>typeBuilder</code> as enclosing transfer object.
      *
      * If more then one generated TO builder is created for enclosing then all
      * of the generated TO builders are added to <code>typeBuilder</code> as
@@ -2029,7 +2121,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return list == null || list.isEmpty();
     }
 
-    private String createDescription(final Set<? extends SchemaNode> schemaNodes, final String moduleName, final String moduleSourcePath) {
+    private String createDescription(final Set<? extends SchemaNode> schemaNodes, final String moduleName) {
         final StringBuilder sb = new StringBuilder();
 
         if (!isNullOrEmpty(schemaNodes)) {
@@ -2042,15 +2134,11 @@ public class BindingGeneratorImpl implements BindingGenerator {
             }
         }
         sb.append(NEW_LINE);
-        sb.append("<br>(Source path: <i>");
-        sb.append(moduleSourcePath);
-        sb.append("</i>):");
-        sb.append(NEW_LINE);
 
         if (verboseClassComments) {
             sb.append("<pre>");
             sb.append(NEW_LINE);
-            sb.append(YangTemplate.generateYangSnipet(schemaNodes));
+            sb.append(encodeAngleBrackets(YangTemplate.generateYangSnipet(schemaNodes)));
             sb.append("</pre>");
             sb.append(NEW_LINE);
         }
@@ -2060,7 +2148,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
     private String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName) {
         final StringBuilder sb = new StringBuilder();
-        final String formattedDescription = YangTemplate.formatToParagraph(schemaNode.getDescription(), 0);
+        final String nodeDescription = encodeAngleBrackets(schemaNode.getDescription());
+        final String formattedDescription = YangTextTemplate.formatToParagraph(nodeDescription, 0);
 
         if (!Strings.isNullOrEmpty(formattedDescription)) {
             sb.append(formattedDescription);
@@ -2083,19 +2172,15 @@ public class BindingGeneratorImpl implements BindingGenerator {
             sb.append(module.getName());
             sb.append("</b>");
             sb.append(NEW_LINE);
-            sb.append("<br>(Source path: <i>");
-            sb.append(module.getModuleSourcePath());
-            sb.append("</i>):");
-            sb.append(NEW_LINE);
             sb.append("<pre>");
             sb.append(NEW_LINE);
-            sb.append(YangTemplate.generateYangSnipet(schemaNode));
+            sb.append(encodeAngleBrackets(YangTemplate.generateYangSnipet(schemaNode)));
             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(YangTemplate.formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot()));
+            sb.append(YangTextTemplate.formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot()));
             sb.append("</i>");
             sb.append(NEW_LINE);
 
@@ -2131,7 +2216,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
     private String createDescription(final Module module) {
         final StringBuilder sb = new StringBuilder();
-        final String formattedDescription = YangTemplate.formatToParagraph(module.getDescription(), 0);
+        final String moduleDescription = encodeAngleBrackets(module.getDescription());
+        final String formattedDescription = YangTextTemplate.formatToParagraph(moduleDescription, 0);
 
         if (!Strings.isNullOrEmpty(formattedDescription)) {
             sb.append(formattedDescription);
@@ -2144,13 +2230,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
             sb.append(module.getName());
             sb.append("</b>");
             sb.append(NEW_LINE);
-            sb.append("<br>Source path: <i>");
-            sb.append(module.getModuleSourcePath());
-            sb.append("</i>):");
-            sb.append(NEW_LINE);
             sb.append("<pre>");
             sb.append(NEW_LINE);
-            sb.append(YangTemplate.generateYangSnipet(module));
+            sb.append(encodeAngleBrackets(YangTemplate.generateYangSnipet(module)));
             sb.append("</pre>");
         }
 
@@ -2196,4 +2278,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");
         return ret.isEmpty() ? "" : ret;
     }
+
+    private static void annotateDeprecatedIfNecessary(final Status status, final GeneratedTypeBuilder builder) {
+        if (status == Status.DEPRECATED) {
+            builder.addAnnotation("", "Deprecated");
+        }
+    }
 }