Merge "ArpHandler to ignore ip packet sent to default GW"
authorChi-Vien Ly <chivly@cisco.com>
Mon, 13 Jan 2014 17:09:57 +0000 (17:09 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 13 Jan 2014 17:09:57 +0000 (17:09 +0000)
74 files changed:
.gitignore
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-persister-api/pom.xml
opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java [new file with mode: 0644]
opendaylight/config/config-persister-directory-adapter/pom.xml
opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java
opendaylight/config/config-persister-directory-xml-adapter/pom.xml
opendaylight/config/config-persister-directory-xml-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/xml/DirectoryStorageAdapterTest.java
opendaylight/config/config-persister-file-adapter/pom.xml
opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java
opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java
opendaylight/config/pom.xml
opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java [moved from opendaylight/config/yang-test/src/test/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java with 64% similarity]
opendaylight/distribution/opendaylight/pom.xml
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java
opendaylight/md-sal/compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/packet-processing.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-statistics.yang
opendaylight/md-sal/model/model-inventory/src/main/yang/netconf-node-inventory.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-topology/pom.xml
opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang
opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang
opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/AugmentationCodec.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/api/CodecRegistry.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/InstanceIdWithSchemaNode.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DeleteRestCallTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/NormalizeNodeTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestConfigDataTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/normalize-node/yang/normalize-node-module [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface2.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface3.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang1/test-interface.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang2/test-interface2.yang [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java
opendaylight/netconf/netconf-ssh/pom.xml
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java

index 18817e7..b079cba 100644 (file)
@@ -20,3 +20,4 @@ opendaylight/northbound/integrationtest/logs/*
 .idea
 xtend-gen
 classes
+out/
index 8933b14..24b1ed9 100644 (file)
@@ -61,6 +61,7 @@
     <osgi.core.version>5.0.0</osgi.core.version>
     <ietf-inet-types.version>2010.09.24.2-SNAPSHOT</ietf-inet-types.version>
     <ietf-yang-types.version>2010.09.24.2-SNAPSHOT</ietf-yang-types.version>
+    <ietf-topology.version>2013.10.21.0-SNAPSHOT</ietf-topology.version>
     <opendaylight-l2-types.version>2013.08.27.1</opendaylight-l2-types.version>
     <yang-ext.version>2013.09.07.1</yang-ext.version>
     <javassist.version>3.17.1-GA</javassist.version>
        <artifactId>ietf-yang-types</artifactId>
        <version>${ietf-yang-types.version}</version>
       </dependency>
+      <dependency>
+       <groupId>org.opendaylight.yangtools.model</groupId>
+       <artifactId>ietf-topology</artifactId>
+       <version>${ietf-topology.version}</version>
+      </dependency>
       <dependency>
        <groupId>org.opendaylight.yangtools.model</groupId>
        <artifactId>opendaylight-l2-types</artifactId>
index 80016a8..f622992 100644 (file)
 
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
diff --git a/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java b/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java
new file mode 100644 (file)
index 0000000..2df07b1
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 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.controller.config.persist.test;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.controller.config.persist.api.PropertiesProvider;
+
+public class PropertiesProviderTest implements PropertiesProvider {
+    private final Map<String,String> properties = new HashMap();
+
+    public void addProperty(String key,String value){
+        properties.put(key,value);
+    }
+    @Override
+    public String getProperty(String key) {
+        return properties.get(key);
+    }
+
+    @Override
+    public String getFullKeyForReporting(String key) {
+        return null;
+    }
+}
index b2da71e..c67a08c 100644 (file)
             <artifactId>mockito-configuration</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-persister-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 
index f17e414..72bd208 100644 (file)
@@ -8,28 +8,32 @@
 
 package org.opendaylight.controller.config.persist.storage.directory;
 
-import org.apache.commons.io.IOUtils;
-import org.junit.Test;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-
 import java.io.File;
 import java.util.Collections;
 import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
-
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.persist.test.PropertiesProviderTest;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 public class DirectoryStorageAdapterTest {
-    DirectoryPersister tested;
+    Persister tested;
 
     @Test
     public void testEmptyDirectory() throws Exception {
         File folder = new File("target/emptyFolder");
         folder.mkdir();
-        tested = new DirectoryPersister((folder));
+
+        PropertiesProviderTest pp = new PropertiesProviderTest();
+        pp.addProperty("directoryStorage",folder.getPath());
+        DirectoryStorageAdapter dsa = new DirectoryStorageAdapter();
+        tested = dsa.instantiate(pp);
         assertEquals(Collections.<ConfigSnapshotHolder>emptyList(), tested.loadLastConfigs());
 
         try {
@@ -60,7 +64,11 @@ public class DirectoryStorageAdapterTest {
     @Test
     public void testOneFile() throws Exception {
         File folder = getFolder("oneFile");
-        tested = new DirectoryPersister((folder));
+        PropertiesProviderTest pp = new PropertiesProviderTest();
+        pp.addProperty("directoryStorage",folder.getPath());
+        DirectoryStorageAdapter dsa = new DirectoryStorageAdapter();
+        tested = dsa.instantiate(pp);
+
         List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
         assertEquals(1, results.size());
         ConfigSnapshotHolder result = results.get(0);
@@ -71,7 +79,11 @@ public class DirectoryStorageAdapterTest {
     @Test
     public void testTwoFiles() throws Exception {
         File folder = getFolder("twoFiles");
-        tested = new DirectoryPersister((folder));
+        PropertiesProviderTest pp = new PropertiesProviderTest();
+        pp.addProperty("directoryStorage",folder.getPath());
+        DirectoryStorageAdapter dsa = new DirectoryStorageAdapter();
+        tested = dsa.instantiate(pp);
+
         List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
         assertEquals(2, results.size());
         assertSnapshot(results.get(0), "twoFilesExpected1");
index b2ea632..96d3a71 100644 (file)
             <artifactId>mockito-configuration</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-persister-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 
index 73061f8..0a36db9 100644 (file)
@@ -8,20 +8,21 @@
 
 package org.opendaylight.controller.config.persist.storage.directory.xml;
 
-import org.junit.Test;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-
 import java.io.File;
 import java.util.Collections;
 import java.util.List;
 import java.util.SortedSet;
-
+import org.junit.Test;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.persist.test.PropertiesProviderTest;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 public class DirectoryStorageAdapterTest {
-    XmlDirectoryPersister tested;
+
+    Persister tested;
 
     @Test
     public void testEmptyDirectory() throws Exception {
@@ -58,7 +59,12 @@ public class DirectoryStorageAdapterTest {
     @Test
     public void testOneFile() throws Exception {
         File folder = getFolder("oneFile");
-        tested = new XmlDirectoryPersister((folder));
+
+        PropertiesProviderTest pp = new PropertiesProviderTest();
+        pp.addProperty("directoryStorage",folder.getPath());
+        XmlDirectoryStorageAdapter xmlDsa = new XmlDirectoryStorageAdapter();
+        tested = xmlDsa.instantiate(pp);
+
         List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
         assertEquals(1, results.size());
         ConfigSnapshotHolder result = results.get(0);
@@ -76,7 +82,12 @@ public class DirectoryStorageAdapterTest {
     @Test
     public void testTwoFiles() throws Exception {
         File folder = getFolder("twoFiles");
-        tested = new XmlDirectoryPersister((folder));
+
+        PropertiesProviderTest pp = new PropertiesProviderTest();
+        pp.addProperty("directoryStorage",folder.getPath());
+        XmlDirectoryStorageAdapter xmlDsa = new XmlDirectoryStorageAdapter();
+        tested = xmlDsa.instantiate(pp);
+
         List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
         assertEquals(2, results.size());
 
index b16cb2b..3cd3e90 100644 (file)
             <artifactId>mockito-configuration</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-persister-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index 3ec8713..1b9948b 100644 (file)
@@ -13,15 +13,6 @@ import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.io.Files;
-import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolderImpl;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.persist.api.PropertiesProvider;
-import org.opendaylight.controller.config.persist.api.StorageAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
@@ -31,9 +22,17 @@ import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import org.apache.commons.lang3.StringUtils;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolderImpl;
+import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.persist.api.PropertiesProvider;
+import org.opendaylight.controller.config.persist.api.StorageAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * StorageAdapter that stores configuration in a plan file.
+ * StorageAdapter that stores configuration in a plain file.
  */
 public class FileStorageAdapter implements StorageAdapter, Persister {
     private static final Logger logger = LoggerFactory.getLogger(FileStorageAdapter.class);
index 0236598..0366dbc 100644 (file)
@@ -11,18 +11,18 @@ package org.opendaylight.controller.config.persist.storage.file;
 import com.google.common.base.Charsets;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-
 import java.io.File;
 import java.nio.file.Files;
 import java.util.Collection;
 import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
-
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.persist.test.PropertiesProviderTest;
 import static junit.framework.Assert.assertFalse;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
@@ -42,6 +42,49 @@ public class FileStorageAdapterTest {
         i = 1;
     }
 
+
+    @Test
+    public void testFileAdapterAsPersister() throws Exception {
+        FileStorageAdapter storage = new FileStorageAdapter();
+        PropertiesProviderTest pp = new PropertiesProviderTest();
+        pp.addProperty("fileStorage",file.getPath());
+        pp.addProperty("numberOfBackups",Integer.toString(Integer.MAX_VALUE));
+
+        Persister configPersister = storage.instantiate(pp);
+        final ConfigSnapshotHolder holder = new ConfigSnapshotHolder() {
+            @Override
+            public String getConfigSnapshot() {
+                return createConfig();
+            }
+
+            @Override
+            public SortedSet<String> getCapabilities() {
+                return createCaps();
+            }
+        };
+        configPersister.persistConfig(holder);
+
+        configPersister.persistConfig(holder);
+
+        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
+                new Predicate<String>() {
+
+                    @Override
+                    public boolean apply(String input) {
+                        if (input.equals(""))
+                            return false;
+                        return true;
+                    }
+                });
+        assertEquals(14, readLines.size());
+
+        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
+        assertEquals(1, lastConf.size());
+        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
+        assertEquals("<config>2</config>",
+                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
+        assertEquals(createCaps(), configSnapshotHolder.getCapabilities());
+    }
     @Test
     public void testFileAdapter() throws Exception {
         FileStorageAdapter storage = new FileStorageAdapter();
index 75b1809..4f02db5 100644 (file)
@@ -32,8 +32,13 @@ public interface ConfigTransactionClient extends
 
     void validateBean(ObjectName configBeanON) throws ValidationException;
 
-    void destroyConfigBean(String moduleName, String instanceName)
-            throws InstanceNotFoundException;
+    @Deprecated
+    /**
+     * Use {@link #destroyModule(String, String)}
+     */
+    void destroyConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException;
+
+    void destroyModule(String moduleName, String instanceName) throws InstanceNotFoundException;
 
     void setAttribute(ObjectName on, String jmxName, Attribute attribute);
 }
index e683d91..3583daf 100644 (file)
@@ -84,12 +84,23 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
+    @Deprecated
+    /**
+     * {@inheritDoc}
+     */
     public void destroyConfigBean(String moduleName, String instanceName)
             throws InstanceNotFoundException {
         destroyModule(ObjectNameUtil.createTransactionModuleON(
                 getTransactionName(), moduleName, instanceName));
     }
 
+    @Override
+    public void destroyModule(String moduleName, String instanceName)
+            throws InstanceNotFoundException {
+        destroyModule(ObjectNameUtil.createTransactionModuleON(
+                getTransactionName(), moduleName, instanceName));
+    }
+
     @Override
     public void abortConfig() {
         configTransactionControllerMXBeanProxy.abortConfig();
index 9f9bca9..36b109f 100644 (file)
                 <artifactId>config-persister-api</artifactId>
                 <version>${config.version}</version>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>config-persister-api</artifactId>
+                <version>${config.version}</version>
+                <type>test-jar</type>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.bgpcep</groupId>
                 <artifactId>mockito-configuration</artifactId>
@@ -4,8 +4,6 @@ import com.google.common.collect.Lists;
 import junit.framework.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
@@ -15,8 +13,14 @@ import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.ObjectName;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 public class NetconfTestImplModuleTest  extends AbstractConfigTest {
 
     public static final String TESTING_DEP_PREFIX = "testing-dep";
@@ -32,17 +36,16 @@ public class NetconfTestImplModuleTest  extends AbstractConfigTest {
     }
 
     @Test
-    public void testDependencyList() throws InstanceAlreadyExistsException, ValidationException,
-            ConflictingVersionException {
+    public void testDependencyList() throws Exception {
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
 
         ObjectName on = createInstance(transaction, instanceName, 4);
         transaction.validateConfig();
-        CommitStatus status = transaction.commit();
+        CommitStatus status1 = transaction.commit();
 
         assertBeanCount(1, factory.getImplementationName());
         assertBeanCount(4 + 1, DepTestImplModuleFactory.NAME);
-        assertStatus(status, 1 + 4 + 1, 0, 0);
+        assertStatus(status1, 1 + 4 + 1, 0, 0);
 
         transaction = configRegistryClient.createTransaction();
 
@@ -56,6 +59,38 @@ public class NetconfTestImplModuleTest  extends AbstractConfigTest {
         assertTestingDeps(testingDeps, 4);
 
         transaction.abortConfig();
+
+        // check that reuse logic works - equals on list of dependencies.
+        transaction = configRegistryClient.createTransaction();
+        CommitStatus status2 = transaction.commit();
+        assertStatus(status2, 0, 0, 6);
+
+        // replace single dependency
+        transaction = configRegistryClient.createTransaction();
+        String instanceName1 = TESTING_DEP_PREFIX + 1;
+        transaction.destroyModule(DepTestImplModuleFactory.NAME, instanceName1);
+        transaction.createModule(DepTestImplModuleFactory.NAME, instanceName1);
+        CommitStatus status3 = transaction.commit();
+        assertStatus(status3, 1, 1, 4);
+
+    }
+
+    @Test
+    public void testNullCheckInListOfDependencies() throws Exception {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        ObjectName on = createInstance(transaction, instanceName, 4);
+        NetconfTestImplModuleMXBean proxy = transaction.newMXBeanProxy(on, NetconfTestImplModuleMXBean.class);
+        try{
+            proxy.setTestingDeps(null);
+            fail();
+        }catch(RuntimeException e) {
+            Throwable cause = e.getCause();
+            assertNotNull(cause);
+            assertTrue("Invalid type " + cause, cause instanceof IllegalArgumentException);
+            assertEquals("Null not supported", cause.getMessage());
+        }
+        proxy.setTestingDeps(Collections.<ObjectName>emptyList());
     }
 
     private void assertTestingDeps(List<ObjectName> testingDeps, int i) {
index 6fca9db..f1eca41 100644 (file)
         <dependency>
          <groupId>org.opendaylight.yangtools.model</groupId>
          <artifactId>ietf-topology</artifactId>
-         <version>2013.07.12.2-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 3ec9f84..de6b818 100644 (file)
@@ -8,19 +8,6 @@
 
 package org.opendaylight.controller.forwardingrulesmanager;
 
-import java.io.Serializable;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-
 import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.ActionType;
 import org.opendaylight.controller.sal.action.Controller;
@@ -62,6 +49,18 @@ import org.opendaylight.controller.switchmanager.Switch;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 /**
  * Configuration Java Object which represents a flow configuration information
  * for Forwarding Rules Manager.
@@ -1044,6 +1043,7 @@ public class FlowConfig implements Serializable {
         }
 
         Flow flow = new Flow(match, getActionList());
+
         if (this.cookie != null) {
             flow.setId(Long.parseLong(cookie));
         }
@@ -1056,6 +1056,8 @@ public class FlowConfig implements Serializable {
         if (this.priority != null) {
             flow.setPriority(Integer.decode(this.priority).shortValue());
         }
+
+
         return flow;
     }
 
index 151fdbf..37d866d 100644 (file)
@@ -25,7 +25,7 @@
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
+            <version>0.7.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
index f72e5b9..5e52e3b 100644 (file)
       <artifactId>sal-binding-util</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>clustering.services</artifactId>
+        <version>0.4.1-SNAPSHOT</version>
+    </dependency>
   </dependencies>
   <packaging>bundle</packaging>
 
index d7a345c..2156a81 100644 (file)
@@ -27,6 +27,8 @@ import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
 import org.opendaylight.controller.sal.utils.GlobalConstants
 import org.opendaylight.controller.sal.utils.INodeConnectorFactory
 import org.opendaylight.controller.sal.utils.INodeFactory
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices
+
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
@@ -143,6 +145,13 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi
             .setService(IPluginOutFlowProgrammerService) //
             .setCallbacks("setFlowProgrammerPublisher", "setFlowProgrammerPublisher") //
             .setRequired(false))
+
+        add(
+            createServiceDependency() //
+            .setService(IClusterGlobalServices) //
+            .setCallbacks("setClusterGlobalServices", "unsetClusterGlobalServices") //
+            .setRequired(false))
+
     }
 
     private def dispatch configure(InventoryAndReadAdapter imp, Component it) {
@@ -162,6 +171,7 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi
             .setService(IDiscoveryService) //
             .setCallbacks("setDiscoveryPublisher", "setDiscoveryPublisher") //
             .setRequired(false))
+
         
     }
     
index 450c7f1..35c641c 100644 (file)
@@ -1,12 +1,21 @@
 package org.opendaylight.controller.sal.compatibility
 
+import java.util.Map
+import java.util.UUID
 import java.util.concurrent.ExecutionException
+import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.Future
+import java.util.EnumSet
 import org.opendaylight.controller.sal.core.Node
 import org.opendaylight.controller.sal.flowprogrammer.Flow
 import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService
 import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService
 import org.opendaylight.controller.sal.utils.Status
 import org.opendaylight.controller.sal.utils.StatusCode
+import org.opendaylight.controller.clustering.services.CacheExistException
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices
+import org.opendaylight.controller.clustering.services.IClusterServices
+
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved
@@ -20,19 +29,14 @@ import org.slf4j.LoggerFactory
 
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId
 
 
 import static extension org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
@@ -43,6 +47,7 @@ import static extension org.opendaylight.controller.sal.compatibility.ToSalConve
 class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
 
     private static val LOG = LoggerFactory.getLogger(FlowProgrammerAdapter);
+    private static val CACHE_NAME = "flowprogrammeradapter.flowtoid";
 
     @Property
     private SalFlowService delegate;
@@ -53,39 +58,38 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
     @Property
     private IPluginOutFlowProgrammerService flowProgrammerPublisher;
 
+    @Property
+    private IClusterGlobalServices clusterGlobalServices;
+
+
+    @Property
+    private Map<Flow, UUID> flowToFlowId = new ConcurrentHashMap<Flow, UUID>();
+
+
     override addFlow(Node node, Flow flow) {
-        return addFlowAsync(node,flow,0)
+        return toFutureStatus(internalAddFlowAsync(node,flow,0));
     }
 
     override modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
-        return modifyFlowAsync(node, oldFlow,newFlow,0)
+        return toFutureStatus(internalModifyFlowAsync(node, oldFlow,newFlow,0));
     }
 
     override removeFlow(Node node, Flow flow) {
-        return removeFlowAsync(node, flow,0);
+        return toFutureStatus(internalRemoveFlowAsync(node, flow,0));
     }
 
     override addFlowAsync(Node node, Flow flow, long rid) {
-        writeFlow(flow.toMDFlow, new NodeKey(new NodeId(node.getNodeIDString())));
+        internalAddFlowAsync(node, flow, rid);
         return toStatus(true);
     }
 
     override modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
-        writeFlow(newFlow.toMDFlow, new NodeKey(new NodeId(node.getNodeIDString())));
+        internalModifyFlowAsync(node, oldFlow, newFlow, rid);
         return toStatus(true);
     }
 
-    override removeFlowAsync(Node node, Flow adflow, long rid) {
-        val flow = adflow.toMDFlow;
-        val modification = this._dataBrokerService.beginTransaction();
-        val flowPath = InstanceIdentifier.builder(Nodes)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, new NodeKey(new NodeId(node.getNodeIDString())))
-                .augmentation(FlowCapableNode)
-                .child(Table, new TableKey(flow.getTableId()))
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
-                .build;
-        modification.removeConfigurationData(flowPath);
-        val commitFuture = modification.commit();
+    override removeFlowAsync(Node node, Flow flow, long rid) {
+        internalRemoveFlowAsync(node, flow, rid);
         return toStatus(true);
     }
 
@@ -114,27 +118,6 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
         }
     }
 
-
-    private def writeFlow(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, NodeKey nodeKey) {
-        val modification = this._dataBrokerService.beginTransaction();
-        val flowPath = InstanceIdentifier.builder(Nodes)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, nodeKey)
-                .augmentation(FlowCapableNode)
-                .child(Table, new TableKey(flow.getTableId()))
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
-                .build;
-        modification.putConfigurationData(flowPath, flow);
-        val commitFuture = modification.commit();
-        try {
-            val result = commitFuture.get();
-            val status = result.getResult();
-        } catch (InterruptedException e) {
-            LOG.error(e.getMessage(), e);
-        } catch (ExecutionException e) {
-            LOG.error(e.getMessage(), e);
-        }
-    }
-
     public static def toStatus(RpcResult<?> result) {
         return toStatus(result.isSuccessful());
     }
@@ -177,4 +160,90 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
                 NodeExperimenterErrorNotification notification) {
         // NOOP : Not supported by AD SAL
     }
+
+    private def Future<RpcResult<TransactionStatus>> writeFlowAsync(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, NodeKey nodeKey){
+        val modification = this._dataBrokerService.beginTransaction();
+        val flowPath = InstanceIdentifier.builder(Nodes)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, nodeKey)
+                .augmentation(FlowCapableNode)
+                .child(Table, new TableKey(flow.getTableId()))
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
+                .build;
+        modification.putConfigurationData(flowPath, flow);
+        return modification.commit();
+    }
+
+    private def Future<RpcResult<TransactionStatus>> internalAddFlowAsync(Node node, Flow flow, long rid){
+        var flowId = getCache().get(flow);
+        if(flowId != null) {
+            removeFlow(node, flow);
+            return internalAddFlowAsync(node, flow, rid);
+        }
+
+        flowId = UUID.randomUUID();
+        getCache().put(flow, flowId);
+
+        return writeFlowAsync(flow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+    }
+
+    private def Future<RpcResult<TransactionStatus>> internalModifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
+        val flowId = getCache().remove(oldFlow);
+        if(flowId == null){
+            throw new IllegalArgumentException("oldFlow is unknown");
+        }
+
+        getCache().put(newFlow, flowId);
+        return writeFlowAsync(newFlow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+    }
+
+
+    private def Future<RpcResult<TransactionStatus>> internalRemoveFlowAsync(Node node, Flow adflow, long rid){
+        val flowId = getCache().remove(adflow);
+        if(flowId == null){
+            throw new IllegalArgumentException("adflow is unknown");
+        }
+        val flow = adflow.toMDFlow(flowId.toString());
+        val modification = this._dataBrokerService.beginTransaction();
+        val flowPath = InstanceIdentifier.builder(Nodes)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, new NodeKey(new NodeId(node.getNodeIDString())))
+                .augmentation(FlowCapableNode)
+                .child(Table, new TableKey(flow.getTableId()))
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
+                .build;
+        modification.removeConfigurationData(flowPath);
+        return modification.commit();
+    }
+
+    private def toFutureStatus(Future<RpcResult<TransactionStatus>> future){
+        try {
+            val result = future.get();
+            return toStatus(result);
+        } catch (InterruptedException e) {
+            return processException(e);
+        } catch (ExecutionException e) {
+            return processException(e);
+        } catch (Exception e){
+            processException(e);
+        }
+        return toStatus(false);
+    }
+
+    private def Map<Flow, UUID> getCache(){
+        if(clusterGlobalServices == null){
+            return new ConcurrentHashMap<Flow, UUID>();
+        }
+
+        var cache = clusterGlobalServices.getCache(CACHE_NAME);
+
+        if(cache == null) {
+            try {
+                cache = clusterGlobalServices.createCache(CACHE_NAME, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            } catch (CacheExistException e) {
+                cache = clusterGlobalServices.getCache(CACHE_NAME);
+            }
+        }
+        return cache as Map<Flow, UUID>;
+
+    }
+
 }
index 56ca1b6..47a3d11 100644 (file)
@@ -137,7 +137,7 @@ class InventoryAndReadAdapter implements IPluginInReadService,
                        for(flow : table.flow){
                                
                                val adsalFlow = ToSalConversionsUtils.toFlow(flow);
-                               val statsFromDataStore = flow.getAugmentation(FlowStatisticsData) as FlowStatisticsData;
+                               val statsFromDataStore = flow.getAugmentation(FlowStatisticsData);
                                
                                if(statsFromDataStore != null){
                                        val it = new FlowOnNode(adsalFlow);
@@ -207,7 +207,7 @@ class InventoryAndReadAdapter implements IPluginInReadService,
                        
                        for (table : dsFlowCapableNode.table){
                                
-                               val tableStats = table.getAugmentation(FlowTableStatisticsData) as FlowTableStatisticsData;
+                               val tableStats = table.getAugmentation(FlowTableStatisticsData);
                                
                                if(tableStats != null){
                                        ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node));
@@ -242,7 +242,7 @@ class InventoryAndReadAdapter implements IPluginInReadService,
                        
                        for(mdsalFlow : table.flow){
                                if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){
-                                       val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData) as FlowStatisticsData;
+                                       val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData);
                                        
                                        if(statsFromDataStore != null){
                                                LOG.debug("Found matching flow in the data store flow table ");
@@ -308,7 +308,7 @@ class InventoryAndReadAdapter implements IPluginInReadService,
                val table= it.readConfigurationData(tableRef) as Table;
                
                if(table != null){
-                       val tableStats = table.getAugmentation(FlowTableStatisticsData) as FlowTableStatisticsData;
+                       val tableStats = table.getAugmentation(FlowTableStatisticsData);
                                
                        if(tableStats != null){
                                nodeStats =  toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node);
@@ -345,7 +345,6 @@ class InventoryAndReadAdapter implements IPluginInReadService,
     }
 
     override onNodeUpdated(NodeUpdated notification) {
-        val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
         val InstanceIdentifier<? extends DataObject> identifier = notification.nodeRef.value  as InstanceIdentifier<? extends DataObject>;
 
         var updateType = UpdateType.CHANGED;
@@ -502,7 +501,7 @@ class InventoryAndReadAdapter implements IPluginInReadService,
         * OpendaylightFlowStatisticsListener interface implementation
         */
        override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
-               throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        //Ignoring this notification as there does not seem to be a way to bubble this up to AD-SAL
        }
        
        override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
@@ -571,4 +570,8 @@ class InventoryAndReadAdapter implements IPluginInReadService,
                
                return it;
        }
+
+       override  getConfiguredNotConnectedNodes() {
+        return Collections.emptySet();
+       }
 }
index b0f6065..5a91e91 100644 (file)
@@ -135,7 +135,7 @@ public class MDFlowMapping {
 
     }
     
-    public static def toMDFlow(Flow sourceFlow) {
+    public static def toMDFlow(Flow sourceFlow, String flowId) {
        if (sourceFlow == null)
             throw new IllegalArgumentException();
        val it = new FlowBuilder();
@@ -143,7 +143,7 @@ public class MDFlowMapping {
        idleTimeout = sourceFlow.idleTimeout as int
        cookie = BigInteger.valueOf(sourceFlow.id)
        priority = sourceFlow.priority as int
-       id = new FlowId(sourceFlow.id)
+       id = new FlowId(flowId)
     
        val sourceActions = sourceFlow.actions;
        val targetActions = new ArrayList<Action>();
index 6fcadea..dc2a7ee 100644 (file)
@@ -16,14 +16,16 @@ import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
 
 class FlowTransaction extends AbstractTransaction {
     
     @Property
-    val SalFlowService salFlowService;
+    val SalFlowService salFlowService;   
+    
     
     new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalFlowService salFlowService) {
-        super(modification)
+        super(modification)        
         _salFlowService = salFlowService;
     }
     
@@ -33,9 +35,10 @@ class FlowTransaction extends AbstractTransaction {
             val tableInstanceId = instanceId.firstIdentifierOf(Table);
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new RemoveFlowInputBuilder(flow);
-            builder.setFlowRef(new FlowRef(instanceId));
+            builder.setFlowRef(new FlowRef(instanceId));            
             builder.setNode(new NodeRef(nodeInstanceId));
             builder.setFlowTable(new FlowTableRef(tableInstanceId));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             _salFlowService.removeFlow(builder.build());            
         }
     }
@@ -50,6 +53,7 @@ class FlowTransaction extends AbstractTransaction {
             builder.setFlowRef(new FlowRef(instanceId));
             val ufb = new UpdatedFlowBuilder(updatedFlow);
             builder.setUpdatedFlow((ufb.build()));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             val ofb = new OriginalFlowBuilder(originalFlow);
             builder.setOriginalFlow(ofb.build());      
             _salFlowService.updateFlow(builder.build());
@@ -64,6 +68,7 @@ class FlowTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new AddFlowInputBuilder(flow);
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             builder.setFlowRef(new FlowRef(instanceId));
             builder.setFlowTable(new FlowTableRef(tableInstanceId));
             _salFlowService.addFlow(builder.build());            
index d68ffa0..f79c9b6 100644 (file)
@@ -14,14 +14,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
 import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
 
 class GroupTransaction extends AbstractTransaction {
     
     @Property
     val SalGroupService groupService;
-    
+        
     new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalGroupService groupService) {
-        super(modification)
+        super(modification)        
         _groupService = groupService;
     }
     
@@ -31,6 +32,7 @@ class GroupTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new RemoveGroupInputBuilder(group);
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             builder.setGroupRef(new GroupRef(instanceId));
             _groupService.removeGroup(builder.build());            
         }
@@ -46,6 +48,7 @@ class GroupTransaction extends AbstractTransaction {
             builder.setGroupRef(new GroupRef(instanceId));
             val ufb = new UpdatedGroupBuilder(updatedGroup);
             builder.setUpdatedGroup((ufb.build()));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             val ofb = new OriginalGroupBuilder(originalGroup);
             builder.setOriginalGroup(ofb.build());      
             _groupService.updateGroup(builder.build());
@@ -60,6 +63,7 @@ class GroupTransaction extends AbstractTransaction {
             val builder = new AddGroupInputBuilder(group);
             builder.setNode(new NodeRef(nodeInstanceId));
             builder.setGroupRef(new GroupRef(instanceId));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             _groupService.addGroup(builder.build());            
         }
     }
index d64f251..594a16c 100644 (file)
@@ -14,14 +14,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter
 import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
 
 class MeterTransaction extends AbstractTransaction {
     
     @Property
     val SalMeterService salMeterService;
-    
+        
     new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalMeterService salMeterService) {
-        super(modification)
+        super(modification)    
         _salMeterService = salMeterService;
     }
     
@@ -32,6 +33,7 @@ class MeterTransaction extends AbstractTransaction {
             val builder = new RemoveMeterInputBuilder(meter);
             builder.setNode(new NodeRef(nodeInstanceId));
             builder.setMeterRef(new MeterRef(instanceId));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             _salMeterService.removeMeter(builder.build());            
         }
     }
@@ -46,6 +48,7 @@ class MeterTransaction extends AbstractTransaction {
             builder.setMeterRef(new MeterRef(instanceId));
             val ufb = new UpdatedMeterBuilder(updatedMeter);
             builder.setUpdatedMeter((ufb.build()));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             val ofb = new OriginalMeterBuilder(originalMeter);
             builder.setOriginalMeter(ofb.build());      
             _salMeterService.updateMeter(builder.build());
@@ -60,6 +63,7 @@ class MeterTransaction extends AbstractTransaction {
             val builder = new AddMeterInputBuilder(meter);
             builder.setNode(new NodeRef(nodeInstanceId));
             builder.setMeterRef(new MeterRef(instanceId));
+            builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
             _salMeterService.addMeter(builder.build());            
         }
     }
index 43754a1..3cc490f 100644 (file)
@@ -49,9 +49,7 @@ module opendaylight-action-types {
                     }
                     
                     leaf max-length {
-                        type uint16 {
-                            range "0..65294";
-                        }
+                        type uint16;
                     }
                 }
             }
@@ -59,9 +57,7 @@ module opendaylight-action-types {
             case controller-action-case {
                 container controller-action {
                  leaf max-length {
-                     type uint16 {
-                         range "0..65294";
-                     }
+                     type uint16;
                  }
              }
             }
index e55c50f..0f5cc71 100644 (file)
@@ -92,7 +92,7 @@ module flow-node-inventory {
     }
 
     typedef flow-id {
-        type uint32; // Note: This doesn't really belong here, and not sure if unint32 is right
+        type inet:uri;
     }
 
     grouping tables {
index bfdf504..00ecdba 100644 (file)
@@ -6,6 +6,8 @@ module packet-processing {
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import ietf-yang-types {prefix yang;revision-date "2010-09-24";} 
     import opendaylight-l2-types {prefix types;revision-date "2013-08-27";}
+    import opendaylight-match-types {prefix match-type;revision-date "2013-10-26";}
+    import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
     
     revision "2013-07-09" {
         description "";
@@ -34,11 +36,44 @@ module packet-processing {
        }
     }
 
+    identity packet-in-reason {
+       description "Base identity for all the available packet in reason"; 
+    }
+    
+    identity no-match {
+       base packet-in-reason;
+       description "No matching flow in the classifier";
+    }
+    
+    identity send-to-controller {
+       base packet-in-reason;
+       description "Explicit instruction to send packet to controller";
+    }
+    
+    identity invalid-ttl {
+       base packet-in-reason;
+       description "Packet with invalid TTL";
+    }
 
     notification packet-received {
        leaf cookie {
                 type cookie;
         }
+        
+        leaf table-id {
+               type table-type:table-id;
+        }
+        
+        leaf packet-in-reason {
+               type identityref {
+                       base packet-in-reason;
+               }
+               }
+        
+        container match {
+                       uses match-type:match;
+        }
+        
         uses raw-packet;
     }
 
@@ -56,4 +91,4 @@ module packet-processing {
                uses raw-packet;
        }
     }
-}
\ No newline at end of file
+}
index 7bbcca3..2b1d993 100644 (file)
@@ -11,6 +11,7 @@ module opendaylight-flow-statistics {
     import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
     import flow-capable-transaction {prefix tr;}
     import sal-flow {prefix flow;}
+    import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
     
 
     revision "2013-08-19" {
@@ -33,7 +34,7 @@ module opendaylight-flow-statistics {
        
        typedef flow-id {
                description "flow id";
-               type yang:counter32;
+               type inet:uri;
        }
        
        grouping flow-and-statistics-map-list {
diff --git a/opendaylight/md-sal/model/model-inventory/src/main/yang/netconf-node-inventory.yang b/opendaylight/md-sal/model/model-inventory/src/main/yang/netconf-node-inventory.yang
new file mode 100644 (file)
index 0000000..b5cde6e
--- /dev/null
@@ -0,0 +1,27 @@
+module netconf-node-inventory {
+    namespace "urn:opendaylight:netconf-node-inventory";
+    prefix "netinv";
+    
+    import opendaylight-inventory { prefix inv; revision-date "2013-08-19";}
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    
+    revision "2014-01-08" {
+        description "Initial revision of Inventory model";
+    }
+    
+    grouping netconf-node-fields {
+        leaf-list initial-capability {
+            type string;
+        }
+        
+        leaf-list current-capability {
+            type string;
+        }
+    }
+    
+    augment /inv:nodes/inv:node {
+        ext:augment-identifier "netconf-node";
+        
+        uses netconf-node-fields;
+    }
+}
\ No newline at end of file
index c91b9dd..e2ce7a9 100644 (file)
     <packaging>bundle</packaging>
     
     <dependencies>
-    <dependency>
-        <groupId>org.opendaylight.controller.model</groupId>
-        <artifactId>model-inventory</artifactId>
-        <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-        <groupId>org.opendaylight.yangtools.model</groupId>
-        <artifactId>ietf-topology</artifactId>
-        <version>2013.07.12.2-SNAPSHOT</version>
-    </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-inventory</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-topology</artifactId>
+            <version>2013.10.21.0-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 </project>
index ceeef45..87de0f5 100644 (file)
@@ -8,7 +8,7 @@ module opendaylight-topology-inventory {
     import ietf-inet-types { prefix "inet"; }
     import opendaylight-inventory {prefix "inv";}
     import opendaylight-topology {prefix "odt";}
-    import network-topology {prefix "topo";}
+    import network-topology {prefix "topo"; revision-date "2013-07-12"; }
 
     organization "TBD";
 
@@ -33,4 +33,4 @@ module opendaylight-topology-inventory {
             type inv:node-connector-ref;
         }
     }
-}
\ No newline at end of file
+}
index 038a1b7..6bbfd4b 100644 (file)
@@ -7,7 +7,7 @@ module opendaylight-topology {
     import yang-ext { prefix "ext"; }
     import ietf-inet-types { prefix "inet"; }
     import opendaylight-inventory {prefix "inv";}
-    import network-topology {prefix "topo";}
+    import network-topology {prefix "topo"; revision-date "2013-07-12"; }
 
     organization "TBD";
 
index 2fecb32..1a10bf6 100644 (file)
@@ -6,7 +6,7 @@ module opendaylight-topology-view  {
 
     import yang-ext { prefix "ext"; }
     import ietf-inet-types { prefix "inet"; }
-    import network-topology {prefix "topo";}
+    import network-topology {prefix "topo"; revision-date "2013-07-12"; }
     import opendaylight-topology {prefix "odl";}
 
     organization "TBD";
@@ -45,4 +45,4 @@ module opendaylight-topology-view  {
         ext:augment-identifier "aggregated-node";
         uses aggregate-node;
     }
-}
\ No newline at end of file
+}
index cdddec7..970e077 100644 (file)
@@ -1,6 +1,7 @@
 package org.opendaylight.controller.sal.binding.dom.serializer.api;
 
 import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 
@@ -12,4 +13,6 @@ public interface AugmentationCodec<A extends Augmentation<?>> extends DomCodec<A
     
     @Override
     public ValueWithQName<A> deserialize(Node<?> input);
+
+    public QName getAugmentationQName();
 }
index b9a4fe8..4565b54 100644 (file)
@@ -10,6 +10,7 @@ import java.util.List;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 
 
 public interface CodecRegistry {
@@ -36,4 +37,6 @@ public interface CodecRegistry {
     void bindingClassEncountered(Class<?> cls);
 
     void putPathToClass(List<QName> names, Class<?> cls);
+
+    public abstract QName getQNameForAugmentation(Class<?> cls);
 }
index 150d0f1..f84503b 100644 (file)
@@ -26,13 +26,13 @@ import org.opendaylight.yangtools.yang.binding.Augmentable
 import com.google.common.collect.ImmutableList
 import org.opendaylight.yangtools.yang.binding.Augmentation
 import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections
 
 class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
     
     private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
     val CodecRegistry codecRegistry;
     
-    val Map<Class<?>,QName> classToQName = new WeakHashMap;
     val Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = new WeakHashMap;
     
     public new(CodecRegistry registry) {
@@ -106,7 +106,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
                 
                 previousAugmentation = null;
             } else {
-                previousQName = resolveQname(baArg.type);
+                previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class);
                 previousAugmentation = baArg.type;
             }
         }
@@ -122,7 +122,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
     
     private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
         val type = argument.type;
-        val qname = resolveQname(type);
+        val qname = BindingReflections.findQName(type);
         if(previousQname == null) {
             return new NodeIdentifier(qname);
         }
@@ -134,7 +134,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         val Map<QName,Object> predicates = new HashMap();
         val type = argument.type;
         val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
-        val qname = resolveQname(type);
+        val qname = BindingReflections.findQName(type);
         val combinedInput =  new ValueWithQName(previousQname,argument.key)
         val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
         for(outputValue :compositeOutput.value) {
@@ -145,15 +145,4 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         }
         return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);
     }
-    
-    def resolveQname(Class<?> class1) {
-        val qname = classToQName.get(class1);
-        if(qname !== null) {
-            return qname;
-        }
-        val qnameField = class1.getField("QNAME");
-        val qnameValue = qnameField.get(null) as QName;
-        classToQName.put(class1,qnameValue);
-        return qnameValue;
-    }
 }
\ No newline at end of file
index cabb1bc..89d9b49 100644 (file)
@@ -44,6 +44,7 @@ import org.opendaylight.yangtools.yang.binding.BindingCodec;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
@@ -153,6 +154,12 @@ public class LazyGeneratedCodecRegistry implements //
         }
         return codec;
     }
