This patch changes the representation of empty Binding lists in
DOM world. Empty lists are equivalent to being non-present, hence
they are not emitted.
This mirrors the getFoo()/nonnullFoo() accessor duality, i.e. empty
lists can be instantiated on-demand as placeholders for nulls.
In DOM world, list nodes are virtual containers, which do not hold
any semantics and are created on demand -- hence it does not make
sense to pass them down to DOM.
This does not create data tree operation changes, as lists are not
directly addressable, hence their WRITE/MERGE semantics are shared
by their parent. Empty merges have not semantic value, as empty
lists disappear on touch. Empty writes end up correctly observing
lifecycle -- empty lists end up disappearing, just as they would
be expected if they have undergone a lifecycle event (such as an
empty merge).
JIRA: MDSAL-456
Change-Id: I78efc4aa4c3b4100ff52490fefe94e2f65f43efc
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
protected static final <E extends DataObject> void streamList(final Class<E> childClass,
final DataObjectStreamer<E> childStreamer, final DataObjectSerializerRegistry registry,
final BindingStreamEventWriter writer, final List<? extends E> value) throws IOException {
protected static final <E extends DataObject> void streamList(final Class<E> childClass,
final DataObjectStreamer<E> childStreamer, final DataObjectSerializerRegistry registry,
final BindingStreamEventWriter writer, final List<? extends E> value) throws IOException {
- if (value != null) {
- writer.startUnkeyedList(childClass, value.size());
+ final int size = nullSize(value);
+ if (size != 0) {
+ writer.startUnkeyedList(childClass, size);
commonStreamList(registry, writer, childStreamer, value);
}
}
commonStreamList(registry, writer, childStreamer, value);
}
}
protected static final <E extends DataObject & Identifiable<?>> void streamMap(final Class<E> childClass,
final DataObjectStreamer<E> childStreamer, final DataObjectSerializerRegistry registry,
final BindingStreamEventWriter writer, final List<? extends E> value) throws IOException {
protected static final <E extends DataObject & Identifiable<?>> void streamMap(final Class<E> childClass,
final DataObjectStreamer<E> childStreamer, final DataObjectSerializerRegistry registry,
final BindingStreamEventWriter writer, final List<? extends E> value) throws IOException {
- if (value != null) {
- writer.startMapNode(childClass, value.size());
+ final int size = nullSize(value);
+ if (size != 0) {
+ writer.startMapNode(childClass, size);
commonStreamList(registry, writer, childStreamer, value);
}
}
commonStreamList(registry, writer, childStreamer, value);
}
}
protected static final <E extends DataObject & Identifiable<?>> void streamOrderedMap(final Class<E> childClass,
final DataObjectStreamer<E> childStreamer, final DataObjectSerializerRegistry registry,
final BindingStreamEventWriter writer, final List<? extends E> value) throws IOException {
protected static final <E extends DataObject & Identifiable<?>> void streamOrderedMap(final Class<E> childClass,
final DataObjectStreamer<E> childStreamer, final DataObjectSerializerRegistry registry,
final BindingStreamEventWriter writer, final List<? extends E> value) throws IOException {
- if (value != null) {
- writer.startOrderedMapNode(childClass, value.size());
+ final int size = nullSize(value);
+ if (size != 0) {
+ writer.startOrderedMapNode(childClass, size);
commonStreamList(registry, writer, childStreamer, value);
}
}
commonStreamList(registry, writer, childStreamer, value);
}
}
private static <T extends DataObject> boolean tryCache(final BindingStreamEventWriter writer, final T value) {
return writer instanceof BindingSerializer ? ((BindingSerializer<?, T>) writer).serialize(value) == null : true;
}
private static <T extends DataObject> boolean tryCache(final BindingStreamEventWriter writer, final T value) {
return writer instanceof BindingSerializer ? ((BindingSerializer<?, T>) writer).serialize(value) == null : true;
}
+
+ private static int nullSize(final List<?> list) {
+ return list == null ? 0 : list.size();
+ }
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
-import java.util.Collections;
import java.util.Optional;
import org.junit.Test;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.RpcComplexUsesAugment;
import java.util.Optional;
import org.junit.Test;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.RpcComplexUsesAugment;
.setContainerWithUses(new ContainerWithUsesBuilder()
.setLeafFromGrouping("foo")
.build())
.setContainerWithUses(new ContainerWithUsesBuilder()
.setLeafFromGrouping("foo")
.build())
- .setListViaUses(Collections.emptyList())
private static ContainerNode getEmptyTop() {
return ImmutableContainerNodeBuilder.create()
.withNodeIdentifier(new NodeIdentifier(TOP_QNAME))
private static ContainerNode getEmptyTop() {
return ImmutableContainerNodeBuilder.create()
.withNodeIdentifier(new NodeIdentifier(TOP_QNAME))
- .withChild(mapNodeBuilder(TOP_LEVEL_LIST_QNAME).build()).build();
}
private static final QName AGUMENT_STRING_Q = QName.create(TOP_QNAME, "augmented-string");
}
private static final QName AGUMENT_STRING_Q = QName.create(TOP_QNAME, "augmented-string");
return path(key).augmentation(augmentation);
}
return path(key).augmentation(augmentation);
}
+ public static Top top() {
+ return new TopBuilder().build();
+ }
+
public static Top top(final TopLevelList... listItems) {
return new TopBuilder().setTopLevelList(Arrays.asList(listItems)).build();
}
public static Top top(final TopLevelList... listItems) {
return new TopBuilder().setTopLevelList(Arrays.asList(listItems)).build();
}