YANG typedefs generation as class with extends key word 96/596/4
authorJozef Gloncak <jgloncak@cisco.com>
Thu, 11 Jul 2013 08:49:23 +0000 (10:49 +0200)
committerJozef Gloncak <jgloncak@cisco.com>
Tue, 16 Jul 2013 11:30:29 +0000 (13:30 +0200)
In case that YANG typedef isn't specified as base type then corresponding
class will be generated with EXTENDS key word and corresponding extended
class.

Change-Id: I36143f485b8e68f471e2a3021ceb7ddc4ad9df2f
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/ExtendedTypedefTest.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/typedef_of_typedef.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/ClassCodeGenerator.java
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorUtil.java
opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/typedef_of_typedef.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java

index bcaf3a062a754e4ea5303723a4159a3226c75bdb..ec57cb4a3ca73185fe428bd25ccae4b6e0d7d60f 100644 (file)
@@ -11,7 +11,6 @@ import static org.opendaylight.controller.binding.generator.util.BindingGenerato
 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findDataSchemaNode;
 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findParentModule;
 
 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findDataSchemaNode;
 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findParentModule;
 
-import java.util.*;
 import java.util.concurrent.Future;
 
 import java.util.ArrayList;
 import java.util.concurrent.Future;
 
 import java.util.ArrayList;
@@ -21,9 +20,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.Future;
 
 
-import org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.controller.binding.generator.util.ReferencedTypeImpl;
 import org.opendaylight.controller.binding.generator.util.Types;
 import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.controller.binding.generator.util.ReferencedTypeImpl;
 import org.opendaylight.controller.binding.generator.util.Types;
 import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
@@ -856,11 +853,11 @@ public final class BindingGeneratorImpl implements BindingGenerator {
                     if (genTOBuilder != null) {
                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
                     }
                     if (genTOBuilder != null) {
                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
                     }
-                } else if(typeDef instanceof BitsTypeDefinition) {
+                } else if (typeDef instanceof BitsTypeDefinition) {
                     GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName);
                     if (genTOBuilder != null) {
                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
                     GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName);
                     if (genTOBuilder != null) {
                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
-                    }                    
+                    }
                 } else {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
                 }
                 } else {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
                 }
@@ -1184,23 +1181,23 @@ public final class BindingGeneratorImpl implements BindingGenerator {
         return genTOBuilder;
     }
 
         return genTOBuilder;
     }
 
-    
-    private GeneratedTOBuilder addEnclosedTOToTypeBuilder( TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder, String leafName) { 
+    private GeneratedTOBuilder addEnclosedTOToTypeBuilder(TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder,
+            String leafName) {
         String className = parseToClassName(leafName);
         GeneratedTOBuilder genTOBuilder = null;
         if (typeDef instanceof UnionType) {
             genTOBuilder = ((TypeProviderImpl) typeProvider).addUnionGeneratedTypeDefinition(
                     typeBuilder.getPackageName(), typeDef, className);
         } else if (typeDef instanceof BitsTypeDefinition) {
         String className = parseToClassName(leafName);
         GeneratedTOBuilder genTOBuilder = null;
         if (typeDef instanceof UnionType) {
             genTOBuilder = ((TypeProviderImpl) typeProvider).addUnionGeneratedTypeDefinition(
                     typeBuilder.getPackageName(), typeDef, className);
         } else if (typeDef instanceof BitsTypeDefinition) {
-            genTOBuilder = ((TypeProviderImpl) typeProvider).bitsTypedefToTransferObject(
-                    typeBuilder.getPackageName(), typeDef, className);
+            genTOBuilder = ((TypeProviderImpl) typeProvider).bitsTypedefToTransferObject(typeBuilder.getPackageName(),
+                    typeDef, className);
         }
         if (genTOBuilder != null) {
             typeBuilder.addEnclosingTransferObject(genTOBuilder);
             return genTOBuilder;
         }
         return null;
         }
         if (genTOBuilder != null) {
             typeBuilder.addEnclosingTransferObject(genTOBuilder);
             return genTOBuilder;
         }
         return null;
-        
+
     }
     }
-    
+
 }
 }
index 4824fa75fd000be4910397bc7bd02f3e3775d6ad..b6d8de62e6d170d6e7e4a44f7cfe6944e2bfed7c 100644 (file)
@@ -27,13 +27,16 @@ import org.opendaylight.controller.yang.model.api.type.*;
 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
 import org.opendaylight.controller.yang.model.util.ExtendedType;
 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
 import org.opendaylight.controller.yang.model.util.ExtendedType;
+
 import org.opendaylight.controller.yang.model.util.StringType;
 import org.opendaylight.controller.yang.model.util.StringType;
+import org.opendaylight.controller.yang.model.util.UnionType;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import static org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil.*;
 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.*;
 
 import static org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil.*;
 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.*;
@@ -361,18 +364,15 @@ public final class TypeProviderImpl implements TypeProvider {
             final String basePackageName = moduleNamespaceToPackageName(module);
 
             final Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();
             final String basePackageName = moduleNamespaceToPackageName(module);
 
             final Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();
+            final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
 
             final Map<String, Type> typeMap = new HashMap<>();
             genTypeDefsContextMap.put(moduleName, typeMap);
 
 
             final Map<String, Type> typeMap = new HashMap<>();
             genTypeDefsContextMap.put(moduleName, typeMap);
 
-            if ((typeDefinitions != null) && (basePackageName != null)) {
-                for (final TypeDefinition<?> typedef : typeDefinitions) {
+            if ((listTypeDefinitions != null) && (basePackageName != null)) {
+                for (final TypeDefinition<?> typedef : listTypeDefinitions) {
                     typedefToGeneratedType(basePackageName, moduleName, typedef);
                 }
                     typedefToGeneratedType(basePackageName, moduleName, typedef);
                 }
-                final List<ExtendedType> extUnions = UnionDependencySort.sort(typeDefinitions);
-                for (final ExtendedType extUnionType : extUnions) {
-                    addUnionGeneratedTypeDefinition(basePackageName, extUnionType, null);
-                }
             }
         }
     }
             }
         }
     }
