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.
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»
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»
--- /dev/null
+/*
+ * 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
+ *
+ * <code>
+ * public IpAddress(Arg1 _arg1) {
+ * super();
+ * this._arg1 = _arg1;
+ * this._arg2 = null;
+ * this._value = null;
+ * }
+ * </code>
+ *
+ * was incorrect and setting
+ *
+ * <code>this._value == null</code>
+ *
+ * was replaced with setting _value to correct value, for example:
+ *
+ * <code>this._value = arg1.getValue()</code> or
+ * <code>this._value = _arg1.getValue().toString().toCharArray()</code>
+ *
+ */
+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<File> sourceFiles = getSourceFiles(resourceDirPath);
+ final SchemaContext context = parser.parseFiles(sourceFiles);
+ final List<Type> types = bindingGenerator.generateTypes(context);
+ final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ generator.generateToFile(sourcesOutputDir);
+ }
+
+}
// 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);
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);
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");
// 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);
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");
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");
--- /dev/null
+ 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;
+ }
+ }
+
+ }
*/
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;
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);
}
final Map<String, TreeMap<Date, ModuleBuilder>> 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);