+    
+    @Override
+    public QName getQNameForAugmentation(Class<?> cls) {
+        checkArgument(Augmentation.class.isAssignableFrom(cls));
+        return getCodecForAugmentation((Class<? extends Augmentation>)cls).getAugmentationQName();
+    }
 
     private static Class<? extends Augmentable<?>> getAugmentableArgumentFrom(
             final Class<? extends Augmentation<?>> augmentation) {
@@ -909,9 +916,11 @@ public class LazyGeneratedCodecRegistry implements //
             Delegator<BindingCodec> {
 
         private BindingCodec delegate;
+        private QName augmentationQName;
 
         public AugmentationCodecWrapper(BindingCodec<Map<QName, Object>, Object> rawCodec) {
             this.delegate = rawCodec;
+            this.augmentationQName = BindingReflections.findQName(rawCodec.getClass());
         }
 
         @Override
@@ -936,6 +945,11 @@ public class LazyGeneratedCodecRegistry implements //
             Object rawCodecValue = getDelegate().deserialize((Map<QName, Object>) input);
             return new ValueWithQName<T>(input.getNodeType(), (T) rawCodecValue);
         }
+        
+        @Override
+        public QName getAugmentationQName() {
+            return augmentationQName;
+        }
     }
 
     private class IdentityCompositeCodec implements IdentitityCodec {
index b10c06f..b0939a0 100644 (file)
@@ -20,8 +20,9 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
 import org.opendaylight.yangtools.concepts.ListenerRegistration\r
 import org.opendaylight.yangtools.concepts.Registration\r
 import org.opendaylight.yangtools.yang.binding.Notification\r
-import org.slf4j.LoggerFactory\rimport org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder
-
+import org.slf4j.LoggerFactory\r
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\r
+\r
 class NotificationBrokerImpl implements NotificationProviderService, AutoCloseable {\r
 \r
     val Multimap<Class<? extends Notification>, NotificationListener<?>> listeners;\r
@@ -178,10 +179,19 @@ class NotifyTask implements Callable<Object> {
     val Notification notification;\r
 \r
     override call() {\r
+        //Only logging the complete notification in debug mode\r
         try {\r
-            log.info("Delivering notification {} to {}",notification,listener);\r
+            if(log.isDebugEnabled){\r
+                log.debug("Delivering notification {} to {}",notification,listener);\r
+            } else {\r
+                log.info("Delivering notification {} to {}",notification.class.name,listener);\r
+            }\r
             listener.onNotification(notification);\r
-            log.info("Notification delivered {} to {}",notification,listener);\r
+            if(log.isDebugEnabled){\r
+                log.debug("Notification delivered {} to {}",notification,listener);\r
+            } else {\r
+                log.info("Notification delivered {} to {}",notification.class.name,listener);\r
+            }\r
         } catch (Exception e) {\r
             log.error("Unhandled exception thrown by listener: {}", listener, e);\r
         }\r
index 1304f0d..e31ae6b 100644 (file)
@@ -1,35 +1,10 @@
 package org.opendaylight.controller.sal.binding.test.bugfix;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+import com.google.common.collect.ImmutableSet;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
@@ -48,16 +23,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -65,21 +37,21 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 public class FlagsSerializationTest extends AbstractDataServiceTest {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
     private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
     private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
-    private static final long FLOW_ID = 1234;
+    private static final String FLOW_ID = "1234";
     private static final short TABLE_ID = (short)0;
     private static final String NODE_ID = "node:1";
 
index ea36f81..55bff1a 100644 (file)
@@ -1,15 +1,6 @@
 package org.opendaylight.controller.sal.binding.test.connect.dom;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Future;
-
+import com.google.common.collect.ImmutableMap;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
@@ -17,13 +8,11 @@ import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.CommitHandlersTransactions;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
@@ -44,14 +33,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -59,7 +44,14 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
 
@@ -69,7 +61,7 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
     private static final QName TABLE_ID_QNAME = QName.create(Table.QNAME, "id");
 
     private static final String NODE_ID = "node:1";
-    private static final FlowId FLOW_ID = new FlowId(1234L);
+    private static final FlowId FLOW_ID = new FlowId("1234");
     private static final Short TABLE_ID = Short.valueOf((short) 0);
 
     private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
index 4740b0d..10e7946 100644 (file)
             <artifactId>sal-common-impl</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-core-spi</artifactId>
index 2323b09..67e2934 100644 (file)
             <scope>test</scope>
             <version>${netconf.version}</version>
         </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>yang-test</artifactId>
-            <scope>test</scope>
-            <version>${netconf.version}</version>
-        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>config-manager</artifactId>
index 6c72a61..d5648a0 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-impl</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-common</artifactId>
-    </dependency>
 
     <!-- Third Party -->
     <dependency>
index 5e798b6..0bd86a3 100644 (file)
@@ -42,7 +42,7 @@
       <artifactId>yang-data-impl</artifactId>
       <version>${yang.version}</version>
     </dependency>
-        <dependency>
+    <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-model-util</artifactId>
       <version>${yang.version}</version>
       <version>2.4</version>
       <scope>test</scope>
     </dependency>
-    <dependency>
-       <groupId>org.opendaylight.yangtools</groupId>
-       <artifactId>yang-model-util</artifactId>
-       <version>0.5.9-SNAPSHOT</version>
-    </dependency>
   </dependencies>
 
   <build>
index 012b51f..60a8f28 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.sal.rest.api;
 
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -66,30 +68,50 @@ public interface RestconfService extends RestconfServiceLegacy {
     @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
                Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+    @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+               Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
     
+    @POST
+    @Path("/operations/{identifier}")
+    @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+               Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+    public StructuredData invokeRpc(@PathParam("identifier") String identifier);
+    
     @GET
     @Path("/config/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
-    
-    @POST
-    @Path("/config/{identifier:.+}")
+
+    @GET
+    @Path("/operational/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public StructuredData readOperationalData(@PathParam("identifier") String identifier);
 
     @PUT
     @Path("/config/{identifier:.+}")
-    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+    @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
 
-    @GET
-    @Path("/operational/{identifier:.+}")
-    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+    @POST
+    @Path("/config/{identifier:.+}")
+    @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public StructuredData readOperationalData(@PathParam("identifier") String identifier);
+    public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+
+    @POST
+    @Path("/config")
+    @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+    public Response createConfigurationData(CompositeNode payload);
+
+    @DELETE
+    @Path("/config/{identifier:.+}")
+    public Response deleteConfigurationData(@PathParam("identifier") String identifier);
 
 }
index 35da98b..9b69c1f 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.sal.rest.api;
 
+import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -33,14 +34,14 @@ public interface RestconfServiceLegacy {
     @Deprecated
     @POST
     @Path("/datastore/{identifier:.+}")
-    @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, 
+    @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @Deprecated
     @PUT
     @Path("/datastore/{identifier:.+}")
-    @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, 
+    @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
 
index 8b1bdef..7f7e860 100644 (file)
@@ -194,7 +194,7 @@ class JsonMapper {
             if (node.getValue() instanceof QName) {
                 IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType).serialize(node.getValue());
                 IdentityValue valueFromDTO = valueDTO.getValuesWithNamespaces().get(0);
-                String moduleName = ControllerContext.getInstance().findModuleByNamespace(
+                String moduleName = ControllerContext.getInstance().findModuleNameByNamespace(
                         URI.create(valueFromDTO.getNamespace()));
                 writer.value(moduleName + ":" + valueFromDTO.getValue());
             } else {
index df6b58c..3436018 100644 (file)
@@ -41,13 +41,13 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
 
     override readConfigurationData(InstanceIdentifier path) {
         checkPreconditions
-        LOG.info("Read Configuration via Restconf: {}",path)
+        LOG.info("Read Configuration via Restconf: {}", path)
         return dataService.readConfigurationData(path);
     }
 
     override readOperationalData(InstanceIdentifier path) {
         checkPreconditions
-        LOG.info("Read Operational via Restconf: {}",path)
+        LOG.info("Read Operational via Restconf: {}", path)
         return dataService.readOperationalData(path);
     }
 
@@ -60,15 +60,28 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
     def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
         checkPreconditions
         val transaction = dataService.beginTransaction;
+        LOG.info("Put Configuration via Restconf: {}", path)
         transaction.putConfigurationData(path, payload);
-        return transaction.commit()
+        return transaction.commit
     }
 
-    def commitOperationalDataPut(InstanceIdentifier path, CompositeNode payload) {
+    def commitConfigurationDataPost(InstanceIdentifier path, CompositeNode payload) {
         checkPreconditions
         val transaction = dataService.beginTransaction;
-        transaction.putOperationalData(path, payload);
-        return transaction.commit()
+        transaction.putConfigurationData(path, payload);
+        if (payload == transaction.createdConfigurationData.get(path)) {
+            LOG.info("Post Configuration via Restconf: {}", path)
+            return transaction.commit
+        }
+        LOG.info("Post Configuration via Restconf was not executed because data already exists: {}", path)
+        return null;
     }
-    
+
+    def commitConfigurationDataDelete(InstanceIdentifier path) {
+        checkPreconditions
+        val transaction = dataService.beginTransaction;
+        transaction.removeConfigurationData(path)
+        return transaction.commit
+    }
+
 }
index 0ded60d..74a32d4 100644 (file)
@@ -78,6 +78,11 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
         Preconditions.checkState(compositeNode == null, "Data can be inconsistent.");
         return Collections.unmodifiableList(values);
     }
+    
+    @Override
+    public boolean isChangeAllowed() {
+        return compositeNode == null ? true : false;
+    }
 
     @Override
     public CompositeNode unwrap() {
@@ -230,4 +235,5 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
     public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
         return unwrap().entrySet();
     }
+
 }
index 1a60e14..308975c 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Map
 import java.util.concurrent.ConcurrentHashMap
 import javax.ws.rs.core.Response
 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.controller.sal.core.api.mount.MountService
 import org.opendaylight.controller.sal.rest.impl.RestUtil
 import org.opendaylight.controller.sal.rest.impl.RestconfProvider
 import org.opendaylight.yangtools.yang.common.QName
@@ -26,16 +27,17 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceNode
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.Module
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
 import org.slf4j.LoggerFactory
 
 import static com.google.common.base.Preconditions.*
-import org.opendaylight.controller.sal.core.api.mount.MountService
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import java.util.ArrayList
 
 class ControllerContext implements SchemaServiceListener {
     val static LOG = LoggerFactory.getLogger(ControllerContext)
@@ -73,6 +75,7 @@ class ControllerContext implements SchemaServiceListener {
     }
 
     public def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) {
+        checkPreconditions
         val ret = InstanceIdentifier.builder();
         val pathArgs = restconfInstance.split("/");
         if (pathArgs.empty) {
@@ -81,24 +84,28 @@ class ControllerContext implements SchemaServiceListener {
         if (pathArgs.head.empty) {
             pathArgs.remove(0)
         }
-        val schemaNode = ret.collectPathArguments(pathArgs, globalSchema.findModule(pathArgs.head));
+        val mountPoints = new ArrayList
+        val schemaNode = ret.collectPathArguments(pathArgs, globalSchema.findModule(pathArgs.head), mountPoints);
         if (schemaNode === null) {
             return null
         }
-        return new InstanceIdWithSchemaNode(ret.toInstance, schemaNode)
+        return new InstanceIdWithSchemaNode(ret.toInstance, schemaNode, mountPoints.last)
     }
 
-    private static def findModule(SchemaContext context,String argument) {
-        //checkPreconditions
+    private def findModule(SchemaContext context,String argument) {
         checkNotNull(argument);
         val startModule = argument.toModuleName();
         return context.getLatestModule(startModule)
     }
-
-    static def getLatestModule(SchemaContext schema,String moduleName) {
-        checkArgument(schema != null);
+    
+    private def getLatestModule(SchemaContext schema,String moduleName) {
+        checkArgument(schema !== null);
         checkArgument(moduleName !== null && !moduleName.empty)
         val modules = schema.modules.filter[m|m.name == moduleName]
+        return modules.filterLatestModule
+    }
+    
+    private def filterLatestModule(Iterable<Module> modules) {
         var latestModule = modules.head
         for (module : modules) {
             if (module.revision.after(latestModule.revision)) {
@@ -107,6 +114,31 @@ class ControllerContext implements SchemaServiceListener {
         }
         return latestModule
     }
+    
+    def findModuleByName(String moduleName) {
+        checkPreconditions
+        checkArgument(moduleName !== null && !moduleName.empty)
+        return globalSchema.getLatestModule(moduleName)
+    }
+    
+    def findModuleByName(String moduleName, InstanceIdentifier partialPath) {
+        checkArgument(moduleName !== null && !moduleName.empty && partialPath !== null && !partialPath.path.empty)
+        val mountPointSchema = mountService?.getMountPoint(partialPath)?.schemaContext;
+        return mountPointSchema?.getLatestModule(moduleName);
+    }
+    
+    def findModuleByNamespace(URI namespace) {
+        checkPreconditions
+        val moduleSchemas = globalSchema.findModuleByNamespace(namespace)
+        return moduleSchemas?.filterLatestModule
+    }
+    
+    def findModuleByNamespace(URI namespace, InstanceIdentifier partialPath) {
+        checkArgument(namespace !== null && !namespace.toString.empty && partialPath !== null && !partialPath.path.empty)
+        val mountPointSchema = mountService?.getMountPoint(partialPath)?.schemaContext;
+        val moduleSchemas = mountPointSchema?.findModuleByNamespace(namespace)
+        return moduleSchemas?.filterLatestModule
+    }
 
     def String toFullRestconfIdentifier(InstanceIdentifier path) {
         checkPreconditions
@@ -136,18 +168,13 @@ class ControllerContext implements SchemaServiceListener {
         throw new IllegalArgumentException("Conversion of generic path argument is not supported");
     }
 
-    def findModuleByNamespace(URI namespace) {
+    def findModuleNameByNamespace(URI namespace) {
         checkPreconditions
         var module = uriToModuleName.get(namespace)
         if (module === null) {
             val moduleSchemas = globalSchema.findModuleByNamespace(namespace);
             if(moduleSchemas === null) return null
-            var latestModule = moduleSchemas.head
-            for (m : moduleSchemas) {
-                if (m.revision.after(latestModule.revision)) {
-                    latestModule = m
-                }
-            }
+            var latestModule = moduleSchemas.filterLatestModule
             if(latestModule === null) return null
             uriToModuleName.put(namespace, latestModule.name)
             module = latestModule.name;
@@ -155,16 +182,10 @@ class ControllerContext implements SchemaServiceListener {
         return module
     }
 
-    def findNamespaceByModule(String module) {
+    def findNamespaceByModuleName(String module) {
         var namespace = moduleNameToUri.get(module)
         if (namespace === null) {
-            val moduleSchemas = globalSchema.modules.filter[it|it.name.equals(module)]
-            var latestModule = moduleSchemas.head
-            for (m : moduleSchemas) {
-                if (m.revision.after(latestModule.revision)) {
-                    latestModule = m
-                }
-            }
+            var latestModule = globalSchema.getLatestModule(module)
             if(latestModule === null) return null
             namespace = latestModule.namespace
             uriToModuleName.put(namespace, latestModule.name)
@@ -235,7 +256,7 @@ class ControllerContext implements SchemaServiceListener {
     }
 
     private def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
-        DataNodeContainer parentNode) {
+        DataNodeContainer parentNode, List<InstanceIdentifier> mountPoints) {
         checkNotNull(strings)
         if (parentNode === null) {
             return null;
@@ -255,8 +276,12 @@ class ControllerContext implements SchemaServiceListener {
             // Node is possibly in other mount point
             val partialPath = builder.toInstance;
             val mountPointSchema = mountService?.getMountPoint(partialPath)?.schemaContext;
-            if(mountPointSchema != null) {
-                return builder.collectPathArguments(strings, mountPointSchema.findModule(strings.head));
+            if(mountPointSchema !== null) {
+                val module = mountPointSchema.findModule(strings.head)
+                if (module !== null) {
+                    mountPoints.add(partialPath)
+                }
+                return builder.collectPathArguments(strings, module, mountPoints);
             }
             return null
         }
@@ -294,7 +319,7 @@ class ControllerContext implements SchemaServiceListener {
         }
         if (targetNode instanceof DataNodeContainer) {
             val remaining = strings.subList(consumed, strings.length);
-            val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer);
+            val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer, mountPoints);
             return result
         }
 
@@ -310,7 +335,7 @@ class ControllerContext implements SchemaServiceListener {
         val allCases = container.childNodes.filter(ChoiceNode).map[cases].flatten
         for (caze : allCases) {
             potentialNode = caze.findInstanceDataChild(name);
-            if(potentialNode != null) {
+            if(potentialNode !== null) {
                 return potentialNode;
             }
         }
index c146954..cdb9599 100644 (file)
@@ -64,6 +64,11 @@ public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void>
         this.namespace = namespace;
     }
 
+    @Override
+    public boolean isChangeAllowed() {
+        return unwrapped == null ? true : false;
+    }
+
     @Override
     public Node<?> unwrap() {
         if (unwrapped == null) {
index ad0654a..ba0e47f 100644 (file)
@@ -7,10 +7,12 @@ public class InstanceIdWithSchemaNode {
 
     private final InstanceIdentifier instanceIdentifier;
     private final DataSchemaNode schemaNode;
+    private final InstanceIdentifier mountPoint;
 
-    public InstanceIdWithSchemaNode(InstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode) {
+    public InstanceIdWithSchemaNode(InstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode, InstanceIdentifier mountPoint) {
         this.instanceIdentifier = instanceIdentifier;
         this.schemaNode = schemaNode;
+        this.mountPoint = mountPoint;
     }
 
     public InstanceIdentifier getInstanceIdentifier() {
@@ -21,4 +23,8 @@ public class InstanceIdWithSchemaNode {
         return schemaNode;
     }
 
+    public InstanceIdentifier getMountPoint() {
+        return mountPoint;
+    }
+
 }
index 40fba88..45f3f7f 100644 (file)
@@ -107,7 +107,7 @@ public class RestCodec {
         public QName deserialize(IdentityValuesDTO data) {
             IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
             String namespace = valueWithNamespace.getNamespace();
-            URI validNamespace = ControllerContext.getInstance().findNamespaceByModule(namespace);
+            URI validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(namespace);
             if (validNamespace == null) {
                 validNamespace = URI.create(namespace);
             }
index 4645a41..a65c0ff 100644 (file)
@@ -1,6 +1,7 @@
 package org.opendaylight.controller.sal.restconf.impl
 
 import java.util.ArrayList
+import java.util.HashMap
 import java.util.List
 import java.util.Set
 import javax.ws.rs.core.Response
@@ -8,6 +9,8 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus
 import org.opendaylight.controller.sal.rest.api.RestconfService
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder
 import org.opendaylight.yangtools.yang.data.api.Node
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
@@ -17,10 +20,12 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.Module
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
 
 import static javax.ws.rs.core.Response.Status.*
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 
 class RestconfImpl implements RestconfService {
 
@@ -55,41 +60,27 @@ class RestconfImpl implements RestconfService {
         return null;
     }
 
-    override readData(String identifier) {
-        val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
-        val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
-        return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
-    }
-
-    override createConfigurationData(String identifier, CompositeNode payload) {
-        val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
-        val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
-        val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
-        switch status.result {
-            case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
-            default: Response.status(INTERNAL_SERVER_ERROR).build
-        }
+    override invokeRpc(String identifier, CompositeNode payload) {
+        return callRpc(identifier.rpcDefinition, payload)
     }
-
-    override updateConfigurationData(String identifier, CompositeNode payload) {
-        val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
-        val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
-        val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
-        switch status.result {
-            case TransactionStatus.COMMITED: Response.status(OK).build
-            default: Response.status(INTERNAL_SERVER_ERROR).build
-        }
+    
+    override invokeRpc(String identifier) {
+        return callRpc(identifier.rpcDefinition, null)
     }
-
-    override invokeRpc(String identifier, CompositeNode payload) {
-        val rpc = identifier.rpcDefinition
+    
+    private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) {
         if (rpc === null) {
             throw new ResponseException(NOT_FOUND, "RPC does not exist.");
         }
-        val value = normalizeNode(payload, rpc.input)
-        val List<Node<?>> input = new ArrayList
-        input.add(value)
-        val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
+        var CompositeNode rpcRequest;
+        if (payload === null) {
+            rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, null, null, null)
+        } else {
+            val value = normalizeNode(payload, rpc.input, null)
+            val List<Node<?>> input = new ArrayList
+            input.add(value)
+            rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
+        }
         val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest);
         if (!rpcResult.successful) {
             throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed")
@@ -100,6 +91,12 @@ class RestconfImpl implements RestconfService {
         return new StructuredData(rpcResult.result, rpc.output)
     }
 
+    override readData(String identifier) {
+        val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
+        val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+        return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+    }
+
     override readConfigurationData(String identifier) {
         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
@@ -116,10 +113,61 @@ class RestconfImpl implements RestconfService {
         updateConfigurationData(identifier, payload);
     }
 
+    override updateConfigurationData(String identifier, CompositeNode payload) {
+        val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
+        val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode, identifierWithSchemaNode.mountPoint)
+        val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
+        switch status.result {
+            case TransactionStatus.COMMITED: Response.status(OK).build
+            default: Response.status(INTERNAL_SERVER_ERROR).build
+        }
+    }
+
     override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
         createConfigurationData(identifier, payload);
     }
 
+    override createConfigurationData(String identifier, CompositeNode payload) {
+        val uncompleteIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
+        var schemaNode = (uncompleteIdentifierWithSchemaNode.schemaNode as DataNodeContainer).getSchemaChildNode(payload)
+        if (schemaNode === null) {
+            schemaNode = payload.findModule(uncompleteIdentifierWithSchemaNode.instanceIdentifier)?.getSchemaChildNode(payload)
+        }
+        val value = normalizeNode(payload, schemaNode, uncompleteIdentifierWithSchemaNode.instanceIdentifier)
+        val completeIdentifierWithSchemaNode = uncompleteIdentifierWithSchemaNode.addLastIdentifierFromData(value, schemaNode)
+        val status = broker.commitConfigurationDataPost(completeIdentifierWithSchemaNode.instanceIdentifier, value)?.get();
+        if (status === null) {
+            return Response.status(ACCEPTED).build
+        }
+        switch status.result {
+            case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
+            default: Response.status(INTERNAL_SERVER_ERROR).build
+        }
+    }
+    
+    override createConfigurationData(CompositeNode payload) {
+        val schemaNode = payload.findModule(null)?.getSchemaChildNode(payload)
+        val value = normalizeNode(payload, schemaNode, null)
+        val identifierWithSchemaNode = addLastIdentifierFromData(null, value, schemaNode)
+        val status = broker.commitConfigurationDataPost(identifierWithSchemaNode.instanceIdentifier, value)?.get();
+        if (status === null) {
+            return Response.status(ACCEPTED).build
+        }
+        switch status.result {
+            case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
+            default: Response.status(INTERNAL_SERVER_ERROR).build
+        }
+    }
+    
+    override deleteConfigurationData(String identifier) {
+        val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
+        val status = broker.commitConfigurationDataDelete(instanceIdentifierWithSchemaNode.getInstanceIdentifier).get;
+        switch status.result {
+            case TransactionStatus.COMMITED: Response.status(OK).build
+            default: Response.status(INTERNAL_SERVER_ERROR).build
+        }
+    }
+
     private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
         val identifierWithSchemaNode = identifier.toInstanceIdentifier
         if (identifierWithSchemaNode === null) {
@@ -128,18 +176,89 @@ class RestconfImpl implements RestconfService {
         return identifierWithSchemaNode
     }
 
-    private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) {
+    private def dispatch Module findModule(CompositeNode data, InstanceIdentifier partialPath) {
+        if (partialPath !== null && !partialPath.path.empty) {
+            return data.nodeType.namespace.findModuleByNamespace(partialPath)
+        } else {
+            return data.nodeType.namespace.findModuleByNamespace
+        }
+    }
+
+    private def dispatch Module findModule(CompositeNodeWrapper data, InstanceIdentifier partialPath) {
+        var Module module = null;
+        if (partialPath !== null && !partialPath.path.empty) {
+            module = data.namespace.findModuleByNamespace(partialPath) // namespace from XML
+            if (module === null) {
+                module = data.namespace.toString.findModuleByName(partialPath) // namespace (module name) from JSON
+            }
+        } else {
+            module = data.namespace.findModuleByNamespace // namespace from XML
+            if (module === null) {
+                module = data.namespace.toString.findModuleByName // namespace (module name) from JSON
+            }
+        }
+        return module
+    }
+    
+    private def dispatch DataSchemaNode getSchemaChildNode(DataNodeContainer parentSchemaNode, CompositeNode data) {
+        return parentSchemaNode?.getDataChildByName(data.nodeType.localName)
+    }
+    
+    private def dispatch DataSchemaNode getSchemaChildNode(DataNodeContainer parentSchemaNode, CompositeNodeWrapper data) {
+        return parentSchemaNode?.getDataChildByName(data.localName)
+    }
+
+    private def InstanceIdWithSchemaNode addLastIdentifierFromData(InstanceIdWithSchemaNode identifierWithSchemaNode, CompositeNode data, DataSchemaNode schemaOfData) {
+        val iiOriginal = identifierWithSchemaNode?.instanceIdentifier
+        var  InstanceIdentifierBuilder iiBuilder = null
+        if (iiOriginal === null) { 
+            iiBuilder = InstanceIdentifier.builder
+        } else {
+            iiBuilder = InstanceIdentifier.builder(iiOriginal)
+        }
+
+        if (schemaOfData instanceof ListSchemaNode) {
+            iiBuilder.nodeWithKey(schemaOfData.QName, (schemaOfData as ListSchemaNode).resolveKeysFromData(data))
+        } else {
+            iiBuilder.node(schemaOfData.QName)
+        }
+        return new InstanceIdWithSchemaNode(iiBuilder.toInstance, schemaOfData, identifierWithSchemaNode?.mountPoint)
+    }
+
+    private def resolveKeysFromData(ListSchemaNode listNode, CompositeNode dataNode) {
+        val keyValues = new HashMap<QName, Object>();
+        for (key : listNode.keyDefinition) {
+            val dataNodeKeyValueObject = dataNode.getSimpleNodesByName(key.localName)?.head?.value
+            if (dataNodeKeyValueObject === null) {
+                throw new ResponseException(BAD_REQUEST, "Data contains list \"" + dataNode.nodeType.localName + "\" which does not contain key: \"" + key.localName + "\"")
+            }
+            keyValues.put(key, dataNodeKeyValueObject);
+        }
+        return keyValues
+    }
+
+    private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema, InstanceIdentifier mountPoint) {
+        if (schema !== null && !schema.containerOrList) {
+            throw new ResponseException(BAD_REQUEST, "Root element has to be container or list yang datatype.");
+        }
         if (node instanceof CompositeNodeWrapper) {
-            normalizeNode(node as CompositeNodeWrapper, schema, null)
+            if ((node  as CompositeNodeWrapper).changeAllowed) {
+                normalizeNode(node as CompositeNodeWrapper, schema, null, mountPoint)
+            }
             return (node as CompositeNodeWrapper).unwrap()
         }
         return node
     }
 
-    private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment) {
+    private def isContainerOrList(DataSchemaNode schemaNode) {
+        return (schemaNode instanceof ContainerSchemaNode) || (schemaNode instanceof ListSchemaNode)
+    }
+
+    private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment,
+        InstanceIdentifier mountPoint) {
         if (schema === null) {
             throw new ResponseException(BAD_REQUEST,
-                "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
+                "Data has bad format.\n\"" + nodeBuilder.localName + "\" does not exist in yang schema.");
         }
         var validQName = schema.QName
         var currentAugment = previousAugment;
@@ -148,15 +267,18 @@ class RestconfImpl implements RestconfService {
         } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
             validQName = QName.create(currentAugment, schema.QName.localName);
         }
-        val moduleName = controllerContext.findModuleByNamespace(validQName.namespace);
+        var moduleName = controllerContext.findModuleNameByNamespace(validQName.namespace);
+        if (moduleName === null && mountPoint !== null && !mountPoint.path.empty) {
+            moduleName = controllerContext.findModuleByNamespace(validQName.namespace, mountPoint)?.name
+        }
         if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
             nodeBuilder.namespace.toString == moduleName) {
             nodeBuilder.qname = validQName
         } else {
             throw new ResponseException(BAD_REQUEST,
-                "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
-                    " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
-                    nodeBuilder.localName + " should be " + moduleName + ".");
+                "Data has bad format.\nIf data is in XML format then namespace for \"" + nodeBuilder.localName +
+                    "\" should be \"" + schema.QName.namespace + "\".\nIf data is in Json format then module name for \"" +
+                    nodeBuilder.localName + "\" should be \"" + moduleName + "\".");
         }
 
         if (nodeBuilder instanceof CompositeNodeWrapper) {
@@ -164,7 +286,7 @@ class RestconfImpl implements RestconfService {
             for (child : children) {
                 normalizeNode(child,
                     findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),
-                    currentAugment)
+                    currentAugment, mountPoint)
             }
             if(schema instanceof ListSchemaNode) {
                 val listKeys = (schema as ListSchemaNode).keyDefinition
@@ -177,7 +299,7 @@ class RestconfImpl implements RestconfService {
                     }
                     if (!foundKey) {
                         throw new ResponseException(BAD_REQUEST,
-                            "Missing key \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"")
+                            "Missing key in URI \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"")
                     }
                 }
             }
index 97f8102..6aa8ada 100644 (file)
@@ -58,6 +58,11 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
         this.namespace = namespace;
     }
 
+    @Override
+    public boolean isChangeAllowed() {
+        return simpleNode == null ? true : false;
+    }
+
     @Override
     public SimpleNode<Object> unwrap() {
         if (simpleNode == null) {
index f2c0c29..afe458d 100644 (file)
@@ -13,7 +13,6 @@ import javax.ws.rs.WebApplicationException;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -207,15 +206,8 @@ public class JsonToCnSnTest {
         assertEquals("lst", compNode.getNodeType().getLocalName());
         verifyCompositeNode(compNode, "simple:list:yang1");
 
-        String exceptionMessage = "";
-        try {
-            TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst");
-        } catch (ResponseException e) {
-            exceptionMessage = String.valueOf(e.getResponse().getEntity());
-        }
-        assertTrue(exceptionMessage
-                .contains("Data has bad format\nIf data is in XML format then namespace for lst should be simple:list:yang2.\n If data is in Json format then module name for lst should be simple-list-yang2."));
-
+        TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst");
+        verifyCompositeNode(compNode, "simple:list:yang1");
     }
 
     @Test
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DeleteRestCallTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DeleteRestCallTest.java
new file mode 100644 (file)
index 0000000..7b164d4
--- /dev/null
@@ -0,0 +1,101 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
+import org.opendaylight.controller.sal.rest.impl.XmlMapper;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import com.google.common.base.Charsets;
+
+public class DeleteRestCallTest extends JerseyTest {
+
+    private static ControllerContext controllerContext;
+    private static BrokerFacade brokerFacade;
+    private static RestconfImpl restconfImpl;
+    private static final MediaType MEDIA_TYPE_DRAFT02 = new MediaType("application", "yang.data+xml");
+
+    @BeforeClass
+    public static void init() throws FileNotFoundException {
+        Set<Module> allModules = TestUtils.loadModulesFrom("/test-config-data/yang1");
+        assertNotNull(allModules);
+        SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+        controllerContext = ControllerContext.getInstance();
+        controllerContext.setSchemas(schemaContext);
+        brokerFacade = mock(BrokerFacade.class);
+        restconfImpl = RestconfImpl.getInstance();
+        restconfImpl.setBroker(brokerFacade);
+        restconfImpl.setControllerContext(controllerContext);
+    }
+
+    @Test
+    public void testDeleteConfigurationData() throws UnsupportedEncodingException, FileNotFoundException {
+        String uri2 = createUri("/config/", "test-interface:interfaces");
+
+        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
+                TransactionStatus.COMMITED).build();
+        Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+        when(brokerFacade.commitConfigurationDataDelete(any(InstanceIdentifier.class))).thenReturn(dummyFuture);
+
+        Response response = target(uri2).request(MEDIA_TYPE_DRAFT02).delete();
+        assertEquals(200, response.getStatus());
+
+        rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(TransactionStatus.FAILED).build();
+        dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+
+        when(brokerFacade.commitConfigurationDataDelete(any(InstanceIdentifier.class))).thenReturn(dummyFuture);
+
+        response = target(uri2).request(MEDIA_TYPE_DRAFT02).delete();
+        assertEquals(500, response.getStatus());
+    }
+
+    private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
+        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
+    }
+
+    @Override
+    protected Application configure() {
+        enable(TestProperties.LOG_TRAFFIC);
+        enable(TestProperties.DUMP_ENTITY);
+        enable(TestProperties.RECORD_LOG_LEVEL);
+        set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue());
+
+        ResourceConfig resourceConfig = new ResourceConfig();
+        resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
+                XmlToCompositeNodeProvider.INSTANCE);
+        return resourceConfig;
+    }
+}
index 2370035..c5f5a1e 100644 (file)
@@ -60,7 +60,7 @@ public class InvokeRpcMethodTest {
         ControllerContext contContext = ControllerContext.getInstance();
         contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules));
         try {
-            contContext.findModuleByNamespace(new URI("invoke:rpc:module"));
+            contContext.findModuleNameByNamespace(new URI("invoke:rpc:module"));
         } catch (URISyntaxException e) {
             assertTrue("Uri wasn't created sucessfuly", false);
         }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/NormalizeNodeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/NormalizeNodeTest.java
new file mode 100644 (file)
index 0000000..83e6ae5
--- /dev/null
@@ -0,0 +1,83 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.*;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public class NormalizeNodeTest extends YangAndXmlAndDataSchemaLoader {
+
+    @BeforeClass
+    public static void initialization() {
+        dataLoad("/normalize-node/yang/");
+    }
+
+    @Test
+    public void namespaceNotNullAndInvalidNamespaceAndNoModuleNameTest() {
+        boolean exceptionReised = false;
+        try {
+            TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath);
+        } catch (ResponseException e) {
+            exceptionReised = true;
+        }
+        assertTrue(exceptionReised);
+    }
+
+    @Test
+    public void namespaceNullTest() {
+        String exceptionMessage = null;
+        try {
+            TestUtils.normalizeCompositeNode(prepareCnSn(null), modules, schemaNodePath);
+        } catch (ResponseException e) {
+            exceptionMessage = String.valueOf(e.getResponse().getEntity());
+        }
+        assertNull(exceptionMessage);
+    }
+
+    @Test
+    public void namespaceValidNamespaceTest() {
+        String exceptionMessage = null;
+        try {
+            TestUtils.normalizeCompositeNode(prepareCnSn("normalize:node:module"), modules, schemaNodePath);
+        } catch (ResponseException e) {
+            exceptionMessage = String.valueOf(e.getResponse().getEntity());
+        }
+        assertNull(exceptionMessage);
+    }
+
+    @Test
+    public void namespaceValidModuleNameTest() {
+        String exceptionMessage = null;
+        try {
+            TestUtils.normalizeCompositeNode(prepareCnSn("normalize-node-module"), modules, schemaNodePath);
+        } catch (ResponseException e) {
+            exceptionMessage = String.valueOf(e.getResponse().getEntity());
+        }
+        assertNull(exceptionMessage);
+    }
+
+    private CompositeNode prepareCnSn(String namespace) {
+        URI uri = null;
+        if (namespace != null) {
+            try {
+                uri = new URI(namespace);
+            } catch (URISyntaxException e) {
+            }
+            assertNotNull(uri);
+        }
+
+        SimpleNodeWrapper lf1 = new SimpleNodeWrapper(uri, "lf1", 43);
+        CompositeNodeWrapper cont = new CompositeNodeWrapper(uri, "cont");
+        cont.addValue(lf1);
+
+        return cont;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestConfigDataTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestConfigDataTest.java
new file mode 100644 (file)
index 0000000..dccf0d3
--- /dev/null
@@ -0,0 +1,210 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.junit.Assert.assertEquals;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.text.ParseException;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
+import org.opendaylight.controller.sal.rest.impl.XmlMapper;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
+
+import com.google.common.base.Charsets;
+
+public class RestConfigDataTest extends JerseyTest {
+
+    private static ControllerContext controllerContext;
+    private static BrokerFacade brokerFacade;
+    private static RestconfImpl restconfImpl;
+    private static MountService mountService;
+    private static SchemaContext schemaContext;
+
+    private static final MediaType MEDIA_TYPE_XML_DRAFT02 = new MediaType("application", "yang.data+xml");
+
+    @BeforeClass
+    public static void init() throws FileNotFoundException {
+        Set<Module> modules = TestUtils.loadModulesFrom("/test-config-data/yang1");
+        schemaContext = TestUtils.loadSchemaContext(modules);
+        initMocking();
+    }
+    
+    private static void initMocking() {
+        controllerContext = ControllerContext.getInstance();
+        controllerContext.setSchemas(schemaContext);
+        mountService = mock(MountService.class);
+        controllerContext.setMountService(mountService);
+        brokerFacade = mock(BrokerFacade.class);
+        restconfImpl = RestconfImpl.getInstance();
+        restconfImpl.setBroker(brokerFacade);
+        restconfImpl.setControllerContext(controllerContext);
+    }
+
+    @Test
+    public void createConfigurationDataTest() throws UnsupportedEncodingException, ParseException {
+        initMocking();
+        String URI_1 = createUri("/config", "");
+        String URI_2 = createUri("/config/", "");
+        String URI_3 = createUri("/config/", "test-interface:interfaces/");
+        String URI_4 = createUri("/config/", "test-interface:interfaces/");
+        String URI_5 = createUri("/config/", "test-interface:interfaces/test-interface2:class");
+
+        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
+                TransactionStatus.COMMITED).build();
+        Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+
+        when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
+                .thenReturn(dummyFuture);
+
+        ArgumentCaptor<InstanceIdentifier> instanceIdCaptor = ArgumentCaptor.forClass(InstanceIdentifier.class);
+        ArgumentCaptor<CompositeNode> compNodeCaptor = ArgumentCaptor.forClass(CompositeNode.class);
+
+        // Test URI_1
+        Entity<String> entity = createEntity("/test-config-data/xml/test-interface.xml");
+        Response response = target(URI_1).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(204, response.getStatus());
+        verify(brokerFacade).commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
+        String identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces]";
+        assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString());
+
+        // Test URI_2
+        response = target(URI_2).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(204, response.getStatus());
+        verify(brokerFacade, times(2))
+                .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
+        assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString());
+
+        // Test URI_3
+        entity = createEntity("/test-config-data/xml/test-interface2.xml");
+        response = target(URI_3).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(204, response.getStatus());
+        verify(brokerFacade, times(3))
+                .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
+
+        identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces, (urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interface[{(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)name=eth0}]]";
+        assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString());
+
+        // Test URI_4
+        Set<Module> modules2 = TestUtils.loadModulesFrom("/test-config-data/yang2");
+        SchemaContext schemaContext2 = TestUtils.loadSchemaContext(modules2);
+        MountInstance mountInstance = mock(MountInstance.class);
+        when(mountInstance.getSchemaContext()).thenReturn(schemaContext2);
+        when(mountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
+
+        entity = createEntity("/test-config-data/xml/test-interface3.xml");
+        response = target(URI_4).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(204, response.getStatus());
+        verify(brokerFacade, times(4))
+                .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
+        identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces, (urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)class]";
+        assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString());
+
+        // Test URI_5
+        response = target(URI_5).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(204, response.getStatus());
+        verify(brokerFacade, times(5))
+                .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
+        identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces, (urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)class, (urn:ietf:params:xml:ns:yang:test-interface2?revision=2014-08-01)class]";
+        assertEquals("Bad format URI", identifier, instanceIdCaptor.getValue().getPath().toString());
+    }
+    
+    @Test
+    public void testExistingData() throws UnsupportedEncodingException {
+        initMocking();
+        String URI_1 = createUri("/config", "");
+        String URI_2 = createUri("/config/", "");
+        String URI_3 = createUri("/config/", "test-interface:interfaces/");
+        String URI_4 = createUri("/config/", "test-interface:interfaces/");
+        String URI_5 = createUri("/config/", "test-interface:interfaces/test-interface2:class");
+
+        when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
+                .thenReturn(null);
+
+        // Test URI_1
+        Entity<String> entity = createEntity("/test-config-data/xml/test-interface.xml");
+        Response response = target(URI_1).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(202, response.getStatus());
+
+        // Test URI_2
+        response = target(URI_2).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(202, response.getStatus());
+
+        // Test URI_3
+        entity = createEntity("/test-config-data/xml/test-interface2.xml");
+        response = target(URI_3).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(202, response.getStatus());
+
+        // Test URI_4
+        Set<Module> modules2 = TestUtils.loadModulesFrom("/test-config-data/yang2");
+        SchemaContext schemaContext2 = TestUtils.loadSchemaContext(modules2);
+        MountInstance mountInstance = mock(MountInstance.class);
+        when(mountInstance.getSchemaContext()).thenReturn(schemaContext2);
+        when(mountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
+
+        entity = createEntity("/test-config-data/xml/test-interface3.xml");
+        response = target(URI_4).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(202, response.getStatus());
+
+        // Test URI_5
+        response = target(URI_5).request(MEDIA_TYPE_XML_DRAFT02).post(entity);
+        assertEquals(202, response.getStatus());
+    }
+
+    private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
+        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
+    }
+
+    private Entity<String> createEntity(final String relativePathToXml) {
+        InputStream inputStream = XmlMapper.class.getResourceAsStream(relativePathToXml);
+        String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(inputStream));
+        Entity<String> entity = Entity.entity(xml, MEDIA_TYPE_XML_DRAFT02);
+
+        return entity;
+    }
+
+    @Override
+    protected Application configure() {
+        enable(TestProperties.LOG_TRAFFIC);
+        enable(TestProperties.DUMP_ENTITY);
+        enable(TestProperties.RECORD_LOG_LEVEL);
+        set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue());
+
+        ResourceConfig resourceConfig = new ResourceConfig();
+        resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
+                XmlToCompositeNodeProvider.INSTANCE);
+        return resourceConfig;
+    }
+}
index 4295c29..3427fbd 100644 (file)
@@ -149,7 +149,7 @@ public final class TestUtils {
         ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext(modules));
 
         prepareMocksForRestconf(modules, restconf);
-        restconf.createConfigurationData(schemaNodePath, compositeNode);
+        restconf.updateConfigurationData(schemaNodePath, compositeNode);
     }
 
     /**
index b18f526..7cce34f 100644 (file)
@@ -12,7 +12,9 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLEncoder;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
@@ -33,9 +35,15 @@ import org.opendaylight.controller.sal.rest.api.Draft01;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.*;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -140,26 +148,34 @@ public class XmlProvidersTest extends JerseyTest {
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
                 TransactionStatus.COMMITED).build();
         Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
-        when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class)))
-                .thenReturn(dummyFuture);
         when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class)))
                 .thenReturn(dummyFuture);
+        when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
+                .thenReturn(dummyFuture);
 
         String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
         Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
         assertEquals(200, response.getStatus());
+
+        uri = createUri("/config/", "ietf-interfaces:interfaces");
         response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
         assertEquals(204, response.getStatus());
 
         uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
         response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
         assertEquals(200, response.getStatus());
+
+        uri = createUri("/config/", "ietf-interfaces:interfaces");
         response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
         assertEquals(204, response.getStatus());
 
         uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
+        entity = Entity.entity(xml, MEDIA_TYPE);
         response = target(uri).request(MEDIA_TYPE).put(entity);
         assertEquals(200, response.getStatus());
+
+        uri = createUri("/datastore/", "ietf-interfaces:interfaces");
+        entity = Entity.entity(xml, MEDIA_TYPE);
         response = target(uri).request(MEDIA_TYPE).post(entity);
         assertEquals(204, response.getStatus());
     }
@@ -172,8 +188,6 @@ public class XmlProvidersTest extends JerseyTest {
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
                 TransactionStatus.FAILED).build();
         Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
-        when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class)))
-                .thenReturn(dummyFuture);
         when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class)))
                 .thenReturn(dummyFuture);
 
@@ -190,9 +204,10 @@ public class XmlProvidersTest extends JerseyTest {
         assertEquals(500, response.getStatus());
 
         uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
-        response = target(uri).request(MEDIA_TYPE).put(entity);
+        entity = Entity.entity(xml, MEDIA_TYPE);
+        response = target(uri).request().put(entity);
         assertEquals(500, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE).post(entity);
+        response = target(uri).request().accept(MEDIA_TYPE).post(entity);
         assertEquals(500, response.getStatus());
     }
 
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/normalize-node/yang/normalize-node-module b/opendaylight/md-sal/sal-rest-connector/src/test/resources/normalize-node/yang/normalize-node-module
new file mode 100644 (file)
index 0000000..15e68ef
--- /dev/null
@@ -0,0 +1,14 @@
+module normalize-node-module {
+  namespace "normalize:node:module";  
+
+  prefix "nonomo";
+  revision 2014-01-09 {    
+  }
+
+    container cont {
+        leaf lf1 {
+            type int32;
+        }
+    }
+  
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface.xml
new file mode 100644 (file)
index 0000000..755c8a9
--- /dev/null
@@ -0,0 +1,8 @@
+<interfaces xmlns="urn:ietf:params:xml:ns:yang:test-interface">
+    <interface>
+        <name>eth0</name>
+        <type>ethernetCsmacd</type>
+        <enabled>false</enabled>
+    </interface>
+</interfaces>
+
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface2.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface2.xml
new file mode 100644 (file)
index 0000000..05db4a5
--- /dev/null
@@ -0,0 +1,5 @@
+<interface>
+    <name>eth0</name>
+    <type>ethernetCsmacd</type>
+    <enabled>false</enabled>
+</interface>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface3.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/xml/test-interface3.xml
new file mode 100644 (file)
index 0000000..e59ba17
--- /dev/null
@@ -0,0 +1,6 @@
+<class xmlns="urn:ietf:params:xml:ns:yang:test-interface2">
+    <student>
+        <name>Thomas</name>
+        <age>23</age>
+    </student>
+</class>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang1/test-interface.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang1/test-interface.yang
new file mode 100644 (file)
index 0000000..f683a69
--- /dev/null
@@ -0,0 +1,30 @@
+module test-interface {
+    yang-version 1;
+    namespace "urn:ietf:params:xml:ns:yang:test-interface";
+    prefix "sn";
+
+    description
+        "test file";   
+
+    revision "2014-07-01" {
+        description
+            "Initial revision";
+        reference "will be defined";
+    }
+    
+    container interfaces {
+        list interface {
+            key "name";
+         
+            leaf name {
+                type string;
+            }
+            leaf type {
+                type string;
+            }
+            leaf enabled {
+                type string;
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang2/test-interface2.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/test-config-data/yang2/test-interface2.yang
new file mode 100644 (file)
index 0000000..13bc0eb
--- /dev/null
@@ -0,0 +1,27 @@
+module test-interface2 {
+    yang-version 1;
+    namespace "urn:ietf:params:xml:ns:yang:test-interface2";
+    prefix "snn";
+
+    description
+        "test file";   
+
+    revision "2014-08-01" {
+        description
+            "Initial revision";
+        reference "will be defined";
+    }
+    
+    container class {
+        list student {
+            key "name";
+         
+            leaf name {
+                type string;
+            }
+            leaf age {
+                type string;
+            }
+        }
+    }
+}
index e7f6129..62ba046 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
@@ -111,6 +107,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdenti
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
 /**
  * Class implement statistics manager related listener interface and augment all the 
  * received statistics data to data stores.
@@ -500,7 +500,7 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
                 sucLogger.debug("Associated original flow is not found in data store. Augmenting flow in operational data store");
                 //TODO: Temporary fix: format [ 1+tableid+1+unaccounted flow counter]
                 long flowKey = Long.parseLong(new String("1"+Short.toString(tableId)+"1"+Integer.toString(this.unaccountedFlowsCounter)));
-                FlowKey newFlowKey = new FlowKey(new FlowId(flowKey));
+                FlowKey newFlowKey = new FlowKey(new FlowId(Long.toString(flowKey)));
                 InstanceIdentifier<Flow> flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
                         .augmentation(FlowCapableNode.class)
                         .child(Table.class, new TableKey(tableId))
index 5dde044..34f131c 100644 (file)
                 <configuration>
                     <instructions>
                         <Bundle-Activator>org.opendaylight.controller.netconf.osgi.NetconfSSHActivator</Bundle-Activator>
-                        <Export-Package>
-                            org.opendaylight.controller.netconf.ssh,
-                        </Export-Package>
                         <Import-Package>
-                            com.google.common.base,
                             ch.ethz.ssh2,
                             ch.ethz.ssh2.signature,
-                            java.net,
-                            javax.annotation,
-                            org.apache.commons.io,
-                            org.opendaylight.controller.netconf.util,
                             org.opendaylight.controller.netconf.util.osgi,
                             org.opendaylight.controller.usermanager,
                             org.opendaylight.controller.sal.authorization,
-                            org.opendaylight.controller.sal.utils,
-                            org.opendaylight.protocol.framework,
                             org.osgi.framework,
                             org.osgi.util.tracker,
                             org.slf4j,
index 0df6d4c..a823864 100644 (file)
@@ -8,17 +8,6 @@
 
 package org.opendaylight.controller.sal.flowprogrammer;
 
-import java.io.Serializable;
-import java.net.Inet6Address;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-
 import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.ActionType;
 import org.opendaylight.controller.sal.action.SetDlType;
@@ -29,6 +18,16 @@ import org.opendaylight.controller.sal.utils.EtherTypes;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.net.Inet6Address;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
 /**
  * Represent a flow: match + actions + flow specific properties
  */
@@ -305,4 +304,5 @@ public class Flow implements Cloneable, Serializable {
         }
         return true;
     }
+
 }

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.