import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import java.io.IOException;
-import java.net.URI;
-import java.util.Set;
import org.opendaylight.controller.cluster.datastore.node.utils.transformer.NormalizedNodePruner;
+import org.opendaylight.controller.cluster.datastore.util.AbstractDataTreeModificationCursor;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModificationCursor;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PruningDataTreeModification implements DataTreeModification {
private static final Logger LOG = LoggerFactory.getLogger(PruningDataTreeModification.class);
- private final DataTreeModification delegate;
- private final Set<URI> validNamespaces;
+ private DataTreeModification delegate;
+ private final SchemaContext schemaContext;
+ private final DataTree dataTree;
- public PruningDataTreeModification(DataTreeModification delegate, Set<URI> validNamespaces) {
+ public PruningDataTreeModification(DataTreeModification delegate, DataTree dataTree, SchemaContext schemaContext) {
this.delegate = delegate;
- this.validNamespaces = validNamespaces;
+ this.dataTree = dataTree;
+ this.schemaContext = schemaContext;
}
@Override
public void delete(YangInstanceIdentifier yangInstanceIdentifier) {
try {
delegate.delete(yangInstanceIdentifier);
- } catch(IllegalArgumentException e){
+ } catch(SchemaValidationFailedException e){
LOG.warn("Node at path : {} does not exist ignoring delete", yangInstanceIdentifier);
}
}
@Override
public void merge(YangInstanceIdentifier yangInstanceIdentifier, NormalizedNode<?, ?> normalizedNode) {
try {
- delegate.merge(yangInstanceIdentifier, normalizedNode);
- } catch (IllegalArgumentException e){
- if(!isValidYangInstanceIdentifier(yangInstanceIdentifier)){
- LOG.warn("Invalid node identifier {} ignoring merge", yangInstanceIdentifier);
- return;
+ if(YangInstanceIdentifier.EMPTY.equals(yangInstanceIdentifier)){
+ pruneAndMergeNode(yangInstanceIdentifier, normalizedNode);
+ } else {
+ delegate.merge(yangInstanceIdentifier, normalizedNode);
}
+ } catch (SchemaValidationFailedException e){
+ LOG.warn("Node at path {} was pruned during merge due to validation error: {}",
+ yangInstanceIdentifier, e.getMessage());
- LOG.warn("Node at path : {} was pruned during merge", yangInstanceIdentifier);
+ pruneAndMergeNode(yangInstanceIdentifier, normalizedNode);
+ }
- NormalizedNode<?,?> pruned = pruneNormalizedNode(normalizedNode);
+ }
- if(pruned != null) {
- delegate.merge(yangInstanceIdentifier, pruned);
- }
- }
+ private void pruneAndMergeNode(YangInstanceIdentifier yangInstanceIdentifier, NormalizedNode<?, ?> normalizedNode) {
+ NormalizedNode<?,?> pruned = pruneNormalizedNode(yangInstanceIdentifier, normalizedNode);
+ if(pruned != null) {
+ delegate.merge(yangInstanceIdentifier, pruned);
+ }
}
@Override
public void write(YangInstanceIdentifier yangInstanceIdentifier, NormalizedNode<?, ?> normalizedNode) {
try {
- delegate.write(yangInstanceIdentifier, normalizedNode);
- } catch (IllegalArgumentException e){
- if(!isValidYangInstanceIdentifier(yangInstanceIdentifier)){
- LOG.warn("Invalid node identifier {} ignoring write", yangInstanceIdentifier);
- return;
+ if(YangInstanceIdentifier.EMPTY.equals(yangInstanceIdentifier)){
+ pruneAndWriteNode(yangInstanceIdentifier, normalizedNode);
+ } else {
+ delegate.write(yangInstanceIdentifier, normalizedNode);
}
+ } catch (SchemaValidationFailedException e){
+ LOG.warn("Node at path : {} was pruned during write due to validation error: {}",
+ yangInstanceIdentifier, e.getMessage());
- LOG.warn("Node at path : {} was pruned during write", yangInstanceIdentifier);
+ pruneAndWriteNode(yangInstanceIdentifier, normalizedNode);
+ }
+ }
- NormalizedNode<?,?> pruned = pruneNormalizedNode(normalizedNode);
+ private void pruneAndWriteNode(YangInstanceIdentifier yangInstanceIdentifier, NormalizedNode<?, ?> normalizedNode) {
+ NormalizedNode<?,?> pruned = pruneNormalizedNode(yangInstanceIdentifier, normalizedNode);
- if(pruned != null) {
- delegate.write(yangInstanceIdentifier, pruned);
- }
+ if(pruned != null) {
+ delegate.write(yangInstanceIdentifier, pruned);
}
}
@Override
public void ready() {
- delegate.ready();
+ try {
+ delegate.ready();
+ } catch (SchemaValidationFailedException e) {
+ DataTreeModification newModification = dataTree.takeSnapshot().newModification();
+ delegate.applyToCursor(new PruningDataTreeModificationCursor(newModification, this));
+
+ delegate = newModification;
+ delegate.ready();
+ }
}
@Override
@Override
public DataTreeModification newModification() {
- return new PruningDataTreeModification(delegate.newModification(), validNamespaces);
+ return new PruningDataTreeModification(delegate.newModification(), dataTree, schemaContext);
}
@VisibleForTesting
- NormalizedNode<?, ?> pruneNormalizedNode(NormalizedNode<?,?> input){
- NormalizedNodePruner pruner = new NormalizedNodePruner(validNamespaces);
+ NormalizedNode<?, ?> pruneNormalizedNode(YangInstanceIdentifier path, NormalizedNode<?,?> input) {
+ NormalizedNodePruner pruner = new NormalizedNodePruner(path, schemaContext);
try {
NormalizedNodeWriter.forStreamWriter(pruner).write(input);
} catch (IOException ioe) {
return pruner.normalizedNode();
}
- public DataTreeModification getDelegate(){
+ public DataTreeModification getResultingModification(){
return delegate;
}
- private boolean isValidYangInstanceIdentifier(YangInstanceIdentifier instanceIdentifier){
- for(YangInstanceIdentifier.PathArgument pathArgument : instanceIdentifier.getPathArguments()){
- if(!validNamespaces.contains(pathArgument.getNodeType().getNamespace())){
- return false;
+ private static class PruningDataTreeModificationCursor extends AbstractDataTreeModificationCursor {
+ private final DataTreeModification toModification;
+ private final PruningDataTreeModification pruningModification;
+
+ PruningDataTreeModificationCursor(DataTreeModification toModification,
+ PruningDataTreeModification pruningModification) {
+ this.toModification = toModification;
+ this.pruningModification = pruningModification;
+ }
+
+ @Override
+ public void write(PathArgument child, NormalizedNode<?, ?> data) {
+ YangInstanceIdentifier path = current().node(child);
+ NormalizedNode<?, ?> prunedNode = pruningModification.pruneNormalizedNode(path, data);
+ if(prunedNode != null) {
+ toModification.write(path, prunedNode);
}
}
- return true;
- }
+ @Override
+ public void merge(PathArgument child, NormalizedNode<?, ?> data) {
+ YangInstanceIdentifier path = current().node(child);
+ NormalizedNode<?, ?> prunedNode = pruningModification.pruneNormalizedNode(path, data);
+ if(prunedNode != null) {
+ toModification.merge(path, prunedNode);
+ }
+ }
+ @Override
+ public void delete(PathArgument child) {
+ try {
+ toModification.delete(current().node(child));
+ } catch(SchemaValidationFailedException e) {
+ // Ignoring since we would've already logged this in the call to the original modification.
+ }
+ }
+ }
}