Handle empty type in NormalizedNode streaming 68/67368/4
authorTom Pantelis <tompantelis@gmail.com>
Sat, 20 Jan 2018 00:19:03 +0000 (19:19 -0500)
committerRobert Varga <nite@hq.sk>
Mon, 22 Jan 2018 19:58:31 +0000 (19:58 +0000)
The yang "empty" type is now represented as
org.opendaylight.yangtools.yang.common.Empty so handle it.

NormalizedNode no longer allows a null value but we still need
to handle NULL_TYPE on input for backwards compatibility. NULL_TYPE
is translated to Empty.

Change-Id: I99b87138d7358d37170cf603d993cd1a4f6a2087
Signed-off-by: Tom Pantelis <tompantelis@gmail.com>
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractNormalizedNodeDataOutput.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ValueTypes.java
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeStreamReaderWriterTest.java
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-test.yang

index c4db2729896f8dfc8c3adcf45044fd4313b9b63e..02bebebd2949d397d9234a27215f1e84de0ce299 100755 (executable)
@@ -484,7 +484,7 @@ abstract class AbstractNormalizedNodeDataOutput implements NormalizedNodeDataOut
             case ValueTypes.YANG_IDENTIFIER_TYPE:
                 writeYangInstanceIdentifierInternal((YangInstanceIdentifier) value);
                 break;
             case ValueTypes.YANG_IDENTIFIER_TYPE:
                 writeYangInstanceIdentifierInternal((YangInstanceIdentifier) value);
                 break;
-            case ValueTypes.NULL_TYPE :
+            case ValueTypes.EMPTY_TYPE:
                 break;
             case ValueTypes.STRING_BYTES_TYPE:
                 final byte[] valueBytes = value.toString().getBytes(StandardCharsets.UTF_8);
                 break;
             case ValueTypes.STRING_BYTES_TYPE:
                 final byte[] valueBytes = value.toString().getBytes(StandardCharsets.UTF_8);
index 3b912e6cb9064e2bd7ff50a5bbaa72e629eea131..cc744438ff627b64594847323623b72cae6772c7 100755 (executable)
@@ -27,6 +27,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.dom.DOMSource;
 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.dom.DOMSource;
 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -333,6 +334,15 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput
             case ValueTypes.YANG_IDENTIFIER_TYPE :
                 return readYangInstanceIdentifierInternal();
 
             case ValueTypes.YANG_IDENTIFIER_TYPE :
                 return readYangInstanceIdentifierInternal();
 
+            case ValueTypes.EMPTY_TYPE:
+            // Leaf nodes no longer allow null values and thus we no longer emit null values. Previously, the "empty"
+            // yang type was represented as null so we translate an incoming null value to Empty. It was possible for
+            // a BI user to set a string leaf to null and we're rolling the dice here but the chances for that are
+            // very low. We'd have to know the yang type but, even if we did, we can't let a null value pass upstream
+            // so we'd have to drop the leaf which might cause other issues.
+            case ValueTypes.NULL_TYPE:
+                return Empty.getInstance();
+
             default :
                 return null;
         }
             default :
                 return null;
         }
index 190f5969aaf395cc6e2ce1b9706d9203f655f8d1..51ff8d35006f5fba38c6b047038965105a6408e8 100644 (file)
@@ -13,7 +13,9 @@ import com.google.common.collect.ImmutableMap.Builder;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.Map;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.Set;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
@@ -33,8 +35,12 @@ final class ValueTypes {
     public static final byte BIG_INTEGER_TYPE = 10;
     public static final byte BIG_DECIMAL_TYPE = 11;
     public static final byte BINARY_TYPE = 12;
     public static final byte BIG_INTEGER_TYPE = 10;
     public static final byte BIG_DECIMAL_TYPE = 11;
     public static final byte BINARY_TYPE = 12;
+    // Leaf nodes no longer allow null values. The "empty" type is now represented as
+    // org.opendaylight.yangtools.yang.common.Empty. This is kept for backwards compatibility.
+    @Deprecated
     public static final byte NULL_TYPE = 13;
     public static final byte STRING_BYTES_TYPE = 14;
     public static final byte NULL_TYPE = 13;
     public static final byte STRING_BYTES_TYPE = 14;
+    public static final byte EMPTY_TYPE = 15;
 
     private static final Map<Class<?>, Byte> TYPES;
 
 
     private static final Map<Class<?>, Byte> TYPES;
 
@@ -51,6 +57,7 @@ final class ValueTypes {
         b.put(BigInteger.class, BIG_INTEGER_TYPE);
         b.put(BigDecimal.class, BIG_DECIMAL_TYPE);
         b.put(byte[].class, BINARY_TYPE);
         b.put(BigInteger.class, BIG_INTEGER_TYPE);
         b.put(BigDecimal.class, BIG_DECIMAL_TYPE);
         b.put(byte[].class, BINARY_TYPE);
+        b.put(Empty.class, EMPTY_TYPE);
 
         TYPES = b.build();
     }
 
         TYPES = b.build();
     }
