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);
+ }
+}
--- /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