@@ -382,23 +382,31 @@ public final class TypeProviderImpl implements TypeProvider {
         if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
 
             final String typedefName = typedef.getQName().getLocalName();
         if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
 
             final String typedefName = typedef.getQName().getLocalName();
-            final TypeDefinition<?> baseTypeDefinition = baseTypeDefForExtendedType(typedef);
-            if (!(baseTypeDefinition instanceof LeafrefTypeDefinition)
-                    && !(baseTypeDefinition instanceof IdentityrefTypeDefinition)) {
-                Type returnType;
-                if (baseTypeDefinition instanceof EnumTypeDefinition) {
-                    final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDefinition;
+            final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
+            if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
+                    && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
+                Type returnType = null;
+                if (innerTypeDefinition instanceof ExtendedType) {
+                    ExtendedType extendedTypeDef = (ExtendedType) innerTypeDefinition;
+                    returnType = resolveExtendedTypeFromTypeDef(extendedTypeDef, basePackageName, typedefName,
+                            moduleName);
+                } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
+                    final GeneratedTOBuilder genTOBuilder = addUnionGeneratedTypeDefinition(basePackageName, typedef,
+                            typedefName);
+                    returnType = genTOBuilder.toInstance();
+                } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
+                    final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
                     returnType = resolveEnumFromTypeDefinition(enumTypeDef, typedefName);
 
                     returnType = resolveEnumFromTypeDefinition(enumTypeDef, typedefName);
 
-                } else if (baseTypeDefinition instanceof BitsTypeDefinition) {
-                    final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) baseTypeDefinition;
-                    GeneratedTOBuilder genTOBuilder = bitsTypedefToTransferObject(basePackageName, bitsTypeDefinition,
-                            typedefName);
+                } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
+                    final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
+                    final GeneratedTOBuilder genTOBuilder = bitsTypedefToTransferObject(basePackageName,
+                            bitsTypeDefinition, typedefName);
                     returnType = genTOBuilder.toInstance();
 
                 } else {
                     final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
                     returnType = genTOBuilder.toInstance();
 
                 } else {
                     final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
-                            .javaTypeForSchemaDefinitionType(baseTypeDefinition);
+                            .javaTypeForSchemaDefinitionType(innerTypeDefinition);
 
                     returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType);
                 }
 
                     returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType);
                 }
@@ -428,12 +436,12 @@ public final class TypeProviderImpl implements TypeProvider {
             genTOBuilder.addEqualsIdentity(genPropBuilder);
             genTOBuilder.addHashIdentity(genPropBuilder);
             genTOBuilder.addToStringProperty(genPropBuilder);
             genTOBuilder.addEqualsIdentity(genPropBuilder);
             genTOBuilder.addHashIdentity(genPropBuilder);
             genTOBuilder.addToStringProperty(genPropBuilder);
-
-            if (typedef instanceof ExtendedType) {
-                final List<String> regExps = resolveRegExpressionsFromTypedef((ExtendedType) typedef);
-                addStringRegExAsConstant(genTOBuilder, regExps);
+            if (javaType == BaseYangTypes.STRING_TYPE) {
+                if (typedef instanceof ExtendedType) {
+                    final List<String> regExps = resolveRegExpressionsFromTypedef((ExtendedType) typedef);
+                    addStringRegExAsConstant(genTOBuilder, regExps);
+                }
             }
             }
-
             return genTOBuilder.toInstance();
         }
         return null;
             return genTOBuilder.toInstance();
         }
         return null;
@@ -479,9 +487,10 @@ public final class TypeProviderImpl implements TypeProvider {
                     final Module unionTypeModule = findParentModuleForTypeDefinition(schemaContext, unionType);
                     if (unionTypeModule != null && unionTypeModule.getName() != null) {
                         final Map<String, Type> innerGenTOs = genTypeDefsContextMap.get(unionTypeModule.getName());
                     final Module unionTypeModule = findParentModuleForTypeDefinition(schemaContext, unionType);
                     if (unionTypeModule != null && unionTypeModule.getName() != null) {
                         final Map<String, Type> innerGenTOs = genTypeDefsContextMap.get(unionTypeModule.getName());
-
-                        final GeneratedTransferObject genTransferObject = (GeneratedTransferObject) innerGenTOs
-                                .get(typeName);
+                        Type genTransferObject = null;
+                        if (innerGenTOs != null) {
+                            genTransferObject = innerGenTOs.get(typeName);
+                        }
                         if (genTransferObject != null) {
                             updateUnionTypeAsProperty(unionGenTransObject, genTransferObject,
                                     genTransferObject.getName());
                         if (genTransferObject != null) {
                             updateUnionTypeAsProperty(unionGenTransObject, genTransferObject,
                                     genTransferObject.getName());
@@ -620,4 +629,103 @@ public final class TypeProviderImpl implements TypeProvider {
         }
     }
 
         }
     }
 
+    private GeneratedTransferObject resolveExtendedTypeFromTypeDef(final ExtendedType extendedType,
+            final String basePackageName, final String typedefName, final String moduleName) {
+
+        if (extendedType == null) {
+            throw new IllegalArgumentException("Extended type cannot be NULL!");
+        }
+        if (basePackageName == null) {
+            throw new IllegalArgumentException("String with base package name cannot be NULL!");
+        }
+        if (typedefName == null) {
+            throw new IllegalArgumentException("String with type definition name cannot be NULL!");
+        }
+
+        final String typeDefName = parseToClassName(typedefName);
+        final String lowTypeDef = extendedType.getQName().getLocalName();
+        final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName);
+
+        final Map<String, Type> typeMap = genTypeDefsContextMap.get(moduleName);
+        if (typeMap != null) {
+            Type type = typeMap.get(lowTypeDef);
+            if (type instanceof GeneratedTransferObject) {
+                genTOBuilder.setExtendsType((GeneratedTransferObject) type);
+            }
+        }
+
+        return genTOBuilder.toInstance();
+    }
+
+    /**
+     * The method find out for each type definition how many immersion (depth)
+     * is necessary to get to the base type. Every type definition is inserted
+     * to the map which key is depth and value is list of type definitions with
+     * equal depth. In next step are lists from this map concatenated to one
+     * list in ascending order according to their depth. All type definitions
+     * are in the list behind all type definitions on which depends.
+     * 
+     * @param unsortedTypeDefinitions
+     *            represents list of type definitions
+     * @return list of type definitions sorted according their each other
+     *         dependencies (type definitions which are depend on other type
+     *         definitions are in list behind them).
+     */
+    private List<TypeDefinition<?>> sortTypeDefinitionAccordingDepth(
+            final Set<TypeDefinition<?>> unsortedTypeDefinitions) {
+        List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
+
+        Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
+        for (TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
+            final int depth = getTypeDefinitionDepth(unsortedTypeDefinition);
+            List<TypeDefinition<?>> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth);
+            if (typeDefinitionsConcreteDepth == null) {
+                typeDefinitionsConcreteDepth = new ArrayList<TypeDefinition<?>>();
+                typeDefinitionsDepths.put(depth, typeDefinitionsConcreteDepth);
+            }
+            typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
+        }
+
+        Set<Integer> depths = typeDefinitionsDepths.keySet(); // keys are in
+                                                              // ascending order
+        for (Integer depth : depths) {
+            sortedTypeDefinition.addAll(typeDefinitionsDepths.get(depth));
+        }
+
+        return sortedTypeDefinition;
+    }
+
+    /**
+     * The method return how many immersion is necessary to get from type
+     * definition to base type.
+     * 
+     * @param typeDefinition
+     *            is type definition for which is depth looked for.
+     * @return how many immersion is necessary to get from type definition to
+     *         base type
+     */
+    private int getTypeDefinitionDepth(final TypeDefinition<?> typeDefinition) {
+        if (typeDefinition == null) {
+            throw new IllegalArgumentException("Type definition can't be null");
+        }
+        int depth = 1;
+        TypeDefinition<?> baseType = typeDefinition.getBaseType();
+
+        if (baseType instanceof ExtendedType) {
+            depth = depth + getTypeDefinitionDepth(typeDefinition.getBaseType());
+        } else if (baseType instanceof UnionType) {
+            List<TypeDefinition<?>> childTypeDefinitions = ((UnionType) baseType).getTypes();
+            int maxChildDepth = 0;
+            int childDepth = 1;
+            for (TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
+                childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition.getBaseType());
+                if (childDepth > maxChildDepth) {
+                    maxChildDepth = childDepth;
+                }
+            }
+            return maxChildDepth;
+        }
+        return depth;
+    }
+
 }
 }
diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/ExtendedTypedefTest.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/ExtendedTypedefTest.java
new file mode 100644 (file)
index 0000000..bbbf469
--- /dev/null
@@ -0,0 +1,137 @@
+package org.opendaylight.controller.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.controller.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.controller.sal.binding.model.api.Constant;
+import org.opendaylight.controller.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.controller.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.controller.sal.binding.model.api.Type;
+import org.opendaylight.controller.sal.binding.yang.types.BaseYangTypes;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
+import org.opendaylight.controller.yang.parser.impl.YangParserImpl;
+
+public class ExtendedTypedefTest {
+
+    private final static List<File> testModels = new ArrayList<File>();
+
+    @BeforeClass
+    public static void loadTestResources() {
+        final File listModelFile = new File(ExtendedTypedefTest.class.getResource("/typedef_of_typedef.yang").getPath());
+        testModels.add(listModelFile);
+    }
+
+    @Test    
+    public void constantGenerationTest() {
+        final YangModelParser parser = new YangParserImpl();
+        final Set<Module> modules = parser.parseYangModels(testModels);
+        final SchemaContext context = parser.resolveSchemaContext(modules);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl();
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        GeneratedTransferObject simpleTypedef4 = null;
+        GeneratedTransferObject extendedTypedefUnion = null;
+        GeneratedTransferObject unionTypedef = null;
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedTransferObject) {
+                if (type.getName().equals("SimpleTypedef4")) {
+                    simpleTypedef4 = (GeneratedTransferObject) type;
+                } else if (type.getName().equals("ExtendedTypedefUnion")) {
+                    extendedTypedefUnion = (GeneratedTransferObject) type;
+                } else if (type.getName().equals("UnionTypedef")) {
+                    unionTypedef = (GeneratedTransferObject) type;
+                }
+            }
+        }
+
+        // simple-typedef4
+        assertNotNull("SimpleTypedef4 not found", simpleTypedef4);
+        assertNotNull("ExtendedTypedefUnion not found", extendedTypedefUnion);
+        assertNotNull("UnionTypedef", unionTypedef);
+
+        List<GeneratedProperty> properties = simpleTypedef4.getProperties();
+        assertTrue("SimpleTypedef4 shouldn't have properties.", properties.isEmpty());
+
+        GeneratedTransferObject extendTO = simpleTypedef4.getExtends();
+        assertNotNull("SimpleTypedef4 should have extend.", extendTO);
+        assertEquals("Incorrect extension for SimpleTypedef4.", "SimpleTypedef3", extendTO.getName());
+        properties = extendTO.getProperties();
+        assertTrue("SimpleTypedef3 shouldn't have properties.", properties.isEmpty());
+
+        extendTO = extendTO.getExtends();
+        assertNotNull("SimpleTypedef3 should have extend.", extendTO);
+        assertEquals("Incorrect extension for SimpleTypedef3.", "SimpleTypedef2", extendTO.getName());
+        properties = extendTO.getProperties();
+        assertTrue("SimpleTypedef2 shouldn't have properties.", properties.isEmpty());
+
+        extendTO = extendTO.getExtends();
+        assertNotNull("SimpleTypedef2 should have extend.", extendTO);
+        assertEquals("SimpleTypedef2 should be extended with SimpleTypedef1.", "SimpleTypedef1", extendTO.getName());
+        properties = extendTO.getProperties();
+        assertEquals("Incorrect number of properties in class SimpleTypedef1.", 1, properties.size());
+
+        assertEquals("Incorrect property's name", "simpleTypedef1", properties.get(0).getName());
+        assertEquals("Property's incorrect type", BaseYangTypes.UINT8_TYPE, properties.get(0).getReturnType());
+
+        extendTO = extendTO.getExtends();
+        assertNull("SimpleTypedef1 shouldn't have extend.", extendTO);
+
+        // extended-typedef-union
+        assertNotNull("ExtendedTypedefUnion object not found", extendedTypedefUnion);
+        properties = extendedTypedefUnion.getProperties();
+        assertTrue("ExtendedTypedefUnion shouldn't have any property", properties.isEmpty());
+
+        extendTO = extendedTypedefUnion.getExtends();
+        assertEquals("Incorrect extension fo ExtendedTypedefUnion.", "UnionTypedef", extendTO.getName());
+        assertNull("UnionTypedef shouldn't be extended", extendTO.getExtends());
+        assertEquals("Incorrect number of properties for UnionTypedef.", 4, extendTO.getProperties().size());
+
+        GeneratedProperty simpleTypedef4Property = null;
+        GeneratedProperty simpleTypedef1Property = null;
+        GeneratedProperty byteTypeProperty = null;
+        GeneratedProperty typedefEnumFruitProperty = null;
+        for (GeneratedProperty genProperty : extendTO.getProperties()) {
+            if (genProperty.getName().equals("simpleTypedef1")) {
+                simpleTypedef1Property = genProperty;
+            } else if (genProperty.getName().equals("simpleTypedef4")) {
+                simpleTypedef4Property = genProperty;
+            } else if (genProperty.getName().equals("byteType")) {
+                byteTypeProperty = genProperty;
+            } else if (genProperty.getName().equals("typedefEnumFruit")) {
+                typedefEnumFruitProperty = genProperty;
+            }
+        }
+
+        assertNotNull("simpleTypedef4 property not found in UnionTypedef", simpleTypedef4Property);
+        assertNotNull("simpleTypedef1 property not found in UnionTypedef", simpleTypedef1Property);
+        assertNotNull("byteType property not found in UnionTypedef", byteTypeProperty);
+        assertNotNull("typedefEnumFruit property not found in UnionTypedef", typedefEnumFruitProperty);
+
+        assertEquals("Incorrect type for property simpleTypedef4.", "SimpleTypedef4", simpleTypedef4Property
+                .getReturnType().getName());
+        assertEquals("Incorrect type for property simpleTypedef1.", "SimpleTypedef1", simpleTypedef1Property
+                .getReturnType().getName());
+        assertEquals("Incorrect type for property byteType.", "ByteType", byteTypeProperty
+                .getReturnType().getName());
+        assertEquals("Incorrect type for property typedefEnumFruit.", "TypedefEnumFruit", typedefEnumFruitProperty
+                .getReturnType().getName());
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/typedef_of_typedef.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/typedef_of_typedef.yang
new file mode 100644 (file)
index 0000000..fc0bab9
--- /dev/null
@@ -0,0 +1,79 @@
+module typedef_typedef {
+    
+    namespace "urn:typedef:typedef";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-09 {
+        
+    }
+
+   typedef byte-type {
+        type bits {
+            bit first-bit {
+                position 10;
+            }
+            bit second-bit {
+                position 20;
+            }
+         }
+    }    
+    
+    
+  typedef typedef-enum-fruit {
+    type enumeration {
+      enum "apple" {
+        value 1;
+        description "gold";
+      }
+      enum "pear" {
+        value 2;
+      }
+    }
+  }    
+    
+    typedef simple-typedef1 {
+        type uint8;
+    }
+    
+    typedef simple-typedef2 {
+        type simple-typedef1;
+    }
+    
+    typedef simple-typedef3 {
+        type simple-typedef2;
+    }
+    
+    typedef simple-typedef4 {
+        type simple-typedef3;
+    }
+    
+    typedef simple-typedef1-1 {
+        type uint16;
+    }
+
+    
+    typedef union-typedef {
+        type union {
+            type simple-typedef1;
+            type simple-typedef4;
+            type byte-type;
+            type typedef-enum-fruit;
+        }
+    }
+    
+    typedef extended-typedef-union {
+        type union-typedef;
+    }
+    
+    
+    typedef extended-typedef-simple {
+        type simple-typedef1;
+    }
+    
+    typedef extended-typedef-enum {
+        type typedef-enum-fruit;
+    }
+}
\ No newline at end of file
index 717988af3efef6afaba36b5ef34bad37218b75ce..31b94a65cad703d8b78ca79c8fbaf94f62ea7f70 100644 (file)
@@ -67,11 +67,14 @@ public final class ClassCodeGenerator implements CodeGenerator {
             }
 
             writer.write(NL);
             }
 
             writer.write(NL);
