BUG-2967: Expose before-state from DataObjectModification 00/18000/1
authorRobert Varga <rovarga@cisco.com>
Thu, 9 Apr 2015 09:32:48 +0000 (11:32 +0200)
committerRobert Varga <rovarga@cisco.com>
Thu, 9 Apr 2015 10:11:32 +0000 (12:11 +0200)
Not exposing the before-state requires users to track this state
themselves. The problem is most visible in the delete case, if
the user needs some attributes to reconstruct keys to other structures
in order to perform cleanup -- they would effectively have to retain
a InstanceIdentifier->data map to efficiently perform deletes.

Rather than forcing everyone to duplicate data, expose the before-state,
as best available. Note that applications still need to deal with the
fact that the before-state in delete can be null -- at least by issuing
a warning to the operator.

Change-Id: I72c886f384254a6808159eaee612b07083073492
Signed-off-by: Robert Varga <rovarga@cisco.com>
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataObjectModification.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LazyDataObjectModification.java

index 678ac34e39d25d54fc12316fc17df1d51c5ed28f..3dc6e4030f56953620ab8762ecae7c32d4ffbd74 100644 (file)
@@ -65,7 +65,17 @@ public interface DataObjectModification<T extends DataObject> extends org.openda
     @Nonnull ModificationType getModificationType();
 
     /**
-     * Returns after state of top level container.
+     * Returns before-state of top level container. Implementations are encouraged,
+     * but not required to provide this state.
+     *
+     * @param root Class representing data container
+     * @return State of object before modification. Null if subtree was not present,
+     *         or the implementation cannot provide the state.
+     */
+    @Nullable T getDataBefore();
+
+    /**
+     * Returns after-state of top level container.
      *
      * @param root Class representing data container
      * @return State of object after modification. Null if subtree is not present.
index a165242b30f08d29902240d868b24ca84464fde9..83d48f77a0889ca9019d88e00cf7f8bb08ba44c6 100644 (file)
@@ -37,7 +37,7 @@ import org.slf4j.LoggerFactory;
  *
  * @param <T> Type of Binding Data Object
  */
-class LazyDataObjectModification<T extends DataObject> implements DataObjectModification<T> {
+final class LazyDataObjectModification<T extends DataObject> implements DataObjectModification<T> {
 
     private final static Logger LOG = LoggerFactory.getLogger(LazyDataObjectModification.class);
 
@@ -57,7 +57,7 @@ class LazyDataObjectModification<T extends DataObject> implements DataObjectModi
         return new LazyDataObjectModification<>(codec,domData);
     }
 
-    static Collection<DataObjectModification<? extends DataObject>> from(final BindingCodecTreeNode<?> parentCodec,
+    private static Collection<DataObjectModification<? extends DataObject>> from(final BindingCodecTreeNode<?> parentCodec,
             final Collection<DataTreeCandidateNode> domChildNodes) {
         final ArrayList<DataObjectModification<? extends DataObject>> result = new ArrayList<>(domChildNodes.size());
         populateList(result, parentCodec, domChildNodes);
@@ -79,7 +79,7 @@ class LazyDataObjectModification<T extends DataObject> implements DataObjectModi
                             parentCodec.yangPathArgumentChild(domChildNode.getIdentifier());
                     populateList(result,type, childCodec, domChildNode);
                 } catch (final IllegalArgumentException e) {
-                    if(type == BindingStructuralType.UNKNOWN) {
+                    if (type == BindingStructuralType.UNKNOWN) {
                         LOG.debug("Unable to deserialize unknown DOM node {}",domChildNode,e);
                     } else {
                         LOG.debug("Binding representation for DOM node {} was not found",domChildNode,e);
@@ -89,7 +89,6 @@ class LazyDataObjectModification<T extends DataObject> implements DataObjectModi
         }
     }
 
-
     private static void populateList(final List<DataObjectModification<? extends DataObject>> result,
             final BindingStructuralType type, final BindingCodecTreeNode<?> childCodec,
             final DataTreeCandidateNode domChildNode) {
@@ -116,6 +115,11 @@ class LazyDataObjectModification<T extends DataObject> implements DataObjectModi
         }
     }
 
+    @Override
+    public T getDataBefore() {
+        return deserialize(domData.getDataBefore());
+    }
+
     @Override
     public T getDataAfter() {
         return deserialize(domData.getDataAfter());
@@ -149,8 +153,8 @@ class LazyDataObjectModification<T extends DataObject> implements DataObjectModi
 
     @Override
     public Collection<DataObjectModification<? extends DataObject>> getModifiedChildren() {
-        if(childNodesCache == null) {
-            childNodesCache = from(codec,domData.getChildNodes());
+        if (childNodesCache == null) {
+            childNodesCache = from(codec, domData.getChildNodes());
         }
         return childNodesCache;
     }
@@ -191,7 +195,7 @@ class LazyDataObjectModification<T extends DataObject> implements DataObjectModi
     }
 
     private T deserialize(final Optional<NormalizedNode<?, ?>> dataAfter) {
-        if(dataAfter.isPresent()) {
+        if (dataAfter.isPresent()) {
             return codec.deserialize(dataAfter.get());
         }
         return null;