«generateConstructorsFromIfcs(type)»
+ «generateCopyConstructor(false)»
+
«generateMethodFieldsFrom(type)»
«generateGetters(false)»
«generateAugmentField(false)»
- «generateConstructor»
+ «generateCopyConstructor(true)»
«generateGetters(true)»
}
'''
- /**
- * Template method which generate constructor for IMPL class.
- *
- * @return string with IMPL class constructor
- */
- def private generateConstructor() '''
- private «type.name»«IMPL»(«type.name»«BUILDER» builder) {
+ def private CharSequence generateCopyConstructor(boolean impl) '''
+ «IF impl»private«ELSE»public«ENDIF» «type.name»«IF impl»«IMPL»«ELSE»«BUILDER»«ENDIF»(«type.name»«IF impl»«BUILDER»«ENDIF» base) {
«val allProps = new ArrayList(properties)»
«val isList = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), type))»
«val keyType = type.getKey»
«removeProperty(allProps, field.name)»
«ENDFOR»
«removeProperty(allProps, "key")»
- if (builder.getKey() == null) {
+ if (base.getKey() == null) {
this._key = new «keyType.importedName»(
«FOR keyProp : keyProps SEPARATOR ", "»
- builder.«keyProp.getterMethodName»()
+ base.«keyProp.getterMethodName»()
«ENDFOR»
);
«FOR field : keyProps»
- this.«field.fieldName» = builder.«field.getterMethodName»();
+ this.«field.fieldName» = base.«field.getterMethodName»();
«ENDFOR»
} else {
- this._key = builder.getKey();
+ this._key = base.getKey();
«FOR field : keyProps»
this.«field.fieldName» = _key.«field.getterMethodName»();
«ENDFOR»
}
«ENDIF»
«FOR field : allProps»
- this.«field.fieldName» = builder.«field.getterMethodName»();
+ this.«field.fieldName» = base.«field.getterMethodName»();
«ENDFOR»
«IF augmentField != null»
- switch (builder.«augmentField.name».size()) {
- case 0:
- this.«augmentField.name» = «Collections.importedName».emptyMap();
- break;
- case 1:
- final «Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = builder.«augmentField.name».entrySet().iterator().next();
- this.«augmentField.name» = «Collections.importedName».<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
- break;
- default :
- this.«augmentField.name» = new «HashMap.importedName»<>(builder.«augmentField.name»);
- }
+ «IF !impl»if (base instanceof «type.name»«IMPL») {«ENDIF»
+ «IF !impl»«type.name»«IMPL» _impl = («type.name»«IMPL») base;«ENDIF»
+ «val prop = if (impl) "base" else "_impl"»
+ switch («prop».«augmentField.name».size()) {
+ case 0:
+ this.«augmentField.name» = «Collections.importedName».emptyMap();
+ break;
+ case 1:
+ final «Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = «prop».«augmentField.name».entrySet().iterator().next();
+ this.«augmentField.name» = «Collections.importedName».<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
+ break;
+ default :
+ this.«augmentField.name» = new «HashMap.importedName»<>(«prop».«augmentField.name»);
+ }
+ «IF !impl»}«ENDIF»
«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.assertEquals;
+import static org.junit.Assert.assertNotNull;
+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.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 com.google.common.collect.Lists;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.Mockito;
+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;
+
+/**
+ * Test correct functionality of copy constructor of generated builder classes.
+ */
+public class Bug532Test extends BaseCompilationTest {
+
+ @Test
+ public void test() throws Exception {
+ final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug532");
+ assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+ final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug532");
+ assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+ generateTestSources("/compilation/list-gen", sourcesOutputDir);
+
+ // Test if sources are compilable
+ testCompilation(sourcesOutputDir, compiledOutputDir);
+
+ ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+ Class<?> linksKeyClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksKey", true, loader);
+ Class<?> linksClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Links", true, loader);
+ Class<?> linksBuilderClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksBuilder", true,
+ loader);
+ Class<?> levelClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.Level", true, loader);
+ Class<?> nodeClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.Node", true, loader);
+ Class<?> nodeListClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.NodeList", true,
+ loader);
+
+ // init default values
+ Byte expectedId = Byte.valueOf("5");
+ String expectedName = "test-link";
+ Integer expectedSize = Integer.valueOf(10);
+ Object expectedLevel = Mockito.mock(levelClass);
+ Integer expectedLinksId = Integer.valueOf(11);
+ Object expectedNode = Mockito.mock(nodeClass);
+ List<?> expectedNodeList = Lists.newArrayList(Mockito.mock(nodeListClass), Mockito.mock(nodeListClass));
+ Constructor<?> keyConstructor = linksKeyClass.getDeclaredConstructor(Byte.class, String.class, Integer.class);
+ Object expectedKey = keyConstructor.newInstance(expectedId, expectedName, expectedSize);
+
+ // create Links object
+ Object linksBuilder = linksBuilderClass.newInstance();
+ linksBuilderClass.getDeclaredMethod("setKey", linksKeyClass).invoke(linksBuilder, expectedKey);
+ linksBuilderClass.getDeclaredMethod("setLevel", levelClass).invoke(linksBuilder, expectedLevel);
+ linksBuilderClass.getDeclaredMethod("setLinksId", Integer.class).invoke(linksBuilder, expectedLinksId);
+ linksBuilderClass.getDeclaredMethod("setNode", nodeClass).invoke(linksBuilder, expectedNode);
+ linksBuilderClass.getDeclaredMethod("setNodeList", List.class).invoke(linksBuilder, expectedNodeList);
+ Object links = linksBuilderClass.getDeclaredMethod("build").invoke(linksBuilder);
+
+ // create LinksBuilder object with constructor with Links object
+ // argument
+ Constructor<?> linksBuilderConstructor = linksBuilderClass.getDeclaredConstructor(linksClass);
+ assertNotNull(linksBuilderConstructor);
+ Object linksBuilderTested = linksBuilderConstructor.newInstance(links);
+
+ // get values from LinksBuilder
+ Object actualKey = linksBuilderClass.getDeclaredMethod("getKey").invoke(linksBuilderTested);
+ Object actualId = linksBuilderClass.getDeclaredMethod("getId").invoke(linksBuilderTested);
+ Object actualName = linksBuilderClass.getDeclaredMethod("getName").invoke(linksBuilderTested);
+ Object actualSize = linksBuilderClass.getDeclaredMethod("getSize").invoke(linksBuilderTested);
+ Object actualLevel = linksBuilderClass.getDeclaredMethod("getLevel").invoke(linksBuilderTested);
+ Object actualLinksId = linksBuilderClass.getDeclaredMethod("getLinksId").invoke(linksBuilderTested);
+ Object actualNode = linksBuilderClass.getDeclaredMethod("getNode").invoke(linksBuilderTested);
+ Object actualNodeList = linksBuilderClass.getDeclaredMethod("getNodeList").invoke(linksBuilderTested);
+
+ // test
+ assertEquals(expectedKey, actualKey);
+ assertEquals(expectedId, actualId);
+ assertEquals(expectedName, actualName);
+ assertEquals(expectedSize, actualSize);
+ assertEquals(expectedLevel, actualLevel);
+ assertEquals(expectedLinksId, actualLinksId);
+ assertEquals(expectedNode, actualNode);
+ assertEquals(expectedNodeList, actualNodeList);
+
+ 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);
+ }
+
+}