+            final boolean oneConstructor;
             if (genTO.isUnionType()) {
             if (genTO.isUnionType()) {
-                writer.write(GeneratorUtil.createConstructors(genTO, indent + TAB, imports, genTO.isAbstract()));
+                oneConstructor = false;
             } else {
             } else {
-                writer.write(GeneratorUtil.createConstructor(genTO, indent + TAB, imports, genTO.isAbstract()) + NL);
+                oneConstructor = true;
             }
             }
+            writer.write(GeneratorUtil.createConstructor(genTO, indent + TAB, imports, genTO.isAbstract(),
+                    oneConstructor));
             writer.write(NL);
 
             for (GeneratedProperty field : fields) {
             writer.write(NL);
 
             for (GeneratedProperty field : fields) {
index dfae4a2ceaad57c3de7555e7867913416aa78535..0e2da819371cf7b962ba0eba39fa980e1e66bdbd 100644 (file)
@@ -17,9 +17,9 @@ import java.util.Map;
 
 import org.opendaylight.controller.binding.generator.util.TypeConstants;
 import org.opendaylight.controller.sal.binding.model.api.*;
 
 import org.opendaylight.controller.binding.generator.util.TypeConstants;
 import org.opendaylight.controller.sal.binding.model.api.*;
+import org.opendaylight.controller.binding.generator.util.Types;
 import org.opendaylight.controller.sal.binding.model.api.Enumeration.Pair;
 import org.opendaylight.controller.sal.binding.model.api.MethodSignature.Parameter;
 import org.opendaylight.controller.sal.binding.model.api.Enumeration.Pair;
 import org.opendaylight.controller.sal.binding.model.api.MethodSignature.Parameter;
-import org.opendaylight.controller.binding.generator.util.Types;
 
 public final class GeneratorUtil {
 
 
 public final class GeneratorUtil {
 
@@ -232,90 +232,244 @@ public final class GeneratorUtil {
         return builder.toString();
     }
 
         return builder.toString();
     }
 
-    public static String createConstructor(GeneratedTransferObject genTransferObject, final String indent,
-            final Map<String, String> availableImports, boolean isIdentity) {
-        StringBuilder builder = new StringBuilder();
+    public static String createConstructor(final GeneratedTransferObject genTransferObject, final String indent,
+            final Map<String, String> availableImports, final boolean isIdentity, final boolean oneConstructor) {
+        if (genTransferObject == null) {
+            throw new IllegalArgumentException("Generated transfer object can't be null");
+        }
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
+        if (availableImports == null) {
+            throw new IllegalArgumentException("Map of available imports can't be null");
+        }
+        GeneratedTransferObject genTOTopParent = getTopParrentTransportObject(genTransferObject);
+        final List<GeneratedProperty> ctorProperties = resolveReadOnlyPropertiesFromTO(genTransferObject
+                .getProperties());
+        final List<GeneratedProperty> ctorPropertiesAllParents = getPropertiesOfAllParents(genTransferObject
+                .getExtends());
 
         final String currentPkg = genTransferObject.getPackageName();
 
         final String currentPkg = genTransferObject.getPackageName();
-        final List<GeneratedProperty> properties = genTransferObject.getProperties();
-        final List<GeneratedProperty> ctorParams = new ArrayList<GeneratedProperty>();
-        if (properties != null) {
-            for (final GeneratedProperty property : properties) {
-                if (property.isReadOnly()) {
-                    ctorParams.add(property);
-                }
+        final String className = genTransferObject.getName();
+
+        String constructorPart = "";
+        if (oneConstructor) {
+            if (genTOTopParent != genTransferObject && genTOTopParent.isUnionType()) {
+                constructorPart = createConstructorForEveryParentProperty(indent, isIdentity, ctorProperties,
+                        ctorPropertiesAllParents, availableImports, currentPkg, className);
+
+            } else {
+                constructorPart = createOneConstructor(indent, isIdentity, ctorProperties, ctorPropertiesAllParents,
+                        availableImports, currentPkg, className);
             }
             }
+
+        } else { // union won't be extended
+            constructorPart = createConstructorForEveryProperty(indent, isIdentity, ctorProperties,
+                    ctorPropertiesAllParents, availableImports, currentPkg, className);
         }
 
         }
 
-        builder.append(createConstructorDeclarationToLeftParenthesis(genTransferObject, indent, isIdentity));
+        return constructorPart;
+    }
 
 
-        final String parameterSeparator = COMMA + GAP;
-        for (final GeneratedProperty ctorParam : ctorParams) {
-            builder.append(createMethodParamDeclaration(ctorParam, availableImports, currentPkg));
-            builder.append(parameterSeparator);
+    private static String createOneConstructor(final String indent, boolean isIdentity,
+            final List<GeneratedProperty> properties, final List<GeneratedProperty> propertiesAllParents,
+            final Map<String, String> availableImports, final String currentPkg, final String className) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
         }
         }
-        if (!ctorParams.isEmpty()) {
-            builder = builder.delete(builder.length() - parameterSeparator.length(), builder.length());
+        if (properties == null) {
+            throw new IllegalArgumentException("List of generated properties can't be null");
         }
         }
-        builder.append(createConstructorDeclarationFromRightParenthesis());
-        builder.append(createConstructorSuperCalling(indent));
-
-        for (final GeneratedProperty ctorParam : ctorParams) {
-            builder.append(createClassAttributeInitialization(indent, ctorParam));
+        if (propertiesAllParents == null) {
+            throw new IllegalArgumentException(
+                    "List of generated properties of all parent transport objects can't be null");
+        }
+        if (availableImports == null) {
+            throw new IllegalArgumentException("Map of available imports can't be null");
         }
         }
+        if (currentPkg == null) {
+            throw new IllegalArgumentException("String with current package can't be null");
+        }
+        if (className == null) {
+            throw new IllegalArgumentException("String with class name can't be null");
+        }
+
+        final StringBuilder builder = new StringBuilder();
 
 
+        List<GeneratedProperty> propertiesAll = new ArrayList<GeneratedProperty>(properties);
+        propertiesAll.addAll(propertiesAllParents);
+
+        builder.append(createConstructorDeclarationToLeftParenthesis(className, indent, isIdentity));
+        builder.append(createMethodPropertiesDeclaration(propertiesAll, availableImports, currentPkg, COMMA + GAP));
+        builder.append(createConstructorDeclarationFromRightParenthesis());
+        builder.append(createConstructorSuper(propertiesAllParents, indent));
+        builder.append(createClassPropertiesInitialization(propertiesAll, indent));
         builder.append(createConstructorClosingPart(indent));
         return builder.toString();
     }
 
         builder.append(createConstructorClosingPart(indent));
         return builder.toString();
     }
 
-    public static String createConstructors(GeneratedTransferObject genTransferObject, final String indent,
-            final Map<String, String> availableImports, boolean isIdentity) {
+    private static String createConstructorForEveryParentProperty(final String indent, final boolean isIdentity,
+            final List<GeneratedProperty> properties, final List<GeneratedProperty> propertiesAllParents,
+            final Map<String, String> availableImports, final String currentPkg, final String className) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
+        if (properties == null) {
+            throw new IllegalArgumentException("List of generated properties can't be null");
+        }
+        if (propertiesAllParents == null) {
+            throw new IllegalArgumentException(
+                    "List of generated properties of all parent transport objects can't be null");
+        }
+        if (availableImports == null) {
+            throw new IllegalArgumentException("Map of available imports can't be null");
+        }
+        if (currentPkg == null) {
+            throw new IllegalArgumentException("String with current package can't be null");
+        }
+        if (className == null) {
+            throw new IllegalArgumentException("String with class name can't be null");
+        }
         final StringBuilder builder = new StringBuilder();
         final StringBuilder builder = new StringBuilder();
+        GeneratedProperty parentProperty;
+        Iterator<GeneratedProperty> parentPropertyIterator = propertiesAllParents.iterator();
 
 
-        final String currentPkg = genTransferObject.getPackageName();
-        final List<GeneratedProperty> properties = genTransferObject.getProperties();
-        final List<GeneratedProperty> ctorParams = new ArrayList<GeneratedProperty>();
-        if (properties != null) {
-            for (final GeneratedProperty property : properties) {
-                if (property.isReadOnly()) {
-                    ctorParams.add(property);
-                }
+        do {
+            parentProperty = null;
+            if (parentPropertyIterator.hasNext()) {
+                parentProperty = parentPropertyIterator.next();
+            }
+
+            List<GeneratedProperty> propertiesAndParentProperties = new ArrayList<GeneratedProperty>();
+            if (parentProperty != null) {
+                propertiesAndParentProperties.add(parentProperty);
             }
             }
+            propertiesAndParentProperties.addAll(properties);
+
+            builder.append(createConstructorDeclarationToLeftParenthesis(className, indent, isIdentity));
+            builder.append(createMethodPropertiesDeclaration(propertiesAndParentProperties, availableImports,
+                    currentPkg, COMMA + GAP));
+            builder.append(createConstructorDeclarationFromRightParenthesis());
+            builder.append(createConstructorSuper(parentProperty, indent));
+            builder.append(createClassPropertiesInitialization(properties, indent));
+            builder.append(createConstructorClosingPart(indent));
+        } while (parentPropertyIterator.hasNext());
+
+        return builder.toString();
+    }
+
+    private static String createConstructorForEveryProperty(final String indent, final boolean isIdentity,
+            final List<GeneratedProperty> properties, final List<GeneratedProperty> propertiesAllParents,
+            final Map<String, String> availableImports, final String currentPkg, final String className) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
+        if (properties == null) {
+            throw new IllegalArgumentException("List of generated properties can't be null");
+        }
+        if (propertiesAllParents == null) {
+            throw new IllegalArgumentException(
+                    "List of generated properties of all parent transport objects can't be null");
+        }
+        if (availableImports == null) {
+            throw new IllegalArgumentException("Map of available imports can't be null");
+        }
+        if (currentPkg == null) {
+            throw new IllegalArgumentException("String with current package can't be null");
+        }
+        if (className == null) {
+            throw new IllegalArgumentException("String with class name can't be null");
         }
 
         }
 
-        GeneratedProperty ctorParam;
-        Iterator<GeneratedProperty> iteratorCtorParams = ctorParams.iterator();
+        final StringBuilder builder = new StringBuilder();
+
+        GeneratedProperty property;
+        Iterator<GeneratedProperty> propertyIterator = properties.iterator();
 
         do {
 
         do {
-            ctorParam = null;
-            if (iteratorCtorParams.hasNext()) {
-                ctorParam = iteratorCtorParams.next();
+            property = null;
+            if (propertyIterator.hasNext()) {
+                property = propertyIterator.next();
             }
             }
-            builder.append(createConstructorDeclarationToLeftParenthesis(genTransferObject, indent, isIdentity));
 
 
-            if (ctorParam != null) {
-                builder.append(createMethodParamDeclaration(ctorParam, availableImports, currentPkg));
+            List<GeneratedProperty> propertyAndTopParentProperties = new ArrayList<GeneratedProperty>();
+            if (property != null) {
+                propertyAndTopParentProperties.add(property);
             }
             }
+            propertyAndTopParentProperties.addAll(propertiesAllParents);
+
+            builder.append(createConstructorDeclarationToLeftParenthesis(className, indent, isIdentity));
+            builder.append(createMethodPropertiesDeclaration(propertyAndTopParentProperties, availableImports,
+                    currentPkg, COMMA + GAP));
             builder.append(createConstructorDeclarationFromRightParenthesis());
             builder.append(createConstructorDeclarationFromRightParenthesis());
-            builder.append(createConstructorSuperCalling(indent));
+            builder.append(createConstructorSuper(propertiesAllParents, indent));
+            builder.append(createClassPropertyInitialization(property, indent));
+            builder.append(createConstructorClosingPart(indent));
+        } while (propertyIterator.hasNext());
 
 
-            if (ctorParam != null) {
-                builder.append(createClassAttributeInitialization(indent, ctorParam));
+        return builder.toString();
+    }
+
+    /**
+     * The method selects from input list of properties only those which have
+     * read only attribute set to true.
+     * 
+     * @param properties
+     *            contains list of properties of generated transfer object
+     * @return subset of <code>properties</code> which have read only attribute
+     *         set to true
+     */
+    private static List<GeneratedProperty> resolveReadOnlyPropertiesFromTO(List<GeneratedProperty> properties) {
+        List<GeneratedProperty> readOnlyProperties = new ArrayList<GeneratedProperty>();
+        if (properties != null) {
+            for (final GeneratedProperty property : properties) {
+                if (property.isReadOnly()) {
+                    readOnlyProperties.add(property);
+                }
             }
             }
+        }
+        return readOnlyProperties;
+    }
 
 
-            builder.append(createConstructorClosingPart(indent));
-        } while (iteratorCtorParams.hasNext());
+    private static String createMethodPropertiesDeclaration(final List<GeneratedProperty> parameters,
+            final Map<String, String> availableImports, final String currentPkg, final String parameterSeparator) {
+        StringBuilder builder = new StringBuilder();
+        if (parameters == null) {
+            throw new IllegalArgumentException("List of generated properties can't be null");
+        }
+        if (availableImports == null) {
+            throw new IllegalArgumentException("Map of available imports can't be null");
+        }
+        if (currentPkg == null) {
+            throw new IllegalArgumentException("String with current package can't be null");
+        }
+        if (parameterSeparator == null) {
+            throw new IllegalArgumentException("String with separator of parameters can't be null");
+        }
 
 
+        for (final GeneratedProperty parameter : parameters) {
+            builder.append(createMethodPropertyDeclaration(parameter, availableImports, currentPkg));
+            builder.append(parameterSeparator);
+        }
+        if (!parameters.isEmpty()) {
+            builder = builder.delete(builder.length() - parameterSeparator.length(), builder.length());
+        }
         return builder.toString();
     }
 
         return builder.toString();
     }
 
