import java.util.Set;
import java.util.concurrent.Callable;
+import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.UnionType;
final class UnionTypeCodec extends ReflectionBasedCodec {
String methodName = "get" + BindingMapping.getClassName(subtype.getQName());
Method valueGetter = unionCls.getMethod(methodName);
Class<?> valueType = valueGetter.getReturnType();
- SchemaUnawareCodec valueCodec = ValueTypeCodec.getCodecFor(valueType, subtype);
+ Codec<Object, Object> valueCodec = UnionTypeCodec.getCodecForType(valueType, subtype);
values.add(new UnionValueOptionContext(valueType,valueGetter, valueCodec));
}
return new UnionTypeCodec(unionCls, values);
};
}
+ private static Codec<Object, Object> getCodecForType(Class valueType, TypeDefinition subtype) {
+ if (subtype.getBaseType() instanceof UnionType) {
+ try {
+ return UnionTypeCodec.loader(valueType, (UnionType) subtype.getBaseType()).call();
+ } catch (final Exception e) {
+ throw new IllegalStateException("Could not construct Union Type Codec");
+ }
+ } else {
+ return ValueTypeCodec.getCodecFor(valueType, subtype);
+ }
+ }
+
@Override
public Object deserialize(final Object input) {
try {
while (rootType.getBaseType() != null) {
rootType = rootType.getBaseType();
}
- if(rootType instanceof EmptyTypeDefinition) {
+ if (rootType instanceof EmptyTypeDefinition) {
return EMPTY_CODEC;
}
return NOOP_CODEC;
--- /dev/null
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.TopLevel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.TopLevelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.Wrapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.WrapperBuilder;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+
+public class UnionTypeTest extends AbstractBindingRuntimeTest {
+
+ private static final String testString = "testtesttest";
+
+ public static final QName WRAPPER_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:union", "2015-01-21", "wrapper");
+ public static final QName WRAP_LEAF_QNAME = QName.create(WRAPPER_QNAME, "wrap");
+
+ private BindingNormalizedNodeCodecRegistry registry;
+
+ @Override
+ public void setup() {
+ super.setup();
+ JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ @Test
+ public void unionTest() {
+ TopLevel topLevel = TopLevelBuilder.getDefaultInstance(testString);
+ Wrapper wrapper = new WrapperBuilder().setWrap(topLevel).build();
+ NormalizedNode<?, ?> topLevelEntry = registry.toNormalizedNode(InstanceIdentifier.builder(Wrapper.class).build(), wrapper).getValue();
+
+ ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(WRAPPER_QNAME))
+ .withChild(ImmutableNodes.leafNode(WRAP_LEAF_QNAME, testString))
+ .build();
+ Assert.assertEquals(topLevelEntry, containerNode);
+ }
+}
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
import org.opendaylight.yangtools.util.LazyCollections;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<GeneratedTOBuilder> implements GeneratedTOBuilder {
private boolean isTypedef = false;
private boolean isUnionType = false;
private boolean isUnionTypeBuilder = false;
+ private TypeDefinition baseType = null;
private Restrictions restrictions;
private GeneratedPropertyBuilder SUID;
private String reference;
this.isTypedef = isTypedef;
}
+ @Override
+ public void setBaseType(final TypeDefinition typeDef) {
+ this.baseType = typeDef;
+ }
+
@Override
public void setIsUnion(final boolean isUnion) {
this.isUnionType = isUnion;
private final List<GeneratedProperty> stringProperties;
private final GeneratedTransferObject extendsType;
private final boolean isTypedef;
+ private final TypeDefinition baseType;
private final boolean isUnionType;
private final boolean isUnionTypeBuilder;
private final Restrictions restrictions;
this.stringProperties = toUnmodifiableProperties(builder.toStringProperties);
this.isTypedef = builder.isTypedef;
+ this.baseType = builder.baseType;
this.isUnionType = builder.isUnionType;
this.isUnionTypeBuilder = builder.isUnionTypeBuilder;
this.restrictions = builder.restrictions;
return isTypedef;
}
+ @Override
+ public TypeDefinition getBaseType() {
+ return baseType;
+ }
+
@Override
public boolean isUnionType() {
return isUnionType;
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
import com.google.common.base.Preconditions
/**
«ENDIF»
«ENDFOR»
+ «IF (genTO.isTypedef() && genTO.getBaseType instanceof BitsTypeDefinition)»
+ «generateGetValueForBitsTypeDef»
+ «ENDIF»
+
«generateHashCode»
«generateEquals»
«generateRangeMethod("range", "_range")»
}
+
+ '''
+
+ /**
+ * Template method which generates the method <code>getValue()</code> for typedef,
+ * which base type is BitsDefinition.
+ *
+ * @return string with the <code>getValue()</code> method definition in JAVA format
+ */
+ def protected generateGetValueForBitsTypeDef() '''
+
+ public boolean[] getValue() {
+ return new boolean[]{
+ «FOR property: genTO.properties SEPARATOR ','»
+ «property.fieldName»
+ «ENDFOR»
+ };
+ }
'''
def private generateLengthMethod(String methodName, String varName) '''
package org.opendaylight.yangtools.sal.binding.model.api;
import java.util.List;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
/**
* Generated Transfer Object extends {@link GeneratedType} and is designed to
boolean isTypedef();
+ /**
+ * Returns Base type of Java representation of YANG typedef if set, otherwise it returns null
+ *
+ * @return Base type of Java representation of YANG typedef if set, otherwise it returns null
+ */
+ TypeDefinition getBaseType();
+
/**
* Return boolean value which describe whether Generated Transfer Object
* was/wasn't created from union YANG type.
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
/**
* Generated Transfer Object Builder is interface that contains methods to build
void setTypedef(boolean isTypedef);
+ /**
+ * Sets the base type for Java representation of YANG typedef
+ *
+ * @param typeDef
+ * Type Definition
+ */
+ void setBaseType(TypeDefinition typeDef);
+
/**
*
* @param isUnion
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ */
+public class TopLevelBuilder {
+
+ public static TopLevel getDefaultInstance(java.lang.String defaultValue) {
+ if (defaultValue.length() <= 4) {
+ return new TopLevel(new NonUnionTestType(defaultValue));
+ }
+ else {
+ return new TopLevel(UnionTestTypeBuilder.getDefaultInstance(defaultValue));
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ *
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ *
+ */
+public class UnionTestTypeBuilder {
+
+ public static UnionTestType getDefaultInstance(java.lang.String defaultValue) {
+ if (defaultValue.length() > 8) {
+ return new UnionTestType(new LowestLevel1(defaultValue));
+ } else {
+ return new UnionTestType(new LowestLevel2(defaultValue));
+ }
+ }
+
+}
--- /dev/null
+module opendaylight-yangtools-union-test {
+
+ namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:union";
+ prefix union-test;
+
+
+ description
+ "This module contains a collection of YANG definitions used for
+ some test cases.";
+
+ revision "2015-01-21" {
+ description
+ "Test model for testing union data types.";
+ }
+
+ typedef lowest-level1 {
+ type string;
+ }
+
+ typedef lowest-level2 {
+ type string;
+ }
+
+ typedef non-union-test-type {
+ type string;
+ }
+
+ typedef union-test-type {
+ type union {
+ type lowest-level1;
+ type lowest-level2;
+ }
+ }
+
+ typedef top-level {
+ type union {
+ type non-union-test-type;
+ type union-test-type;
+ }
+ }
+
+ container wrapper {
+ leaf wrap {
+ type top-level;
+ }
+ }
+}
\ No newline at end of file
genTOBuilder.setReference(typeDef.getReference());
genTOBuilder.setSchemaPath(typeDef.getPath().getPathFromRoot());
genTOBuilder.setModuleName(moduleName);
+ genTOBuilder.setBaseType(typeDef);
final List<Bit> bitList = bitsTypeDefinition.getBits();
GeneratedPropertyBuilder genPropertyBuilder;
<version>0.7.0-SNAPSHOT</version>
<packaging>pom</packaging>
- <prerequisites>
- <maven>3.0.4</maven>
- </prerequisites>
-
<properties>
<!-- Model versions -->
<ietf.topology.version>2013.10.21.7-SNAPSHOT</ietf.topology.version>
<relativePath>/../../common/parent/pom.xml</relativePath>
</parent>
-
<modelVersion>4.0.0</modelVersion>
<artifactId>mockito-configuration</artifactId>
<description>Default mockito configuration</description>
<packaging>jar</packaging><!-- not needed in OSGi -->
<name>${project.artifactId}</name>
- <prerequisites>
- <maven>3.0.4</maven>
- </prerequisites>
<dependencies>
<!-- all those dependencies will be in test scope as mockito-configuration should be referenced as test scope dependency -->
<groupId>org.opendaylight.yangtools</groupId>
<version>0.7.0-SNAPSHOT</version>
<packaging>pom</packaging>
- <prerequisites>
- <maven>3.0.4</maven>
- </prerequisites>
<properties>
<yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
parser.parseFiles(Arrays.asList(extdef, unionbug, inet));
}
+ @Test
+ public void testUnionWithBits() throws Exception {
+ File unionbits = new File(getClass().getResource("/types/union-with-bits/union-bits-model.yang").toURI());
+ YangContextParser parser = new YangParserImpl();
+ parser.parseFiles(Arrays.asList(unionbits));
+ }
+
}
--- /dev/null
+module unionbitsmodel {
+ namespace "urn:ubt";
+ prefix "ubt";
+
+ revision 2014-12-10 {
+ }
+
+ typedef port-state-v13 {
+ description
+ "Current state of the physical port. These are not configurable from the controller.";
+
+ type bits {
+ bit link_down {
+ //description "No physical link present.";
+ position 0;
+ }
+
+ bit blocked {
+ //description "Port is blocked";
+ position 1;
+ }
+
+ bit live {
+ //description "Live for Fast Failover Group.";
+ position 2;
+ }
+ }
+ }
+
+ typedef port-state-v10 {
+ description "Current state of the physical port. These are not configurable from the controller.";
+
+ type bits {
+ bit link_down {
+ description "No physical link present.";
+ position 0;
+ }
+
+ bit blocked {
+ description "Port is blocked";
+ position 1;
+ }
+ bit live {
+ description "Live for Fast Failover Group.";
+ position 2;
+ }
+ bit stp_listen {
+ description "Not learning or relaying frames.";
+ }
+ }
+ }
+
+ typedef my-union-type {
+ type union {
+ type port-state-v13;
+ type port-state-v10;
+ }
+ }
+}
\ No newline at end of file