summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java24
-rw-r--r--infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegatorTest.java68
-rw-r--r--infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/HoneycombWriteInfraTest.java52
-rw-r--r--infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/NestedAugmentationWriteTest.java28
-rw-r--r--infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/Writer.java16
-rw-r--r--infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java15
-rw-r--r--infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericListWriter.java4
-rw-r--r--infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericWriter.java24
-rw-r--r--infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java22
-rw-r--r--infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java9
-rw-r--r--infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericListWriterTest.java6
-rw-r--r--infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericWriterTest.java15
-rw-r--r--infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/NoopWriters.java63
-rw-r--r--infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilderTest.java6
-rw-r--r--infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java60
-rw-r--r--infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriterTest.java31
-rw-r--r--infra/translate-spi/src/main/java/io/fd/honeycomb/translate/spi/write/WriterCustomizer.java14
-rw-r--r--infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriter.java19
-rw-r--r--infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriter.java11
-rw-r--r--infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistry.java11
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriterTest.java10
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriterTest.java4
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistryTest.java2
-rw-r--r--samples/interfaces/mapping/src/main/java/io/fd/honeycomb/samples/interfaces/mapping/config/InterfaceWriterCustomizer.java10
24 files changed, 384 insertions, 140 deletions
diff --git a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java
index ccc4057..66dcbe5 100644
--- a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java
+++ b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java
@@ -124,12 +124,13 @@ public final class ModifiableDataTreeDelegator extends ModifiableDataTreeManager
LOG.debug("ConfigDataTree.modify() diff: {}", modificationDiff);
// Distinguish between updates (create + update) and deletes
- final WriterRegistry.DataObjectUpdates baUpdates = toBindingAware(modificationDiff.getUpdates());
+ final WriterRegistry.DataObjectUpdates baUpdates =
+ toBindingAware(writerRegistry, modificationDiff.getUpdates());
LOG.debug("ConfigDataTree.modify() extracted updates={}", baUpdates);
WriteContext ctx = getTransactionWriteContext();
try {
- writerRegistry.update(baUpdates, ctx);
+ writerRegistry.processModifications(baUpdates, ctx);
final CheckedFuture<Void, TransactionCommitFailedException> contextUpdateResult =
((TransactionMappingContext) ctx.getMappingContext()).submit();
@@ -193,14 +194,15 @@ public final class ModifiableDataTreeDelegator extends ModifiableDataTreeManager
return new TransactionWriteContext(serializer, beforeTx, afterTx, mappingContext);
}
- private WriterRegistry.DataObjectUpdates toBindingAware(
+ private WriterRegistry.DataObjectUpdates toBindingAware(final WriterRegistry registry,
final Map<YangInstanceIdentifier, NormalizedNodeUpdate> biNodes) {
- return ModifiableDataTreeDelegator.toBindingAware(biNodes, serializer);
+ return ModifiableDataTreeDelegator.toBindingAware(registry, biNodes, serializer);
}
}
@VisibleForTesting
static WriterRegistry.DataObjectUpdates toBindingAware(
+ final WriterRegistry registry,
final Map<YangInstanceIdentifier, NormalizedNodeUpdate> biNodes,
final BindingNormalizedNodeSerializer serializer) {
@@ -209,15 +211,27 @@ public final class ModifiableDataTreeDelegator extends ModifiableDataTreeManager
HashMultimap.create();
for (Map.Entry<YangInstanceIdentifier, NormalizedNodeUpdate> biEntry : biNodes.entrySet()) {
+ final InstanceIdentifier<?> keyedId = serializer.fromYangInstanceIdentifier(biEntry.getKey());
final InstanceIdentifier<?> unkeyedIid =
- RWUtils.makeIidWildcarded(serializer.fromYangInstanceIdentifier(biEntry.getKey()));
+ RWUtils.makeIidWildcarded(keyedId);
NormalizedNodeUpdate normalizedNodeUpdate = biEntry.getValue();
final DataObjectUpdate dataObjectUpdate = toDataObjectUpdate(normalizedNodeUpdate, serializer);
if (dataObjectUpdate != null) {
if (dataObjectUpdate instanceof DataObjectUpdate.DataObjectDelete) {
+ // is delete
dataObjectDeletes.put(unkeyedIid, (DataObjectUpdate.DataObjectDelete) dataObjectUpdate);
+ } else if (dataObjectUpdate.getDataBefore() != null && !registry.writerSupportsUpdate(unkeyedIid)) {
+ // is update and direct update operation is not supported
+ // breaks update to delete + create pair
+
+ dataObjectDeletes.put(unkeyedIid,
+ (DataObjectUpdate.DataObjectDelete) DataObjectUpdate.DataObjectDelete
+ .create(keyedId, dataObjectUpdate.getDataBefore(), null));
+ dataObjectUpdates
+ .put(unkeyedIid, DataObjectUpdate.create(keyedId, null, dataObjectUpdate.getDataAfter()));
} else {
+ // is create
dataObjectUpdates.put(unkeyedIid, dataObjectUpdate);
}
}
diff --git a/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegatorTest.java b/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegatorTest.java
index 432833b..ccd35a9 100644
--- a/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegatorTest.java
+++ b/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegatorTest.java
@@ -128,8 +128,9 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
dataModification.commit();
final Multimap<InstanceIdentifier<?>, DataObjectUpdate> map = HashMultimap.create();
- map.put(DEFAULT_ID, DataObjectUpdate.create(DEFAULT_ID, DEFAULT_DATA_OBJECT, DEFAULT_DATA_OBJECT));
- verify(writer).update(eq(new WriterRegistry.DataObjectUpdates(map, ImmutableMultimap.of())), any(WriteContext.class));
+ // data before should be null as it is create
+ map.put(DEFAULT_ID, DataObjectUpdate.create(DEFAULT_ID, null, DEFAULT_DATA_OBJECT));
+ verify(writer).processModifications(eq(new WriterRegistry.DataObjectUpdates(map, ImmutableMultimap.of())), any(WriteContext.class));
assertEquals(nestedList, dataTree.takeSnapshot().readNode(NESTED_LIST_ID).get());
}
@@ -147,7 +148,7 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
final WriterRegistry.Reverter reverter = mock(WriterRegistry.Reverter.class);
final TranslationException failedOnUpdateException = new TranslationException("update failed");
doThrow(new WriterRegistry.BulkUpdateException(DEFAULT_ID, update, Collections.singleton(DEFAULT_ID), reverter, failedOnUpdateException))
- .when(writer).update(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
+ .when(writer).processModifications(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
try {
// Run the test
@@ -157,7 +158,7 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
dataModification.commit();
fail("WriterRegistry.RevertSuccessException was expected");
} catch (WriterRegistry.Reverter.RevertSuccessException e) {
- verify(writer).update(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
+ verify(writer).processModifications(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
assertThat(e.getFailedIds(), hasItem(DEFAULT_ID));
verify(reverter).revert(any(WriteContext.class));
}
@@ -173,7 +174,7 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
final WriterRegistry.BulkUpdateException bulkFailEx =
new WriterRegistry.BulkUpdateException(DEFAULT_ID, update, Collections.singleton(DEFAULT_ID), reverter,
failedOnUpdateException);
- doThrow(bulkFailEx).when(writer).update(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
+ doThrow(bulkFailEx).when(writer).processModifications(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
// Fail on revert:
doThrow(new WriterRegistry.Reverter.RevertFailedException(bulkFailEx))
@@ -187,7 +188,7 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
dataModification.commit();
fail("WriterRegistry.Reverter.RevertFailedException was expected");
} catch (WriterRegistry.Reverter.RevertFailedException e) {
- verify(writer).update(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
+ verify(writer).processModifications(any(WriterRegistry.DataObjectUpdates.class), any(WriteContext.class));
verify(reverter).revert(any(WriteContext.class));
assertEquals(bulkFailEx, e.getCause());
}
@@ -200,7 +201,7 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
@Test
public void testToBindingAware() throws Exception {
when(serializer.fromNormalizedNode(any(YangInstanceIdentifier.class), eq(null))).thenReturn(null);
-
+ when(writer.writerSupportsUpdate(any())).thenReturn(true);
final Map<YangInstanceIdentifier, NormalizedNodeUpdate> biNodes = new HashMap<>();
// delete
final QName nn1 = QName.create("namespace", "nn1");
@@ -229,7 +230,7 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
biNodes.put(yid3, NormalizedNodeUpdate.create(yid3, nn3B, nn3A));
final WriterRegistry.DataObjectUpdates dataObjectUpdates =
- ModifiableDataTreeDelegator.toBindingAware(biNodes, serializer);
+ ModifiableDataTreeDelegator.toBindingAware(writer, biNodes, serializer);
assertThat(dataObjectUpdates.getDeletes().size(), is(1));
assertThat(dataObjectUpdates.getDeletes().keySet(), hasItem(((InstanceIdentifier<?>) iid1)));
@@ -245,6 +246,57 @@ public class ModifiableDataTreeDelegatorTest extends ModificationBaseTest {
assertThat(dataObjectUpdates.getTypeIntersection().size(), is(3));
}
+ @Test
+ public void testToBindingAwareUpdateNotSupported() throws Exception {
+ when(serializer.fromNormalizedNode(any(YangInstanceIdentifier.class), eq(null))).thenReturn(null);
+ when(writer.writerSupportsUpdate(any())).thenReturn(false);
+ final Map<YangInstanceIdentifier, NormalizedNodeUpdate> biNodes = new HashMap<>();
+ // delete
+ final QName nn1 = QName.create("namespace", "nn1");
+ final YangInstanceIdentifier yid1 = mockYid(nn1);
+ final InstanceIdentifier iid1 = mockIid(yid1, DataObject1.class);
+ final NormalizedNode nn1B = mockNormalizedNode(nn1);
+ final DataObject1 do1B = mockDataObject(yid1, iid1, nn1B, DataObject1.class);
+ biNodes.put(yid1, NormalizedNodeUpdate.create(yid1, nn1B, null));
+
+ // create
+ final QName nn2 = QName.create("namespace", "nn1");
+ final YangInstanceIdentifier yid2 = mockYid(nn2);
+ final InstanceIdentifier iid2 = mockIid(yid2, DataObject2.class);;
+ final NormalizedNode nn2A = mockNormalizedNode(nn2);
+ final DataObject2 do2A = mockDataObject(yid2, iid2, nn2A, DataObject2.class);
+ biNodes.put(yid2, NormalizedNodeUpdate.create(yid2, null, nn2A));
+
+ // processModifications
+ final QName nn3 = QName.create("namespace", "nn1");
+ final YangInstanceIdentifier yid3 = mockYid(nn3);
+ final InstanceIdentifier iid3 = mockIid(yid3, DataObject3.class);
+ final NormalizedNode nn3B = mockNormalizedNode(nn3);
+ final DataObject3 do3B = mockDataObject(yid3, iid3, nn3B, DataObject3.class);
+ final NormalizedNode nn3A = mockNormalizedNode(nn3);
+ final DataObject3 do3A = mockDataObject(yid3, iid3, nn3A, DataObject3.class);;
+ biNodes.put(yid3, NormalizedNodeUpdate.create(yid3, nn3B, nn3A));
+
+ final WriterRegistry.DataObjectUpdates dataObjectUpdates =
+ ModifiableDataTreeDelegator.toBindingAware(writer, biNodes, serializer);
+
+ // should have also id and data for delete as delete + create pair was created
+ assertThat(dataObjectUpdates.getDeletes().size(), is(2));
+ assertThat(dataObjectUpdates.getDeletes().keySet(),
+ hasItems(((InstanceIdentifier<?>) iid1), (InstanceIdentifier<?>) iid3));
+ assertThat(dataObjectUpdates.getDeletes().values(), hasItems(
+ ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid1, do1B, null)),
+ ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid3, do3B, null))));
+
+ assertThat(dataObjectUpdates.getUpdates().size(), is(2));
+ assertThat(dataObjectUpdates.getUpdates().keySet(), hasItems( (InstanceIdentifier<?>) iid2, (InstanceIdentifier<?>) iid3));
+ assertThat(dataObjectUpdates.getUpdates().values(), hasItems(
+ DataObjectUpdate.create(iid2, null, do2A),
+ DataObjectUpdate.create(iid3, null, do3A)));
+
+ assertThat(dataObjectUpdates.getTypeIntersection().size(), is(3));
+ }
+
private <D extends DataObject> D mockDataObject(final YangInstanceIdentifier yid1,
final InstanceIdentifier iid1,
final NormalizedNode nn1B,
diff --git a/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/HoneycombWriteInfraTest.java b/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/HoneycombWriteInfraTest.java
index cd1816f..a740e01 100644
--- a/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/HoneycombWriteInfraTest.java
+++ b/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/HoneycombWriteInfraTest.java
@@ -176,22 +176,22 @@ public class HoneycombWriteInfraTest extends AbstractInfraTest {
// verify(complexAugmentWriter).update(eq(COMPLEX_AUGMENT_ID), eq(null), eq(getComplexAugment()), any(WriteContext.class));
// 1
inOrder.verify(complexAugmentContainerWriter)
- .update(eq(Ids.COMPLEX_AUGMENT_CONTAINER_ID), eq(null), eq(getComplexAugmentContainer()), any(WriteContext.class));
+ .processModification(eq(Ids.COMPLEX_AUGMENT_CONTAINER_ID), eq(null), eq(getComplexAugmentContainer()), any(WriteContext.class));
// 2
inOrder.verify(c3Writer)
- .update(eq(Ids.C3_ID), eq(null), eq(getC3()), any(WriteContext.class));
+ .processModification(eq(Ids.C3_ID), eq(null), eq(getC3()), any(WriteContext.class));
// 2
verify(simpleAugmentWriter)
- .update(eq(Ids.SIMPLE_AUGMENT_ID), eq(null), eq(getSimpleAugment()), any(WriteContext.class));
+ .processModification(eq(Ids.SIMPLE_AUGMENT_ID), eq(null), eq(getSimpleAugment()), any(WriteContext.class));
// 3
inOrder.verify(simpleContainerWriter)
- .update(eq(Ids.SIMPLE_CONTAINER_ID), eq(null), eq(getSimpleContainer()), any(WriteContext.class));
+ .processModification(eq(Ids.SIMPLE_CONTAINER_ID), eq(null), eq(getSimpleContainer()), any(WriteContext.class));
// 4
inOrder.verify(containerWithChoiceWriter)
- .update(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(null), eq(getContainerWithChoiceWithComplexCase()), any(WriteContext.class));
+ .processModification(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(null), eq(getContainerWithChoiceWithComplexCase()), any(WriteContext.class));
// 5
inOrder.verify(containerFromGroupingWriter)
- .update(eq(Ids.CONTAINER_FROM_GROUPING_ID), eq(null), eq(getContainerFromGrouping()), any(WriteContext.class));
+ .processModification(eq(Ids.CONTAINER_FROM_GROUPING_ID), eq(null), eq(getContainerFromGrouping()), any(WriteContext.class));
final KeyedInstanceIdentifier<ListInContainer, ListInContainerKey> keyedListInContainer1 =
Ids.CONTAINER_WITH_LIST_ID.child(ListInContainer.class, new ListInContainerKey((long) 1));
@@ -204,21 +204,21 @@ public class HoneycombWriteInfraTest extends AbstractInfraTest {
// 6 - two items
inOrder.verify(nestedListWriter)
- .update(eq(keyedNestedList1), eq(null), eq(getSingleNestedList("1")), any(WriteContext.class));
+ .processModification(eq(keyedNestedList1), eq(null), eq(getSingleNestedList("1")), any(WriteContext.class));
verify(nestedListWriter)
- .update(eq(keyedNestedList2), eq(null), eq(getSingleNestedList("2")), any(WriteContext.class));
+ .processModification(eq(keyedNestedList2), eq(null), eq(getSingleNestedList("2")), any(WriteContext.class));
// 7 - two items
inOrder.verify(listInContainerWriter)
- .update(eq(keyedListInContainer1), eq(null), eq(getSingleListInContainer((long)1)), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer1), eq(null), eq(getSingleListInContainer((long)1)), any(WriteContext.class));
verify(listInContainerWriter)
- .update(eq(keyedListInContainer2), eq(null), eq(getSingleListInContainer((long)2)), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer2), eq(null), eq(getSingleListInContainer((long)2)), any(WriteContext.class));
// 8
inOrder.verify(containerInListWriter)
- .update(eq(keyedListInContainer1.child(ContainerInList.class)), eq(null), eq(getContainerInList("1")), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer1.child(ContainerInList.class)), eq(null), eq(getContainerInList("1")), any(WriteContext.class));
verify(containerInListWriter)
- .update(eq(keyedListInContainer2.child(ContainerInList.class)), eq(null), eq(getContainerInList("2")), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer2.child(ContainerInList.class)), eq(null), eq(getContainerInList("2")), any(WriteContext.class));
// 9 - Ignored because the container has no leaves, only complex child nodes
// inOrder.verify(containerWithListWriter)
@@ -280,39 +280,39 @@ public class HoneycombWriteInfraTest extends AbstractInfraTest {
// Deletes are handled in reverse order
// 1
inOrder.verify(containerInListWriter)
- .update(eq(keyedListInContainer1.child(ContainerInList.class)), eq(getContainerInList("1")), eq(null), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer1.child(ContainerInList.class)), eq(getContainerInList("1")), eq(null), any(WriteContext.class));
verify(containerInListWriter)
- .update(eq(keyedListInContainer2.child(ContainerInList.class)), eq(getContainerInList("2")), eq(null), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer2.child(ContainerInList.class)), eq(getContainerInList("2")), eq(null), any(WriteContext.class));
// 2
inOrder.verify(listInContainerWriter)
- .update(eq(keyedListInContainer1), eq(getSingleListInContainer((long)1)), eq(null), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer1), eq(getSingleListInContainer((long)1)), eq(null), any(WriteContext.class));
verify(listInContainerWriter)
- .update(eq(keyedListInContainer2), eq(getSingleListInContainer((long)2)), eq(null), any(WriteContext.class));
+ .processModification(eq(keyedListInContainer2), eq(getSingleListInContainer((long)2)), eq(null), any(WriteContext.class));
// 3
inOrder.verify(nestedListWriter)
- .update(eq(keyedNestedList1), eq(getSingleNestedList("1")), eq(null), any(WriteContext.class));
+ .processModification(eq(keyedNestedList1), eq(getSingleNestedList("1")), eq(null), any(WriteContext.class));
verify(nestedListWriter)
- .update(eq(keyedNestedList2), eq(getSingleNestedList("2")), eq(null), any(WriteContext.class));
+ .processModification(eq(keyedNestedList2), eq(getSingleNestedList("2")), eq(null), any(WriteContext.class));
// 4
inOrder.verify(containerFromGroupingWriter)
- .update(eq(Ids.CONTAINER_FROM_GROUPING_ID), eq(getContainerFromGrouping()), eq(null), any(WriteContext.class));
+ .processModification(eq(Ids.CONTAINER_FROM_GROUPING_ID), eq(getContainerFromGrouping()), eq(null), any(WriteContext.class));
// 5
inOrder.verify(containerWithChoiceWriter)
- .update(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(getContainerWithChoiceWithComplexCase()), eq(null), any(WriteContext.class));
+ .processModification(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(getContainerWithChoiceWithComplexCase()), eq(null), any(WriteContext.class));
// 6
inOrder.verify(simpleContainerWriter)
- .update(eq(Ids.SIMPLE_CONTAINER_ID), eq(getSimpleContainer()), eq(null), any(WriteContext.class));
+ .processModification(eq(Ids.SIMPLE_CONTAINER_ID), eq(getSimpleContainer()), eq(null), any(WriteContext.class));
// 7
verify(simpleAugmentWriter)
- .update(eq(Ids.SIMPLE_AUGMENT_ID), eq(getSimpleAugment()), eq(null), any(WriteContext.class));
+ .processModification(eq(Ids.SIMPLE_AUGMENT_ID), eq(getSimpleAugment()), eq(null), any(WriteContext.class));
// 8
inOrder.verify(c3Writer)
- .update(eq(Ids.C3_ID), eq(getC3()), eq(null), any(WriteContext.class));
+ .processModification(eq(Ids.C3_ID), eq(getC3()), eq(null), any(WriteContext.class));
// 9
inOrder.verify(complexAugmentContainerWriter)
- .update(eq(Ids.COMPLEX_AUGMENT_CONTAINER_ID), eq(getComplexAugmentContainer()), eq(null), any(WriteContext.class));
+ .processModification(eq(Ids.COMPLEX_AUGMENT_CONTAINER_ID), eq(getComplexAugmentContainer()), eq(null), any(WriteContext.class));
for (Writer<?> orderedWriter : orderedWriters) {
verify(orderedWriter).getManagedDataObjectType();
@@ -493,7 +493,7 @@ public class HoneycombWriteInfraTest extends AbstractInfraTest {
verify(containerWithChoiceWriter, atLeastOnce()).getManagedDataObjectType();
verify(containerWithChoiceWriter)
- .update(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(null), eq(containerWithChoice), any(WriteContext.class));
+ .processModification(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(null), eq(containerWithChoice), any(WriteContext.class));
verifyNoMoreInteractions(containerWithChoiceWriter);
// Test delete sub-node
@@ -504,7 +504,7 @@ public class HoneycombWriteInfraTest extends AbstractInfraTest {
verify(containerWithChoiceWriter, atLeastOnce()).getManagedDataObjectType();
verify(containerWithChoiceWriter)
- .update(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(containerWithChoice), eq(containerWithChoiceEmpty), any(WriteContext.class));
+ .processModification(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(containerWithChoice), eq(containerWithChoiceEmpty), any(WriteContext.class));
verifyNoMoreInteractions(containerWithChoiceWriter);
// Test write with subtree node that's not handled by subtree writer
diff --git a/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/NestedAugmentationWriteTest.java b/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/NestedAugmentationWriteTest.java
index 3b7d4a1..37dac0f 100644
--- a/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/NestedAugmentationWriteTest.java
+++ b/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/NestedAugmentationWriteTest.java
@@ -162,7 +162,7 @@ public class NestedAugmentationWriteTest extends AbstractInfraTest {
dataModification.commit();
- verify(simpleAugmentWriter).update(eq(SIMPLE_AUGMENT_ID), eq(null), eq(simpleAugment()), any(WriteContext.class));
+ verify(simpleAugmentWriter).processModification(eq(SIMPLE_AUGMENT_ID), eq(null), eq(simpleAugment()), any(WriteContext.class));
}
@Test
@@ -181,9 +181,9 @@ public class NestedAugmentationWriteTest extends AbstractInfraTest {
dataModification.commit();
- verify(augTargetWriter).update(eq(AUG_TARGET_ID), eq(null), eq(data), any(WriteContext.class));
- verify(fromAugmentWriter).update(eq(FROM_AUGMENT_ID), eq(null), eq(fromAugmentSimple(augData)), any(WriteContext.class));
- verify(simpleNestedAugmentWriter).update(eq(SIMPLE_NESTED_AUGMENT_ID), eq(null), eq(augData), any(WriteContext.class));
+ verify(augTargetWriter).processModification(eq(AUG_TARGET_ID), eq(null), eq(data), any(WriteContext.class));
+ verify(fromAugmentWriter).processModification(eq(FROM_AUGMENT_ID), eq(null), eq(fromAugmentSimple(augData)), any(WriteContext.class));
+ verify(simpleNestedAugmentWriter).processModification(eq(SIMPLE_NESTED_AUGMENT_ID), eq(null), eq(augData), any(WriteContext.class));
}
private SimpleAugment simpleAugment() {
@@ -204,9 +204,9 @@ public class NestedAugmentationWriteTest extends AbstractInfraTest {
dataModification.commit();
- verify(augTargetWriter).update(eq(AUG_TARGET_ID), eq(null), eq(data), any(WriteContext.class));
- verify(fromAugmentWriter).update(eq(FROM_AUGMENT_ID), eq(null), eq(fromAugment()), any(WriteContext.class));
- verify(fromAugment2Writer).update(eq(FROM_AUGMENT2_ID), eq(null), eq(fromAugment2()), any(WriteContext.class));
+ verify(augTargetWriter).processModification(eq(AUG_TARGET_ID), eq(null), eq(data), any(WriteContext.class));
+ verify(fromAugmentWriter).processModification(eq(FROM_AUGMENT_ID), eq(null), eq(fromAugment()), any(WriteContext.class));
+ verify(fromAugment2Writer).processModification(eq(FROM_AUGMENT2_ID), eq(null), eq(fromAugment2()), any(WriteContext.class));
}
@Test
@@ -228,10 +228,10 @@ public class NestedAugmentationWriteTest extends AbstractInfraTest {
dataModification.commit();
final ArgumentCaptor<DataObject> doCaptor = ArgumentCaptor.forClass(DataObject.class);
- verify(augTargetWriter).update(eq(AUG_TARGET_ID), eq(null), doCaptor.capture(), any(WriteContext.class));
+ verify(augTargetWriter).processModification(eq(AUG_TARGET_ID), eq(null), doCaptor.capture(), any(WriteContext.class));
assertEquals(data.getSomeLeaf(), ((AugTarget)doCaptor.getValue()).getSomeLeaf());
- verify(fromAugmentWriter).update(eq(FROM_AUGMENT_ID), eq(null), doCaptor.capture(), any(WriteContext.class));
+ verify(fromAugmentWriter).processModification(eq(FROM_AUGMENT_ID), eq(null), doCaptor.capture(), any(WriteContext.class));
assertEquals(fromAugment.getSomeLeaf(), ((FromAugment)doCaptor.getValue()).getSomeLeaf());
@@ -241,9 +241,9 @@ public class NestedAugmentationWriteTest extends AbstractInfraTest {
FROM_AUGMENT_LIST_AUGMENT_ID.child(FromAugmentEntry.class, new FromAugmentEntryKey("2"));
verify(fromAugmentListWriter)
- .update(eq(keyedNestedList1), eq(null), eq(entries.get(0)), any(WriteContext.class));
+ .processModification(eq(keyedNestedList1), eq(null), eq(entries.get(0)), any(WriteContext.class));
verify(fromAugmentListWriter)
- .update(eq(keyedNestedList2), eq(null), eq(entries.get(1)), any(WriteContext.class));
+ .processModification(eq(keyedNestedList2), eq(null), eq(entries.get(1)), any(WriteContext.class));
}
@Test
@@ -270,19 +270,19 @@ public class NestedAugmentationWriteTest extends AbstractInfraTest {
dataModification.commit();
// verify aug target update:
- verify(augTargetWriter).update(eq(AUG_TARGET_ID), eq(null), eq(data), any(WriteContext.class));
+ verify(augTargetWriter).processModification(eq(AUG_TARGET_ID), eq(null), eq(data), any(WriteContext.class));
// verify list customizer update:
final KeyedInstanceIdentifier<ListFromAugment, ListFromAugmentKey> keyedNestedList =
LIST_AUGMENT_ID.child(ListFromAugment.class, new ListFromAugmentKey("some-leaf-val"));
final ArgumentCaptor<DataObject> doCaptor = ArgumentCaptor.forClass(DataObject.class);
verify(listFromAugmentWriter)
- .update(eq(keyedNestedList), eq(null), doCaptor.capture(), any(WriteContext.class));
+ .processModification(eq(keyedNestedList), eq(null), doCaptor.capture(), any(WriteContext.class));
assertEquals(list.get(0).getSomeLeaf(), ((ListFromAugment) doCaptor.getValue()).getSomeLeaf());
// verify list augmentation customizer update:
verify(listFromAugmentAugmentWriter)
- .update(eq(keyedNestedList.augmentation(ListFromAugmentAugment.class)), eq(null), doCaptor.capture(),
+ .processModification(eq(keyedNestedList.augmentation(ListFromAugmentAugment.class)), eq(null), doCaptor.capture(),
any(WriteContext.class));
assertEquals(listAugmentation.getNewLeaf(), ((ListFromAugmentAugment) doCaptor.getValue()).getNewLeaf());
}
diff --git a/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/Writer.java b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/Writer.java
index e653801..1a16b72 100644
--- a/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/Writer.java
+++ b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/Writer.java
@@ -33,7 +33,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public interface Writer<D extends DataObject> extends SubtreeManager<D> {
/**
- * Handle update operation. U from CRUD.
+ * Process modifications and translate them as create/update/delete operations to lower level
*
* @param id Identifier of data being written
* @param dataBefore Old data
@@ -41,8 +41,14 @@ public interface Writer<D extends DataObject> extends SubtreeManager<D> {
* @param ctx Write context enabling writer to get information about candidate data as well as current data
* @throws WriteFailedException if update failed
*/
- void update(@Nonnull final InstanceIdentifier<? extends DataObject> id,
- @Nullable final DataObject dataBefore,
- @Nullable final DataObject dataAfter,
- @Nonnull final WriteContext ctx) throws WriteFailedException;
+ void processModification(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+ @Nullable final DataObject dataBefore,
+ @Nullable final DataObject dataAfter,
+ @Nonnull final WriteContext ctx) throws WriteFailedException;
+
+ /**
+ * Indicates whether there is direct support for updating nodes handled by this writer,
+ * or they must be broken up to individual deletes and creates.
+ */
+ boolean supportsDirectUpdate();
}
diff --git a/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java
index 5520c00..a297b6d 100644
--- a/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java
+++ b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java
@@ -41,12 +41,19 @@ public interface WriterRegistry {
* @throws BulkUpdateException in case bulk update fails
* @throws TranslationException in case some other error occurs while processing update request
*/
- void update(@Nonnull DataObjectUpdates updates,
- @Nonnull WriteContext ctx) throws TranslationException;
+ void processModifications(@Nonnull DataObjectUpdates updates,
+ @Nonnull WriteContext ctx) throws TranslationException;
/**
- * Simple DTO containing updates for {@link WriterRegistry}. Currently only deletes and updates (create + update)
- * are distinguished.
+ * Indicates direct support for update operation on provided type
+ *
+ * @param type data object type
+ */
+ boolean writerSupportsUpdate(@Nonnull InstanceIdentifier<?> type);
+
+ /**
+ * Simple DTO containing updates for {@link WriterRegistry}. Currently only deletes and updates (create +
+ * update) are distinguished.
*/
@Beta
final class DataObjectUpdates {
diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericListWriter.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericListWriter.java
index 4e05ce0..6fbef8e 100644
--- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericListWriter.java
+++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericListWriter.java
@@ -16,6 +16,8 @@
package io.fd.honeycomb.translate.impl.write;
+import static io.fd.honeycomb.translate.impl.write.GenericWriter.isUpdateSupported;
+
import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
import io.fd.honeycomb.translate.util.RWUtils;
import io.fd.honeycomb.translate.util.write.AbstractGenericWriter;
@@ -39,7 +41,7 @@ public final class GenericListWriter<D extends DataObject & Identifiable<K>, K e
public GenericListWriter(@Nonnull final InstanceIdentifier<D> type,
@Nonnull final ListWriterCustomizer<D, K> customizer) {
- super(type);
+ super(type, isUpdateSupported(customizer));
this.customizer = customizer;
}
diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericWriter.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericWriter.java
index 30d15e3..086936e 100644
--- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericWriter.java
+++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/GenericWriter.java
@@ -23,18 +23,40 @@ import io.fd.honeycomb.translate.write.WriteFailedException;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Generic writer with customizable behavior thanks to injected customizer.
*/
public final class GenericWriter<D extends DataObject> extends AbstractGenericWriter<D> {
+ private static final Logger LOG = LoggerFactory.getLogger(GenericWriter.class);
+ private static final String UPDATE_M = "updateCurrentAttributes";
private final WriterCustomizer<D> customizer;
public GenericWriter(@Nonnull final InstanceIdentifier<D> type,
@Nonnull final WriterCustomizer<D> customizer) {
- super(type);
+ super(type, isUpdateSupported(customizer));
this.customizer = customizer;
+
+ }
+
+ static boolean isUpdateSupported(final @Nonnull WriterCustomizer<?> customizer) {
+ try {
+ // if customizer overrides updateCurrentAttributes method, it will be used, otherwise updates will be broken into individual
+ // delete + create pairs
+ final Class<? extends WriterCustomizer> customizerClass = customizer.getClass();
+ final Class<?> updateDeclaringClass = customizerClass
+ .getMethod(UPDATE_M, InstanceIdentifier.class, DataObject.class, DataObject.class, WriteContext.class)
+ .getDeclaringClass();
+ final boolean supportsUpdate = !WriterCustomizer.class.equals(updateDeclaringClass);
+ LOG.debug("Customizer {} update support : {}|Update declaring class {}", customizerClass, supportsUpdate,
+ updateDeclaringClass);
+ return supportsUpdate;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("Unable to detect if customizer supports update", e);
+ }
}
@Override
diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java
index 418f4b4..e21297a 100644
--- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java
+++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java
@@ -92,8 +92,8 @@ final class FlatWriterRegistry implements WriterRegistry {
}
@Override
- public void update(@Nonnull final DataObjectUpdates updates,
- @Nonnull final WriteContext ctx) throws TranslationException {
+ public void processModifications(@Nonnull final DataObjectUpdates updates,
+ @Nonnull final WriteContext ctx) throws TranslationException {
if (updates.isEmpty()) {
return;
}
@@ -115,6 +115,17 @@ final class FlatWriterRegistry implements WriterRegistry {
LOG.trace("Update successful for: {}", updates);
}
+ @Override
+ public boolean writerSupportsUpdate(@Nonnull final InstanceIdentifier<?> type) {
+ Writer writer = getWriter(type);
+
+ if(writer == null){
+ writer = getSubtreeWriterResponsible(type);
+ }
+
+ return checkNotNull(writer, "Unable to find writer for %s", type).supportsDirectUpdate();
+ }
+
private void singleUpdate(@Nonnull final Multimap<InstanceIdentifier<?>, ? extends DataObjectUpdate> updates,
@Nonnull final WriteContext ctx) throws WriteFailedException {
if (updates.isEmpty()) {
@@ -136,16 +147,17 @@ final class FlatWriterRegistry implements WriterRegistry {
LOG.trace("Performing single type update with writer: {}", writer);
for (DataObjectUpdate singleUpdate : singleTypeUpdates) {
- writer.update(singleUpdate.getId(), singleUpdate.getDataBefore(), singleUpdate.getDataAfter(), ctx);
+ writer.processModification(singleUpdate.getId(), singleUpdate.getDataBefore(), singleUpdate.getDataAfter(), ctx);
}
}
+ @Nullable
private Writer<?> getSubtreeWriterResponsible(final InstanceIdentifier<?> singleType) {
return writers.values().stream()
.filter(w -> w instanceof SubtreeWriter)
.filter(w -> ((SubtreeWriter<?>) w).getHandledChildTypes().contains(singleType))
.findFirst()
- .get();
+ .orElse(null);
}
private Collection<DataObjectUpdate> getParentDataObjectUpdate(final WriteContext ctx,
@@ -208,7 +220,7 @@ final class FlatWriterRegistry implements WriterRegistry {
for (DataObjectUpdate singleUpdate : writersData) {
try {
- writer.update(singleUpdate.getId(), singleUpdate.getDataBefore(), singleUpdate.getDataAfter(), ctx);
+ writer.processModification(singleUpdate.getId(), singleUpdate.getDataBefore(), singleUpdate.getDataAfter(), ctx);
processedNodes.add(singleUpdate.getId());
LOG.trace("Update successful for type: {}", writerType);
LOG.debug("Update successful for: {}", singleUpdate);
diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java
index fc6ecc6..b2a571b 100644
--- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java
+++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java
@@ -62,11 +62,16 @@ final class SubtreeWriter<D extends DataObject> implements Writer<D> {
}
@Override
- public void update(
+ public void processModification(
@Nonnull final InstanceIdentifier<? extends DataObject> id,
@Nullable final DataObject dataBefore,
@Nullable final DataObject dataAfter, @Nonnull final WriteContext ctx) throws WriteFailedException {
- delegate.update(id, dataBefore, dataAfter, ctx);
+ delegate.processModification(id, dataBefore, dataAfter, ctx);
+ }
+
+ @Override
+ public boolean supportsDirectUpdate() {
+ return delegate.supportsDirectUpdate();
}
@Override
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericListWriterTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericListWriterTest.java
index 2f50ece..91785b2 100644
--- a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericListWriterTest.java
+++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericListWriterTest.java
@@ -71,13 +71,13 @@ public class GenericListWriterTest {
(InstanceIdentifier<IdentifiableDataObject>) InstanceIdentifier.create(Collections
.singleton(new InstanceIdentifier.IdentifiableItem<>(IdentifiableDataObject.class, keyAfter)));
- writer.update(DATA_OBJECT_ID, before, after, ctx);
+ writer.processModification(DATA_OBJECT_ID, before, after, ctx);
verify(customizer).updateCurrentAttributes(keyedIdBefore, before, after, ctx);
- writer.update(DATA_OBJECT_ID, before, null, ctx);
+ writer.processModification(DATA_OBJECT_ID, before, null, ctx);
verify(customizer).deleteCurrentAttributes(keyedIdBefore, before, ctx);
- writer.update(DATA_OBJECT_ID, null, after, ctx);
+ writer.processModification(DATA_OBJECT_ID, null, after, ctx);
verify(customizer).writeCurrentAttributes(keyedIdAfter, after, ctx);
}
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericWriterTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericWriterTest.java
index 3caea57..c9d381a 100644
--- a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericWriterTest.java
+++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/GenericWriterTest.java
@@ -17,6 +17,8 @@
package io.fd.honeycomb.translate.impl.write;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
@@ -53,13 +55,13 @@ public class GenericWriterTest {
@Test
public void testUpdate() throws Exception {
assertEquals(DATA_OBJECT_ID, writer.getManagedDataObjectType());
- writer.update(DATA_OBJECT_ID, before, after, ctx);
+ writer.processModification(DATA_OBJECT_ID, before, after, ctx);
verify(customizer).updateCurrentAttributes(DATA_OBJECT_ID, before, after, ctx);
- writer.update(DATA_OBJECT_ID, before, null, ctx);
+ writer.processModification(DATA_OBJECT_ID, before, null, ctx);
verify(customizer).deleteCurrentAttributes(DATA_OBJECT_ID, before, ctx);
- writer.update(DATA_OBJECT_ID, null, after, ctx);
+ writer.processModification(DATA_OBJECT_ID, null, after, ctx);
verify(customizer).writeCurrentAttributes(DATA_OBJECT_ID, after, ctx);
}
@@ -85,4 +87,11 @@ public class GenericWriterTest {
writer = new GenericWriter<>(DATA_OBJECT_ID, customizer);
writer.deleteCurrentAttributes(DATA_OBJECT_ID, before, ctx);
}
+
+ @Test
+ public void testUpdateSupported() {
+ assertFalse(GenericWriter.isUpdateSupported(new NoopWriters.NonDirectUpdateWriterCustomizer()));
+ assertTrue(GenericWriter.isUpdateSupported(new NoopWriters.DirectUpdateWriterCustomizer()));
+ assertTrue(GenericWriter.isUpdateSupported(new NoopWriters.ParentImplDirectUpdateWriterCustomizer()));
+ }
} \ No newline at end of file
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/NoopWriters.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/NoopWriters.java
new file mode 100644
index 0000000..8ea91d2
--- /dev/null
+++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/NoopWriters.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.translate.impl.write;
+
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class NoopWriters {
+
+ private NoopWriters() {
+ }
+
+ public static class NonDirectUpdateWriterCustomizer implements WriterCustomizer<DataObject> {
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<DataObject> id,
+ @Nonnull final DataObject dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ // NOOP
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<DataObject> id,
+ @Nonnull final DataObject dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ // NOOP
+ }
+ }
+
+ public static class DirectUpdateWriterCustomizer extends NonDirectUpdateWriterCustomizer {
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<DataObject> id,
+ @Nonnull final DataObject dataBefore, @Nonnull final DataObject dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ // is direct support
+ }
+ }
+
+ public static class ParentImplDirectUpdateWriterCustomizer extends DirectUpdateWriterCustomizer {
+ // parent impls directly
+ }
+}
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilderTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilderTest.java
index feaba72..dd1adb3 100644
--- a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilderTest.java
+++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilderTest.java
@@ -87,9 +87,9 @@ public class FlatWriterRegistryBuilderTest {
Multimaps.forMap(Collections.singletonMap(id, update)),
Multimaps.forMap(Collections.emptyMap()));
final WriteContext ctx = mock(WriteContext.class);
- build.update(updates, ctx);
+ build.processModifications(updates, ctx);
- verify(writer).update(id, before, after, ctx);
+ verify(writer).processModification(id, before, after, ctx);
}
@Test(expected = IllegalArgumentException.class)
@@ -104,7 +104,7 @@ public class FlatWriterRegistryBuilderTest {
final WriterRegistry.DataObjectUpdates updates = new WriterRegistry.DataObjectUpdates(
Multimaps.forMap(Collections.singletonMap(id2, update2)),
Multimaps.forMap(Collections.emptyMap()));
- build.update(updates, mock(WriteContext.class));
+ build.processModifications(updates, mock(WriteContext.class));
}
@Test
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java
index f66ab8f..72a91cb 100644
--- a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java
+++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java
@@ -84,10 +84,10 @@ public class FlatWriterRegistryTest {
final DataObject1 dataObject = mock(DataObject1.class);
updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
updates.put(DataObject1.IID, DataObjectUpdate.create(iid2, dataObject, dataObject));
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
- verify(writer1).update(iid, dataObject, dataObject, ctx);
- verify(writer1).update(iid2, dataObject, dataObject, ctx);
+ verify(writer1).processModification(iid, dataObject, dataObject, ctx);
+ verify(writer1).processModification(iid2, dataObject, dataObject, ctx);
// Invoked when registry is being created
verifyNoMoreInteractions(writer1);
verifyZeroInteractions(writer2);
@@ -105,11 +105,11 @@ public class FlatWriterRegistryTest {
final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
final DataObject2 dataObject2 = mock(DataObject2.class);
updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
final InOrder inOrder = inOrder(writer1, writer2);
- inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
- inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
+ inOrder.verify(writer1).processModification(iid, dataObject, dataObject, ctx);
+ inOrder.verify(writer2).processModification(iid2, dataObject2, dataObject2, ctx);
verifyNoMoreInteractions(writer1);
verifyNoMoreInteractions(writer2);
@@ -128,12 +128,12 @@ public class FlatWriterRegistryTest {
final DataObject2 dataObject2 = mock(DataObject2.class);
deletes.put(
DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(ImmutableMultimap.of(), deletes), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(ImmutableMultimap.of(), deletes), ctx);
final InOrder inOrder = inOrder(writer1, writer2);
// Reversed order of invocation, first writer2 and then writer1
- inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
- inOrder.verify(writer1).update(iid, dataObject, null, ctx);
+ inOrder.verify(writer2).processModification(iid2, dataObject2, null, ctx);
+ inOrder.verify(writer1).processModification(iid, dataObject, null, ctx);
verifyNoMoreInteractions(writer1);
verifyNoMoreInteractions(writer2);
@@ -159,15 +159,15 @@ public class FlatWriterRegistryTest {
DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
// Writer 2 update
updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, deletes), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, deletes), ctx);
final InOrder inOrder = inOrder(writer1, writer2);
// Reversed order of invocation, first writer2 and then writer1 for deletes
- inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
- inOrder.verify(writer1).update(iid, dataObject, null, ctx);
+ inOrder.verify(writer2).processModification(iid2, dataObject2, null, ctx);
+ inOrder.verify(writer1).processModification(iid, dataObject, null, ctx);
// Then also updates are processed
- inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
- inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
+ inOrder.verify(writer1).processModification(iid, dataObject, dataObject, ctx);
+ inOrder.verify(writer2).processModification(iid2, dataObject2, dataObject2, ctx);
verifyNoMoreInteractions(writer1);
verifyNoMoreInteractions(writer2);
@@ -181,7 +181,7 @@ public class FlatWriterRegistryTest {
final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
addUpdate(updates, DataObject1.class);
addUpdate(updates, DataObject2.class);
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
}
@Test
@@ -191,14 +191,14 @@ public class FlatWriterRegistryTest {
// Writer1 always fails
doThrow(new RuntimeException()).when(writer1)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
addUpdate(updates, DataObject1.class);
addUpdate(updates, DataObject2.class);
try {
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
fail("Bulk update should have failed on writer1");
} catch (WriterRegistry.BulkUpdateException e) {
assertThat(e.getUnrevertedSubtrees(), hasSize(2));
@@ -215,7 +215,7 @@ public class FlatWriterRegistryTest {
// Writer1 always fails
doThrow(new RuntimeException()).when(writer3)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
addUpdate(updates, DataObject1.class);
@@ -226,26 +226,26 @@ public class FlatWriterRegistryTest {
updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, before2, after2));
try {
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
fail("Bulk update should have failed on writer1");
} catch (WriterRegistry.BulkUpdateException e) {
assertThat(e.getUnrevertedSubtrees().size(), is(1));
final InOrder inOrder = inOrder(writer1, writer2, writer3);
inOrder.verify(writer1)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
inOrder.verify(writer2)
- .update(iid2, before2, after2, ctx);
+ .processModification(iid2, before2, after2, ctx);
inOrder.verify(writer3)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
e.revertChanges(revertWriteContext);
// Revert changes. Successful updates are iterated in reverse
// also binding other write context,to verify if update context is not reused
inOrder.verify(writer2)
- .update(iid2, after2, before2, revertWriteContext);
+ .processModification(iid2, after2, before2, revertWriteContext);
inOrder.verify(writer1)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), eq(revertWriteContext));
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), eq(revertWriteContext));
verifyNoMoreInteractions(writer3);
}
}
@@ -258,7 +258,7 @@ public class FlatWriterRegistryTest {
// Writer1 always fails
doThrow(new RuntimeException()).when(writer3)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
addUpdate(updates, DataObject1.class);
@@ -266,12 +266,12 @@ public class FlatWriterRegistryTest {
addUpdate(updates, DataObjects.DataObject3.class);
try {
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
fail("Bulk update should have failed on writer1");
} catch (WriterRegistry.BulkUpdateException e) {
// Writer1 always fails from now
doThrow(new RuntimeException()).when(writer1)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
try {
e.revertChanges(revertWriteContext);
} catch (WriterRegistry.Reverter.RevertFailedException e1) {
@@ -293,19 +293,19 @@ public class FlatWriterRegistryTest {
// Writer1 always fails
doThrow(new RuntimeException()).when(writer1)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class),
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class),
any(WriteContext.class));
final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
addKeyedUpdate(updates,DataObjects.DataObject1ChildK.class);
addUpdate(updates, DataObject1.class);
try {
- flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ flatWriterRegistry.processModifications(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
fail("Bulk update should have failed on writer1");
} catch (WriterRegistry.BulkUpdateException e) {
// Writer1 always fails from now
doThrow(new RuntimeException()).when(writer1)
- .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class),
+ .processModification(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class),
any(WriteContext.class));
try {
e.revertChanges(revertWriteContext);
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriterTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriterTest.java
index ff2f831..65b2f37 100644
--- a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriterTest.java
+++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriterTest.java
@@ -16,15 +16,21 @@
package io.fd.honeycomb.translate.impl.write.registry;
-import static org.hamcrest.CoreMatchers.hasItem;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import com.google.common.collect.Sets;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.translate.impl.write.NoopWriters.DirectUpdateWriterCustomizer;
+import io.fd.honeycomb.translate.impl.write.NoopWriters.NonDirectUpdateWriterCustomizer;
+import io.fd.honeycomb.translate.impl.write.NoopWriters.ParentImplDirectUpdateWriterCustomizer;
import io.fd.honeycomb.translate.util.DataObjects;
import io.fd.honeycomb.translate.write.Writer;
import java.util.Collections;
+import java.util.Set;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Test;
@@ -79,7 +85,28 @@ public class SubtreeWriterTest {
assertEquals(writer.getManagedDataObjectType(), forWriter.getManagedDataObjectType());
assertEquals(1, forWriter.getHandledChildTypes().size());
- assertThat(forWriter.getHandledChildTypes(), CoreMatchers.hasItem(DataObjects.DataObject4.DataObject41.DataObject411.IID));
+ assertThat(forWriter.getHandledChildTypes(),
+ CoreMatchers.hasItem(DataObjects.DataObject4.DataObject41.DataObject411.IID));
+ }
+
+ @Test
+ public void testUpdateSupported() {
+ // test supportsDirectUpdate(), because subtree writer overrides this method and delegate call on delegate writer
+ final InstanceIdentifier<DataObject> fakeIID = InstanceIdentifier.create(DataObject.class);
+ final Set<InstanceIdentifier<?>> handledChildren = Collections.emptySet();
+
+ final NonDirectUpdateWriterCustomizer nonDirectCustomizer = new NonDirectUpdateWriterCustomizer();
+ final DirectUpdateWriterCustomizer directCustomizer = new DirectUpdateWriterCustomizer();
+ final ParentImplDirectUpdateWriterCustomizer parentImplCustomizer =
+ new ParentImplDirectUpdateWriterCustomizer();
+
+ final GenericWriter<DataObject> nonDirectWriter = new GenericWriter<>(fakeIID, nonDirectCustomizer);
+ final GenericWriter<DataObject> directWriter = new GenericWriter<>(fakeIID, directCustomizer);
+ final GenericWriter<DataObject> parentImplWriter = new GenericWriter<>(fakeIID, parentImplCustomizer);
+
+ assertFalse(SubtreeWriter.createForWriter(handledChildren, nonDirectWriter).supportsDirectUpdate());
+ assertTrue(SubtreeWriter.createForWriter(handledChildren, directWriter).supportsDirectUpdate());
+ assertTrue(SubtreeWriter.createForWriter(handledChildren, parentImplWriter).supportsDirectUpdate());
}
} \ No newline at end of file
diff --git a/infra/translate-spi/src/main/java/io/fd/honeycomb/translate/spi/write/WriterCustomizer.java b/infra/translate-spi/src/main/java/io/fd/honeycomb/translate/spi/write/WriterCustomizer.java
index 8148657..308713e 100644
--- a/infra/translate-spi/src/main/java/io/fd/honeycomb/translate/spi/write/WriterCustomizer.java
+++ b/infra/translate-spi/src/main/java/io/fd/honeycomb/translate/spi/write/WriterCustomizer.java
@@ -46,6 +46,8 @@ public interface WriterCustomizer<D extends DataObject> {
/**
* Handle update operation. U from CRUD.
+ * By default, updates will be broken into delete + create.
+ * Override this if there is a direct support for updates on lower level
*
* @param id Identifier(from root) of data being written
* @param dataBefore Old data
@@ -54,10 +56,14 @@ public interface WriterCustomizer<D extends DataObject> {
*
* @throws WriteFailedException if update was unsuccessful
*/
- void updateCurrentAttributes(@Nonnull final InstanceIdentifier<D> id,
- @Nonnull final D dataBefore,
- @Nonnull final D dataAfter,
- @Nonnull final WriteContext writeContext) throws WriteFailedException;
+ default void updateCurrentAttributes(@Nonnull final InstanceIdentifier<D> id,
+ @Nonnull final D dataBefore,
+ @Nonnull final D dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ throw new UnsupportedOperationException(
+ "Default implementation of updateCurrentAttributes should not be invoked." +
+ "Either override this method or do not invoke it directly");
+ }
/**
* Handle delete operation. D from CRUD.
diff --git a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriter.java b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriter.java
index ff2174e..e2ea115 100644
--- a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriter.java
+++ b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriter.java
@@ -18,8 +18,8 @@ package io.fd.honeycomb.translate.util.write;
import static com.google.common.base.Preconditions.checkArgument;
-import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.write.WriteFailedException;
import io.fd.honeycomb.translate.write.Writer;
import javax.annotation.Nonnull;
@@ -34,9 +34,11 @@ public abstract class AbstractGenericWriter<D extends DataObject> implements Wri
private static final Logger LOG = LoggerFactory.getLogger(AbstractGenericWriter.class);
private final InstanceIdentifier<D> instanceIdentifier;
+ private final boolean supportsUpdate;
- protected AbstractGenericWriter(final InstanceIdentifier<D> type) {
+ protected AbstractGenericWriter(final InstanceIdentifier<D> type, final boolean supportsUpdate) {
this.instanceIdentifier = RWUtils.makeIidWildcarded(type);
+ this.supportsUpdate = supportsUpdate;
}
protected void writeCurrent(final InstanceIdentifier<D> id, final D data, final WriteContext ctx)
@@ -67,10 +69,10 @@ public abstract class AbstractGenericWriter<D extends DataObject> implements Wri
@SuppressWarnings("unchecked")
@Override
- public void update(@Nonnull final InstanceIdentifier<? extends DataObject> id,
- @Nullable final DataObject dataBefore,
- @Nullable final DataObject dataAfter,
- @Nonnull final WriteContext ctx) throws WriteFailedException {
+ public void processModification(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+ @Nullable final DataObject dataBefore,
+ @Nullable final DataObject dataAfter,
+ @Nonnull final WriteContext ctx) throws WriteFailedException {
LOG.debug("{}: Updating : {}", this, id);
LOG.trace("{}: Updating : {}, from: {} to: {}", this, id, dataBefore, dataAfter);
@@ -134,4 +136,9 @@ public abstract class AbstractGenericWriter<D extends DataObject> implements Wri
public String toString() {
return String.format("Writer[%s]", getManagedDataObjectType().getTargetType().getSimpleName());
}
+
+ @Override
+ public boolean supportsDirectUpdate() {
+ return supportsUpdate;
+ }
}
diff --git a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriter.java b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriter.java
index f06e6ae..7b68376 100644
--- a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriter.java
+++ b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriter.java
@@ -49,9 +49,9 @@ public final class BindingBrokerWriter<D extends DataObject> implements Writer<D
}
@Override
- public void update(@Nonnull final InstanceIdentifier<? extends DataObject> id,
- @Nullable final DataObject dataBefore, @Nullable final DataObject dataAfter,
- @Nonnull final WriteContext ctx) throws WriteFailedException {
+ public void processModification(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+ @Nullable final DataObject dataBefore, @Nullable final DataObject dataAfter,
+ @Nonnull final WriteContext ctx) throws WriteFailedException {
final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
writeTransaction.put(CONFIGURATION, (InstanceIdentifier<DataObject>) id, dataAfter);
final CheckedFuture<Void, TransactionCommitFailedException> result = writeTransaction.submit();
@@ -61,4 +61,9 @@ public final class BindingBrokerWriter<D extends DataObject> implements Writer<D
throw new WriteFailedException(id, e);
}
}
+
+ @Override
+ public boolean supportsDirectUpdate() {
+ return false;
+ }
}
diff --git a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistry.java b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistry.java
index 8f15c6f..13ae12f 100644
--- a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistry.java
+++ b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistry.java
@@ -20,6 +20,7 @@ import io.fd.honeycomb.translate.TranslationException;
import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.write.registry.WriterRegistry;
import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
* Empty registry that does not perform any changes. Can be used in data layer, if we want to disable passing data to
@@ -28,12 +29,18 @@ import javax.annotation.Nonnull;
public class NoopWriterRegistry implements WriterRegistry, AutoCloseable {
@Override
- public void update(@Nonnull final DataObjectUpdates updates,
- @Nonnull final WriteContext ctx) throws TranslationException {
+ public void processModifications(@Nonnull final DataObjectUpdates updates,
+ @Nonnull final WriteContext ctx) throws TranslationException {
// NOOP
}
@Override
+ public boolean writerSupportsUpdate(@Nonnull final InstanceIdentifier<?> type) {
+ // returns true to make higher level performance better(does not have to break updates to delete+create pairs)
+ return true;
+ }
+
+ @Override
public void close() throws Exception {
// NOOP
}
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriterTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriterTest.java
index 14c9c60..9b95f76 100644
--- a/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriterTest.java
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/AbstractGenericWriterTest.java
@@ -51,7 +51,7 @@ public class AbstractGenericWriterTest {
@Test
public void testDelete() throws Exception {
before = mock(DataObject.class);
- t.update(id, before, null, ctx);
+ t.processModification(id, before, null, ctx);
verify(t).deleteCurrentAttributes(id, before, ctx);
}
@@ -59,7 +59,7 @@ public class AbstractGenericWriterTest {
@Test
public void testUpdate() throws Exception {
before = mock(DataObject.class);
- t.update(id, before, after, ctx);
+ t.processModification(id, before, after, ctx);
verify(t).updateCurrentAttributes(id, before, after, ctx);
}
@@ -67,7 +67,7 @@ public class AbstractGenericWriterTest {
@Test
public void testNoUpdate() throws Exception {
before = mock(DataObject.class);
- t.update(id, before, before, ctx);
+ t.processModification(id, before, before, ctx);
verify(t, times(0)).updateCurrentAttributes(id, before, after, ctx);
}
@@ -75,7 +75,7 @@ public class AbstractGenericWriterTest {
@Test
public void testCreate() throws Exception {
before = mock(DataObject.class);
- t.update(id, null, after, ctx);
+ t.processModification(id, null, after, ctx);
verify(t).writeCurrentAttributes(id, after, ctx);
}
@@ -83,7 +83,7 @@ public class AbstractGenericWriterTest {
private static class TestingWriter extends AbstractGenericWriter<DataObject> {
TestingWriter() {
- super(InstanceIdentifier.create(DataObject.class));
+ super(InstanceIdentifier.create(DataObject.class), false);
}
@Override
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriterTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriterTest.java
index 84dbb7b..9e09112 100644
--- a/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriterTest.java
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/BindingBrokerWriterTest.java
@@ -58,7 +58,7 @@ public class BindingBrokerWriterTest {
public void testWrite() throws Exception {
assertEquals(id, bbWriter.getManagedDataObjectType());
- bbWriter.update(id, data, data, ctx);
+ bbWriter.processModification(id, data, data, ctx);
verify(broker).newWriteOnlyTransaction();
verify(tx).put(LogicalDatastoreType.CONFIGURATION, id, data);
verify(tx).submit();
@@ -67,6 +67,6 @@ public class BindingBrokerWriterTest {
@Test(expected = io.fd.honeycomb.translate.write.WriteFailedException.class)
public void testFailedWrite() throws Exception {
when(tx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("failing")));
- bbWriter.update(id, data, data, ctx);
+ bbWriter.processModification(id, data, data, ctx);
}
} \ No newline at end of file
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistryTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistryTest.java
index 411f24b..642e9f8 100644
--- a/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistryTest.java
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/write/NoopWriterRegistryTest.java
@@ -23,7 +23,7 @@ public class NoopWriterRegistryTest {
@Test
public void testNoop() throws Exception {
final NoopWriterRegistry noopWriterRegistry = new NoopWriterRegistry();
- noopWriterRegistry.update(null, null);
+ noopWriterRegistry.processModifications(null, null);
noopWriterRegistry.close();
}
} \ No newline at end of file
diff --git a/samples/interfaces/mapping/src/main/java/io/fd/honeycomb/samples/interfaces/mapping/config/InterfaceWriterCustomizer.java b/samples/interfaces/mapping/src/main/java/io/fd/honeycomb/samples/interfaces/mapping/config/InterfaceWriterCustomizer.java
index af185d8..01d2900 100644
--- a/samples/interfaces/mapping/src/main/java/io/fd/honeycomb/samples/interfaces/mapping/config/InterfaceWriterCustomizer.java
+++ b/samples/interfaces/mapping/src/main/java/io/fd/honeycomb/samples/interfaces/mapping/config/InterfaceWriterCustomizer.java
@@ -54,15 +54,15 @@ public class InterfaceWriterCustomizer implements ListWriterCustomizer<Interface
}
}
+ /*
+ * For nodes that does not have support for update operation directly, there's no need to override
+ * updateCurrentAttributes method. Updates will be handlers as combination of delete + create. If you want to
+ * implement update directly, override method updateCurrentAttributes
@Override
public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,
@Nonnull final Interface dataBefore, @Nonnull final Interface dataAfter,
@Nonnull final WriteContext writeContext) throws WriteFailedException {
- // There are cases when lower layer does not support all of the CRUD operations, in which case, the handler
- // should look like this (This will reject configuration from upper layers, returning error/rpc-error):
- throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter,
- new UnsupportedOperationException("Unable to update interface data, unsupported at lower layer"));
- }
+ }*/
@Override
public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,