Fix derived types missing pattern restrictions
[mdsal.git] / binding / mdsal-binding-generator-impl / src / main / java / org / opendaylight / mdsal / binding / yang / types / TypeProviderImpl.java
index c1a4bc48e432096c9ab9b498ec709c81fc46d706..72a46406ed8a550806961f7a10ce01d9ed1ed0b3 100644 (file)
@@ -7,11 +7,10 @@
  */
 package org.opendaylight.mdsal.binding.yang.types;
 
-import static org.opendaylight.mdsal.binding.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
+import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.encodeAngleBrackets;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
-
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
@@ -36,12 +35,6 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.apache.commons.lang3.StringEscapeUtils;
 import org.opendaylight.mdsal.binding.generator.spi.TypeProvider;
-import org.opendaylight.mdsal.binding.generator.util.BindingGeneratorUtil;
-import org.opendaylight.mdsal.binding.generator.util.TypeConstants;
-import org.opendaylight.mdsal.binding.generator.util.Types;
-import org.opendaylight.mdsal.binding.generator.util.generated.type.builder.EnumerationBuilderImpl;
-import org.opendaylight.mdsal.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
-import org.opendaylight.mdsal.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.mdsal.binding.model.api.AccessModifier;
 import org.opendaylight.mdsal.binding.model.api.ConcreteType;
 import org.opendaylight.mdsal.binding.model.api.Enumeration;
