*/
void setBaseType(TypeDefinition<?> typeDef);
+ boolean isUnion();
+
/**
*
* @param isUnion
}
typeProvider.putReferencedType(leaf.getPath(), returnType);
} else if (typeDef instanceof UnionTypeDefinition) {
- GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((UnionTypeDefinition) typeDef, typeBuilder, leaf,
- parentModule);
- if (genTOBuilder != null) {
- returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
- // Store the inner type within the union so that we can find the reference for it
- context.addInnerTypedefType(typeDef.getPath(), returnType);
- }
+ final UnionTypeDefinition unionDef = (UnionTypeDefinition)typeDef;
+ returnType = addTOToTypeBuilder(unionDef, typeBuilder, leaf, parentModule);
+ // Store the inner type within the union so that we can find the reference for it
+ context.addInnerTypedefType(typeDef.getPath(), returnType);
} else if (typeDef instanceof BitsTypeDefinition) {
GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((BitsTypeDefinition) typeDef, typeBuilder, leaf,
parentModule);
returnType = new ReferencedTypeImpl(enumBuilder.getIdentifier());
typeProvider.putReferencedType(node.getPath(), returnType);
} else if (typeDef instanceof UnionTypeDefinition) {
- final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((UnionTypeDefinition)typeDef, typeBuilder,
- node, parentModule);
- if (genTOBuilder != null) {
- returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
- }
+ final UnionTypeDefinition unionDef = (UnionTypeDefinition)typeDef;
+ returnType = addTOToTypeBuilder(unionDef, typeBuilder, node, parentModule);
} else if (typeDef instanceof BitsTypeDefinition) {
final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((BitsTypeDefinition)typeDef, typeBuilder,
node, parentModule);
return true;
}
- private Type createReturnTypeForUnion(final GeneratedTOBuilder genTOBuilder, final TypeDefinition<?> typeDef,
+ private Type createReturnTypeForUnion(final GeneratedTOBuilder genTOBuilder, final UnionTypeDefinition typeDef,
final GeneratedTypeBuilder typeBuilder, final Module parentModule) {
- final GeneratedTOBuilder returnType = typeProvider.newGeneratedTOBuilder(genTOBuilder.getIdentifier());
-
- addCodegenInformation(returnType, parentModule, typeDef);
- returnType.setSchemaPath(typeDef.getPath());
- returnType.setModuleName(parentModule.getName());
+ final GeneratedTOBuilder returnTypeBuilder = typeProvider.newGeneratedTOBuilder(genTOBuilder.getIdentifier());
+ returnTypeBuilder.setIsUnion(true);
+ addCodegenInformation(returnTypeBuilder, parentModule, typeDef);
+ returnTypeBuilder.setSchemaPath(typeDef.getPath());
+ returnTypeBuilder.setModuleName(parentModule.getName());
+ final GeneratedTransferObject returnType = returnTypeBuilder.build();
genTOBuilder.setTypedef(true);
genTOBuilder.setIsUnion(true);
AbstractTypeProvider.addUnitsToGenTO(genTOBuilder, typeDef.getUnits().orElse(null));
+ createUnionBuilder(genTOBuilder, typeBuilder, returnType, parentModule);
+ return returnType;
+ }
-
- final GeneratedTOBuilder unionBuilder = createUnionBuilder(genTOBuilder, typeBuilder);
-
+ private void createUnionBuilder(final GeneratedTOBuilder genTOBuilder, final GeneratedTypeBuilder typeBuilder,
+ final GeneratedTransferObject returnType, final Module parentModule) {
+ // Append enclosing path hierarchy without dots
+ final StringBuilder sb = new StringBuilder();
+ genTOBuilder.getIdentifier().localNameComponents().forEach(sb::append);
+ final GeneratedTOBuilder unionBuilder = typeProvider.newGeneratedTOBuilder(
+ JavaTypeName.create(typeBuilder.getPackageName(), sb.append("Builder").toString()));
+ unionBuilder.setIsUnionBuilder(true);
final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
method.setReturnType(returnType);
method.setAccessModifier(AccessModifier.PUBLIC);
method.setStatic(true);
+ final GeneratedTransferObject unionBuilderType = unionBuilder.build();
final Set<Type> types = typeProvider.getAdditionalTypes().get(parentModule);
if (types == null) {
- typeProvider.getAdditionalTypes().put(parentModule,
- Sets.newHashSet(unionBuilder.build()));
+ typeProvider.getAdditionalTypes().put(parentModule, Sets.newHashSet(unionBuilderType));
} else {
- types.add(unionBuilder.build());
+ types.add(unionBuilderType);
}
- return returnType.build();
- }
-
- private GeneratedTOBuilder createUnionBuilder(final GeneratedTOBuilder genTOBuilder,
- final GeneratedTypeBuilder typeBuilder) {
- // Append enclosing path hierarchy without dots
- final StringBuilder sb = new StringBuilder();
- genTOBuilder.getIdentifier().localNameComponents().forEach(sb::append);
- final GeneratedTOBuilder unionBuilder = typeProvider.newGeneratedTOBuilder(
- JavaTypeName.create(typeBuilder.getPackageName(), sb.append("Builder").toString()));
- unionBuilder.setIsUnionBuilder(true);
- return unionBuilder;
}
private GeneratedTypeBuilder addDefaultInterfaceDefinition(final ModuleContext context,
return addDefaultInterfaceDefinition(packageName, schemaNode, baseInterface, context);
}
-
/**
* Instantiates generated type builder with <code>packageName</code> and
* <code>schemaNode</code>.
* parent module
* @return generated TO builder for <code>typeDef</code>
*/
- private GeneratedTOBuilder addTOToTypeBuilder(final UnionTypeDefinition typeDef,
+ private Type addTOToTypeBuilder(final UnionTypeDefinition typeDef,
final GeneratedTypeBuilder typeBuilder, final DataSchemaNode leaf, final Module parentModule) {
final List<GeneratedTOBuilder> types = typeProvider.provideGeneratedTOBuildersForUnionTypeDef(
typeBuilder.getIdentifier().createEnclosed(BindingMapping.getClassName(leaf.getQName())),
checkState(!types.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typeDef);
final List<GeneratedTOBuilder> genTOBuilders = new ArrayList<>(types);
final GeneratedTOBuilder resultTOBuilder = types.remove(0);
- for (final GeneratedTOBuilder genTOBuilder : types) {
- resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
+ types.forEach(resultTOBuilder::addEnclosingTransferObject);
+ genTOBuilders.forEach(typeBuilder::addEnclosingTransferObject);
+
+ for (GeneratedTOBuilder builder : types) {
+ if (builder.isUnion()) {
+ final GeneratedTransferObject type = builder.build();
+ createUnionBuilder(builder, typeBuilder, type, parentModule);
+ }
}
- processEnclosedTOBuilderes(typeBuilder, genTOBuilders);
- return resultTOBuilder;
+ return createReturnTypeForUnion(resultTOBuilder, typeDef, typeBuilder, parentModule);
}
/**
}
- private static GeneratedTOBuilder processEnclosedTOBuilderes(final GeneratedTypeBuilder typeBuilder,
- final List<GeneratedTOBuilder> genTOBuilders) {
- for (final GeneratedTOBuilder genTOBuilder : genTOBuilders) {
- typeBuilder.addEnclosingTransferObject(genTOBuilder);
- }
- return genTOBuilders.get(0);
- }
-
/**
* Adds the implemented types to type builder.
*
private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef,
final Type javaType, final String moduleName) {
Preconditions.checkNotNull(javaType, "javaType cannot be null");
- final String propertyName = "value";
final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef, moduleName);
genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef));
- final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName);
+ final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty("value");
genPropBuilder.setReturnType(javaType);
genTOBuilder.addEqualsIdentity(genPropBuilder);
genTOBuilder.addHashIdentity(genPropBuilder);
final Module module = findParentModule(schemaContext, parentNode);
final GeneratedTOBuilder unionGenTOBuilder = newGeneratedTOBuilder(typeName);
+ unionGenTOBuilder.setIsUnion(true);
unionGenTOBuilder.setSchemaPath(typedef.getPath());
unionGenTOBuilder.setModuleName(module.getName());
addCodegenInformation(unionGenTOBuilder, typedef);
-
generatedTOBuilders.add(unionGenTOBuilder);
- unionGenTOBuilder.setIsUnion(true);
// Pattern string is the key, XSD regex is the value. The reason for this choice is that the pattern carries
// also negation information and hence guarantees uniqueness.
final GeneratedPropertyBuilder propertyBuilder;
propertyBuilder = parentUnionGenTOBuilder.addProperty(BindingMapping.getPropertyName(
newTOBuilderName.simpleName()));
- propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0));
+ propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0).build());
parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Iterables;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.model.api.GeneratedProperty;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.MethodSignature;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class Mdsal320Test {
+
+ @Test
+ public void mdsal320Test() {
+ final SchemaContext context = YangParserTestUtils.parseYangResource("/mdsal320.yang");
+
+ final List<Type> generateTypes = new BindingGeneratorImpl().generateTypes(context);
+ assertNotNull(generateTypes);
+ assertEquals(4, generateTypes.size());
+
+ final Type fooType = generateTypes.stream().filter(type -> type.getFullyQualifiedName()
+ .equals("org.opendaylight.yang.gen.v1.urn.odl.yt320.norev.Foo")).findFirst().get();
+ assertTrue(fooType instanceof GeneratedType);
+ final GeneratedType foo = (GeneratedType) fooType;
+
+ GeneratedTransferObject bar = null;
+ GeneratedTransferObject bar1 = null;
+ for (GeneratedType enc : foo.getEnclosedTypes()) {
+ switch (enc.getName()) {
+ case "Bar":
+ assertTrue(enc instanceof GeneratedTransferObject);
+ bar = (GeneratedTransferObject) enc;
+ break;
+ case "Bar$1":
+ assertTrue(enc instanceof GeneratedTransferObject);
+ bar1 = (GeneratedTransferObject) enc;
+ break;
+ default:
+ throw new IllegalStateException("Unexpected type " + enc);
+ }
+ }
+ assertNotNull(bar);
+ assertTrue(bar.isUnionType());
+ assertNotNull(bar1);
+ assertTrue(bar1.isUnionType());
+
+ final MethodSignature getBar = Iterables.getOnlyElement(foo.getMethodDefinitions());
+ final Type getBarType = getBar.getReturnType();
+ assertTrue(getBarType instanceof GeneratedTransferObject);
+ final GeneratedTransferObject getBarTO = (GeneratedTransferObject) getBarType;
+ assertTrue(getBarTO.isUnionType());
+ assertEquals(bar, getBarTO);
+
+ final GeneratedProperty bar1Prop = bar.getProperties().stream().filter(prop -> "bar$1".equals(prop.getName()))
+ .findFirst().get();
+ final Type bar1PropRet = bar1Prop.getReturnType();
+ assertEquals(bar1, bar1PropRet);
+ }
+}
final SchemaContext context = YangParserTestUtils.parseYangResource("/mdsal324.yang");
final List<Type> generateTypes = new BindingGeneratorImpl().generateTypes(context);
assertNotNull(generateTypes);
- assertEquals(4, generateTypes.size());
+ assertEquals(6, generateTypes.size());
}
}
--- /dev/null
+module yt320 {
+ namespace "urn:odl:yt320";
+ prefix yt320;
+
+ container foo {
+ leaf bar {
+ type union {
+ type enumeration {
+ enum "foo";
+ }
+ type string {
+ length 2;
+ }
+ type union {
+ type enumeration {
+ enum bar;
+ }
+ type string {
+ length 1;
+ }
+ }
+ }
+ }
+ }
+}
+
import java.util.List;
import org.opendaylight.mdsal.binding.model.api.GeneratedProperty;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
this.isUnionType = isUnion;
}
+ @Override
+ public final boolean isUnion() {
+ return isUnionType;
+ }
+
@Override
public final void setIsUnionBuilder(final boolean isUnionTypeBuilder) {
this.isUnionTypeBuilder = isUnionTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.GeneratedProperty;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
-import org.opendaylight.mdsal.binding.model.api.Restrictions;
import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.model.api.Restrictions;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
private final String moduleName;
private final SchemaPath schemaPath;
- public GTO(final CodegenGeneratedTOBuilder builder) {
+ GTO(final CodegenGeneratedTOBuilder builder) {
super(builder);
this.restrictions = builder.restrictions;
this.reference = builder.reference;
return actualType.restrictions;
}
+ def protected generateInnerClass(GeneratedType innerClass) '''
+ «IF innerClass instanceof GeneratedTransferObject»
+ «val innerJavaType = javaType.getEnclosedType(innerClass.identifier)»
+ «IF innerClass.unionType»
+ «new UnionTemplate(innerJavaType, innerClass).generateAsInnerClass»
+ «ELSE»
+ «new ClassTemplate(innerJavaType, innerClass).generateAsInnerClass»
+ «ENDIF»
+ «ENDIF»
+ '''
+
def static Restrictions getRestrictions(Type type) {
if (type instanceof ConcreteType) {
return type.restrictions
def protected innerClassesDeclarations() '''
«IF !type.enclosedTypes.empty»
«FOR innerClass : type.enclosedTypes SEPARATOR "\n"»
- «IF (innerClass instanceof GeneratedTransferObject)»
- «new ClassTemplate(javaType.getEnclosedType(innerClass.identifier), innerClass).generateAsInnerClass»
- «ENDIF»
+ «generateInnerClass(innerClass)»
«ENDFOR»
«ENDIF»
'''
import org.opendaylight.mdsal.binding.model.api.AnnotationType
import org.opendaylight.mdsal.binding.model.api.Constant
import org.opendaylight.mdsal.binding.model.api.Enumeration
-import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
import org.opendaylight.mdsal.binding.model.api.GeneratedType
import org.opendaylight.mdsal.binding.model.api.MethodSignature
import org.opendaylight.mdsal.binding.model.util.TypeConstants
def private generateInnerClasses() '''
«IF !enclosedGeneratedTypes.empty»
«FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
- «IF (innerClass instanceof GeneratedTransferObject)»
- «val innerJavaType = javaType.getEnclosedType(innerClass.identifier)»
- «IF innerClass.unionType»
- «val unionTemplate = new UnionTemplate(innerJavaType, innerClass)»
- «unionTemplate.generateAsInnerClass»
- «ELSE»
- «val classTemplate = new ClassTemplate(innerJavaType, innerClass)»
- «classTemplate.generateAsInnerClass»
- «ENDIF»
-
- «ENDIF»
+ «generateInnerClass(innerClass)»
«ENDFOR»
«ENDIF»
'''
CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir);
}
+ @Test
+ public void twoNestedUnionsTest() throws Exception {
+ final File sourcesOutputDir = CompilationTestUtils.generatorOutput("mdsal320");
+ final File compiledOutputDir = CompilationTestUtils.compilerOutput("mdsal320");
+ generateTestSources("/compilation/mdsal320", sourcesOutputDir);
+ CompilationTestUtils.testCompilation(sourcesOutputDir, compiledOutputDir);
+ CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir);
+ }
+
private static void testReturnTypeIdentityref(final Class<?> clazz, final String methodName,
final String returnTypeStr) throws NoSuchMethodException {
Method method = clazz.getMethod(methodName);
--- /dev/null
+module yt320 {
+ namespace "urn:odl:yt320";
+ prefix yt320;
+
+ container foo {
+ leaf bar {
+ type union {
+ type enumeration {
+ enum "foo";
+ }
+ type string {
+ length 2;
+ }
+ type union {
+ type enumeration {
+ enum bar;
+ }
+ type string {
+ length 1;
+ }
+ }
+ }
+ }
+ }
+}
+