-    private static String createConstructorDeclarationToLeftParenthesis(GeneratedTransferObject genTransferObject,
-            final String indent, boolean isIdentity) {
+    private static String createConstructorDeclarationToLeftParenthesis(final String className, final String indent,
+            final boolean isIdentity) {
+        if (className == null) {
+            throw new IllegalArgumentException("String with class name can't be null");
+        }
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
         final StringBuilder builder = new StringBuilder();
         builder.append(indent);
         builder.append(isIdentity ? PROTECTED : PUBLIC);
         builder.append(GAP);
         final StringBuilder builder = new StringBuilder();
         builder.append(indent);
         builder.append(isIdentity ? PROTECTED : PUBLIC);
         builder.append(GAP);
-        builder.append(genTransferObject.getName());
+        builder.append(className);
         builder.append(LB);
         return builder.toString();
     }
         builder.append(LB);
         return builder.toString();
     }
@@ -326,13 +480,48 @@ public final class GeneratorUtil {
         return builder.toString();
     }
 
         return builder.toString();
     }
 
-    private static String createConstructorSuperCalling(String indent) {
-        final StringBuilder builder = new StringBuilder();
-        builder.append(indent + TAB + "super();" + NL);
+    private static String createConstructorSuper(final List<GeneratedProperty> propertiesAllParents, final String indent) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
+        if (propertiesAllParents == null) {
+            throw new IllegalArgumentException("List of all parent's properties can't be null");
+        }
+        StringBuilder builder = new StringBuilder();
+        builder.append(indent + TAB + "super(");
+        String propertySeparator = COMMA + GAP;
+        for (GeneratedProperty superProperty : propertiesAllParents) {
+            builder.append(superProperty.getName());
+            builder.append(propertySeparator);
+        }
+        if (!propertiesAllParents.isEmpty()) {
+            builder = builder.delete(builder.length() - propertySeparator.length(), builder.length());
+        }
+
+        builder.append(");" + NL);
         return builder.toString();
     }
 
         return builder.toString();
     }
 