@@ -54,6 +47,12 @@ import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBu
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
+import org.opendaylight.mdsal.binding.model.util.TypeConstants;
+import org.opendaylight.mdsal.binding.model.util.Types;
+import org.opendaylight.mdsal.binding.model.util.generated.type.builder.EnumerationBuilderImpl;
+import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedPropertyBuilderImpl;
+import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -91,6 +90,7 @@ import org.slf4j.LoggerFactory;
 
 public final class TypeProviderImpl implements TypeProvider {
     private static final Logger LOG = LoggerFactory.getLogger(TypeProviderImpl.class);
+    private static final Pattern GROUPS_PATTERN = Pattern.compile("\\[(.*?)\\]");
     private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
 
     // Backwards compatibility: Union types used to be instantiated in YANG namespace, which is no longer
@@ -195,7 +195,7 @@ public final class TypeProviderImpl implements TypeProvider {
         Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
         Preconditions.checkArgument(typeDefinition.getQName() != null,
                 "Type Definition cannot have non specified QName (QName cannot be NULL!)");
-        String typedefName = typeDefinition.getQName().getLocalName();
+        final String typedefName = typeDefinition.getQName().getLocalName();
         Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
 
         // Deal with base types
@@ -227,13 +227,13 @@ public final class TypeProviderImpl implements TypeProvider {
 
         Type returnType = javaTypeForExtendedType(typeDefinition);
         if (r != null && returnType instanceof GeneratedTransferObject) {
-            GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
-            Module module = findParentModule(schemaContext, parentNode);
-            String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
-            String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typeDefinition.getPath());
-            String genTOName = BindingMapping.getClassName(typedefName);
-            String name = packageName + "." + genTOName;
-            if (!(returnType.getFullyQualifiedName().equals(name))) {
+            final GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
+            final Module module = findParentModule(schemaContext, parentNode);
+            final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+            final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typeDefinition.getPath());
+            final String genTOName = BindingMapping.getClassName(typedefName);
+            final String name = packageName + "." + genTOName;
+            if (!returnType.getFullyQualifiedName().equals(name)) {
                 returnType = shadedTOWithRestrictions(gto, r);
             }
         }
@@ -241,14 +241,14 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, final Restrictions r) {
-        GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
-        GeneratedTransferObject parent = gto.getSuperType();
+        final GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
+        final GeneratedTransferObject parent = gto.getSuperType();
         if (parent != null) {
             gtob.setExtendsType(parent);
         }
         gtob.setRestrictions(r);
-        for (GeneratedProperty gp : gto.getProperties()) {
-            GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
+        for (final GeneratedProperty gp : gto.getProperties()) {
+            final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
             gpb.setValue(gp.getValue());
             gpb.setReadOnly(gp.isReadOnly());
             gpb.setAccessModifier(gp.getAccessModifier());
@@ -262,8 +262,8 @@ public final class TypeProviderImpl implements TypeProvider {
     private boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode) {
         final SchemaNode leafRefValueNode;
         final RevisionAwareXPath leafRefXPath = leafref.getPathStatement();
-        final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(leafRefXPath.toString()
-                .replaceAll("\\[(.*?)\\]", ""), leafRefXPath.isAbsolute());
+        final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(
+            GROUPS_PATTERN.matcher(leafRefXPath.toString()).replaceAll(""), leafRefXPath.isAbsolute());
 
         ///// skip leafrefs in augments - they're checked once augments are resolved
         final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
@@ -292,14 +292,14 @@ public final class TypeProviderImpl implements TypeProvider {
         }
         /////
 
-        Module parentModule = getParentModule(parentNode);
+        final Module parentModule = getParentModule(parentNode);
         if (!leafRefStrippedXPath.isAbsolute()) {
             leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
                     parentNode, leafRefStrippedXPath);
         } else {
             leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
         }
-        return (leafRefValueNode != null) ? leafRefValueNode.equals(parentNode) : false;
+        return leafRefValueNode != null ? leafRefValueNode.equals(parentNode) : false;
     }
 
     /**
@@ -345,7 +345,7 @@ public final class TypeProviderImpl implements TypeProvider {
                 returnType = provideTypeForEnum(enumTypeDef, typedefName, typeDefinition);
             } else {
                 final Module module = findParentModule(schemaContext, typeDefinition);
-                Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
+                final Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
                 if (module != null) {
                     final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
                     final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
@@ -378,11 +378,11 @@ public final class TypeProviderImpl implements TypeProvider {
      *         <code>idref</code>
      */
     private Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref) {
-        QName baseIdQName = idref.getIdentity().getQName();
-        Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
+        final QName baseIdQName = idref.getIdentity().getQName();
+        final Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
                 baseIdQName.getRevision());
         IdentitySchemaNode identity = null;
-        for (IdentitySchemaNode id : module.getIdentities()) {
+        for (final IdentitySchemaNode id : module.getIdentities()) {
             if (id.getQName().equals(baseIdQName)) {
                 identity = id;
             }
@@ -393,8 +393,8 @@ public final class TypeProviderImpl implements TypeProvider {
         final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath());
         final String genTypeName = BindingMapping.getClassName(identity.getQName());
 
-        Type baseType = Types.typeForClass(Class.class);
-        Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
+        final Type baseType = Types.typeForClass(Class.class);
+        final Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
         return Types.parameterizedTypeFor(baseType, paramType);
     }
 
@@ -423,15 +423,65 @@ public final class TypeProviderImpl implements TypeProvider {
                 "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 (baseTypeDef instanceof LeafrefTypeDefinition || baseTypeDef instanceof IdentityrefTypeDefinition) {
+            /*
+             * This is backwards compatibility baggage from way back when. The problem at hand is inconsistency between
+             * the fact that identity is mapped to a Class, which is also returned from leaves which specify it like
+             * this:
+             *
+             *     identity iden;
+             *
+             *     container foo {
+             *         leaf foo {
+             *             type identityref {
+             *                 base iden;
+             *             }
+             *         }
+             *     }
+             *
+             * This results in getFoo() returning Class<? extends Iden>, which looks fine on the surface, but gets more
+             * dicey when we throw in:
+             *
+             *     typedef bar-ref {
+             *         type identityref {
+             *             base iden;
+             *         }
+             *     }
+             *
+             *     container bar {
+             *         leaf bar {
+             *             type bar-ref;
+             *         }
+             *     }
+             *
+             * Now we have competing requirements: typedef would like us to use encapsulation to capture the defined
+             * type, while getBar() wants us to retain shape with getFoo(), as it should not matter how the identityref
+             * is formed.
+             *
+             * In this particular case getFoo() won just after the Binding Spec was frozen, hence we do not generate
+             * an encapsulation for identityref typedefs.
+             *
+             * In case you are thinking we could get by having foo-ref map to a subclass of Iden, that is not a good
+             * option, as it would look as though it is the product of a different construct:
+             *
+             *     identity bar-ref {
+             *         base iden;
+             *     }
+             *
+             * Leading to a rather nice namespace clash and also slight incompatibility with unknown third-party
+             * sub-identities of iden.
+             *
+             * The story behind leafrefs is probably similar, but that needs to be ascertained.
+             */
+            return null;
+        }
 
-            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());
-                }
+        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;
@@ -591,7 +641,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
         final String enumerationName = BindingMapping.getClassName(enumName);
 
-        Module module = findParentModule(schemaContext, parentNode);
+        final Module module = findParentModule(schemaContext, parentNode);
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
 
         final EnumerationBuilderImpl enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
@@ -686,7 +736,7 @@ public final class TypeProviderImpl implements TypeProvider {
         Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!");
         final Module[] modulesArray = new Module[modules.size()];
         int i = 0;
-        for (Module modul : modules) {
+        for (final Module modul : modules) {
             modulesArray[i++] = modul;
         }
         final List<Module> modulesSortedByDependency = org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort
@@ -735,9 +785,10 @@ public final class TypeProviderImpl implements TypeProvider {
     private Type typedefToGeneratedType(final String basePackageName, final Module module, final TypeDefinition<?> typedef) {
         final String moduleName = module.getName();
         final Date moduleRevision = module.getRevision();
-        if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
+        if (basePackageName != null && moduleName != null && typedef != null && typedef.getQName() != null) {
             final String typedefName = typedef.getQName().getLocalName();
             final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
+            // See generatedTypeForExtendedDefinitionType() above for rationale behind this special case.
             if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
                     && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
                 Type returnType = null;
@@ -752,10 +803,10 @@ public final class TypeProviderImpl implements TypeProvider {
                     makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
                     returnType = genTOBuilder.toInstance();
                     // union builder
-                    GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
+                    final GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
                             genTOBuilder.getName() + "Builder");
                     unionBuilder.setIsUnionBuilder(true);
-                    MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
+                    final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
                     method.setReturnType(returnType);
                     method.addParameter(Types.STRING, "defaultValue");
                     method.setAccessModifier(AccessModifier.PUBLIC);
@@ -857,7 +908,7 @@ public final class TypeProviderImpl implements TypeProvider {
         Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef);
 
         final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
-        for (GeneratedTOBuilder genTOBuilder : builders) {
+        for (final GeneratedTOBuilder genTOBuilder : builders) {
             resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
         }
 
@@ -909,15 +960,17 @@ public final class TypeProviderImpl implements TypeProvider {
 
         generatedTOBuilders.add(unionGenTOBuilder);
         unionGenTOBuilder.setIsUnion(true);
-        final List<String> regularExpressions = new ArrayList<String>();
+        final List<String> regularExpressions = new ArrayList<>();
         for (final TypeDefinition<?> unionType : unionTypes) {
             final String unionTypeName = unionType.getQName().getLocalName();
-            if (unionType.getBaseType() != null) {
-                resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, regularExpressions,
-                        parentNode);
+
+            // If we have a base type we should follow the type definition backwards, except for identityrefs, as those
+            // do not follow type encapsulation -- we use the general case for that.
+            if (unionType.getBaseType() != null  && !(unionType instanceof IdentityrefTypeDefinition)) {
+                resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, regularExpressions, parentNode);
             } else if (unionType instanceof UnionTypeDefinition) {
-                generatedTOBuilders.addAll(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionTypeDefinition) unionType,
-                        basePackageName, parentNode));
+                generatedTOBuilders.addAll(resolveUnionSubtypeAsUnion(unionGenTOBuilder,
+                    (UnionTypeDefinition) unionType, basePackageName, parentNode));
             } else if (unionType instanceof EnumTypeDefinition) {
                 final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
                         unionTypeName, unionGenTOBuilder);
@@ -1005,6 +1058,21 @@ public final class TypeProviderImpl implements TypeProvider {
                 if (javaType != null) {
                     updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
                 }
+            } else if (baseType instanceof LeafrefTypeDefinition) {
+                final Type javaType = javaTypeForSchemaDefinitionType(baseType, parentNode);
+                boolean typeExist = false;
+                for (final GeneratedPropertyBuilder generatedPropertyBuilder : parentUnionGenTOBuilder
+                        .getProperties()) {
+                    final Type origType = ((GeneratedPropertyBuilderImpl) generatedPropertyBuilder).getReturnType();
+                    if (origType != null && javaType != null && javaType == origType) {
+                        typeExist = true;
+                        break;
+                    }
+                }
+                if (!typeExist && javaType != null) {
+                    updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, new StringBuilder(javaType.getName())
+                            .append(parentUnionGenTOBuilder.getName()).append("Value").toString());
+                }
             }
             if (baseType instanceof StringTypeDefinition) {
                 regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
@@ -1048,8 +1116,8 @@ public final class TypeProviderImpl implements TypeProvider {
         if (!(newTypeDef instanceof UnionTypeDefinition)) {
             final Module parentModule = findParentModule(schemaContext, parentNode);
             if (parentModule != null && parentModule.getName() != null) {
-                Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
-                Map<String, Type> genTOsMap = modulesByDate.get(parentModule.getRevision());
+                final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
+                final Map<String, Type> genTOsMap = modulesByDate.get(parentModule.getRevision());
                 genTOsMap.put(newTypeDef.getQName().getLocalName(), genTOBuilder.toInstance());
             }
         }
@@ -1095,7 +1163,7 @@ public final class TypeProviderImpl implements TypeProvider {
         final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath());
         final String typeDefTOName = typedef.getQName().getLocalName();
 
-        if ((packageName != null) && (typeDefTOName != null)) {
+        if (packageName != null && typeDefTOName != null) {
             final String genTOName = BindingMapping.getClassName(typeDefTOName);
             final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTOName);
             final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
@@ -1136,7 +1204,7 @@ public final class TypeProviderImpl implements TypeProvider {
         Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
 
         if (typeDef instanceof BitsTypeDefinition) {
-            BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
+            final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
 
             final String typeName = BindingMapping.getClassName(typeDefName);
             final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
@@ -1151,7 +1219,7 @@ public final class TypeProviderImpl implements TypeProvider {
             final List<Bit> bitList = bitsTypeDefinition.getBits();
             GeneratedPropertyBuilder genPropertyBuilder;
             for (final Bit bit : bitList) {
-                String name = bit.getName();
+                final String name = bit.getName();
                 genPropertyBuilder = genTOBuilder.addProperty(BindingMapping.getPropertyName(name));
                 genPropertyBuilder.setReadOnly(true);
                 genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
@@ -1189,7 +1257,7 @@ public final class TypeProviderImpl implements TypeProvider {
         }
 
         final List<String> regExps = new ArrayList<>(patternConstraints.size());
-        for (PatternConstraint patternConstraint : patternConstraints) {
+        for (final PatternConstraint patternConstraint : patternConstraints) {
             final String regEx = patternConstraint.getRegularExpression();
             final String modifiedRegEx = StringEscapeUtils.escapeJava(regEx);
             regExps.add(modifiedRegEx);
@@ -1269,8 +1337,10 @@ public final class TypeProviderImpl implements TypeProvider {
         genTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
         genTOBuilder.setModuleName(moduleName);
         genTOBuilder.setTypedef(true);
-        Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
+        final Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
         genTOBuilder.setRestrictions(r);
+        addStringRegExAsConstant(genTOBuilder, resolveRegExpressionsFromTypedef(typedef));
+
         if (typedef.getStatus() == Status.DEPRECATED) {
             genTOBuilder.addAnnotation("", "Deprecated");
         }
@@ -1288,7 +1358,7 @@ public final class TypeProviderImpl implements TypeProvider {
         }
 
         if (typeMap != null) {
-            Type type = typeMap.get(innerTypeDef);
+            final Type type = typeMap.get(innerTypeDef);
             if (type instanceof GeneratedTransferObject) {
                 genTOBuilder.setExtendsType((GeneratedTransferObject) type);
             }
@@ -1308,7 +1378,7 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     private static void makeSerializable(final GeneratedTOBuilderImpl gto) {
         gto.addImplementsType(Types.typeForClass(Serializable.class));
-        GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
+        final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
         prop.setValue(Long.toString(BindingGeneratorUtil.computeDefaultSUID(gto)));
         gto.setSUID(prop);
     }
@@ -1329,21 +1399,21 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     private static List<TypeDefinition<?>> sortTypeDefinitionAccordingDepth(
             final Collection<TypeDefinition<?>> unsortedTypeDefinitions) {
-        List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
+        final List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
 
-        Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
-        for (TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
-            final int depth = getTypeDefinitionDepth(unsortedTypeDefinition);
+        final Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
+        for (final TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
+            final Integer depth = getTypeDefinitionDepth(unsortedTypeDefinition);
             List<TypeDefinition<?>> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth);
             if (typeDefinitionsConcreteDepth == null) {
-                typeDefinitionsConcreteDepth = new ArrayList<TypeDefinition<?>>();
+                typeDefinitionsConcreteDepth = new ArrayList<>();
                 typeDefinitionsDepths.put(depth, typeDefinitionsConcreteDepth);
             }
             typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
         }
 
         // SortedMap guarantees order corresponding to keys in ascending order
-        for (List<TypeDefinition<?>> v : typeDefinitionsDepths.values()) {
+        for (final List<TypeDefinition<?>> v : typeDefinitionsDepths.values()) {
             sortedTypeDefinition.addAll(v);
         }
 
@@ -1364,7 +1434,7 @@ public final class TypeProviderImpl implements TypeProvider {
         if (typeDefinition == null) {
             return 1;
         }
-        TypeDefinition<?> baseType = typeDefinition.getBaseType();
+        final TypeDefinition<?> baseType = typeDefinition.getBaseType();
         if (baseType == null) {
             return 1;
         }
@@ -1373,10 +1443,10 @@ public final class TypeProviderImpl implements TypeProvider {
         if (baseType.getBaseType() != null) {
             depth = depth + getTypeDefinitionDepth(baseType);
         } else if (baseType instanceof UnionTypeDefinition) {
-            List<TypeDefinition<?>> childTypeDefinitions = ((UnionTypeDefinition) baseType).getTypes();
+            final List<TypeDefinition<?>> childTypeDefinitions = ((UnionTypeDefinition) baseType).getTypes();
             int maxChildDepth = 0;
             int childDepth = 1;
-            for (TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
+            for (final TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
                 childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition);
                 if (childDepth > maxChildDepth) {
                     maxChildDepth = childDepth;
@@ -1397,19 +1467,19 @@ public final class TypeProviderImpl implements TypeProvider {
      * @return string with the number suffix incremented by one (or 1 is added)
      */
     private static String provideAvailableNameForGenTOBuilder(final String name) {
-        Matcher mtch = NUMBERS_PATTERN.matcher(name);
+        final Matcher mtch = NUMBERS_PATTERN.matcher(name);
         if (mtch.find()) {
-            final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
+            final int newSuffix = Integer.parseInt(name.substring(mtch.start())) + 1;
             return name.substring(0, mtch.start()) + newSuffix;
-        } else {
-            return name + 1;
         }
+
+        return name + 1;
     }
 
     public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
         if (!Strings.isNullOrEmpty(units)) {
             to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
-            GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
+            final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
             prop.setReturnType(Types.STRING);
             to.addToStringProperty(prop);
         }
@@ -1421,30 +1491,30 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     public String getTypeDefaultConstruction(final LeafSchemaNode node, final String defaultValue) {
-        TypeDefinition<?> type = CompatUtils.compatLeafType(node);
-        QName typeQName = type.getQName();
-        TypeDefinition<?> base = baseTypeDefForExtendedType(type);
+        final TypeDefinition<?> type = CompatUtils.compatLeafType(node);
+        final QName typeQName = type.getQName();
+        final TypeDefinition<?> base = baseTypeDefForExtendedType(type);
         Preconditions.checkNotNull(type, "Cannot provide default construction for null type of %s", node);
         Preconditions.checkNotNull(defaultValue, "Cannot provide default construction for null default statement of %s",
                 node);
 
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         String result = null;
         if (base instanceof BinaryTypeDefinition) {
             result = binaryToDef(defaultValue);
         } else if (base instanceof BitsTypeDefinition) {
             String parentName;
             String className;
-            Module parent = getParentModule(node);
-            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            final Module parent = getParentModule(node);
+            final Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
             path.next();
-            if (!(path.hasNext())) {
+            if (!path.hasNext()) {
                 parentName = BindingMapping.getClassName(parent.getName()) + "Data";
-                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                final String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
                 className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
             } else {
-                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
+                final String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
                 parentName = BindingMapping.getClassName(parent.getName());
                 className = packageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
             }
@@ -1456,20 +1526,20 @@ public final class TypeProviderImpl implements TypeProvider {
         } else if (base instanceof EmptyTypeDefinition) {
             result = typeToBooleanDef(defaultValue);
         } else if (base instanceof EnumTypeDefinition) {
-            char[] defValArray = defaultValue.toCharArray();
-            char first = Character.toUpperCase(defaultValue.charAt(0));
+            final char[] defValArray = defaultValue.toCharArray();
+            final char first = Character.toUpperCase(defaultValue.charAt(0));
             defValArray[0] = first;
-            String newDefVal = new String(defValArray);
+            final String newDefVal = new String(defValArray);
             String className;
             if (type.getBaseType() != null) {
-                Module m = getParentModule(type);
-                String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
+                final Module m = getParentModule(type);
+                final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
                 className = packageName + "." + BindingMapping.getClassName(typeQName);
             } else {
-                Module parentModule = getParentModule(node);
-                String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, node.getPath());
+                final Module parentModule = getParentModule(node);
+                final String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, node.getPath());
                 className = packageName + "." + BindingMapping.getClassName(node.getQName());
             }
             result = className + "." + newDefVal;
@@ -1518,10 +1588,10 @@ public final class TypeProviderImpl implements TypeProvider {
 
         if (type.getBaseType() != null && !(base instanceof LeafrefTypeDefinition)
                 && !(base instanceof EnumTypeDefinition) && !(base instanceof UnionTypeDefinition)) {
-            Module m = getParentModule(type);
-            String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
-            String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
-            String className = packageName + "." + BindingMapping.getClassName(typeQName);
+            final Module m = getParentModule(type);
+            final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
+            final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
+            final String className = packageName + "." + BindingMapping.getClassName(typeQName);
             sb.insert(0, "new " + className + "(");
             sb.insert(sb.length(), ')');
         }
@@ -1549,9 +1619,9 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private static String binaryToDef(final String defaultValue) {
-        StringBuilder sb = new StringBuilder();
-        BaseEncoding en = BaseEncoding.base64();
-        byte[] encoded = en.decode(defaultValue);
+        final StringBuilder sb = new StringBuilder();
+        final BaseEncoding en = BaseEncoding.base64();
+        final byte[] encoded = en.decode(defaultValue);
         sb.append("new byte[] {");
         for (int i = 0; i < encoded.length; i++) {
             sb.append(encoded[i]);
@@ -1566,9 +1636,9 @@ public final class TypeProviderImpl implements TypeProvider {
     private static final Comparator<Bit> BIT_NAME_COMPARATOR = (o1, o2) -> o1.getName().compareTo(o2.getName());
 
     private static String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue, final boolean isExt) {
-        List<Bit> bits = new ArrayList<>(type.getBits());
+        final List<Bit> bits = new ArrayList<>(type.getBits());
         Collections.sort(bits, BIT_NAME_COMPARATOR);
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         if (!isExt) {
             sb.append("new ");
             sb.append(className);
@@ -1591,9 +1661,9 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private Module getParentModule(final SchemaNode node) {
-        QName qname = node.getPath().getPathFromRoot().iterator().next();
-        URI namespace = qname.getNamespace();
-        Date revision = qname.getRevision();
+        final QName qname = node.getPath().getPathFromRoot().iterator().next();
+        final URI namespace = qname.getNamespace();
+        final Date revision = qname.getRevision();
         return schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
     }
 
@@ -1615,7 +1685,7 @@ public final class TypeProviderImpl implements TypeProvider {
                     } else {
                         dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
                     }
-                    String result = getTypeDefaultConstruction((LeafSchemaNode) dataNode, defaultValue);
+                    final String result = getTypeDefaultConstruction((LeafSchemaNode) dataNode, defaultValue);
                     return result;
                 }
             } else {
@@ -1632,18 +1702,18 @@ public final class TypeProviderImpl implements TypeProvider {
         String className;
 
         if (type.getBaseType() != null) {
-            QName typeQName = type.getQName();
+            final QName typeQName = type.getQName();
             Module module = null;
-            Set<Module> modules = schemaContext.findModuleByNamespace(typeQName.getNamespace());
+            final Set<Module> modules = schemaContext.findModuleByNamespace(typeQName.getNamespace());
             if (modules.size() > 1) {
-                for (Module m : modules) {
+                for (final Module m : modules) {
                     if (m.getRevision().equals(typeQName.getRevision())) {
                         module = m;
                         break;
                     }
                 }
                 if (module == null) {
-                    List<Module> modulesList = new ArrayList<>(modules);
+                    final List<Module> modulesList = new ArrayList<>(modules);
                     Collections.sort(modulesList, (o1, o2) -> o1.getRevision().compareTo(o2.getRevision()));
                     module = modulesList.get(0);
                 }
@@ -1651,24 +1721,24 @@ public final class TypeProviderImpl implements TypeProvider {
                 module = modules.iterator().next();
             }
 
-            String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+            final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
             className = basePackageName + "." + BindingMapping.getClassName(typeQName);
         } else {
-            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
-            QName first = path.next();
-            if (!(path.hasNext())) {
-                URI namespace = first.getNamespace();
-                Date revision = first.getRevision();
-                Module parent = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
-                parentName = BindingMapping.getClassName((parent).getName()) + "Data";
-                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+            final Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            final QName first = path.next();
+            if (!path.hasNext()) {
+                final URI namespace = first.getNamespace();
+                final Date revision = first.getRevision();
+                final Module parent = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                parentName = BindingMapping.getClassName(parent.getName()) + "Data";
+                final String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
                 className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
             } else {
-                URI namespace = first.getNamespace();
-                Date revision = first.getRevision();
-                Module parentModule = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
-                String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, UNION_PATH);
+                final URI namespace = first.getNamespace();
+                final Date revision = first.getRevision();
+                final Module parentModule = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                final String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, UNION_PATH);
                 className = packageName + "." + BindingMapping.getClassName(node.getQName());
             }
         }
@@ -1676,7 +1746,7 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private static String union(final String className, final String defaultValue, final LeafSchemaNode node) {
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         sb.append("new ");
         sb.append(className);
         sb.append("(\"");
@@ -1687,11 +1757,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
     @Override
     public String getConstructorPropertyName(final SchemaNode node) {
-        if (node instanceof TypeDefinition<?>) {
-            return "value";
-        } else {
-            return "";
-        }
+        return node instanceof TypeDefinition<?> ? "value" : "";
     }
 
     @Override