*/package org.opendaylight.yangtools.binding.data.codec.gen.impl;
import com.google.common.base.Preconditions;
-
import java.util.HashMap;
import java.util.Map;
-
import org.opendaylight.yangtools.binding.data.codec.util.ChoiceDispatchSerializer;
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSource {
while (rootType.getBaseType() != null) {
rootType = rootType.getBaseType();
}
- if(rootType instanceof BooleanTypeDefinition) {
+ if(rootType instanceof BooleanTypeDefinition || rootType instanceof EmptyTypeDefinition) {
prefix = "is";
}
}
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
-
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
-
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-
import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
while (typeDef.getBaseType() != null) {
typeDef = typeDef.getBaseType();
}
- if (typeDef instanceof BooleanTypeDefinition) {
+ if (typeDef instanceof BooleanTypeDefinition || typeDef instanceof EmptyTypeDefinition) {
return "is" + suffix;
}
return GETTER_PREFIX + suffix;
private Codec<Object, Object> getCodec(final Class<?> valueType, final DataSchemaNode schema) {
+ final TypeDefinition<?> instantiatedType;
+ if (schema instanceof LeafSchemaNode) {
+ instantiatedType = ((LeafSchemaNode) schema).getType();
+ } else if (schema instanceof LeafListSchemaNode) {
+ instantiatedType = ((LeafListSchemaNode) schema).getType();
+ } else {
+ throw new IllegalArgumentException("Unsupported leaf node type " + schema.getClass());
+ }
if (Class.class.equals(valueType)) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Codec<Object, Object> casted = (Codec) identityCodec;
@SuppressWarnings({ "unchecked", "rawtypes" })
final Codec<Object, Object> casted = (Codec) instanceIdentifierCodec;
return casted;
- } else if (BindingReflections.isBindingClass(valueType)) {
- final TypeDefinition<?> instantiatedType;
- if (schema instanceof LeafSchemaNode) {
- instantiatedType = ((LeafSchemaNode) schema).getType();
- } else if (schema instanceof LeafListSchemaNode) {
- instantiatedType = ((LeafListSchemaNode) schema).getType();
- } else {
- instantiatedType = null;
- }
- if (instantiatedType != null) {
- return getCodec(valueType, instantiatedType);
+ } else if (Boolean.class.equals(valueType)) {
+ if(instantiatedType instanceof EmptyTypeDefinition) {
+ return ValueTypeCodec.EMPTY_CODEC;
}
+ } else if (BindingReflections.isBindingClass(valueType)) {
+ return getCodec(valueType, instantiatedType);
}
return ValueTypeCodec.NOOP_CODEC;
}
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
/**
}
};
+ public static final SchemaUnawareCodec EMPTY_CODEC = new SchemaUnawareCodec() {
+
+ @Override
+ public Object serialize(Object arg0) {
+ // Empty type has null value in NormalizedNode and Composite Node
+ // representation
+ return null;
+ }
+
+ @Override
+ public Object deserialize(Object arg0) {
+ /* Empty type has boolean.TRUE representation in Binding-aware world
+ * otherwise it is null / false.
+ * So when codec is triggered, empty leaf is present, that means we
+ * are safe to return true.
+ */
+ return Boolean.TRUE;
+ }
+ };
+
+ private static final Callable<? extends SchemaUnawareCodec> EMPTY_LOADER = new Callable<SchemaUnawareCodec>() {
+
+ @Override
+ public SchemaUnawareCodec call() throws Exception {
+ return EMPTY_CODEC;
+ }
+ };
+
public static SchemaUnawareCodec getCodecFor(final Class<?> typeClz, final TypeDefinition<?> def) {
if (BindingReflections.isBindingClass(typeClz)) {
return getCachedSchemaUnawareCodec(typeClz, getCodecLoader(typeClz, def));
}
+ TypeDefinition<?> rootType = def;
+ while (rootType.getBaseType() != null) {
+ rootType = rootType.getBaseType();
+ }
+ if(rootType instanceof EmptyTypeDefinition) {
+ return EMPTY_CODEC;
+ }
return NOOP_CODEC;
}
return EnumerationCodec.loader(typeClz, (EnumTypeDefinition) rootType);
} else if (rootType instanceof BitsTypeDefinition) {
return BitsCodec.loader(typeClz, (BitsTypeDefinition) rootType);
+ } else if (rootType instanceof EmptyTypeDefinition) {
+ return EMPTY_LOADER;
}
return EncapsulatedValueCodec.loader(typeClz);
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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 static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.top.level.list.choice.in.list.EmptyLeaf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.top.level.list.choice.in.list.EmptyLeafBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.ChoiceInList;
+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.DataObject;
+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.NormalizedNode;
+
+
+public class EmptyLeafTest extends AbstractBindingRuntimeTest {
+
+ private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+ private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+ .child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+ private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+ .augmentation(TreeLeafOnlyAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+ .augmentation(TreeComplexUsesAugment.class);
+ private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+ 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 testCaseWithEmptyLeafType() {
+ TopLevelList withEmptyCase = new TopLevelListBuilder()
+ .setKey(TOP_FOO_KEY)
+ .setChoiceInList(new EmptyLeafBuilder().setEmptyType(true).build())
+ .build();
+ Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> dom = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, withEmptyCase);
+ Entry<InstanceIdentifier<?>, DataObject> readed = registry.fromNormalizedNode(dom.getKey(),dom.getValue());
+ ChoiceInList list = ((TopLevelList) readed.getValue()).getChoiceInList();
+ assertTrue(list instanceof EmptyLeaf);
+ assertTrue(((EmptyLeaf) list).isEmptyType());
+ }
+
+ private RpcComplexUsesAugment createComplexData() {
+ return new RpcComplexUsesAugmentBuilder()
+ .setContainerWithUses(new ContainerWithUsesBuilder()
+ .setLeafFromGrouping("foo")
+ .build())
+ .setListViaUses(Collections.<ListViaUses>emptyList())
+ .build();
+ }
+
+}
case complex-via-uses {
uses complex-from-grouping;
}
+ case empty-leaf {
+ leaf empty-type {
+ type empty;
+ }
+ }
}
augment "/test:put-top/test:input/test:top-level-list/test:choice-in-list" {
<ctrie.version>0.2.0</ctrie.version>
<exam.version>3.0.0</exam.version>
<groovy.version>2.1.6</groovy.version>
+ <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
<ietf.topology.version>2013.10.21.2-SNAPSHOT</ietf.topology.version>
<ietf.inet.types.version>2010.09.24.4-SNAPSHOT</ietf.inet.types.version>
<ietf.yang.types.version>2010.09.24.4-SNAPSHOT</ietf.yang.types.version>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-util</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.thirdparty</groupId>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>concepts</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>object-cache-api</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>object-cache-guava</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>object-cache-noop</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-model-api</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-api</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-spi</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-util</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-impl</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-java-api-generator</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-common</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-api</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-codec-gson</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-model-api</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-model-util</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-binding</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-api</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-impl</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin-spi</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-inet-types</artifactId>
- <version>2010.09.24.4-SNAPSHOT</version>
+ <version>${ietf.inet.types.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-yang-types</artifactId>
- <version>2010.09.24.4-SNAPSHOT</version>
+ <version>${ietf.yang.types.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-yang-types-20130715</artifactId>
- <version>2013.07.15.1-SNAPSHOT</version>
+ <version>${ietf.yang.types.20130715.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-ted</artifactId>
- <version>2013.10.21.2-SNAPSHOT</version>
+ <version>${ietf.topology.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology</artifactId>
- <version>2013.10.21.2-SNAPSHOT</version>
+ <version>${ietf.topology.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology-isis</artifactId>
- <version>2013.10.21.2-SNAPSHOT</version>
+ <version>${ietf.topology.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology-l3-unicast-igp</artifactId>
- <version>2013.10.21.2-SNAPSHOT</version>
+ <version>${ietf.topology.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology-ospf</artifactId>
- <version>2013.10.21.2-SNAPSHOT</version>
+ <version>${ietf.topology.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology-l3-unicast</artifactId>
- <version>2013.10.21.2-SNAPSHOT</version>
+ <version>${ietf.topology.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-composite-node</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-client-api</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-common</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-util</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-test-service</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-client-impl</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-jaxrs-api</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>bug527-test-model</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>bug1196-test-model</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <version>${yangtools.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>websocket-client</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>object-cache-api</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>object-cache-guava</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>object-cache-noop</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>util</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-type-provider</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-operations</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-data-codec</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>features-test</artifactId>
- <version>${project.version}</version>
+ <version>${yangtools.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<name>${project.artifactId}</name>
<description>${project.artifactId}</description>
- <properties>
- <ietf.topology.version>2013.10.21.2-SNAPSHOT</ietf.topology.version>
- <ietf.inet.types.version>2010.09.24.4-SNAPSHOT</ietf.inet.types.version>
- <ietf.yang.types.version>2010.09.24.4-SNAPSHOT</ietf.yang.types.version>
- <ietf.restconf.version>2013.10.19.1-SNAPSHOT</ietf.restconf.version>
- </properties>
-
<modules>
<module>ietf-inet-types</module>
<module>ietf-yang-types</module>
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-
import java.io.IOException;
import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.concepts.Path;
*
*/
public class InstanceIdentifier<T extends DataObject> implements Path<InstanceIdentifier<? extends DataObject>>, Immutable, Serializable {
- private static final long serialVersionUID = 1L;
+ private static final Field PATHARGUMENTS_FIELD;
+ private static final long serialVersionUID = 2L;
/*
* Protected to differentiate internal and external access. Internal
* access is required never to modify the contents. References passed
* to outside entities have to be wrapped in an unmodifiable view.
*/
- protected final Iterable<PathArgument> pathArguments;
+ protected transient final Iterable<PathArgument> pathArguments;
private final Class<T> targetType;
private final boolean wildcarded;
private final int hash;
+ static {
+ final Field f;
+ try {
+ f = InstanceIdentifier.class.getDeclaredField("pathArguments");
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ f.setAccessible(true);
+ PATHARGUMENTS_FIELD = f;
+ }
+
InstanceIdentifier(final Class<T> type, final Iterable<PathArgument> pathArguments, final boolean wildcarded, final int hash) {
this.pathArguments = Preconditions.checkNotNull(pathArguments);
this.targetType = Preconditions.checkNotNull(type);
}
private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
- out.writeObject(targetType);
- out.writeBoolean(wildcarded);
- out.writeInt(hash);
- out.write(Iterables.size(pathArguments));
+ out.defaultWriteObject();
+ out.writeInt(Iterables.size(pathArguments));
for (Object o : pathArguments) {
out.writeObject(o);
}
}
private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
- // TODO Auto-generated method stub
+ in.defaultReadObject();
+
+ final int size = in.readInt();
+ final List<PathArgument> args = new ArrayList<>(size);
+ for (int i = 0; i < size; ++i) {
+ args.add((PathArgument) in.readObject());
+ }
+
+ try {
+ PATHARGUMENTS_FIELD.set(this, ImmutableList.copyOf(args));
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ throw new IOException(e);
+ }
}
}
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
private static final AtomicReferenceFieldUpdater<YangInstanceIdentifier, String> TOSTRINGCACHE_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(YangInstanceIdentifier.class, String.class, "toStringCache");
private static final YangInstanceIdentifier EMPTY = trustedCreate(Collections.<PathArgument>emptyList());
+ private static final Field PATHARGUMENTS_FIELD;
- private static final long serialVersionUID = 2L;
- private final Iterable<PathArgument> pathArguments;
+ private static final long serialVersionUID = 3L;
+ private transient final Iterable<PathArgument> pathArguments;
private final int hash;
- private transient volatile ImmutableList<PathArgument> legacyPath = null;
+ private volatile ImmutableList<PathArgument> legacyPath = null;
private transient volatile String toStringCache = null;
+ static {
+ final Field f;
+ try {
+ f = YangInstanceIdentifier.class.getDeclaredField("pathArguments");
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ f.setAccessible(true);
+
+ PATHARGUMENTS_FIELD = f;
+ }
+
private final ImmutableList<PathArgument> getLegacyPath() {
// Temporary variable saves a volatile read
ImmutableList<PathArgument> ret = legacyPath;
}
return ret;
}
+
+ private void readObject(final ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
+ inputStream.defaultReadObject();
+
+ try {
+ PATHARGUMENTS_FIELD.set(this, legacyPath);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ throw new IOException(e);
+ }
+ }
+
+ private void writeObject(final ObjectOutputStream outputStream) throws IOException {
+ /*
+ * This may look strange, but what we are doing here is side-stepping the fact
+ * that pathArguments is not generally serializable. We are forcing instantiation
+ * of the legacy path, which is an ImmutableList (thus Serializable) and write
+ * it out. The read path does the opposite -- it reads the legacyPath and then
+ * uses invocation API to set the field.
+ */
+ getLegacyPath();
+ outputStream.defaultWriteObject();
+ }
}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
-
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map.Entry;
-
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
assertNotNull( node1.toString() ); // for code coverage
}
+
+ @Test
+ public void serializationTest() throws IOException, ClassNotFoundException {
+ final YangInstanceIdentifier expected = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2));
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(expected);
+ oos.close();
+
+ final byte[] bytes = bos.toByteArray();
+ final ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+ final ObjectInputStream ois = new ObjectInputStream(bis);
+
+ final YangInstanceIdentifier read = (YangInstanceIdentifier) ois.readObject();
+ assertEquals(0, ois.available());
+ ois.close();
+
+ assertEquals(expected, read);
+ }
}
protected AbstractImmutableNormalizedValueNode(final K nodeIdentifier, final V value) {
super(nodeIdentifier);
if (value == null) {
- LOGGER.warn("The value of node " + nodeIdentifier.getNodeType() + " is null");
+ /*
+ * Null value is allowed for empty type definition so it should be debug,
+ * but still we are logging it in case we need to debug missing values.
+ */
+ LOGGER.debug("The value of node {} is null",nodeIdentifier.getNodeType());
}
this.value = value;
}