-    private static String createConstructorClosingPart(String indent) {
+    private static String createConstructorSuper(final GeneratedProperty parentProperty, final String indent) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
+        if (parentProperty == null) {
+            throw new IllegalArgumentException("Parent property can't be null");
+        }
+        StringBuilder builder = new StringBuilder();
+        if (parentProperty != null) {
+            builder.append(indent + TAB + "super(");
+            builder.append(parentProperty.getName());
+            builder.append(");" + NL);
+        }
+        return builder.toString();
+    }
+
+    private static String createConstructorClosingPart(final String indent) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
         final StringBuilder builder = new StringBuilder();
         builder.append(indent);
         builder.append(RCB);
         final StringBuilder builder = new StringBuilder();
         builder.append(indent);
         builder.append(RCB);
@@ -340,25 +529,55 @@ public final class GeneratorUtil {
         return builder.toString();
     }
 
         return builder.toString();
     }
 
-    private static String createClassAttributeInitialization(String indent, GeneratedProperty methodParameter) {
+    private static String createClassPropertiesInitialization(final List<GeneratedProperty> properties,
+            final String indent) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
+        if (properties == null) {
+            throw new IllegalArgumentException("List of generated class properties can't be null");
+        }
+        final StringBuilder builder = new StringBuilder();
+        for (final GeneratedProperty property : properties) {
+            createClassPropertyInitialization(property, indent);
+        }
+        return builder.toString();
+    }
+
+    private static String createClassPropertyInitialization(final GeneratedProperty property, final String indent) {
+        if (indent == null) {
+            throw new IllegalArgumentException("String with indent can't be null");
+        }
+        if (property == null) {
+            throw new IllegalArgumentException("List of generated class properties can't be null");
+        }
         final StringBuilder builder = new StringBuilder();
         builder.append(indent);
         builder.append(TAB);
         builder.append("this.");
         final StringBuilder builder = new StringBuilder();
         builder.append(indent);
         builder.append(TAB);
         builder.append("this.");
-        builder.append(methodParameter.getName());
+        builder.append(property.getName());
         builder.append(" = ");
         builder.append(" = ");
-        builder.append(methodParameter.getName());
+        builder.append(property.getName());
         builder.append(SC);
         builder.append(NL);
         return builder.toString();
     }
 
         builder.append(SC);
         builder.append(NL);
         return builder.toString();
     }
 
