summaryrefslogtreecommitdiffstats
path: root/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w
diff options
context:
space:
mode:
Diffstat (limited to 'v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w')
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/ChildVppWriter.java33
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java22
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriteContext.java32
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java64
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/AbstractCompositeVppWriter.java146
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeChildVppWriter.java4
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeListVppWriter.java56
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeRootVppWriter.java10
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ChildVppWriterCustomizer.java11
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ListVppWriterCustomizer.java12
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/RootVppWriterCustomizer.java27
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java130
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/NoopWriterCustomizer.java4
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java26
14 files changed, 426 insertions, 151 deletions
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/ChildVppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/ChildVppWriter.java
index 93c1092b6..243a6528d 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/ChildVppWriter.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/ChildVppWriter.java
@@ -21,19 +21,46 @@ import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Child VPP writer allowing its parent to pass the builder object
+ *
+ * @param <C> Specific DataObject derived type, that is handled by this writer
+ */
@Beta
public interface ChildVppWriter<D extends DataObject> extends VppWriter<D> {
+ /**
+ * Extract data object managed by this writer from parent data and perform write.
+ *
+ * @param parentId Id of parent node
+ * @param parentDataAfter Parent data from modification to extract data object from
+ * @param ctx Write context for current modification
+ */
void writeChild(@Nonnull final InstanceIdentifier<? extends DataObject> parentId,
@Nonnull final DataObject parentDataAfter,
- @Nonnull WriteContext ctx);
+ @Nonnull final WriteContext ctx);
+ /**
+ * Extract data object managed by this writer(if necessary) from parent data and perform delete.
+ *
+ * @param parentId Id of parent node
+ * @param parentDataBefore Parent data before modification to extract data object from
+ * @param ctx Write context for current modification
+ */
void deleteChild(@Nonnull final InstanceIdentifier<? extends DataObject> parentId,
@Nonnull final DataObject parentDataBefore,
- @Nonnull WriteContext ctx);
+ @Nonnull final WriteContext ctx);
+ /**
+ * Extract data object managed by this writer(if necessary) from parent data and perform delete.
+ *
+ * @param parentId Id of parent node
+ * @param parentDataBefore Parent data before modification to extract data object from
+ * @param parentDataAfter Parent data from modification to extract data object from
+ * @param ctx Write context for current modification
+ */
void updateChild(@Nonnull final InstanceIdentifier<? extends DataObject> parentId,
@Nonnull final DataObject parentDataBefore,
@Nonnull final DataObject parentDataAfter,
- @Nonnull WriteContext ctx);
+ @Nonnull final WriteContext ctx);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java
index 617e11cc1..f8a49a271 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java
@@ -18,16 +18,30 @@ package io.fd.honeycomb.v3po.impl.trans.w;
import com.google.common.annotations.Beta;
import io.fd.honeycomb.v3po.impl.trans.SubtreeManager;
-import java.util.List;
+import io.fd.honeycomb.v3po.impl.trans.VppException;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Base VPP writer, responsible for translation between DataObjects and VPP APIs. Handling all update operations(create, update, delete)
+ *
+ * @param <D> Specific DataObject derived type, that is handled by this writer
+ */
@Beta
public interface VppWriter<D extends DataObject> extends SubtreeManager<D> {
+ /**
+ * Handle update operation. U from CRUD.
+ *
+ * @param id Identifier(from root) of data being written
+ * @param dataBefore Old data
+ * @param dataAfter New, updated data
+ * @param ctx Write context enabling writer to get information about candidate data as well as current data
+ */
void update(@Nonnull final InstanceIdentifier<? extends DataObject> id,
- @Nonnull final List<? extends DataObject> dataBefore,
- @Nonnull final List<? extends DataObject> data,
- @Nonnull final WriteContext ctx);
+ @Nullable final DataObject dataBefore,
+ @Nullable final DataObject dataAfter,
+ @Nonnull final WriteContext ctx) throws VppException;
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriteContext.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriteContext.java
index 49759f20f..3aaf83250 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriteContext.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriteContext.java
@@ -16,16 +16,42 @@
package io.fd.honeycomb.v3po.impl.trans.w;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
import io.fd.honeycomb.v3po.impl.trans.util.Context;
-import java.util.List;
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Context providing information about current state of DataTree to writers
+ */
+@Beta
public interface WriteContext {
- List<? extends DataObject> readBefore(InstanceIdentifier<? extends DataObject> currentId);
+ /**
+ * Read any data object before current modification was applied
+ *
+ * @param currentId Id of an object to read
+ *
+ * @return Data before the modification was applied
+ */
+ Optional<DataObject> readBefore(@Nonnull final InstanceIdentifier<? extends DataObject> currentId);
- List<? extends DataObject> readAfter(InstanceIdentifier<? extends DataObject> currentId);
+ /**
+ * Read any data object from current modification
+ *
+ * @param currentId Id of an object to read
+ *
+ * @return Data from the modification
+ */
+ Optional<DataObject> readAfter(@Nonnull final InstanceIdentifier<? extends DataObject> currentId);
+ /**
+ * Get key value storage for customizers
+ *
+ * @return Context for customizers
+ */
+ @Nonnull
Context getContext();
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java
new file mode 100644
index 000000000..4b09ff29e
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 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.v3po.impl.trans.w;
+
+import com.google.common.annotations.Beta;
+import io.fd.honeycomb.v3po.impl.trans.VppException;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Special {@link VppWriter} capable of performing bulk updates
+ */
+@Beta
+public interface WriterRegistry extends VppWriter<DataObject> {
+
+ /**
+ * Performs bulk update
+ *
+ * @throws BulkUpdateException in case bulk update fails
+ */
+ void update(@Nonnull final Map<InstanceIdentifier<?>, DataObject> dataBefore,
+ @Nonnull final Map<InstanceIdentifier<?>, DataObject> dataAfter,
+ @Nonnull final WriteContext ctx) throws VppException, BulkUpdateException;
+
+ @Beta
+ public class BulkUpdateException extends VppException {
+
+ private final Revert runnable;
+
+ public BulkUpdateException(final InstanceIdentifier<?> id, final RuntimeException e, final Revert runnable) {
+ super("Bulk edit failed at " + id, e);
+ this.runnable = runnable;
+ }
+
+ public void revertChanges() throws VppException {
+ runnable.revert();
+ }
+ }
+
+ /**
+ * Abstraction over revert mechanism in cast of a bulk update failure
+ */
+ @Beta
+ public interface Revert {
+
+ public void revert() throws VppException;
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/AbstractCompositeVppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/AbstractCompositeVppWriter.java
index 44690bd28..6e8f8bc85 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/AbstractCompositeVppWriter.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/AbstractCompositeVppWriter.java
@@ -18,10 +18,9 @@ package io.fd.honeycomb.v3po.impl.trans.w.impl;
import static com.google.common.base.Preconditions.checkArgument;
-import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import io.fd.honeycomb.v3po.impl.trans.VppException;
import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import io.fd.honeycomb.v3po.impl.trans.w.ChildVppWriter;
import io.fd.honeycomb.v3po.impl.trans.w.VppWriter;
@@ -32,10 +31,10 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,25 +43,16 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
private static final Logger LOG = LoggerFactory.getLogger(AbstractCompositeVppWriter.class);
- public static final Function<DataObject, Object> INDEX_FUNCTION = new Function<DataObject, Object>() {
- @Override
- public Object apply(final DataObject input) {
- return input instanceof Identifiable<?>
- ? ((Identifiable<?>) input).getKey()
- : input;
- }
- };
-
- private final Map<Class<? extends DataObject>, ChildVppWriter<? extends ChildOf<D>>> childReaders;
- private final Map<Class<? extends DataObject>, ChildVppWriter<? extends Augmentation<D>>> augReaders;
+ private final Map<Class<? extends DataObject>, ChildVppWriter<? extends ChildOf<D>>> childWriters;
+ private final Map<Class<? extends DataObject>, ChildVppWriter<? extends Augmentation<D>>> augWriters;
private final InstanceIdentifier<D> instanceIdentifier;
public AbstractCompositeVppWriter(final Class<D> type,
- final List<ChildVppWriter<? extends ChildOf<D>>> childReaders,
- final List<ChildVppWriter<? extends Augmentation<D>>> augReaders) {
+ final List<ChildVppWriter<? extends ChildOf<D>>> childWriters,
+ final List<ChildVppWriter<? extends Augmentation<D>>> augWriters) {
this.instanceIdentifier = InstanceIdentifier.create(type);
- this.childReaders = VppRWUtils.uniqueLinkedIndex(childReaders, VppRWUtils.MANAGER_CLASS_FUNCTION);
- this.augReaders = VppRWUtils.uniqueLinkedIndex(augReaders, VppRWUtils.MANAGER_CLASS_AUG_FUNCTION);
+ this.childWriters = VppRWUtils.uniqueLinkedIndex(childWriters, VppRWUtils.MANAGER_CLASS_FUNCTION);
+ this.augWriters = VppRWUtils.uniqueLinkedIndex(augWriters, VppRWUtils.MANAGER_CLASS_AUG_FUNCTION);
}
protected void writeCurrent(final InstanceIdentifier<D> id, final D data, final WriteContext ctx) {
@@ -71,12 +61,12 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
LOG.trace("{}: Writing current attributes", this);
writeCurrentAttributes(id, data, ctx);
- for (ChildVppWriter<? extends ChildOf<D>> child : childReaders.values()) {
+ for (ChildVppWriter<? extends ChildOf<D>> child : childWriters.values()) {
LOG.debug("{}: Writing child in: {}", this, child);
child.writeChild(id, data, ctx);
}
- for (ChildVppWriter<? extends Augmentation<D>> child : augReaders.values()) {
+ for (ChildVppWriter<? extends Augmentation<D>> child : augWriters.values()) {
LOG.debug("{}: Writing augment in: {}", this, child);
child.writeChild(id, data, ctx);
}
@@ -97,12 +87,12 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
LOG.trace("{}: Updating current attributes", this);
updateCurrentAttributes(id, dataBefore, dataAfter, ctx);
- for (ChildVppWriter<? extends ChildOf<D>> child : childReaders.values()) {
+ for (ChildVppWriter<? extends ChildOf<D>> child : childWriters.values()) {
LOG.debug("{}: Updating child in: {}", this, child);
child.updateChild(id, dataBefore, dataAfter, ctx);
}
- for (ChildVppWriter<? extends Augmentation<D>> child : augReaders.values()) {
+ for (ChildVppWriter<? extends Augmentation<D>> child : augWriters.values()) {
LOG.debug("{}: Updating augment in: {}", this, child);
child.updateChild(id, dataBefore, dataAfter, ctx);
}
@@ -114,12 +104,12 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
LOG.debug("{}: Deleting current: {} dataBefore: {}", this, id, dataBefore);
// delete in reversed order
- for (ChildVppWriter<? extends Augmentation<D>> child : reverseCollection(augReaders.values())) {
+ for (ChildVppWriter<? extends Augmentation<D>> child : reverseCollection(augWriters.values())) {
LOG.debug("{}: Deleting augment in: {}", this, child);
child.deleteChild(id, dataBefore, ctx);
}
- for (ChildVppWriter<? extends ChildOf<D>> child : reverseCollection(childReaders.values())) {
+ for (ChildVppWriter<? extends ChildOf<D>> child : reverseCollection(childWriters.values())) {
LOG.debug("{}: Deleting child in: {}", this, child);
child.deleteChild(id, dataBefore, ctx);
}
@@ -131,20 +121,20 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
@SuppressWarnings("unchecked")
@Override
public void update(@Nonnull final InstanceIdentifier<? extends DataObject> id,
- @Nonnull final List<? extends DataObject> dataBefore,
- @Nonnull final List<? extends DataObject> dataAfter,
- @Nonnull final WriteContext ctx) {
+ @Nullable final DataObject dataBefore,
+ @Nullable final DataObject dataAfter,
+ @Nonnull final WriteContext ctx) throws VppException {
LOG.debug("{}: Updating : {}", this, id);
LOG.trace("{}: Updating : {}, from: {} to: {}", this, id, dataBefore, dataAfter);
if (idPointsToCurrent(id)) {
if(isWrite(dataBefore, dataAfter)) {
- writeAll((InstanceIdentifier<D>) id, dataAfter, ctx);
+ writeCurrent((InstanceIdentifier<D>) id, castToManaged(dataAfter), ctx);
} else if(isDelete(dataBefore, dataAfter)) {
- deleteAll((InstanceIdentifier<D>) id, dataBefore, ctx);
+ deleteCurrent((InstanceIdentifier<D>) id, castToManaged(dataBefore), ctx);
} else {
- checkArgument(!dataBefore.isEmpty() && !dataAfter.isEmpty(), "No data to process");
- updateAll((InstanceIdentifier<D>) id, dataBefore, dataAfter, ctx);
+ checkArgument(dataBefore != null && dataAfter != null, "No data to process");
+ updateCurrent((InstanceIdentifier<D>) id, castToManaged(dataBefore), castToManaged(dataAfter), ctx);
}
} else {
if (isWrite(dataBefore, dataAfter)) {
@@ -152,89 +142,47 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
} else if (isDelete(dataBefore, dataAfter)) {
deleteSubtree(id, dataBefore, ctx);
} else {
- checkArgument(!dataBefore.isEmpty() && !dataAfter.isEmpty(), "No data to process");
+ checkArgument(dataBefore != null && dataAfter != null, "No data to process");
updateSubtree(id, dataBefore, dataAfter, ctx);
}
}
}
- protected void updateAll(final @Nonnull InstanceIdentifier<D> id,
- final @Nonnull List<? extends DataObject> dataBefore,
- final @Nonnull List<? extends DataObject> dataAfter, final WriteContext ctx) {
- LOG.trace("{}: Updating all : {}", this, id);
-
- final Map<Object, ? extends DataObject> indexedAfter = indexData(dataAfter);
- final Map<Object, ? extends DataObject> indexedBefore = indexData(dataBefore);
-
- for (Map.Entry<Object, ? extends DataObject> after : indexedAfter.entrySet()) {
- final DataObject before = indexedBefore.get(after.getKey());
- if(before == null) {
- writeCurrent(id, castToManaged(after.getValue()), ctx);
- } else {
- updateCurrent(id, castToManaged(before), castToManaged(after.getValue()), ctx);
- }
- }
-
- // Delete the rest in dataBefore
- for (Object deletedNodeKey : Sets.difference(indexedBefore.keySet(), indexedAfter.keySet())) {
- final DataObject deleted = indexedBefore.get(deletedNodeKey);
- deleteCurrent(id, castToManaged(deleted), ctx);
- }
- }
-
- private static Map<Object, ? extends DataObject> indexData(final List<? extends DataObject> data) {
- return Maps.uniqueIndex(data, INDEX_FUNCTION);
- }
-
- protected void deleteAll(final @Nonnull InstanceIdentifier<D> id,
- final @Nonnull List<? extends DataObject> dataBefore, final WriteContext ctx) {
- LOG.trace("{}: Deleting all : {}", this, id);
- for (DataObject singleValue : dataBefore) {
- checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(singleValue.getClass()));
- deleteCurrent(id, castToManaged(singleValue), ctx);
- }
+ private void checkDataType(final @Nullable DataObject dataAfter) {
+ checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(dataAfter.getClass()));
}
private D castToManaged(final DataObject data) {
- checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(data.getClass()));
+ checkDataType(data);
return getManagedDataObjectType().getTargetType().cast(data);
}
- protected void writeAll(final @Nonnull InstanceIdentifier<D> id,
- final @Nonnull List<? extends DataObject> dataAfter, final WriteContext ctx) {
- LOG.trace("{}: Writing all : {}", this, id);
- for (DataObject singleValue : dataAfter) {
- checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(singleValue.getClass()));
- writeCurrent(id, castToManaged(singleValue), ctx);
- }
- }
-
- private static boolean isWrite(final List<? extends DataObject> dataBefore,
- final List<? extends DataObject> dataAfter) {
- return dataBefore.isEmpty() && !dataAfter.isEmpty();
+ private static boolean isWrite(final DataObject dataBefore,
+ final DataObject dataAfter) {
+ return dataBefore == null && dataAfter != null;
}
- private static boolean isDelete(final List<? extends DataObject> dataBefore,
- final List<? extends DataObject> dataAfter) {
- return dataAfter.isEmpty() && !dataBefore.isEmpty();
+ private static boolean isDelete(final DataObject dataBefore,
+ final DataObject dataAfter) {
+ return dataAfter == null && dataBefore != null;
}
private void writeSubtree(final InstanceIdentifier<? extends DataObject> id,
- final List<? extends DataObject> dataAfter, final WriteContext ctx) {
+ final DataObject dataAfter, final WriteContext ctx) throws VppException {
LOG.debug("{}: Writing subtree: {}", this, id);
final VppWriter<? extends ChildOf<D>> vppWriter = getNextWriter(id);
if (vppWriter != null) {
LOG.debug("{}: Writing subtree: {} in: {}", this, id, vppWriter);
- vppWriter.update(id, Collections.<DataObject>emptyList(), dataAfter, ctx);
+ vppWriter.update(id, null, dataAfter, ctx);
} else {
// If there's no dedicated writer, use write current
// But we need current data after to do so
final InstanceIdentifier<D> currentId = VppRWUtils.cutId(id, getManagedDataObjectType());
- List<? extends DataObject> currentDataAfter = ctx.readAfter(currentId);
+ Optional<DataObject> currentDataAfter = ctx.readAfter(currentId);
LOG.debug("{}: Dedicated subtree writer missing for: {}. Writing current.", this,
VppRWUtils.getNextId(id, getManagedDataObjectType()).getType(), currentDataAfter);
- writeAll(currentId, currentDataAfter, ctx);
+ writeCurrent(currentId, castToManaged(currentDataAfter.get()), ctx);
}
}
@@ -244,32 +192,34 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
@SuppressWarnings("unchecked")
private void deleteSubtree(final InstanceIdentifier<? extends DataObject> id,
- final List<? extends DataObject> dataBefore, final WriteContext ctx) {
+ final DataObject dataBefore, final WriteContext ctx) throws VppException {
LOG.debug("{}: Deleting subtree: {}", this, id);
final VppWriter<? extends ChildOf<D>> vppWriter = getNextWriter(id);
if (vppWriter != null) {
LOG.debug("{}: Deleting subtree: {} in: {}", this, id, vppWriter);
- vppWriter.update(id, dataBefore, Collections.<DataObject>emptyList(), ctx);
+ vppWriter.update(id, dataBefore, null, ctx);
} else {
updateSubtreeFromCurrent(id, ctx);
}
}
+ @SuppressWarnings("unchecked")
private void updateSubtreeFromCurrent(final InstanceIdentifier<? extends DataObject> id, final WriteContext ctx) {
final InstanceIdentifier<D> currentId = VppRWUtils.cutId(id, getManagedDataObjectType());
- List<? extends DataObject> currentDataBefore = ctx.readBefore(currentId);
- List<? extends DataObject> currentDataAfter = ctx.readAfter(currentId);
+ Optional<DataObject> currentDataBefore = ctx.readBefore(currentId);
+ Optional<DataObject> currentDataAfter = ctx.readAfter(currentId);
LOG.debug("{}: Dedicated subtree writer missing for: {}. Updating current without subtree", this,
VppRWUtils.getNextId(id, getManagedDataObjectType()).getType(), currentDataAfter);
- updateAll((InstanceIdentifier<D>) id, currentDataBefore, currentDataAfter, ctx);
+ updateCurrent((InstanceIdentifier<D>) id, castToManaged(currentDataBefore.orNull()),
+ castToManaged(currentDataAfter.orNull()), ctx);
}
@SuppressWarnings("unchecked")
private void updateSubtree(final InstanceIdentifier<? extends DataObject> id,
- final List<? extends DataObject> dataBefore,
- final List<? extends DataObject> dataAfter,
- final WriteContext ctx) {
+ final DataObject dataBefore,
+ final DataObject dataAfter,
+ final WriteContext ctx) throws VppException {
LOG.debug("{}: Updating subtree: {}", this, id);
final VppWriter<? extends ChildOf<D>> vppWriter = getNextWriter(id);
@@ -283,11 +233,11 @@ public abstract class AbstractCompositeVppWriter<D extends DataObject> implement
private VppWriter<? extends ChildOf<D>> getNextWriter(final InstanceIdentifier<? extends DataObject> id) {
final Class<? extends DataObject> next = VppRWUtils.getNextId(id, getManagedDataObjectType()).getType();
- return childReaders.get(next);
+ return childWriters.get(next);
}
private static <T> List<T> reverseCollection(final Collection<T> original) {
- // TODO find a better reverse mechanism (probably a different collection for child readers is necessary)
+ // TODO find a better reverse mechanism (probably a different collection for child writers is necessary)
final ArrayList<T> list = Lists.newArrayList(original);
Collections.reverse(list);
return list;
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeChildVppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeChildVppWriter.java
index 919bbaa0f..d94e4fedf 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeChildVppWriter.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeChildVppWriter.java
@@ -35,9 +35,9 @@ public class CompositeChildVppWriter<D extends DataObject> extends AbstractCompo
public CompositeChildVppWriter(@Nonnull final Class<D> type,
@Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childWriters,
- @Nonnull final List<ChildVppWriter<? extends Augmentation<D>>> augReaders,
+ @Nonnull final List<ChildVppWriter<? extends Augmentation<D>>> augWriters,
@Nonnull final ChildVppWriterCustomizer<D> customizer) {
- super(type, childWriters, augReaders);
+ super(type, childWriters, augWriters);
this.customizer = customizer;
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeListVppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeListVppWriter.java
index 8914d3757..1722b4652 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeListVppWriter.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeListVppWriter.java
@@ -16,11 +16,16 @@
package io.fd.honeycomb.v3po.impl.trans.w.impl;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import io.fd.honeycomb.v3po.impl.trans.w.ChildVppWriter;
import io.fd.honeycomb.v3po.impl.trans.w.WriteContext;
import io.fd.honeycomb.v3po.impl.trans.w.impl.spi.ListVppWriterCustomizer;
import java.util.List;
+import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.ChildOf;
@@ -32,20 +37,30 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public class CompositeListVppWriter<D extends DataObject & Identifiable<K>, K extends Identifier<D>> extends AbstractCompositeVppWriter<D>
implements ChildVppWriter<D> {
+ public static final Function<DataObject, Object> INDEX_FUNCTION = new Function<DataObject, Object>() {
+ @Override
+ public Object apply(final DataObject input) {
+ return input instanceof Identifiable<?>
+ ? ((Identifiable<?>) input).getKey()
+ : input;
+ }
+ };
+
+
private final ListVppWriterCustomizer<D, K> customizer;
public CompositeListVppWriter(@Nonnull final Class<D> type,
- @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childReaders,
- @Nonnull final List<ChildVppWriter<? extends Augmentation<D>>> augReaders,
+ @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childWriters,
+ @Nonnull final List<ChildVppWriter<? extends Augmentation<D>>> augWriters,
@Nonnull final ListVppWriterCustomizer<D, K> customizer) {
- super(type, childReaders, augReaders);
+ super(type, childWriters, augWriters);
this.customizer = customizer;
}
public CompositeListVppWriter(@Nonnull final Class<D> type,
- @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childReaders,
+ @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childWriters,
@Nonnull final ListVppWriterCustomizer<D, K> customizer) {
- this(type, childReaders, VppRWUtils.<D>emptyAugWriterList(), customizer);
+ this(type, childWriters, VppRWUtils.<D>emptyAugWriterList(), customizer);
}
public CompositeListVppWriter(@Nonnull final Class<D> type,
@@ -78,7 +93,9 @@ public class CompositeListVppWriter<D extends DataObject & Identifiable<K>, K ex
@Nonnull final WriteContext ctx) {
final InstanceIdentifier<D> currentId = VppRWUtils.appendTypeToId(parentId, getManagedDataObjectType());
final List<D> currentData = customizer.extract(currentId, parentData);
- writeAll(currentId, currentData, ctx);
+ for (D entry : currentData) {
+ writeCurrent(currentId, entry, ctx);
+ }
}
@Override
@@ -87,7 +104,9 @@ public class CompositeListVppWriter<D extends DataObject & Identifiable<K>, K ex
@Nonnull final WriteContext ctx) {
final InstanceIdentifier<D> currentId = VppRWUtils.appendTypeToId(parentId, getManagedDataObjectType());
final List<D> dataBefore = customizer.extract(currentId, parentDataBefore);
- deleteAll(currentId, dataBefore, ctx);
+ for (D entry : dataBefore) {
+ deleteCurrent(currentId, entry, ctx);
+ }
}
@Override
@@ -95,9 +114,26 @@ public class CompositeListVppWriter<D extends DataObject & Identifiable<K>, K ex
@Nonnull final DataObject parentDataBefore, @Nonnull final DataObject parentDataAfter,
@Nonnull final WriteContext ctx) {
final InstanceIdentifier<D> currentId = VppRWUtils.appendTypeToId(parentId, getManagedDataObjectType());
- final List<D> dataBefore = customizer.extract(currentId, parentDataBefore);
- final List<D> dataAfter = customizer.extract(currentId, parentDataAfter);
- updateAll(currentId, dataBefore, dataAfter, ctx);
+ final ImmutableMap<Object, D>
+ dataBefore = Maps.uniqueIndex(customizer.extract(currentId, parentDataBefore), INDEX_FUNCTION);
+ final ImmutableMap<Object, D>
+ dataAfter = Maps.uniqueIndex(customizer.extract(currentId, parentDataAfter), INDEX_FUNCTION);
+
+ for (Map.Entry<Object, D> after : dataAfter.entrySet()) {
+ final D before = dataBefore.get(after.getKey());
+ if(before == null) {
+ writeCurrent(currentId, after.getValue(), ctx);
+ } else {
+ updateCurrent(currentId, before, after.getValue(), ctx);
+ }
+ }
+
+ // Delete the rest in dataBefore
+ for (Object deletedNodeKey : Sets.difference(dataBefore.keySet(), dataAfter.keySet())) {
+ final D deleted = dataBefore.get(deletedNodeKey);
+ deleteCurrent(currentId, deleted, ctx);
+ }
+
}
@Override
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeRootVppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeRootVppWriter.java
index 6be5651b3..a7139e57a 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeRootVppWriter.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/CompositeRootVppWriter.java
@@ -32,17 +32,17 @@ public class CompositeRootVppWriter<D extends DataObject> extends AbstractCompos
private final RootVppWriterCustomizer<D> customizer;
public CompositeRootVppWriter(@Nonnull final Class<D> type,
- @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childReaders,
- @Nonnull final List<ChildVppWriter<? extends Augmentation<D>>> augReaders,
+ @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childWriters,
+ @Nonnull final List<ChildVppWriter<? extends Augmentation<D>>> augWriters,
@Nonnull final RootVppWriterCustomizer<D> customizer) {
- super(type, childReaders, augReaders);
+ super(type, childWriters, augWriters);
this.customizer = customizer;
}
public CompositeRootVppWriter(@Nonnull final Class<D> type,
- @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childReaders,
+ @Nonnull final List<ChildVppWriter<? extends ChildOf<D>>> childWriters,
@Nonnull final RootVppWriterCustomizer<D> customizer) {
- this(type, childReaders, VppRWUtils.<D>emptyAugWriterList(), customizer);
+ this(type, childWriters, VppRWUtils.<D>emptyAugWriterList(), customizer);
}
public CompositeRootVppWriter(@Nonnull final Class<D> type,
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ChildVppWriterCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ChildVppWriterCustomizer.java
index 5ea504209..1e79c6830 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ChildVppWriterCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ChildVppWriterCustomizer.java
@@ -22,9 +22,20 @@ import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * {@link io.fd.honeycomb.v3po.impl.trans.w.impl.CompositeChildVppWriter} SPI to customize its behavior
+ *
+ * @param <D> Specific DataObject derived type (Identifiable), that is handled by this customizer
+ */
@Beta
public interface ChildVppWriterCustomizer<D extends DataObject> extends RootVppWriterCustomizer<D> {
+ /**
+ * Get child of parentData identified by currentId
+ *
+ * @param currentId Identifier(from root) of data being extracted
+ * @param parentData Parent data object from which managed data object must be extracted
+ */
@Nonnull
Optional<D> extract(@Nonnull final InstanceIdentifier<D> currentId, @Nonnull final DataObject parentData);
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ListVppWriterCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ListVppWriterCustomizer.java
index edd8de930..6e72fc719 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ListVppWriterCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/ListVppWriterCustomizer.java
@@ -24,9 +24,21 @@ import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * {@link io.fd.honeycomb.v3po.impl.trans.w.impl.CompositeListVppWriter} SPI to customize its behavior
+ *
+ * @param <C> Specific DataObject derived type (Identifiable), that is handled by this customizer
+ * @param <K> Specific Identifier for handled type (C)
+ */
@Beta
public interface ListVppWriterCustomizer<C extends DataObject & Identifiable<K>, K extends Identifier<C>> extends RootVppWriterCustomizer<C> {
+ /**
+ * Get children of parentData identified by currentId
+ *
+ * @param currentId Identifier(from root) of data being extracted
+ * @param parentData Parent data object from which managed data object must be extracted
+ */
@Nonnull
List<C> extract(@Nonnull final InstanceIdentifier<C> currentId, @Nonnull final DataObject parentData);
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/RootVppWriterCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/RootVppWriterCustomizer.java
index 6a2d0c2bf..0fa89d2af 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/RootVppWriterCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/impl/spi/RootVppWriterCustomizer.java
@@ -22,18 +22,45 @@ import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * {@link io.fd.honeycomb.v3po.impl.trans.w.impl.CompositeRootVppWriter} SPI to customize its behavior
+ *
+ * @param <D> Specific DataObject derived type, that is handled by this customizer
+ */
@Beta
public interface RootVppWriterCustomizer<D extends DataObject> {
+ /**
+ * Handle write operation. C from CRUD.
+ *
+ * @param id Identifier(from root) of data being written
+ * @param dataAfter New data to be written
+ * @param writeContext Write context can be used to store any useful information and then utilized by other customizers
+ */
void writeCurrentAttributes(@Nonnull final InstanceIdentifier<D> id,
@Nonnull final D dataAfter,
@Nonnull final Context writeContext);
+ /**
+ * Handle update operation. U from CRUD.
+ *
+ * @param id Identifier(from root) of data being written
+ * @param dataBefore Old data
+ * @param dataAfter New, updated data
+ * @param writeContext Write context can be used to store any useful information and then utilized by other customizers
+ */
void updateCurrentAttributes(@Nonnull final InstanceIdentifier<D> id,
@Nonnull final D dataBefore,
@Nonnull final D dataAfter,
@Nonnull final Context writeContext);
+ /**
+ * Handle delete operation. D from CRUD.
+ *
+ * @param id Identifier(from root) of data being written
+ * @param dataBefore Old data being deleted
+ * @param writeContext Write context can be used to store any useful information and then utilized by other customizers
+ */
void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<D> id,
@Nonnull final D dataBefore,
@Nonnull final Context writeContext);
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java
index 6df960626..d20e69a8b 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java
@@ -16,39 +16,60 @@
package io.fd.honeycomb.v3po.impl.trans.w.util;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import io.fd.honeycomb.v3po.impl.trans.VppException;
import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import io.fd.honeycomb.v3po.impl.trans.w.VppWriter;
import io.fd.honeycomb.v3po.impl.trans.w.WriteContext;
+import io.fd.honeycomb.v3po.impl.trans.w.WriterRegistry;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Simple reader registry able to perform and aggregated read (ROOT read) on top of all
- * provided readers. Also able to delegate a specific read to one of the delegate readers.
+ * Simple writer registry able to perform and aggregated read (ROOT write) on top of all
+ * provided writers. Also able to delegate a specific read to one of the delegate writers.
*
- * This could serve as a utility to hold & hide all available readers in upper layers.
+ * This could serve as a utility to hold & hide all available writers in upper layers.
*/
-public final class DelegatingWriterRegistry implements VppWriter<DataObject> {
+public final class DelegatingWriterRegistry implements WriterRegistry {
- private final Map<Class<? extends DataObject>, VppWriter<? extends DataObject>> rootReaders;
+ private static final Logger LOG = LoggerFactory.getLogger(DelegatingWriterRegistry.class);
+
+ private static final Function<InstanceIdentifier<?>, Class<? extends DataObject>> ID_TO_CLASS =
+ new Function<InstanceIdentifier<?>, Class<? extends DataObject>>() {
+ @Override
+ public Class<? extends DataObject> apply(final InstanceIdentifier<?> input) {
+ return input.getTargetType();
+ }
+ };
+
+ private final Map<Class<? extends DataObject>, VppWriter<? extends DataObject>> rootWriters;
/**
* Create new {@link DelegatingWriterRegistry}
*
- * @param rootReaders List of delegate readers
+ * @param rootWriters List of delegate writers
*/
- public DelegatingWriterRegistry(@Nonnull final List<VppWriter<? extends DataObject>> rootReaders) {
- this.rootReaders = VppRWUtils.uniqueLinkedIndex(checkNotNull(rootReaders), VppRWUtils.MANAGER_CLASS_FUNCTION);
+ public DelegatingWriterRegistry(@Nonnull final List<VppWriter<? extends DataObject>> rootWriters) {
+ this.rootWriters = VppRWUtils.uniqueLinkedIndex(checkNotNull(rootWriters), VppRWUtils.MANAGER_CLASS_FUNCTION);
}
/**
- * @throws UnsupportedOperationException This getter is not supported for reader registry since it does not manage a
+ * @throws UnsupportedOperationException This getter is not supported for writer registry since it does not manage a
* specific node type
*/
@Nonnull
@@ -59,14 +80,95 @@ public final class DelegatingWriterRegistry implements VppWriter<DataObject> {
@Override
public void update(@Nonnull final InstanceIdentifier<? extends DataObject> id,
- @Nonnull final List<? extends DataObject> dataBefore,
- @Nonnull final List<? extends DataObject> dataAfter,
- @Nonnull final WriteContext ctx) {
+ @Nullable final DataObject dataBefore,
+ @Nullable final DataObject dataAfter,
+ @Nonnull final WriteContext ctx) throws VppException {
final InstanceIdentifier.PathArgument first = checkNotNull(
Iterables.getFirst(id.getPathArguments(), null), "Empty id");
- final VppWriter<? extends DataObject> vppWriter = rootReaders.get(first.getType());
+ final VppWriter<? extends DataObject> vppWriter = rootWriters.get(first.getType());
checkNotNull(vppWriter,
- "Unable to write %s. Missing writer. Current writers for: %s", id, rootReaders.keySet());
+ "Unable to write %s. Missing writer. Current writers for: %s", id, rootWriters.keySet());
vppWriter.update(id, dataBefore, dataAfter, ctx);
}
+
+ @Override
+ public void update(@Nonnull final Map<InstanceIdentifier<?>, DataObject> nodesBefore,
+ @Nonnull final Map<InstanceIdentifier<?>, DataObject> nodesAfter,
+ @Nonnull final WriteContext ctx) throws VppException {
+ checkAllWritersPresent(nodesBefore);
+ checkAllWritersPresent(nodesAfter);
+
+ final List<InstanceIdentifier<?>> processedNodes = Lists.newArrayList();
+
+ for (Map.Entry<Class<? extends DataObject>, VppWriter<? extends DataObject>> rootWriterEntry : rootWriters
+ .entrySet()) {
+
+ final InstanceIdentifier<? extends DataObject> id = rootWriterEntry.getValue().getManagedDataObjectType();
+
+ final DataObject dataBefore = nodesBefore.get(id);
+ final DataObject dataAfter = nodesAfter.get(id);
+
+ // No change to current writer
+ if(dataBefore == null && dataAfter == null) {
+ continue;
+ }
+
+ LOG.debug("ChangesProcessor.applyChanges() processing dataBefore={}, dataAfter={}", dataBefore, dataAfter);
+
+ try {
+ update(id, dataBefore, dataAfter, ctx);
+ processedNodes.add(id);
+ } catch (RuntimeException e) {
+ LOG.error("Error while processing data change of: {} (before={}, after={})", id, dataBefore, dataAfter, e);
+ throw new BulkUpdateException(id, e, new RevertImpl(this, processedNodes, nodesBefore, nodesAfter, ctx));
+ }
+ }
+
+ }
+
+ private void checkAllWritersPresent(final @Nonnull Map<InstanceIdentifier<?>, DataObject> nodesBefore) {
+ checkArgument(rootWriters.keySet().containsAll(Collections2.transform(nodesBefore.keySet(), ID_TO_CLASS)),
+ "Unable to handle all changes. Missing dedicated writers for: %s",
+ Sets.difference(nodesBefore.keySet(), rootWriters.keySet()));
+ }
+
+ private static final class RevertImpl implements Revert {
+ private final WriterRegistry delegatingWriterRegistry;
+ private final List<InstanceIdentifier<?>> processedNodes;
+ private final Map<InstanceIdentifier<?>, DataObject> nodesBefore;
+ private final Map<InstanceIdentifier<?>, DataObject> nodesAfter;
+ private final WriteContext ctx;
+
+ public RevertImpl(final WriterRegistry delegatingWriterRegistry,
+ final List<InstanceIdentifier<?>> processedNodes,
+ final Map<InstanceIdentifier<?>, DataObject> nodesBefore,
+ final Map<InstanceIdentifier<?>, DataObject> nodesAfter, final WriteContext ctx) {
+ this.delegatingWriterRegistry = delegatingWriterRegistry;
+ this.processedNodes = processedNodes;
+ this.nodesBefore = nodesBefore;
+ this.nodesAfter = nodesAfter;
+ this.ctx = ctx;
+ }
+
+ @Override
+ public void revert() throws VppException {
+
+ final ListIterator<InstanceIdentifier<?>> iterator = processedNodes.listIterator(processedNodes.size());
+
+ while (iterator.hasPrevious()) {
+ final InstanceIdentifier<?> node = iterator.previous();
+ LOG.debug("ChangesProcessor.revertChanges() processing node={}", node);
+
+ final DataObject dataBefore = nodesBefore.get(node);
+ final DataObject dataAfter = nodesAfter.get(node);
+
+ // revert a change by invoking writer with reordered arguments
+ try {
+ delegatingWriterRegistry.update(node, dataAfter, dataBefore, ctx);
+ } catch (RuntimeException e) {
+ throw new RuntimeException();
+ }
+ }
+ }
+ }
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/NoopWriterCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/NoopWriterCustomizer.java
index 4f02a1d5e..7691f558b 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/NoopWriterCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/NoopWriterCustomizer.java
@@ -22,6 +22,10 @@ import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Customizer not performing any changes on current level. Suitable for nodes that don't have any leaves and all of
+ * its child nodes are managed by dedicated writers
+ */
public class NoopWriterCustomizer<D extends DataObject> implements RootVppWriterCustomizer<D> {
@Override
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java
index 7c1a63da6..8efcc6189 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/TransactionWriteContext.java
@@ -20,9 +20,8 @@ import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
import io.fd.honeycomb.v3po.impl.trans.util.Context;
import io.fd.honeycomb.v3po.impl.trans.w.WriteContext;
-import java.util.Collections;
-import java.util.List;
import java.util.Map;
+import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
@@ -32,7 +31,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-public class TransactionWriteContext implements WriteContext, AutoCloseable {
+/**
+ * Transaction based WriteContext
+ */
+public final class TransactionWriteContext implements WriteContext, AutoCloseable {
private final DOMDataReadOnlyTransaction beforeTx;
private final DOMDataReadOnlyTransaction afterTx;
@@ -48,39 +50,39 @@ public class TransactionWriteContext implements WriteContext, AutoCloseable {
this.ctx = new Context();
}
+ // TODO make this asynchronous
+
@Override
- public List<? extends DataObject> readBefore(final InstanceIdentifier<? extends DataObject> currentId) {
+ public Optional<DataObject> readBefore(@Nonnull final InstanceIdentifier<? extends DataObject> currentId) {
return read(currentId, beforeTx);
}
- private List<? extends DataObject> read(final InstanceIdentifier<? extends DataObject> currentId,
+ private Optional<DataObject> read(final InstanceIdentifier<? extends DataObject> currentId,
final DOMDataReadOnlyTransaction tx) {
- // FIXME how to read all for list (using wildcarded ID) ?
-
final YangInstanceIdentifier path = serializer.toYangInstanceIdentifier(currentId);
final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read =
tx.read(LogicalDatastoreType.CONFIGURATION, path);
try {
+ // TODO once the APIs are asynchronous use just Futures.transform
final Optional<NormalizedNode<?, ?>> optional = read.checkedGet();
if (!optional.isPresent()) {
- return Collections.<DataObject>emptyList();
+ return Optional.absent();
}
final NormalizedNode<?, ?> data = optional.get();
- final Map.Entry<InstanceIdentifier<?>, DataObject> entry =
- serializer.fromNormalizedNode(path, data);
+ final Map.Entry<InstanceIdentifier<?>, DataObject> entry = serializer.fromNormalizedNode(path, data);
- return Collections.singletonList(entry.getValue());
+ return Optional.of(entry.getValue());
} catch (ReadFailedException e) {
throw new IllegalStateException("Unable to perform read", e);
}
}
@Override
- public List<? extends DataObject> readAfter(final InstanceIdentifier<? extends DataObject> currentId) {
+ public Optional<DataObject> readAfter(@Nonnull final InstanceIdentifier<? extends DataObject> currentId) {
return read(currentId, afterTx);
}