Merge "BUG-1281: introduce XML event stream writer"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 11 Jul 2014 10:03:55 +0000 (10:03 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 11 Jul 2014 10:03:55 +0000 (10:03 +0000)
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTree.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeSnapshot.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/RootModificationApplyOperation.java [new file with mode: 0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModificationMetadataTreeTest.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java

index c5303e1dbed558c54d2ca709959a98bdff0710c8..7013e55ad1fccdafcb4eb0c9e1550bfa9a4352df 100644 (file)
@@ -7,8 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
@@ -16,12 +17,13 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.RootModificationApplyOperation.LatestOperationHolder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 /**
  * Read-only snapshot of the data tree.
@@ -31,7 +33,7 @@ final class InMemoryDataTree implements DataTree {
     private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
 
     private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
-    private ModificationApplyOperation applyOper = new AlwaysFailOperation();
+    private final LatestOperationHolder operationHolder = new LatestOperationHolder();
     private SchemaContext currentSchemaContext;
     private TreeNode rootNode;
 
@@ -48,7 +50,7 @@ final class InMemoryDataTree implements DataTree {
     public synchronized void setSchemaContext(final SchemaContext newSchemaContext) {
         Preconditions.checkNotNull(newSchemaContext);
 
-        LOG.info("Attepting to install schema context {}", newSchemaContext);
+        LOG.info("Attempting to install schema context {}", newSchemaContext);
 
         /*
          * FIXME: we should walk the schema contexts, both current and new and see
@@ -61,7 +63,7 @@ final class InMemoryDataTree implements DataTree {
         // Ready to change the context now, make sure no operations are running
         rwLock.writeLock().lock();
         try {
-            this.applyOper = newApplyOper;
+            this.operationHolder.setCurrent(newApplyOper);
             this.currentSchemaContext = newSchemaContext;
         } finally {
             rwLock.writeLock().unlock();
@@ -72,7 +74,7 @@ final class InMemoryDataTree implements DataTree {
     public InMemoryDataTreeSnapshot takeSnapshot() {
         rwLock.readLock().lock();
         try {
-            return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, applyOper);
+            return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, operationHolder.newSnapshot());
         } finally {
             rwLock.readLock().unlock();
         }
index 3c903e7831b33f6cb459a4404b2a3be0f15078d7..206c27372cb0b286ea7545f6d739e9c8869cd81c 100644 (file)
@@ -7,9 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
 import java.util.Map.Entry;
 
 import javax.annotation.concurrent.GuardedBy;
@@ -25,18 +22,21 @@ import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
 final class InMemoryDataTreeModification implements DataTreeModification {
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
-    private final ModificationApplyOperation strategyTree;
+    private final RootModificationApplyOperation strategyTree;
     private final InMemoryDataTreeSnapshot snapshot;
     private final ModifiedNode rootNode;
 
     @GuardedBy("this")
     private boolean sealed = false;
 
-    InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
+    InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final RootModificationApplyOperation resolver) {
         this.snapshot = Preconditions.checkNotNull(snapshot);
-        this.strategyTree = Preconditions.checkNotNull(resolver);
+        this.strategyTree = Preconditions.checkNotNull(resolver).snapshot();
         this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode());
     }
 
@@ -117,7 +117,11 @@ final class InMemoryDataTreeModification implements DataTreeModification {
 
     private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
         LOG.trace("Resolving modification apply strategy for {}", path);
-        return TreeNodeUtils.findNodeChecked(strategyTree, path);
+        if(rootNode.getType() == ModificationType.UNMODIFIED) {
+            strategyTree.upgradeIfPossible();
+        }
+
+        return TreeNodeUtils.<ModificationApplyOperation>findNodeChecked(strategyTree, path);
     }
 
     private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
index 7c1c1719a462d0419d3cb029b0ecc0a054b61d27..9c0bd584351ced92a98c741c570d9a8e716013a1 100644 (file)
@@ -1,8 +1,6 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
@@ -10,13 +8,16 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
 final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
-    private final ModificationApplyOperation applyOper;
+    private final RootModificationApplyOperation applyOper;
     private final SchemaContext schemaContext;
     private final TreeNode rootNode;
 
     InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final TreeNode rootNode,
-            final ModificationApplyOperation applyOper) {
+            final RootModificationApplyOperation applyOper) {
         this.schemaContext = Preconditions.checkNotNull(schemaContext);
         this.rootNode = Preconditions.checkNotNull(rootNode);
         this.applyOper = Preconditions.checkNotNull(applyOper);
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/RootModificationApplyOperation.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/RootModificationApplyOperation.java
new file mode 100644 (file)
index 0000000..fd3b734
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
+
+import com.google.common.base.Optional;
+
+public abstract class RootModificationApplyOperation implements ModificationApplyOperation {
+
+    @Override
+    public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+        return getDelegate().getChild(child);
+    }
+
+    @Override
+    public final void checkApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current)
+            throws DataValidationFailedException {
+        getDelegate().checkApplicable(path, modification, current);
+    }
+
+    @Override
+    public final Optional<TreeNode> apply(final ModifiedNode modification, final Optional<TreeNode> currentMeta, final Version version) {
+        return getDelegate().apply(modification, currentMeta, version);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return getDelegate().equals(obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return getDelegate().hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return getDelegate().toString();
+    }
+
+    @Override
+    public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+        getDelegate().verifyStructure(modification);
+    }
+
+    abstract ModificationApplyOperation getDelegate();
+
+    public abstract RootModificationApplyOperation snapshot();
+
+    public abstract void upgradeIfPossible();
+
+
+
+    public static RootModificationApplyOperation from(final ModificationApplyOperation resolver) {
+        if(resolver instanceof RootModificationApplyOperation) {
+            return ((RootModificationApplyOperation) resolver).snapshot();
+        }
+        return new NotUpgradable(resolver);
+    }
+
+    private static final class Upgradable extends RootModificationApplyOperation {
+
+        private final LatestOperationHolder holder;
+        private ModificationApplyOperation delegate;
+
+
+        public Upgradable(final LatestOperationHolder holder, final ModificationApplyOperation delegate) {
+            this.holder = holder;
+            this.delegate = delegate;
+
+        }
+
+        @Override
+        public void upgradeIfPossible() {
+            ModificationApplyOperation holderCurrent = holder.getCurrent();
+            if(holderCurrent != delegate) {
+                // FIXME: Allow update only if there is addition of models, not removals.
+                delegate = holderCurrent;
+            }
+
+        }
+
+        @Override
+        ModificationApplyOperation getDelegate() {
+            return delegate;
+        }
+
+        @Override
+        public RootModificationApplyOperation snapshot() {
+            return new Upgradable(holder,getDelegate());
+        }
+
+    }
+
+    private static final class NotUpgradable extends RootModificationApplyOperation {
+
+        private final ModificationApplyOperation delegate;
+
+        public NotUpgradable(final ModificationApplyOperation delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public ModificationApplyOperation getDelegate() {
+            return delegate;
+        }
+
+        @Override
+        public void upgradeIfPossible() {
+            // Intentional noop
+        }
+
+        @Override
+        public RootModificationApplyOperation snapshot() {
+            return this;
+        }
+    }
+
+    public static class LatestOperationHolder {
+
+        private ModificationApplyOperation current = new AlwaysFailOperation();
+
+        public ModificationApplyOperation getCurrent() {
+            return current;
+        }
+
+        public void setCurrent(final ModificationApplyOperation newApplyOper) {
+            current = newApplyOper;
+        }
+
+        public RootModificationApplyOperation newSnapshot() {
+            return new Upgradable(this,current);
+        }
+
+    }
+}
index 54a4a88cbb47644280d363083136d5e4989fdb7b..003c20fe7ca069329e8b5be5c990ea7f93fbd709 100644 (file)
@@ -7,7 +7,15 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
-import com.google.common.base.Optional;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -24,14 +32,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+import com.google.common.base.Optional;
 
 
 
@@ -97,13 +98,13 @@ public class ModificationMetadataTreeTest {
                     .build();
 
     private SchemaContext schemaContext;
-    private ModificationApplyOperation applyOper;
+    private RootModificationApplyOperation rootOper;
 
     @Before
     public void prepare() {
         schemaContext = TestModel.createTestContext();
         assertNotNull("Schema context must not be null.", schemaContext);
-        applyOper = SchemaAwareApplyOperation.from(schemaContext);
+        rootOper = RootModificationApplyOperation.from(SchemaAwareApplyOperation.from(schemaContext));
     }
 
     /**
@@ -145,8 +146,8 @@ public class ModificationMetadataTreeTest {
     @Test
     public void basicReadWrites() {
         DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), applyOper),
-                new SchemaAwareApplyOperationRoot(schemaContext));
+                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper),
+                rootOper);
         Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
         assertTrue(originalBarNode.isPresent());
         assertSame(BAR_NODE, originalBarNode.get());
index 6305dd7c88b42d3708830a1760169c3c04cd0ae9..fbf4c4389b05f140dbc3452c367a18627f707109 100644 (file)
@@ -11,7 +11,6 @@ import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
-
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -21,7 +20,6 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
@@ -242,8 +240,9 @@ public final class SchemaContextUtil {
         return findNodeInModule(module, path);
     }
 
-    public static GroupingDefinition findGrouping(final SchemaContext context, final Module module, final List<QName> path) {
-        QName first = path.get(0);
+    public static GroupingDefinition findGrouping(final SchemaContext context, final Module module, final Iterable<QName> path) {
+        Iterator<QName> iterator = path.iterator();
+        QName first = iterator.next();
         Module m = context.findModuleByNamespace(first.getNamespace()).iterator().next();
         DataNodeContainer currentParent = m;
         for (QName qname : path) {
@@ -626,8 +625,12 @@ public final class SchemaContextUtil {
     }
 
     private static DataSchemaNode getResultFromUses(final UsesNode u, final String currentName, final SchemaContext ctx) {
-        SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPathFromRoot());
-
+        SchemaNode targetGrouping = SchemaContextUtil.findNodeInSchemaContext(ctx, u.getGroupingPath()
+                .getPathFromRoot());
+        if (!(targetGrouping instanceof GroupingDefinition)) {
+            targetGrouping = findGrouping(ctx, getParentModule(targetGrouping, ctx), u.getGroupingPath()
+                    .getPathFromRoot());
+        }
         Preconditions.checkArgument(targetGrouping instanceof GroupingDefinition,
                 "Failed to generate code for augment in %s", u);
         GroupingDefinition gr = (GroupingDefinition) targetGrouping;