@@ -60,9 +67,7 @@ final class ValueTypes {
     }
 
     public static byte getSerializableType(Object node) {
     }
 
     public static byte getSerializableType(Object node) {
-        if (node == null) {
-            return NULL_TYPE;
-        }
+        Objects.requireNonNull(node);
 
         final Byte type = TYPES.get(node.getClass());
         if (type != null) {
 
         final Byte type = TYPES.get(node.getClass());
         if (type != null) {
index e2e5aa4befda521a389f37e7c6df020464767e35..147cc663d956ca4d7f4bac89d187407b575cfb38 100644 (file)
@@ -26,6 +26,7 @@ import org.apache.commons.lang.SerializationUtils;
 import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.util.TestModel;
 import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -92,6 +93,7 @@ public class NormalizedNodeStreamReaderWriterTest {
                         new NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME))
                         .withChild(entry1).withChild(entry2).build())
                 .withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4}))
                         new NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME))
                         .withChild(entry1).withChild(entry2).build())
                 .withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4}))
+                .withChild(ImmutableNodes.leafNode(TestModel.EMPTY_QNAME, Empty.getInstance()))
                 .withChild(Builders.orderedMapBuilder()
                       .withNodeIdentifier(new NodeIdentifier(TestModel.ORDERED_LIST_QNAME))
                       .withChild(ImmutableNodes.mapEntry(TestModel.ORDERED_LIST_ENTRY_QNAME,
                 .withChild(Builders.orderedMapBuilder()
                       .withNodeIdentifier(new NodeIdentifier(TestModel.ORDERED_LIST_QNAME))
                       .withChild(ImmutableNodes.mapEntry(TestModel.ORDERED_LIST_ENTRY_QNAME,
index 72b8a3bb7f2e3eea6f325ba3753a83338087c12d..7cdd7839954397c440858070adb6268013124b4e 100644 (file)
@@ -94,6 +94,7 @@ public final class TestModel {
     public static final QName CHOICE_QNAME = QName.create(TEST_QNAME, "choice");
     public static final QName SHOE_QNAME = QName.create(TEST_QNAME, "shoe");
     public static final QName ANY_XML_QNAME = QName.create(TEST_QNAME, "any");
     public static final QName CHOICE_QNAME = QName.create(TEST_QNAME, "choice");
     public static final QName SHOE_QNAME = QName.create(TEST_QNAME, "shoe");
     public static final QName ANY_XML_QNAME = QName.create(TEST_QNAME, "any");
+    public static final QName EMPTY_QNAME = QName.create(TEST_QNAME, "empty-leaf");
     public static final QName INVALID_QNAME = QName.create(TEST_QNAME, "invalid");
     private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
     private static final String DATASTORE_AUG_YANG = "/odl-datastore-augmentation.yang";
     public static final QName INVALID_QNAME = QName.create(TEST_QNAME, "invalid");
     private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
     private static final String DATASTORE_AUG_YANG = "/odl-datastore-augmentation.yang";
index 613288dadd8d75b801456e175adaab0f81cf1a1f..294b001a8509c7469c8714e630b9488baff6440e 100644 (file)
@@ -160,5 +160,9 @@ module odl-datastore-test {
 
         anyxml any {
         }
 
         anyxml any {
         }
+
+        leaf empty-leaf {
+            type empty;
+        }
     }
 }
     }
 }