+ @Override
+ public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
+ if (modification.getModificationType() == ModificationType.WRITE) {
+ verifyWrittenStructure(modification.getWrittenValue());
+ }
+ }
+
+ protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
+
+ @Override
+ public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ switch (modification.getModificationType()) {
+ case DELETE:
+ checkDeleteApplicable(modification, current);
+ case SUBTREE_MODIFIED:
+ checkSubtreeModificationApplicable(path,modification, current);
+ return;
+ case WRITE:
+ checkWriteApplicable(path,modification, current);
+ return;
+ case MERGE:
+ checkMergeApplicable(path,modification,current);
+ return;
+ case UNMODIFIED:
+ return;
+ default:
+ throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
+ }
+
+ }
+
+ protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ Optional<StoreMetadataNode> original = modification.getOriginal();
+ if (original.isPresent() && current.isPresent()) {
+ /*
+ * We need to do conflict detection only and only if the value of leaf changed
+ * before two transactions. If value of leaf is unchanged between two transactions
+ * it should not cause transaction to fail, since result of this merge
+ * leads to same data.
+ */
+ if(!original.get().getData().equals(current.get().getData())) {
+
+ checkNotConflicting(path,original.get(), current.get());
+ }
+ }
+ }
+
+ protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ Optional<StoreMetadataNode> original = modification.getOriginal();
+ if (original.isPresent() && current.isPresent()) {
+ checkNotConflicting(path,original.get(), current.get());
+ } else if(original.isPresent()) {
+ throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
+ }
+ }
+
+ protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException {
+ checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction.");
+ checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction");
+ }
+
+ protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
+ final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
+
+ private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+ }
+