-
New Feature
-
Resolution: Done
-
High
-
None
Current ClusteredDataTreeChangeListener exposes the details about what changed in the entire tree.
There are a number of users which receive these changes like this:
@Override
public void onDataTreeChanged(Collection<DataTreeModification<Config>> changes) {
updateConfig(Iterables.getLast(changes).getRootNode().getDataAfter());
}
i.e. they are interested only in the last state.
Since we are overlaying on DOMDataBroker, whose version of DTCL provides a List of changes, it should be trivial to support:
@FunctionalInterface public interface DataListener<T extends DataObject> { // Note: needs a better name void dataChangedTo(@Nullable T data); }
and users doing just:
@Override public void dataChangedTo(Config data) { // the contents of updateConfig(data); }
This will make for much simpler users, as this also covers the case of onInitialData(). Furthermore users do not care about data locality – hence this should imply ClusteredDataTreeChangeListener in all cases, without the distinction available through DataTreeChangeListener – i.e. an implementation could be (just painting a picture!)
@FunctionalInterface interface DataObjectListenerAdapter<T extends DataObject> extends ClusteredDataTreeChangeListener<T>, DataListener<T> { @Override public final void onInitialData() { dataChangedTo(null); } @Override public final void onDataTreeChanged(Collection<DataTreeModification<T>> changes) { dataChangedTo(Iterables.getLast(changes).getRootNode().getDataAfter()); } }
Implementation-wise, mdsal-binding-dom-adapter can perform the equivalent of getLast()... on top of DOM data (which is a List, not a Collection) and just decode the last fragment – which will be very efficient indeed.
There is a wrinkle with wildcard InstanceIdentifiers, where this approach falls flat. As a first step, DataBroker.registerListener() should reject wildcards with an IllegalArgumentException. A follow-up will provide similar interfaces which report the InstanceIdentifier as well (and thus can deal with wildcards).
A further use case is comparison on before-value and after-value, so another interface like:
@FunctionalInterface interface DataChangeListener<T extends DataObject> { void dataChanged(@Nullable T previousValue, @Nullable T currentValue); }
which is to say: previousValue = first.getRootNode().getDataBefore(), currentValue = last.getRootNode().getDataAfter() in terms of DTCL.