From: Martin Vitez Date: Wed, 9 Jul 2014 14:17:59 +0000 (+0200) Subject: BUG-1276: fixed generated union constructor X-Git-Tag: release/helium~321^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=2b26351fad1af347c60c20762de92be8a5f229a1;p=yangtools.git BUG-1276: fixed generated union constructor Current generated definition of union constructor public UnionType(Arg1 _arg1) { super(); this._arg1 = _arg1; this._arg2 = null; this._value = null; } was incorrect and setting this._value == null was replaced with setting _value to correct value, for example: this._value = arg1.getValue() or this._value = _arg1.getValue().toString().toCharArray() Change-Id: I837e5e1fc6845937d19abcdc8e2f8d52b410d316 Signed-off-by: Martin Vitez --- diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionTemplate.xtend index f9c27fe865..94cfe1e8d0 100644 --- a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionTemplate.xtend +++ b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionTemplate.xtend @@ -9,6 +9,7 @@ package org.opendaylight.yangtools.sal.java.api.generator import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject import java.beans.ConstructorProperties +import org.opendaylight.yangtools.sal.binding.model.api.Enumeration /** * Template for generating JAVA class. @@ -37,14 +38,15 @@ class UnionTemplate extends ClassTemplate { private def unionConstructors() ''' «FOR property : finalProperties SEPARATOR "\n"» - «val isCharArray = "char[]".equals(property.returnType.name)» + «val propRet = property.returnType» + «val isCharArray = "char[]".equals(propRet.name)» «IF isCharArray» /** * Constructor provided only for using in JMX. Don't use it for * construction new object of this union type. */ @«ConstructorProperties.importedName»("«property.name»") - public «type.name»(«property.returnType.importedName» «property.fieldName») { + public «type.name»(«propRet.importedName» «property.fieldName») { «String.importedName» defVal = new «String.importedName»(«property.fieldName»); «type.name» defInst = «type.name»Builder.getDefaultInstance(defVal); «FOR other : finalProperties» @@ -61,7 +63,28 @@ class UnionTemplate extends ClassTemplate { super(«parentProperties.asArguments»); this.«property.fieldName» = «property.fieldName»; «FOR other : finalProperties» - «IF property != other»this.«other.fieldName» = null;«ENDIF» + «IF property != other» + «IF "value".equals(other.name)» + «IF "java.lang.String".equals(propRet.fullyQualifiedName)» + ««« type string + this.«other.fieldName» = «property.fieldName».toCharArray(); + «ELSEIF "byte[]".equals(propRet.name)» + ««« type binary + this.«other.fieldName» = new «String.importedName»(«property.fieldName»).toCharArray(); + «ELSEIF propRet.fullyQualifiedName.startsWith("java.lang") || propRet instanceof Enumeration» + ««« type int*, uint or enumeration* + this.«other.fieldName» = «property.fieldName».toString().toCharArray(); + «ELSEIF propRet instanceof GeneratedTransferObject && (propRet as GeneratedTransferObject).unionType» + ««« union type + this.«other.fieldName» = «property.fieldName».getValue(); + «ELSE» + ««« generated type + this.«other.fieldName» = «property.fieldName».getValue().toString().toCharArray(); + «ENDIF» + «ELSE» + this.«other.fieldName» = null; + «ENDIF» + «ENDIF» «ENDFOR» } «ENDIF» diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug1276Test.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug1276Test.java new file mode 100644 index 0000000000..d2653f2252 --- /dev/null +++ b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug1276Test.java @@ -0,0 +1,105 @@ +/* + * 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.yangtools.sal.java.api.generator.test; + +import static org.junit.Assert.assertTrue; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsConstructor; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles; +import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import org.junit.Test; +import org.opendaylight.yangtools.sal.binding.model.api.Type; +import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +/** + * Previous construction of union constructor + * + * + * public IpAddress(Arg1 _arg1) { + * super(); + * this._arg1 = _arg1; + * this._arg2 = null; + * this._value = null; + * } + * + * + * was incorrect and setting + * + * this._value == null + * + * was replaced with setting _value to correct value, for example: + * + * this._value = arg1.getValue() or + * this._value = _arg1.getValue().toString().toCharArray() + * + */ +public class Bug1276Test extends BaseCompilationTest { + + @Test + public void test() throws Exception { + final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug1276"); + assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir()); + final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug1276"); + assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir()); + + generateTestSources("/compilation/bug1276", sourcesOutputDir); + + // Test if sources are compilable + testCompilation(sourcesOutputDir, compiledOutputDir); + + ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() }); + Class ipAddressClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.IpAddress", true, loader); + Class ipv4AddressClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.Ipv4Address", true, loader); + Class hostClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.Host", true, loader); + + Constructor ipAddressConstructor = assertContainsConstructor(ipAddressClass, ipv4AddressClass); + Constructor ipv4addressConstructor = assertContainsConstructor(ipv4AddressClass, String.class); + Constructor hostConstructor = assertContainsConstructor(hostClass, ipAddressClass); + + // test IpAddress with Ipv4Address argument + Object ipv4address = ipv4addressConstructor.newInstance("192.168.0.1"); + Object ipAddress = ipAddressConstructor.newInstance(ipv4address); + Method getValue = ipAddressClass.getDeclaredMethod("getValue"); + char[] expected = "192.168.0.1".toCharArray(); + Object actual = getValue.invoke(ipAddress); + assertTrue(actual instanceof char[]); + assertTrue(Arrays.equals(expected, (char[]) actual)); + + // test Host with IpAddress argument + Object host = hostConstructor.newInstance(ipAddress); + getValue = hostClass.getDeclaredMethod("getValue"); + actual = getValue.invoke(host); + assertTrue(actual instanceof char[]); + assertTrue(Arrays.equals(expected, (char[]) actual)); + + cleanUp(sourcesOutputDir, compiledOutputDir); + } + + private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception { + final List sourceFiles = getSourceFiles(resourceDirPath); + final SchemaContext context = parser.parseFiles(sourceFiles); + final List types = bindingGenerator.generateTypes(context); + final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types)); + generator.generateToFile(sourcesOutputDir); + } + +} diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java index f8b2eda1a6..f310d5a487 100644 --- a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java +++ b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java @@ -228,7 +228,8 @@ public class TypedefCompilationTest extends BaseCompilationTest { // typedef string-ext3 assertFalse(stringExt3Class.isInterface()); - assertContainsFieldWithValue(stringExt3Class, "serialVersionUID", Long.TYPE, -2751063130555484180L, String.class); + assertContainsFieldWithValue(stringExt3Class, "serialVersionUID", Long.TYPE, -2751063130555484180L, + String.class); assertEquals(1, stringExt3Class.getDeclaredFields().length); expectedConstructor = assertContainsConstructor(stringExt3Class, String.class); assertContainsConstructor(stringExt3Class, stringExt3Class); @@ -244,7 +245,8 @@ public class TypedefCompilationTest extends BaseCompilationTest { assertFalse(myDecimalTypeClass.isInterface()); assertContainsField(myDecimalTypeClass, VAL, BigDecimal.class); assertContainsField(myDecimalTypeClass, RANGE, List.class); - assertContainsFieldWithValue(myDecimalTypeClass, "serialVersionUID", Long.TYPE, 3143735729419861095L, BigDecimal.class); + assertContainsFieldWithValue(myDecimalTypeClass, "serialVersionUID", Long.TYPE, 3143735729419861095L, + BigDecimal.class); assertEquals(3, myDecimalTypeClass.getDeclaredFields().length); assertContainsMethod(myDecimalTypeClass, BigDecimal.class, "getValue"); expectedConstructor = assertContainsConstructor(myDecimalTypeClass, BigDecimal.class); @@ -268,7 +270,8 @@ public class TypedefCompilationTest extends BaseCompilationTest { assertFalse(unionExt1Class.isInterface()); assertContainsField(unionExt1Class, "_int16", Short.class); assertContainsField(unionExt1Class, "_int32", Integer.class); - assertContainsFieldWithValue(unionExt1Class, "serialVersionUID", Long.TYPE, -5610530488718168882L, Short.class); + assertContainsFieldWithValue(unionExt1Class, "serialVersionUID", Long.TYPE, -5610530488718168882L, + new Class[] { Short.class }, Short.valueOf("1")); assertEquals(4, unionExt1Class.getDeclaredFields().length); assertContainsMethod(unionExt1Class, Short.class, "getInt16"); assertContainsMethod(unionExt1Class, Integer.class, "getInt32"); @@ -280,7 +283,8 @@ public class TypedefCompilationTest extends BaseCompilationTest { // typedef union-ext2 assertFalse(unionExt2Class.isInterface()); - assertContainsFieldWithValue(unionExt2Class, "serialVersionUID", Long.TYPE, -8833407459073585206L, Short.class); + assertContainsFieldWithValue(unionExt2Class, "serialVersionUID", Long.TYPE, -8833407459073585206L, + new Class[] { Short.class }, Short.valueOf("1")); assertEquals(1, unionExt2Class.getDeclaredFields().length); assertEquals(0, unionExt2Class.getDeclaredMethods().length); assertContainsConstructor(unionExt2Class, Short.class); @@ -293,8 +297,10 @@ public class TypedefCompilationTest extends BaseCompilationTest { assertFalse(unionExt3Class.isInterface()); assertContainsField(unionExt3Class, "_string", String.class); assertContainsField(unionExt3Class, "_unionExt2", unionExt2Class); - assertContainsFieldWithValue(unionExt3Class, UNITS, String.class, "object id", String.class); - assertContainsFieldWithValue(unionExt3Class, "serialVersionUID", Long.TYPE, 4347887914884631036L, String.class); + assertContainsFieldWithValue(unionExt3Class, UNITS, String.class, "object id", new Class[] { String.class }, + ""); + assertContainsFieldWithValue(unionExt3Class, "serialVersionUID", Long.TYPE, 4347887914884631036L, + new Class[] { String.class }, ""); assertEquals(5, unionExt3Class.getDeclaredFields().length); assertContainsMethod(unionExt3Class, String.class, "getString"); assertContainsMethod(unionExt3Class, unionExt2Class, "getUnionExt2"); @@ -310,7 +316,8 @@ public class TypedefCompilationTest extends BaseCompilationTest { assertContainsField(unionExt4Class, "_int32Ext2", int32Ext2Class); assertContainsField(unionExt4Class, "_empty", Boolean.class); assertContainsField(unionExt4Class, "_myDecimalType", myDecimalTypeClass); - assertContainsFieldWithValue(unionExt4Class, "serialVersionUID", Long.TYPE, 4299836385615211130L, Boolean.class); + assertContainsFieldWithValue(unionExt4Class, "serialVersionUID", Long.TYPE, 4299836385615211130L, + new Class[] { Boolean.class }, false); assertEquals(6, unionExt4Class.getDeclaredFields().length); assertContainsMethod(unionExt4Class, unionExt3Class, "getUnionExt3"); assertContainsMethod(unionExt4Class, int32Ext2Class, "getInt32Ext2"); diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1276/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1276/foo.yang new file mode 100644 index 0000000000..9f7722787f --- /dev/null +++ b/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1276/foo.yang @@ -0,0 +1,62 @@ + module foo { + + namespace "test:yang:union"; + prefix "foo"; + + revision 2014-07-15 { + } + + + typedef ip-address { + type union { + type ipv4-address; + type ipv6-address; + } + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + } + + typedef domain-name { + type string { + pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + } + + typedef host { + type union { + type ip-address; + type domain-name; + } + } + + typedef int-type { + type union { + type binary; + type int8; + } + } + + } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/TypeUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/TypeUtils.java index 61b47f2cf5..d59b0215a6 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/TypeUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/TypeUtils.java @@ -7,6 +7,8 @@ */ package org.opendaylight.yangtools.yang.parser.builder.impl; +import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findBaseIdentity; + import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -86,6 +88,18 @@ public final class TypeUtils { toRemove.add(unionType); } } + // special handling for identityref types under union + for (TypeDefinitionBuilder unionType : union.getTypedefs()) { + if (unionType instanceof IdentityrefTypeBuilder) { + IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) unionType; + IdentitySchemaNodeBuilder identity = findBaseIdentity(modules, module, idref.getBaseString(), + idref.getLine()); + if (identity == null) { + throw new YangParseException(module.getName(), idref.getLine(), "Failed to find base identity"); + } + idref.setBaseIdentity(identity); + } + } unionTypes.removeAll(toRemove); } @@ -93,6 +107,10 @@ public final class TypeUtils { final Map> modules, final ModuleBuilder module) { final QName utQName = ut.getQName(); final ModuleBuilder dependentModuleBuilder = BuilderUtils.getModuleByPrefix(module, utQName.getPrefix()); + if (dependentModuleBuilder == null) { + throw new YangParseException(module.getName(), union.getLine(), "No module found with prefix " + + utQName.getPrefix()); + } final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder, utQName.getLocalName(), module.getName(), union.getLine()); union.setTypedef(resolvedType);