-    private static String createMethodParamDeclaration(GeneratedProperty methodParameter,
-            final Map<String, String> availableImports, String currentPkg) {
+    private static String createMethodPropertyDeclaration(final GeneratedProperty property,
+            final Map<String, String> availableImports, final String currentPkg) {
+        if (property == null) {
+            throw new IllegalArgumentException("Generated property can't be null");
+        }
+        if (availableImports == null) {
+            throw new IllegalArgumentException("Map of available imports can't be null");
+        }
+        if (currentPkg == null) {
+            throw new IllegalArgumentException("String with current package can't be null");
+        }
         final StringBuilder builder = new StringBuilder();
         final StringBuilder builder = new StringBuilder();
-        builder.append(getExplicitType(methodParameter.getReturnType(), availableImports, currentPkg));
+        builder.append(getExplicitType(property.getReturnType(), availableImports, currentPkg));
         builder.append(GAP);
         builder.append(GAP);
-        builder.append(methodParameter.getName());
+        builder.append(property.getName());
         return builder.toString();
     }
 
         return builder.toString();
     }
 
@@ -784,6 +1003,51 @@ public final class GeneratorUtil {
         return false;
     }
 
         return false;
     }
 
+    /**
+     * The method returns reference to highest (top parent) Generated Transfer
+     * Object.
+     * 
+     * @param childTransportObject
+     *            is generated transfer object which can be extended by other
+     *            generated transfer object
+     * @return in first case that <code>childTransportObject</code> isn't
+     *         extended then <code>childTransportObject</code> is returned. In
+     *         second case the method is recursive called until first case.
+     */
+    private static GeneratedTransferObject getTopParrentTransportObject(GeneratedTransferObject childTransportObject) {
+        if (childTransportObject == null) {
+            throw new IllegalArgumentException("Parameter childTransportObject can't be null.");
+        }
+        if (childTransportObject.getExtends() == null) {
+            return childTransportObject;
+        } else {
+            return getTopParrentTransportObject(childTransportObject.getExtends());
+        }
+    }
+
+    /**
+     * The method returns the list of the properties of all extending generated
+     * transfer object from <code>genTO</code> to highest parent generated
+     * transfer object
+     * 
+     * @param genTO
+     * @return the list of all properties from actual to highest parent
+     *         generated transfer object. In case when extension exists the
+     *         method is recursive called.
+     */
+    private static List<GeneratedProperty> getPropertiesOfAllParents(GeneratedTransferObject genTO) {
+        List<GeneratedProperty> propertiesOfAllParents = new ArrayList<GeneratedProperty>();
+        if (genTO != null) {
+            final List<GeneratedProperty> allPropertiesOfTO = genTO.getProperties();
+            List<GeneratedProperty> readOnlyPropertiesOfTO = resolveReadOnlyPropertiesFromTO(allPropertiesOfTO);
+            propertiesOfAllParents.addAll(readOnlyPropertiesOfTO);
+            if (genTO.getExtends() != null) {
+                propertiesOfAllParents.addAll(getPropertiesOfAllParents(genTO.getExtends()));
+            }
+        }
+        return propertiesOfAllParents;
+    }
+
     public static String createStaticInicializationBlock(GeneratedTransferObject genTransferObject, String indent) {
 
         final StringBuilder builder = new StringBuilder();
     public static String createStaticInicializationBlock(GeneratedTransferObject genTransferObject, String indent) {
 
         final StringBuilder builder = new StringBuilder();
diff --git a/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/typedef_of_typedef.yang b/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/typedef_of_typedef.yang
new file mode 100644 (file)
index 0000000..3aa6770
--- /dev/null
@@ -0,0 +1,79 @@
+module typedef_typedef {
+    
+    namespace "urn:typedef:typedef";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-09 {
+        
+    }
+
+   typedef byte-type {
+        type bits {
+            bit first-bit {
+                position 10;
+            }
+            bit second-bit {
+                position 20;
+            }
+         }
+    }    
+    
+    
+  typedef typedef-enum-fruit {
+    type enumeration {
+      enum "apple" {
+        value 1;
+        description "gold";
+      }
+      enum "pear" {
+        value 2;
+      }
+    }
+  }    
+    
+    typedef simple-typedef1 {
+       type uint8;
+    }
+    
+    typedef simple-typedef2 {
+        type simple-typedef1;
+    }
+    
+    typedef simple-typedef3 {
+        type simple-typedef2;
+    }
+    
+    typedef simple-typedef4 {
+        type simple-typedef3;
+    }
+    
+    typedef simple-typedef1-1 {
+        type uint16;
+    }    
+
+    
+    typedef union-typedef {
+        type union {
+            type simple-typedef1;
+            type simple-typedef4;
+            type byte-type;
+            type typedef-enum-fruit;
+        }
+    }    
+    
+    typedef extended-typedef-union {
+        type union-typedef;
+    }
+    
+    
+    typedef extended-typedef-simple {
+        type simple-typedef1;
+    }
+    
+    typedef extended-typedef-enum {
+        type typedef-enum-fruit;
+    }
+}
\ No newline at end of file
index 487c10cbf95cefc5c5e6a916a51442bbb533211d..53ffc2ea0befcde78208461fa5831ef0bcebdf09 100755 (executable)
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.yang.data.impl;\r
-\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.PrintStream;\r
-import java.net.URI;\r
-import java.util.Date;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-import org.junit.Assert;\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-import org.opendaylight.controller.yang.common.QName;\r
-import org.opendaylight.controller.yang.data.api.CompositeNode;\r
-import org.opendaylight.controller.yang.data.api.Node;\r
-import org.opendaylight.controller.yang.data.api.SimpleNode;\r
-import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
-import org.opendaylight.controller.yang.model.api.SchemaContext;\r
-import org.w3c.dom.Document;\r
-\r
-/**\r
- * @author michal.rehak\r
- *\r
- */\r
-public class NodeUtilsTest {\r
-    \r
-    private QName qName;\r
-    private CompositeNode network;\r
-\r
-    /**\r
-     * @throws Exception\r
-     */\r
-    @Before\r
-    public void setUp() throws Exception {\r
-        qName = new QName(\r
-                new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), \r
-                new Date(42), "yang-data-impl-mutableTest");\r
-        network = NodeHelper.buildTestConfigTree(qName);\r
-    }\r
-\r
-    /**\r
-     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildPath(org.opendaylight.controller.yang.data.api.Node)}.\r
-     * @throws Exception \r
-     */\r
-    @Test\r
-    public void testBuildPath() throws Exception {\r
-        SimpleNode<?> needle = network.getCompositesByName("topologies").iterator().next()\r
-            .getCompositesByName("topology").iterator().next()\r
-            .getSimpleNodesByName("topology-id").iterator().next();\r
-        String breadCrumbs = NodeUtils.buildPath(needle);\r
-        \r
-        Assert.assertEquals("network.topologies.topology.topology-id", breadCrumbs);\r
-    }\r
-\r
-    /**\r
-     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildShadowDomTree(org.opendaylight.controller.yang.data.api.CompositeNode)}.\r
-     * @throws Exception \r
-     */\r
-    @Test\r
-    public void testBuildShadowDomTree() throws Exception {\r
-        Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
-        ByteArrayOutputStream actual = new ByteArrayOutputStream();\r
-        NodeHelper.dumpDoc(networkShadow, new PrintStream(actual));\r
-        \r
-        Assert.assertEquals(2760, new String(actual.toByteArray()).length());\r
-    }\r
-\r
-    /**\r
-     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#findNodeByXpath(org.w3c.dom.Document, java.lang.String)}.\r
-     * @throws Exception \r
-     */\r
-    @Test\r
-    public void testFindNodeByXpath() throws Exception {\r
-        Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
-        SimpleNode<String> needle = NodeUtils.findNodeByXpath(networkShadow, \r
-                "//node[node-id='nodeId_19']//termination-point[2]/tp-id");\r
-        Assert.assertNotNull(needle);\r
-        Assert.assertEquals("tpId_18", needle.getValue());\r
-    }\r
-\r
-    /**\r
-     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildNodeMap(java.util.List)}.\r
-     */\r
-    @Test\r
-    public void testBuildNodeMap() {\r
-        CompositeNode topology = network.getCompositesByName("topologies").iterator().next()\r
-            .getCompositesByName("topology").iterator().next();\r
-        \r
-        Map<QName, List<Node<?>>> nodeMap = NodeUtils.buildNodeMap(topology.getChildren());\r
-        Assert.assertEquals(3, nodeMap.size());\r
-    }\r
-    \r
-    /**\r
-     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildMapOfListNodes(org.opendaylight.controller.yang.model.api.SchemaContext)}.\r
-     */\r
-    @Test\r
-    public void testBuildMapOfListNodes() {\r
-        SchemaContext schemaCtx = NodeHelper.loadSchemaContext();\r
-        Map<String, ListSchemaNode> mapOfLists = NodeUtils.buildMapOfListNodes(schemaCtx);\r
-        Assert.assertEquals(5, mapOfLists.size());\r
-    }\r
-\r
-}\r
+/*
+ * 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.controller.yang.data.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.data.api.CompositeNode;
+import org.opendaylight.controller.yang.data.api.Node;
+import org.opendaylight.controller.yang.data.api.SimpleNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.w3c.dom.Document;
+
+/**
+ * @author michal.rehak
+ *
+ */
+public class NodeUtilsTest {
+    
+    private QName qName;
+    private CompositeNode network;
+
+    /**
+     * @throws Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        qName = new QName(
+                new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), 
+                new Date(42), "yang-data-impl-mutableTest");
+        network = NodeHelper.buildTestConfigTree(qName);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildPath(org.opendaylight.controller.yang.data.api.Node)}.
+     * @throws Exception 
+     */
+    @Test
+    public void testBuildPath() throws Exception {
+        SimpleNode<?> needle = network.getCompositesByName("topologies").iterator().next()
+            .getCompositesByName("topology").iterator().next()
+            .getSimpleNodesByName("topology-id").iterator().next();
+        String breadCrumbs = NodeUtils.buildPath(needle);
+        
+        Assert.assertEquals("network.topologies.topology.topology-id", breadCrumbs);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildShadowDomTree(org.opendaylight.controller.yang.data.api.CompositeNode)}.
+     * @throws Exception 
+     */
+    @Test
+    public void testBuildShadowDomTree() throws Exception {
+        Document networkShadow = NodeUtils.buildShadowDomTree(network);
+        ByteArrayOutputStream actual = new ByteArrayOutputStream();
+        NodeHelper.dumpDoc(networkShadow, new PrintStream(actual));
+        
+        Assert.assertEquals(2760, new String(actual.toByteArray()).length());
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#findNodeByXpath(org.w3c.dom.Document, java.lang.String)}.
+     * @throws Exception 
+     */
+    @Test
+    public void testFindNodeByXpath() throws Exception {
+        Document networkShadow = NodeUtils.buildShadowDomTree(network);
+        SimpleNode<String> needle = NodeUtils.findNodeByXpath(networkShadow, 
+                "//node[node-id='nodeId_19']//termination-point[2]/tp-id");
+        Assert.assertNotNull(needle);
+        Assert.assertEquals("tpId_18", needle.getValue());
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildNodeMap(java.util.List)}.
+     */
+    @Test
+    public void testBuildNodeMap() {
+        CompositeNode topology = network.getCompositesByName("topologies").iterator().next()
+            .getCompositesByName("topology").iterator().next();
+        
+        Map<QName, List<Node<?>>> nodeMap = NodeUtils.buildNodeMap(topology.getChildren());
+        Assert.assertEquals(3, nodeMap.size());
+    }
+    
+    /**
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildMapOfListNodes(org.opendaylight.controller.yang.model.api.SchemaContext)}.
+     */
+    @Test
+    public void testBuildMapOfListNodes() {
+        SchemaContext schemaCtx = NodeHelper.loadSchemaContext();
+        Map<String, ListSchemaNode> mapOfLists = NodeUtils.buildMapOfListNodes(schemaCtx);
+        Assert.assertEquals(5, mapOfLists.size());
+    }
+
+}