Merge "Fixed add/delete/modify RPC for group/flow/remove reach the test provider"
authorEd Warnicke <eaw@cisco.com>
Sun, 8 Dec 2013 14:23:01 +0000 (14:23 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sun, 8 Dec 2013 14:23:01 +0000 (14:23 +0000)
69 files changed:
opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolder.java
opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolderImpl.java [new file with mode: 0644]
opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java
opendaylight/config/config-persister-directory-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryPersister.java
opendaylight/config/config-persister-directory-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/directory/DirectoryStorageAdapterTest.java
opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedCapabilities.txt [moved from opendaylight/config/config-persister-directory-adapter/src/test/resources/expectedCapabilities.txt with 100% similarity]
opendaylight/config/config-persister-directory-adapter/src/test/resources/oneFileExpected/expectedSnapshot.xml [moved from opendaylight/config/config-persister-directory-adapter/src/test/resources/expectedSnapshot.xml with 100% similarity]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt [new file with mode: 0644]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml [new file with mode: 0644]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt [new file with mode: 0644]
opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml [new file with mode: 0644]
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/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/FtlFilePersister.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleField.java
opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/AbstractDependencyAttribute.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/Dependency.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/DependencyAttribute.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListAttribute.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListDependenciesAttribute.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/TOAttribute.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/SchemaContextTest.java
opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang
opendaylight/config/yang-test/src/main/yang/config-test-impl.yang
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/statistics/DataBrokerRuntimeMXBeanImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/statistics/DomBrokerRuntimeMXBeanImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/yang/opendaylight-dom-broker-impl.yang
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/NoOpStorageAdapter.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregator.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/Util.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandlerTest.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/DummyAdapter.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/PersisterAggregatorTest.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised2.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised3.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised4.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised5.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised6.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml

index 654326a..37d29d7 100644 (file)
@@ -4,14 +4,15 @@ import java.util.SortedSet;
 
 public interface ConfigSnapshotHolder {
 
-        /**
-         * Get part of get-config document that contains just
-         */
-        String getConfigSnapshot();
+    /**
+     * Get part of get-config document that contains just
+     */
+    String getConfigSnapshot();
 
 
-        /**
-         * Get only required capabilities referenced by the snapshot.
-         */
-        SortedSet<String> getCapabilities();
-    }
+    /**
+     * Get only required capabilities referenced by the snapshot.
+     */
+    SortedSet<String> getCapabilities();
+
+}
diff --git a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolderImpl.java b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolderImpl.java
new file mode 100644 (file)
index 0000000..a0586df
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.config.persist.api;
+
+import java.util.SortedSet;
+
+public class ConfigSnapshotHolderImpl implements ConfigSnapshotHolder {
+
+    private final String snapshot;
+    private final SortedSet<String> caps;
+    private final String fileName;
+
+    public ConfigSnapshotHolderImpl(String configSnapshot, SortedSet<String> capabilities, String fileName) {
+        this.snapshot = configSnapshot;
+        this.caps = capabilities;
+        this.fileName = fileName;
+    }
+
+    @Override
+    public String getConfigSnapshot() {
+        return snapshot;
+    }
+
+    @Override
+    public SortedSet<String> getCapabilities() {
+        return caps;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    @Override
+    public String toString() {
+        return "ConfigSnapshotHolderImpl{" +
+                "snapshot='" + snapshot + '\'' +
+                ", caps=" + caps +
+                ", fileName='" + fileName + '\'' +
+                '}';
+    }
+}
index 1448e55..5509c99 100644 (file)
@@ -8,9 +8,8 @@
 
 package org.opendaylight.controller.config.persist.api;
 
-import com.google.common.base.Optional;
-
 import java.io.IOException;
+import java.util.List;
 
 /**
  * Base interface for persister implementation.
@@ -19,7 +18,7 @@ public interface Persister extends AutoCloseable {
 
     void persistConfig(ConfigSnapshotHolder configSnapshotHolder) throws IOException;
 
-    Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException;
+    List<ConfigSnapshotHolder> loadLastConfigs() throws IOException;
 
     @Override
     void close();
index 25628b6..39595ed 100644 (file)
@@ -8,10 +8,10 @@
 package org.opendaylight.controller.config.persist.storage.directory;
 
 import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
 import com.google.common.io.Files;
 import org.apache.commons.io.IOUtils;
 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -64,30 +64,25 @@ public class DirectoryPersister implements Persister {
     }
 
     @Override
-    public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
+    public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
         File[] filesArray = storage.listFiles();
-        if (filesArray.length == 0) {
-            return Optional.absent();
+        if (filesArray == null || filesArray.length == 0) {
+            return Collections.emptyList();
         }
         List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
         Collections.sort(sortedFiles);
         // combine all found files
+        logger.debug("Reading files in following order: {}", sortedFiles);
 
-        SortedSet<String> combinedCapabilities = new TreeSet<>();
-        StringBuilder modulesBuilder = new StringBuilder(), servicesBuilder = new StringBuilder();
+        List<ConfigSnapshotHolder> result = new ArrayList<>();
         for (File file : sortedFiles) {
             logger.trace("Adding file '{}' to combined result", file);
 
             final MyLineProcessor lineProcessor = new MyLineProcessor(file.getAbsolutePath());
             Files.readLines(file, ENCODING, lineProcessor);
-
-            modulesBuilder.append(lineProcessor.getModules());
-            servicesBuilder.append(lineProcessor.getServices());
-            combinedCapabilities.addAll(lineProcessor.getCapabilities());
+            result.add(lineProcessor.getConfigSnapshotHolder(header, middle, footer));
         }
-        String combinedSnapshot = header + modulesBuilder.toString() + middle + servicesBuilder.toString() + footer;
-        ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, combinedCapabilities);
-        return Optional.of(result);
+        return result;
     }
 
 
@@ -165,25 +160,11 @@ class MyLineProcessor implements com.google.common.io.LineProcessor<String> {
         return caps;
     }
 
-}
-
-class ConfigSnapshotHolderImpl implements ConfigSnapshotHolder {
-
-    private final String snapshot;
-    private final SortedSet<String> caps;
-
-    public ConfigSnapshotHolderImpl(String configSnapshot, SortedSet<String> capabilities) {
-        this.snapshot = configSnapshot;
-        this.caps = capabilities;
-    }
-
-    @Override
-    public String getConfigSnapshot() {
-        return snapshot;
+    ConfigSnapshotHolder getConfigSnapshotHolder(String header, String middle, String footer) {
+        String combinedSnapshot = header + getModules() + middle + getServices() + footer;
+        ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, getCapabilities(), fileNameForReporting);
+        return result;
     }
 
-    @Override
-    public SortedSet<String> getCapabilities() {
-        return caps;
-    }
 }
+
index 53ab4c2..f17e414 100644 (file)
@@ -8,14 +8,13 @@
 
 package org.opendaylight.controller.config.persist.storage.directory;
 
-import com.google.common.base.Optional;
 import org.apache.commons.io.IOUtils;
-import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 
 import java.io.File;
-import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -25,21 +24,13 @@ import static org.junit.Assert.fail;
 
 public class DirectoryStorageAdapterTest {
     DirectoryPersister tested;
-    SortedSet<String> expectedCapabilities;
-    String expectedSnapshot;
-
-    @Before
-    public void setUp() throws Exception {
-        expectedCapabilities = new TreeSet<>(IOUtils.readLines(getClass().getResourceAsStream("/expectedCapabilities.txt")));
-        expectedSnapshot = IOUtils.toString(getClass().getResourceAsStream("/expectedSnapshot.xml"));
-    }
 
     @Test
     public void testEmptyDirectory() throws Exception {
         File folder = new File("target/emptyFolder");
         folder.mkdir();
         tested = new DirectoryPersister((folder));
-        assertEquals(Optional.<ConfigSnapshotHolder>absent(), tested.loadLastConfig());
+        assertEquals(Collections.<ConfigSnapshotHolder>emptyList(), tested.loadLastConfigs());
 
         try {
             tested.persistConfig(new ConfigSnapshotHolder() {
@@ -70,22 +61,28 @@ public class DirectoryStorageAdapterTest {
     public void testOneFile() throws Exception {
         File folder = getFolder("oneFile");
         tested = new DirectoryPersister((folder));
-        assertExpected();
+        List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
+        assertEquals(1, results.size());
+        ConfigSnapshotHolder result = results.get(0);
+        assertSnapshot(result, "oneFileExpected");
     }
 
-    private void assertExpected() throws IOException {
-        Optional<ConfigSnapshotHolder> maybeResult = tested.loadLastConfig();
-        assertTrue(maybeResult.isPresent());
-        ConfigSnapshotHolder result = maybeResult.get();
-        assertEquals(expectedCapabilities, result.getCapabilities());
-        assertEquals(expectedSnapshot, result.getConfigSnapshot());
-    }
 
     @Test
     public void testTwoFiles() throws Exception {
         File folder = getFolder("twoFiles");
         tested = new DirectoryPersister((folder));
-        assertExpected();
+        List<ConfigSnapshotHolder> results = tested.loadLastConfigs();
+        assertEquals(2, results.size());
+        assertSnapshot(results.get(0), "twoFilesExpected1");
+        assertSnapshot(results.get(1), "twoFilesExpected2");
+    }
+
+    private void assertSnapshot(ConfigSnapshotHolder result, String directory) throws Exception {
+        SortedSet<String> expectedCapabilities = new TreeSet<>(IOUtils.readLines(getClass().getResourceAsStream("/" + directory + "/expectedCapabilities.txt")));
+        String expectedSnapshot = IOUtils.toString(getClass().getResourceAsStream("/" + directory + "/expectedSnapshot.xml"));
+        assertEquals(expectedCapabilities, result.getCapabilities());
+        assertEquals(expectedSnapshot, result.getConfigSnapshot());
     }
 
 }
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedCapabilities.txt
new file mode 100644 (file)
index 0000000..ef35fdd
--- /dev/null
@@ -0,0 +1 @@
+urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected1/expectedSnapshot.xml
new file mode 100644 (file)
index 0000000..2b1d06e
--- /dev/null
@@ -0,0 +1,84 @@
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
+            <name>yang-schema-service</name>
+        </module>
+        <module>
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</type>
+            <name>hash-map-data-store</name>
+        </module>
+        <module>
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+            <name>dom-broker</name>
+            <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
+                <name>ref_hash-map-data-store</name>
+            </data-store>
+        </module>
+        <module>
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+            <name>binding-broker-impl</name>
+            <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+                <name>ref_binding-notification-broker</name>
+            </notification-service>
+            <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                <name>ref_binding-data-broker</name>
+            </data-broker>
+        </module>
+        <module>
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+            <name>runtime-mapping-singleton</name>
+        </module>
+        <module>
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+            <name>binding-notification-broker</name>
+        </module>
+    </modules>
+    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <service>
+            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+            <instance>
+                <name>ref_yang-schema-service</name>
+                <provider>/config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']</provider>
+            </instance>
+        </service>
+        <service>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+            <instance>
+                <name>ref_binding-notification-broker</name>
+                <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
+            </instance>
+        </service>
+        <service>
+            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
+            <instance>
+                <name>ref_hash-map-data-store</name>
+                <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</provider>
+            </instance>
+        </service>
+        <service>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <instance>
+                <name>ref_binding-broker-impl</name>
+                <provider>/config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']</provider>
+            </instance>
+        </service>
+        <service>
+            <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+            <instance>
+                <name>ref_runtime-mapping-singleton</name>
+                <provider>/config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']</provider>
+            </instance>
+        </service>
+        <service>
+            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+            <instance>
+                <name>ref_dom-broker</name>
+                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']</provider>
+            </instance>
+        </service>
+    </services>
+</data>
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedCapabilities.txt
new file mode 100644 (file)
index 0000000..9924111
--- /dev/null
@@ -0,0 +1,19 @@
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
+urn:ietf:params:netconf:capability:candidate:1.0
+urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04
+urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12
+urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
+urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24
+urn:ietf:params:netconf:capability:rollback-on-error:1.0
+urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24
+urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16
+urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09
+urn:opendaylight:params:xml:ns:yang:iana?module=iana&revision=2013-08-16
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&revision=2013-08-19
diff --git a/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml b/opendaylight/config/config-persister-directory-adapter/src/test/resources/twoFilesExpected2/expectedSnapshot.xml
new file mode 100644 (file)
index 0000000..887cb2c
--- /dev/null
@@ -0,0 +1,25 @@
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</type>
+            <name>binding-data-broker</name>
+            <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+                <name>ref_dom-broker</name>
+            </dom-broker>
+            <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+                <name>ref_runtime-mapping-singleton</name>
+            </mapping-service>
+        </module>
+    </modules>
+    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <service>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+            <instance>
+                <name>ref_binding-data-broker</name>
+                <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
+            </instance>
+        </service>
+    </services>
+</data>
index 66d0414..3ec8713 100644 (file)
@@ -15,17 +15,19 @@ 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 org.xml.sax.SAXException;
 
-import javax.xml.parsers.ParserConfigurationException;
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -105,7 +107,7 @@ public class FileStorageAdapter implements StorageAdapter, Persister {
         } else {
             numberOfStoredBackups = Integer.MAX_VALUE;
         }
-
+        logger.trace("Property {} set to {}", NUMBER_OF_BACKUPS, numberOfStoredBackups);
         return result;
     }
 
@@ -164,27 +166,23 @@ public class FileStorageAdapter implements StorageAdapter, Persister {
     }
 
     @Override
-    public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
+    public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
         Preconditions.checkNotNull(storage, "Storage file is null");
 
         if (!storage.exists()) {
-            return Optional.absent();
+            return Collections.emptyList();
         }
 
         final LineProcessor lineProcessor = new LineProcessor();
-        String result = Files.readLines(storage, ENCODING, lineProcessor);
-
-        try {
-            if (lineProcessor.getConfigSnapshot().isPresent() == false) {
-                return Optional.absent();
-            } else {
-                return Optional.<ConfigSnapshotHolder> of(new PersistedConfigImpl(lineProcessor.getConfigSnapshot(),
-                        lineProcessor.getCapabilities()));
-            }
+        Files.readLines(storage, ENCODING, lineProcessor);
 
-        } catch (ParserConfigurationException | SAXException e) {
-            throw new IOException("Unable to load last config ", e);
+        if (lineProcessor.getConfigSnapshot().isPresent() == false) {
+            return Collections.emptyList();
+        } else {
+            return Arrays.<ConfigSnapshotHolder>asList(new ConfigSnapshotHolderImpl(lineProcessor.getConfigSnapshot().get(),
+                    lineProcessor.getCapabilities(), storage.getAbsolutePath()));
         }
+
     }
 
     private static final class LineProcessor implements com.google.common.io.LineProcessor<String> {
@@ -227,15 +225,16 @@ public class FileStorageAdapter implements StorageAdapter, Persister {
             return true;
         }
 
-        Optional<String> getConfigSnapshot() throws IOException, SAXException, ParserConfigurationException {
+        Optional<String> getConfigSnapshot() {
             final String xmlContent = snapshotBuffer.toString();
-            if (xmlContent == null || xmlContent.equals("")) {
+            if (xmlContent.equals("")) {
                 return Optional.absent();
-            } else
+            } else {
                 return Optional.of(xmlContent);
+            }
         }
 
-        SortedSet<String> getCapabilities() throws IOException, SAXException, ParserConfigurationException {
+        SortedSet<String> getCapabilities() {
             return caps;
         }
 
@@ -251,25 +250,4 @@ public class FileStorageAdapter implements StorageAdapter, Persister {
         return "FileStorageAdapter [storage=" + storage + "]";
     }
 
-    private class PersistedConfigImpl implements ConfigSnapshotHolder {
-
-        private final String snapshot;
-        private final SortedSet<String> caps;
-
-        public PersistedConfigImpl(Optional<String> configSnapshot, SortedSet<String> capabilities) {
-            this.snapshot = configSnapshot.get();
-            this.caps = capabilities;
-        }
-
-        @Override
-        public String getConfigSnapshot() {
-            return snapshot;
-        }
-
-        @Override
-        public SortedSet<String> getCapabilities() {
-            return caps;
-        }
-    }
-
 }
index ed50184..0236598 100644 (file)
@@ -9,7 +9,6 @@
 package org.opendaylight.controller.config.persist.storage.file;
 
 import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import org.junit.Before;
@@ -20,11 +19,11 @@ 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 static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
@@ -75,11 +74,12 @@ public class FileStorageAdapterTest {
                 });
         assertEquals(14, readLines.size());
 
-        Optional<ConfigSnapshotHolder> lastConf = storage.loadLastConfig();
-        assertTrue(lastConf.isPresent());
+        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
+        assertEquals(1, lastConf.size());
+        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
         assertEquals("<config>2</config>",
-                lastConf.get().getConfigSnapshot().replaceAll("\\s", ""));
-        assertEquals(createCaps(), lastConf.get().getCapabilities());
+                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
+        assertEquals(createCaps(), configSnapshotHolder.getCapabilities());
     }
 
     private SortedSet<String> createCaps() {
@@ -123,10 +123,11 @@ public class FileStorageAdapterTest {
                 });
         assertEquals(7, readLines.size());
 
-        Optional<ConfigSnapshotHolder> lastConf = storage.loadLastConfig();
-        assertTrue(lastConf.isPresent());
+        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
+        assertEquals(1, lastConf.size());
+        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
         assertEquals("<config>2</config>",
-                lastConf.get().getConfigSnapshot().replaceAll("\\s", ""));
+                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
     }
 
     @Test
@@ -163,10 +164,11 @@ public class FileStorageAdapterTest {
 
         assertEquals(14, readLines.size());
 
-        Optional<ConfigSnapshotHolder> lastConf = storage.loadLastConfig();
-        assertTrue(lastConf.isPresent());
+        List<ConfigSnapshotHolder> lastConf = storage.loadLastConfigs();
+        assertEquals(1, lastConf.size());
+        ConfigSnapshotHolder configSnapshotHolder = lastConf.get(0);
         assertEquals("<config>3</config>",
-               lastConf.get().getConfigSnapshot().replaceAll("\\s", ""));
+                configSnapshotHolder.getConfigSnapshot().replaceAll("\\s", ""));
         assertFalse(readLines.contains(holder.getConfigSnapshot()));
     }
 
@@ -178,14 +180,14 @@ public class FileStorageAdapterTest {
         FileStorageAdapter storage = new FileStorageAdapter();
         storage.setFileStorage(file);
 
-        Optional<ConfigSnapshotHolder> elementOptional = storage.loadLastConfig();
-        assertThat(elementOptional.isPresent(), is(false));
+        List<ConfigSnapshotHolder> elementOptional = storage.loadLastConfigs();
+        assertThat(elementOptional.size(), is(0));
     }
 
     @Test(expected = NullPointerException.class)
     public void testNoProperties() throws Exception {
         FileStorageAdapter storage = new FileStorageAdapter();
-        storage.loadLastConfig();
+        storage.loadLastConfigs();
     }
 
     @Test(expected = NullPointerException.class)
index b0b6f3d..f721895 100644 (file)
@@ -7,19 +7,9 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl;
 
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Pattern;
-
+import com.google.common.annotations.VisibleForTesting;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.directives.AnnotationsDirective;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.directives.ConstructorsDirective;
@@ -33,11 +23,18 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.directives
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.annotations.VisibleForTesting;
-
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
 
 public class FtlFilePersister {
     private static final Logger logger = LoggerFactory
@@ -56,7 +53,7 @@ public class FtlFilePersister {
                         ftlFile.getFtlTempleteLocation());
                 try {
                     template.process(ftlFile, writer);
-                } catch (TemplateException e) {
+                } catch (Throwable e) {
                     throw new IllegalStateException(
                             "Template error while generating " + ftlFile, e);
                 }
index 3a6ff18..6da6801 100644 (file)
@@ -21,13 +21,13 @@ import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute.Dependency;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.Dependency;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.TypedAttribute;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.TypedAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation.Parameter;
@@ -39,6 +39,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Meth
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 
 import javax.management.openmbean.SimpleType;
@@ -112,8 +113,8 @@ public class TemplateFactory {
 
             // convert attributes to getters
             for (AttributeIfc attributeIfc : entry.getAttributes()) {
-                String returnType = null;
-                returnType = getReturnType(entry, attributeIfc);
+                String returnType;
+                returnType = getReturnType(attributeIfc);
                 String getterName = "get"
                         + attributeIfc.getUpperCaseCammelCase();
                 MethodDeclaration getter = new MethodDeclaration(returnType,
@@ -132,7 +133,7 @@ public class TemplateFactory {
                     fields.add(field);
                 }
                 MethodDeclaration operation = new MethodDeclaration(
-                        getReturnType(entry, rpc.getReturnType()), rpc.getName(), fields);
+                        getReturnType(rpc.getReturnType()), rpc.getName(), fields);
                 methods.add(operation);
             }
 
@@ -150,28 +151,35 @@ public class TemplateFactory {
         return result;
     }
 
-    private static String getReturnType(RuntimeBeanEntry entry, AttributeIfc attributeIfc) {
+    // FIXME: put into Type.toString
+    static String serializeType(Type type) {
+        if (type instanceof ParameterizedType){
+            ParameterizedType parameterizedType = (ParameterizedType) type;
+            StringBuffer sb = new StringBuffer();
+            sb.append(parameterizedType.getRawType().getFullyQualifiedName());
+            sb.append("<");
+            boolean first = true;
+            for(Type parameter: parameterizedType.getActualTypeArguments()) {
+                if (first) {
+                    first = false;
+                } else {
+                    sb.append(",");
+                }
+                sb.append(serializeType(parameter));
+            }
+            sb.append(">");
+            return sb.toString();
+        } else {
+            return type.getFullyQualifiedName();
+        }
+    }
+
+
+    private static String getReturnType(AttributeIfc attributeIfc) {
         String returnType;
         if (attributeIfc instanceof TypedAttribute) {
-            returnType = ((TypedAttribute) attributeIfc).getType()
-                    .getFullyQualifiedName();
-        } else if (attributeIfc instanceof TOAttribute) {
-            String fullyQualifiedName = FullyQualifiedNameHelper
-                    .getFullyQualifiedName(entry.getPackageName(),
-                            attributeIfc.getUpperCaseCammelCase());
-
-            returnType = fullyQualifiedName;
-        } else if (attributeIfc instanceof ListAttribute) {
-            AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
-                    .getInnerAttribute();
-
-            String innerTpe = innerAttr instanceof TypedAttribute ? ((TypedAttribute) innerAttr)
-                    .getType().getFullyQualifiedName()
-                    : FullyQualifiedNameHelper.getFullyQualifiedName(
-                            entry.getPackageName(),
-                            attributeIfc.getUpperCaseCammelCase());
-
-            returnType = "java.util.List<" + innerTpe + ">";
+            Type type = ((TypedAttribute) attributeIfc).getType();
+            returnType = serializeType(type);
         } else if (attributeIfc == VoidAttribute.getInstance()) {
             return "void";
         } else {
@@ -292,8 +300,7 @@ public class TemplateFactory {
     public static GeneralInterfaceTemplate mXBeanInterfaceTemplateFromMbe(
             ModuleMXBeanEntry mbe) {
         MXBeanInterfaceAttributesProcessor attrProcessor = new MXBeanInterfaceAttributesProcessor();
-        attrProcessor.processAttributes(mbe.getAttributes(),
-                mbe.getPackageName());
+        attrProcessor.processAttributes(mbe.getAttributes());
         GeneralInterfaceTemplate ifcTemplate = new GeneralInterfaceTemplate(
                 getHeaderFromEntry(mbe), mbe.getPackageName(),
                 mbe.getMXBeanInterfaceName(), Lists.<String> newArrayList(),
@@ -306,7 +313,7 @@ public class TemplateFactory {
             ModuleMXBeanEntry mbe) {
         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
         TOAttributesProcessor processor = new TOAttributesProcessor();
-        processor.processAttributes(mbe.getAttributes(), mbe.getPackageName());
+        processor.processAttributes(mbe.getAttributes());
         for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor
                 .getTOs()) {
             List<Constructor> constructors = Lists.newArrayList();
@@ -345,7 +352,7 @@ public class TemplateFactory {
             yangPropertiesToTypesMap.put(returnType.getAttributeYangName(), returnType);
         }
 
-        processor.processAttributes(yangPropertiesToTypesMap, rbe.getPackageName());
+        processor.processAttributes(yangPropertiesToTypesMap);
         for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor
                 .getTOs()) {
             List<Constructor> constructors = Lists.newArrayList();
@@ -372,36 +379,29 @@ public class TemplateFactory {
 
         private final List<TOInternal> tos = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes,
-                String packageName) {
+        void processAttributes(Map<String, AttributeIfc> attributes) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 AttributeIfc attributeIfc = attrEntry.getValue();
                 if (attributeIfc instanceof TOAttribute) {
-                    createTOInternal(packageName, attributeIfc);
+                    createTOInternal((TOAttribute) attributeIfc);
                 }
                 if (attributeIfc instanceof ListAttribute) {
                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
                             .getInnerAttribute();
                     if (innerAttr instanceof TOAttribute) {
-                        createTOInternal(packageName, innerAttr);
+                        createTOInternal((TOAttribute) innerAttr);
                     }
                 }
             }
         }
 
-        private void createTOInternal(String packageName,
-                AttributeIfc attributeIfc) {
-            String fullyQualifiedName = FullyQualifiedNameHelper
-                    .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
+        private void createTOInternal(TOAttribute toAttribute) {
 
-            String type = fullyQualifiedName;
-            String name = attributeIfc.getUpperCaseCammelCase();
-            Map<String, AttributeIfc> attrs = ((TOAttribute) attributeIfc)
-                    .getCapitalizedPropertiesToTypesMap();
-            // recursive processing
-            processAttributes(attrs, packageName);
+            Map<String, AttributeIfc> attrs = toAttribute.getCapitalizedPropertiesToTypesMap();
+            // recursive processing of TO's attributes
+            processAttributes(attrs);
 
-            tos.add(new TOInternal(type, name, attrs, packageName));
+            tos.add(new TOInternal(toAttribute.getType(), attrs));
         }
 
         List<TOInternal> getTOs() {
@@ -409,20 +409,22 @@ public class TemplateFactory {
         }
 
         private static class TOInternal {
-            private final String type, name;
+            private final String fullyQualifiedName, name;
             private List<Field> fields;
             private List<MethodDefinition> methods;
 
-            public TOInternal(String type, String name,
+            public TOInternal(Type type, Map<String, AttributeIfc> attrs) {
+                this(type.getFullyQualifiedName(), type.getName(), attrs, type.getPackageName());
+            }
+
+            public TOInternal(String fullyQualifiedName, String name,
                     Map<String, AttributeIfc> attrs, String packageName) {
-                super();
-                this.type = type;
+                this.fullyQualifiedName = fullyQualifiedName;
                 this.name = name;
                 processAttrs(attrs, packageName);
             }
 
-            private void processAttrs(Map<String, AttributeIfc> attrs,
-                    String packageName) {
+            private void processAttrs(Map<String, AttributeIfc> attrs, String packageName) {
                 fields = Lists.newArrayList();
                 methods = Lists.newArrayList();
 
@@ -431,25 +433,14 @@ public class TemplateFactory {
                     String varName = BindingGeneratorUtil
                             .parseToValidParamName(attrEntry.getKey());
 
-                    String fullyQualifiedName = null;
+                    String fullyQualifiedName;
                     if (attrEntry.getValue() instanceof TypedAttribute) {
-                        Type innerType = ((TypedAttribute) attrEntry.getValue())
-                                .getType();
-                        fullyQualifiedName = innerType.getFullyQualifiedName();
-                    } else if (attrEntry.getValue() instanceof ListAttribute) {
-                        AttributeIfc innerAttr = ((ListAttribute) attrEntry
-                                .getValue()).getInnerAttribute();
-
-                        String innerTpe = innerAttr instanceof TypedAttribute ? ((TypedAttribute) innerAttr)
-                                .getType().getFullyQualifiedName()
-                                : FullyQualifiedNameHelper
-                                        .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
-
-                        fullyQualifiedName = "java.util.List<" + innerTpe + ">";
-                    } else
+                        Type type = ((TypedAttribute) attrEntry.getValue()).getType();
+                        fullyQualifiedName = serializeType(type);
+                    } else {
                         fullyQualifiedName = FullyQualifiedNameHelper
                                 .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
-
+                    }
                     fields.add(new Field(fullyQualifiedName, varName));
 
                     String getterName = "get" + innerName;
@@ -470,7 +461,7 @@ public class TemplateFactory {
             }
 
             String getType() {
-                return type;
+                return fullyQualifiedName;
             }
 
             String getName() {
@@ -488,38 +479,16 @@ public class TemplateFactory {
     }
 
     private static class MXBeanInterfaceAttributesProcessor {
-        private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
         private final List<MethodDeclaration> methods = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes,
-                String packageName) {
+        void processAttributes(Map<String, AttributeIfc> attributes) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 String returnType;
                 AttributeIfc attributeIfc = attrEntry.getValue();
 
                 if (attributeIfc instanceof TypedAttribute) {
-                    returnType = ((TypedAttribute) attributeIfc).getType()
-                            .getFullyQualifiedName();
-                } else if (attributeIfc instanceof TOAttribute) {
-                    String fullyQualifiedName = FullyQualifiedNameHelper
-                            .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
-
-                    returnType = fullyQualifiedName;
-                } else if (attributeIfc instanceof ListAttribute) {
-                    String fullyQualifiedName = null;
-
-                    AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
-                            .getInnerAttribute();
-                    if (innerAttr instanceof JavaAttribute) {
-                        fullyQualifiedName = ((JavaAttribute) innerAttr)
-                                .getType().getFullyQualifiedName();
-                    } else if (innerAttr instanceof TOAttribute) {
-                        fullyQualifiedName = FullyQualifiedNameHelper
-                                .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
-                    }
-
-                    returnType = STRING_FULLY_QUALIFIED_NAME.concat("<")
-                            .concat(fullyQualifiedName).concat(">");
+                    TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
+                    returnType = serializeType(typedAttribute.getType());
                 } else {
                     throw new UnsupportedOperationException(
                             "Attribute not supported: "
@@ -565,14 +534,14 @@ public class TemplateFactory {
                 AttributeIfc attributeIfc = attrEntry.getValue();
 
                 if (attributeIfc instanceof TypedAttribute) {
-                    type = ((TypedAttribute) attributeIfc).getType()
-                            .getFullyQualifiedName();
+                    TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
+                    type = serializeType(typedAttribute.getType());
                 } else if (attributeIfc instanceof TOAttribute) {
                     String fullyQualifiedName = FullyQualifiedNameHelper
                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
 
                     type = fullyQualifiedName;
-                } else if (attributeIfc instanceof ListAttribute) {
+                } else if (attributeIfc instanceof ListAttribute) {  //FIXME: listAttribute might extend TypedAttribute
                     String fullyQualifiedName = null;
                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
                             .getInnerAttribute();
@@ -617,8 +586,8 @@ public class TemplateFactory {
                 AttributeIfc attributeIfc = attrEntry.getValue();
 
                 if (attributeIfc instanceof TypedAttribute) {
-                    type = ((TypedAttribute) attributeIfc).getType()
-                            .getFullyQualifiedName();
+                    TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
+                    type = serializeType(typedAttribute.getType());
                 } else if (attributeIfc instanceof TOAttribute) {
                     String fullyQualifiedName = FullyQualifiedNameHelper
                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
@@ -651,9 +620,9 @@ public class TemplateFactory {
                 List<Annotation> annotations = Lists
                         .newArrayList(overrideAnnotation);
 
-                if (attributeIfc instanceof DependencyAttribute) {
+                if (attributeIfc instanceof AbstractDependencyAttribute) {
                     isDependency = true;
-                    dependency = ((DependencyAttribute) attributeIfc)
+                    dependency = ((AbstractDependencyAttribute) attributeIfc)
                             .getDependency();
                     annotations.add(Annotation
                             .createRequireIfcAnnotation(dependency.getSie()));
index 293696d..5624e16 100644 (file)
@@ -7,11 +7,13 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model;
 
+
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.Dependency;
+
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute.Dependency;
-
 public class ModuleField extends Field {
 
     private final String nullableDefault, attributeName;
@@ -22,10 +24,14 @@ public class ModuleField extends Field {
             String attributeName, String nullableDefault, boolean isDependency,
             Dependency dependency) {
         super(modifiers, type, name);
-        this.nullableDefault = nullableDefault;
         this.dependent = isDependency;
         this.dependency = dependency;
         this.attributeName = attributeName;
+        if (type.startsWith(List.class.getName()) && nullableDefault == null) {
+            String generics = type.substring(List.class.getName().length());
+            nullableDefault = "new " + ArrayList.class.getName() + generics + "()";
+        }
+        this.nullableDefault = nullableDefault;
     }
 
     public ModuleField(String type, String name, String attributeName,
@@ -49,4 +55,5 @@ public class ModuleField extends Field {
     public String getAttributeName() {
         return attributeName;
     }
+
 }
index d0646f4..f7197d1 100644 (file)
@@ -52,8 +52,14 @@ package ${packageName};
     public void validate(){
     <#list moduleFields as field>
         <#if field.dependent==true && field.dependency.mandatory==true>
+        <#if field.type?starts_with("java.util.List")>
+        for(javax.management.ObjectName dep : ${field.name}) {
+            dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, dep, ${field.name}JmxAttribute);
+        }
+        <#else>
         dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, ${field.name}, ${field.name}JmxAttribute);
         </#if>
+        </#if>
     </#list>
         customValidation();
     }
@@ -65,10 +71,17 @@ package ${packageName};
     // caches of resolved dependencies
     <#list moduleFields as field>
     <#if field.dependent==true>
+        <#if field.type?starts_with("java.util.List")>
+        private java.util.List<${field.dependency.sie.exportedOsgiClassName}> ${field.name}Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>();
+        protected final java.util.List<${field.dependency.sie.exportedOsgiClassName}> get${field.attributeName}Dependency(){
+            return ${field.name}Dependency;
+        }
+        <#else>
         private ${field.dependency.sie.exportedOsgiClassName} ${field.name}Dependency;
         protected final ${field.dependency.sie.exportedOsgiClassName} get${field.attributeName}Dependency(){
             return ${field.name}Dependency;
         }
+        </#if>
     </#if>
     </#list>
 
@@ -79,12 +92,18 @@ package ${packageName};
 
             <#list moduleFields as field>
                 <#if field.dependent==true>
-
                     <#if field.dependency.mandatory==false>
                         if(${field.name}!=null) {
                     </#if>
 
-                    ${field.name}Dependency = dependencyResolver.resolveInstance(${field.dependency.sie.exportedOsgiClassName}.class, ${field.name}, ${field.name}JmxAttribute);
+                    <#if field.type?starts_with("java.util.List")>
+            ${field.name}Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>();
+            for(javax.management.ObjectName dep : ${field.name}) {
+                ${field.name}Dependency.add(dependencyResolver.resolveInstance(${field.dependency.sie.exportedOsgiClassName}.class, dep, ${field.name}JmxAttribute));
+            }
+                    <#else>
+            ${field.name}Dependency = dependencyResolver.resolveInstance(${field.dependency.sie.exportedOsgiClassName}.class, ${field.name}, ${field.name}JmxAttribute);
+                    </#if>
 
                     <#if field.dependency.mandatory==false>
                         }
index 0d6ec3c..2f14374 100644 (file)
@@ -75,6 +75,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 
+//TODO: refactor
 public class JMXGeneratorTest extends AbstractGeneratorTest {
 
     JMXGenerator jmxGenerator;
@@ -84,19 +85,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
     File generatedResourcesDir;
 
     private static final List<String> expectedModuleFileNames = ServiceInterfaceEntryTest
-            .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " +
-                    "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " +
-                    "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " +
-                    "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " +
-                    "AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " +
-                    "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " +
-                    "AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, " +
-                    "DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, " +
-                    "DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, " +
-                    "DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, " +
-                    "EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " +
-                    "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " +
-                    "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
+            .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
 
     private static final List<String> expectedBGPNames = ServiceInterfaceEntryTest
             .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, " +
@@ -119,38 +108,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                     "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
                     "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java]");
     private static final List<String> expectedAllFileNames = ServiceInterfaceEntryTest
-            .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " +
-                    "AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, " +
-                    "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " +
-                    "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " +
-                    "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " +
-                    "AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " +
-                    "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " +
-                    "AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, " +
-                    "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " +
-                    "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, " +
-                    "AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AsyncEventBusModule.java, " +
-                    "AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " +
-                    "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " +
-                    "AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, " +
-                    "BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java," +
-                    " BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, " +
-                    "BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, " +
-                    "DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, " +
-                    "DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, " +
-                    "DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, " +
-                    "DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, " +
-                    "EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, " +
-                    "EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " +
-                    "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " +
-                    "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, " +
-                    "NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, " +
-                    "NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, " +
-                    "NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " +
-                    "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " +
-                    "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " +
-                    "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
-                    "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
+            .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
     private static final List<String> expectedGenerateMBEsListNames = ServiceInterfaceEntryTest
             .toFileNames("[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]");
 
@@ -381,7 +339,11 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
                         + ".threads.java.DynamicThreadPoolModuleFactory",//
                 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
-                        + ".threads.java.NamingThreadFactoryModuleFactory");
+                        + ".threads.java.NamingThreadFactoryModuleFactory", //
+                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
+                        + ".threads.java.ThreadPoolRegistryImplModuleFactory");
+
+
         assertThat(lines, equalTo(expectedLines));
 
     }
index 70a4edd..a7110b8 100644 (file)
@@ -8,11 +8,14 @@
 package org.opendaylight.controller.config.yangjmxgenerator;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
 import com.google.common.collect.Sets;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
@@ -21,6 +24,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 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.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
@@ -338,7 +342,7 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                                 moduleLocalNameFromXPath);
                         yangToAttributes = fillConfiguration(choiceCaseNode,
                                 currentModule, typeProviderWrapper,
-                                qNamesToSIEs, schemaContext);
+                                qNamesToSIEs, schemaContext, packageName);
                         checkUniqueAttributesWithGeneratedClass(
                                 uniqueGeneratedClassesNames, when.getQName(),
                                 yangToAttributes);
@@ -484,12 +488,12 @@ public class ModuleMXBeanEntry extends AbstractEntry {
             ChoiceCaseNode choiceCaseNode, Module currentModule,
             TypeProviderWrapper typeProviderWrapper,
             Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            SchemaContext schemaContext) {
+            SchemaContext schemaContext, String packageName) {
         Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
         for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
             AttributeIfc attributeValue = getAttributeValue(attrNode,
                     currentModule, qNamesToSIEs, typeProviderWrapper,
-                    schemaContext);
+                    schemaContext, packageName);
             yangToAttributes.put(attributeValue.getAttributeYangName(),
                     attributeValue);
         }
@@ -549,11 +553,12 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         }
     }
 
-    private static int getChildNodeSizeWithoutUses(ContainerSchemaNode csn) {
+    private static int getChildNodeSizeWithoutUses(DataNodeContainer csn) {
         int result = 0;
         for (DataSchemaNode dsn : csn.getChildNodes()) {
-            if (dsn.isAddedByUses() == false)
+            if (dsn.isAddedByUses() == false) {
                 result++;
+            }
         }
         return result;
     }
@@ -561,7 +566,7 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     private static AttributeIfc getAttributeValue(DataSchemaNode attrNode,
             Module currentModule,
             Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext) {
+            TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext, String packageName) {
 
         if (attrNode instanceof LeafSchemaNode) {
             // simple type
@@ -570,49 +575,75 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         } else if (attrNode instanceof ContainerSchemaNode) {
             // reference or TO
             ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
-            if (containerSchemaNode.getUses().size() == 1
-                    && getChildNodeSizeWithoutUses(containerSchemaNode) == 0) {
-                // reference
-                UsesNode usesNode = containerSchemaNode.getUses().iterator()
-                        .next();
-                checkState(usesNode.getRefines().size() == 1,
-                        "Unexpected 'refine' child node size of "
-                                + containerSchemaNode);
-                LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines()
-                        .values().iterator().next();
-                checkState(refine.getUnknownSchemaNodes().size() == 1,
-                        "Unexpected unknown schema node size of " + refine);
-                UnknownSchemaNode requiredIdentity = refine
-                        .getUnknownSchemaNodes().iterator().next();
-                checkState(
-                        ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
-                                .getNodeType()),
-                        "Unexpected language extension " + requiredIdentity);
-                String prefixAndIdentityLocalName = requiredIdentity
-                        .getNodeParameter();
-                // import should point to a module
-                ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
-                        prefixAndIdentityLocalName, currentModule,
-                        qNamesToSIEs, schemaContext);
-                boolean mandatory = refine.getConstraints().isMandatory();
-                return new DependencyAttribute(attrNode, serviceInterfaceEntry,
-                        mandatory, attrNode.getDescription());
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(containerSchemaNode,
+                    attrNode, currentModule, qNamesToSIEs, schemaContext);
+            if (dependencyAttributeOptional.isPresent()) {
+                return dependencyAttributeOptional.get();
             } else {
-                return TOAttribute.create(containerSchemaNode,
-                        typeProviderWrapper);
+                return TOAttribute.create(containerSchemaNode, typeProviderWrapper, packageName);
             }
+
         } else if (attrNode instanceof LeafListSchemaNode) {
             return ListAttribute.create((LeafListSchemaNode) attrNode,
                     typeProviderWrapper);
         } else if (attrNode instanceof ListSchemaNode) {
-            return ListAttribute.create((ListSchemaNode) attrNode,
-                    typeProviderWrapper);
+            ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode;
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(listSchemaNode,
+                    attrNode, currentModule, qNamesToSIEs, schemaContext);
+            if (dependencyAttributeOptional.isPresent()) {
+                return dependencyAttributeOptional.get();
+            } else {
+                return ListAttribute.create(listSchemaNode, typeProviderWrapper, packageName);
+            }
         } else {
             throw new UnsupportedOperationException(
                     "Unknown configuration node " + attrNode.toString());
         }
     }
 
+    private static Optional<? extends AbstractDependencyAttribute> extractDependency(DataNodeContainer dataNodeContainer,
+                                                            DataSchemaNode attrNode,
+                                                            Module currentModule,
+                                                            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+                                                            SchemaContext schemaContext) {
+        if (dataNodeContainer.getUses().size() == 1
+                && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
+            // reference
+            UsesNode usesNode = dataNodeContainer.getUses().iterator()
+                    .next();
+            checkState(usesNode.getRefines().size() == 1,
+                    "Unexpected 'refine' child node size of "
+                            + dataNodeContainer);
+            LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines()
+                    .values().iterator().next();
+            checkState(refine.getUnknownSchemaNodes().size() == 1,
+                    "Unexpected unknown schema node size of " + refine);
+            UnknownSchemaNode requiredIdentity = refine
+                    .getUnknownSchemaNodes().iterator().next();
+            checkState(
+                    ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
+                            .getNodeType()),
+                    "Unexpected language extension " + requiredIdentity);
+            String prefixAndIdentityLocalName = requiredIdentity
+                    .getNodeParameter();
+            // import should point to a module
+            ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
+                    prefixAndIdentityLocalName, currentModule,
+                    qNamesToSIEs, schemaContext);
+            boolean mandatory = refine.getConstraints().isMandatory();
+            AbstractDependencyAttribute reference;
+            if (dataNodeContainer instanceof ContainerSchemaNode ){
+                reference = new DependencyAttribute(attrNode, serviceInterfaceEntry,
+                    mandatory, attrNode.getDescription());
+            } else {
+                reference = new ListDependenciesAttribute(attrNode, serviceInterfaceEntry,
+                        mandatory, attrNode.getDescription());
+            }
+            return Optional.of(reference);
+        }
+        return Optional.absent();
+    }
+
     private static ServiceInterfaceEntry findSIE(
             String prefixAndIdentityLocalName, Module currentModule,
             Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
index 9b82f12..f19a46d 100644 (file)
@@ -67,7 +67,7 @@ public class RuntimeBeanEntry {
     private final Set<Rpc> rpcs;
 
     @VisibleForTesting
-    public RuntimeBeanEntry(String packageName,
+    RuntimeBeanEntry(String packageName,
             DataSchemaNode nodeForReporting, String yangName,
             String javaNamePrefix, boolean isRoot,
             Optional<String> keyYangName, List<AttributeIfc> attributes,
@@ -228,7 +228,7 @@ public class RuntimeBeanEntry {
                 ContainerSchemaNode container = (ContainerSchemaNode) child;
                 // this can be either TO or hierarchical RB
                 TOAttribute toAttribute = TOAttribute.create(container,
-                        typeProviderWrapper);
+                        typeProviderWrapper, packageName);
                 attributes.add(toAttribute);
             } else if (child instanceof ListSchemaNode) {
                 if (isInnerStateBean(child)) {
@@ -239,7 +239,7 @@ public class RuntimeBeanEntry {
                     runtimeBeanEntries.add(hierarchicalChild);
                 } else /* ordinary list attribute */{
                     ListAttribute listAttribute = ListAttribute.create(
-                            (ListSchemaNode) child, typeProviderWrapper);
+                            (ListSchemaNode) child, typeProviderWrapper, packageName);
                     attributes.add(listAttribute);
                 }
 
@@ -280,7 +280,7 @@ public class RuntimeBeanEntry {
                     } else if (rpcDefinition.getOutput().getChildNodes().size() == 1) {
                         DataSchemaNode returnDSN = rpcDefinition.getOutput()
                                 .getChildNodes().iterator().next();
-                        returnType = getReturnTypeAttribute(returnDSN, typeProviderWrapper);
+                        returnType = getReturnTypeAttribute(returnDSN, typeProviderWrapper, packageName);
 
                     } else {
                         throw new IllegalArgumentException(
@@ -311,16 +311,17 @@ public class RuntimeBeanEntry {
                 attributes, rpcs);
     }
 
-    private static AttributeIfc getReturnTypeAttribute(DataSchemaNode child, TypeProviderWrapper typeProviderWrapper) {
+    private static AttributeIfc getReturnTypeAttribute(DataSchemaNode child, TypeProviderWrapper typeProviderWrapper,
+                                                       String packageName) {
         if (child instanceof LeafSchemaNode) {
             LeafSchemaNode leaf = (LeafSchemaNode) child;
             return new JavaAttribute(leaf, typeProviderWrapper);
         } else if (child instanceof ContainerSchemaNode) {
             ContainerSchemaNode container = (ContainerSchemaNode) child;
-            TOAttribute toAttribute = TOAttribute.create(container, typeProviderWrapper);
+            TOAttribute toAttribute = TOAttribute.create(container, typeProviderWrapper, packageName);
             return toAttribute;
         } else if (child instanceof ListSchemaNode) {
-            return ListAttribute.create((ListSchemaNode) child, typeProviderWrapper);
+            return ListAttribute.create((ListSchemaNode) child, typeProviderWrapper, packageName);
         } else if (child instanceof LeafListSchemaNode) {
             return ListAttribute.create((LeafListSchemaNode) child, typeProviderWrapper);
         } else {
diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/AbstractDependencyAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/AbstractDependencyAttribute.java
new file mode 100644 (file)
index 0000000..eb1c9e4
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.yangjmxgenerator.attribute;
+
+import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public abstract class AbstractDependencyAttribute extends AbstractAttribute  implements TypedAttribute  {
+
+    protected final Dependency dependency;
+    protected final String nullableDescription, nullableDefault;
+
+    public AbstractDependencyAttribute(DataSchemaNode attrNode,
+                                       ServiceInterfaceEntry sie, boolean mandatory,
+                                       String nullableDescription) {
+        super(attrNode);
+        dependency = new Dependency(sie, mandatory);
+        this.nullableDescription = nullableDescription;
+        nullableDefault = null;
+    }
+
+    public Dependency getDependency() {
+        return dependency;
+    }
+
+    @Override
+    public String getNullableDescription() {
+        return nullableDescription;
+    }
+
+    @Override
+    public String getNullableDefault() {
+        return nullableDefault;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        if (!super.equals(o))
+            return false;
+
+        AbstractDependencyAttribute that = (AbstractDependencyAttribute) o;
+
+        if (dependency != null ? !dependency.equals(that.dependency)
+                : that.dependency != null)
+            return false;
+        if (nullableDefault != null ? !nullableDefault
+                .equals(that.nullableDefault) : that.nullableDefault != null)
+            return false;
+        if (nullableDescription != null ? !nullableDescription
+                .equals(that.nullableDescription)
+                : that.nullableDescription != null)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (dependency != null ? dependency.hashCode() : 0);
+        result = 31
+                * result
+                + (nullableDescription != null ? nullableDescription.hashCode()
+                        : 0);
+        result = 31 * result
+                + (nullableDefault != null ? nullableDefault.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getName() + "{" + getAttributeYangName() + ","
+                + "dependency=" + dependency + '}';
+    }
+
+
+}
diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/Dependency.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/Dependency.java
new file mode 100644 (file)
index 0000000..38de6e1
--- /dev/null
@@ -0,0 +1,45 @@
+package org.opendaylight.controller.config.yangjmxgenerator.attribute;
+
+import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry;
+
+public class Dependency {
+        private final ServiceInterfaceEntry sie;
+        private final boolean mandatory;
+
+        public Dependency(ServiceInterfaceEntry sie, boolean mandatory) {
+            this.sie = sie;
+            this.mandatory = mandatory;
+        }
+
+        public ServiceInterfaceEntry getSie() {
+            return sie;
+        }
+
+        public boolean isMandatory() {
+            return mandatory;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o)
+                return true;
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            Dependency that = (Dependency) o;
+
+            if (mandatory != that.mandatory)
+                return false;
+            if (!sie.equals(that.sie))
+                return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = sie.hashCode();
+            result = 31 * result + (mandatory ? 1 : 0);
+            return result;
+        }
+    }
index 1912b75..d8df78a 100644 (file)
@@ -15,19 +15,13 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import javax.management.ObjectName;
 import javax.management.openmbean.SimpleType;
 
-public class DependencyAttribute extends AbstractAttribute implements
-        TypedAttribute {
+public class DependencyAttribute extends AbstractDependencyAttribute {
 
-    private final Dependency dependency;
-    private final String nullableDescription, nullableDefault;
 
     public DependencyAttribute(DataSchemaNode attrNode,
             ServiceInterfaceEntry sie, boolean mandatory,
             String nullableDescription) {
-        super(attrNode);
-        dependency = new Dependency(sie, mandatory);
-        this.nullableDescription = nullableDescription;
-        nullableDefault = null;
+        super(attrNode, sie, mandatory, nullableDescription);
     }
 
     @Override
@@ -35,109 +29,9 @@ public class DependencyAttribute extends AbstractAttribute implements
         return Types.typeForClass(ObjectName.class);
     }
 
-    public Dependency getDependency() {
-        return dependency;
-    }
-
-    @Override
-    public String getNullableDescription() {
-        return nullableDescription;
-    }
-
-    @Override
-    public String getNullableDefault() {
-        return nullableDefault;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o)
-            return true;
-        if (o == null || getClass() != o.getClass())
-            return false;
-        if (!super.equals(o))
-            return false;
-
-        DependencyAttribute that = (DependencyAttribute) o;
-
-        if (dependency != null ? !dependency.equals(that.dependency)
-                : that.dependency != null)
-            return false;
-        if (nullableDefault != null ? !nullableDefault
-                .equals(that.nullableDefault) : that.nullableDefault != null)
-            return false;
-        if (nullableDescription != null ? !nullableDescription
-                .equals(that.nullableDescription)
-                : that.nullableDescription != null)
-            return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode();
-        result = 31 * result + (dependency != null ? dependency.hashCode() : 0);
-        result = 31
-                * result
-                + (nullableDescription != null ? nullableDescription.hashCode()
-                        : 0);
-        result = 31 * result
-                + (nullableDefault != null ? nullableDefault.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "DependencyAttribute{" + getAttributeYangName() + ","
-                + "dependency=" + dependency + '}';
-    }
-
     @Override
     public SimpleType<?> getOpenType() {
         return SimpleType.OBJECTNAME;
     }
 
-    public static class Dependency {
-        private final ServiceInterfaceEntry sie;
-        private final boolean mandatory;
-
-        public Dependency(ServiceInterfaceEntry sie, boolean mandatory) {
-            this.sie = sie;
-            this.mandatory = mandatory;
-        }
-
-        public ServiceInterfaceEntry getSie() {
-            return sie;
-        }
-
-        public boolean isMandatory() {
-            return mandatory;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o)
-                return true;
-            if (o == null || getClass() != o.getClass())
-                return false;
-
-            Dependency that = (Dependency) o;
-
-            if (mandatory != that.mandatory)
-                return false;
-            if (!sie.equals(that.sie))
-                return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = sie.hashCode();
-            result = 31 * result + (mandatory ? 1 : 0);
-            return result;
-        }
-    }
-
 }
index 083b0b5..73b557e 100644 (file)
@@ -7,24 +7,27 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.attribute;
 
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-
 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
-public class ListAttribute extends AbstractAttribute {
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import java.util.List;
+
+public class ListAttribute extends AbstractAttribute implements TypedAttribute {
 
     private final String nullableDescription, nullableDefault;
-    private final AttributeIfc innerAttribute;
+    private final TypedAttribute innerAttribute;
 
     public static ListAttribute create(ListSchemaNode node,
-            TypeProviderWrapper typeProvider) {
+            TypeProviderWrapper typeProvider, String packageName) {
 
-        AttributeIfc innerAttribute = TOAttribute.create(node, typeProvider);
+        TOAttribute innerAttribute = TOAttribute.create(node, typeProvider, packageName);
 
         return new ListAttribute(node, innerAttribute, node.getDescription());
     }
@@ -32,12 +35,12 @@ public class ListAttribute extends AbstractAttribute {
     public static ListAttribute create(LeafListSchemaNode node,
             TypeProviderWrapper typeProvider) {
 
-        AttributeIfc innerAttribute = new JavaAttribute(node, typeProvider);
+        JavaAttribute innerAttribute = new JavaAttribute(node, typeProvider);
 
         return new ListAttribute(node, innerAttribute, node.getDescription());
     }
 
-    ListAttribute(DataSchemaNode attrNode, AttributeIfc innerAttribute,
+    ListAttribute(DataSchemaNode attrNode, TypedAttribute innerAttribute,
             String description) {
         super(attrNode);
         this.nullableDescription = description;
@@ -99,14 +102,24 @@ public class ListAttribute extends AbstractAttribute {
         return true;
     }
 
+
+    @Override
+    public Type getType() {
+        return Types.parameterizedTypeFor(Types.typeForClass(List.class), innerAttribute.getType());
+    }
+
     @Override
     public ArrayType<?> getOpenType() {
-        OpenType<?> inerOpenType = innerAttribute.getOpenType();
+        OpenType<?> innerOpenType = innerAttribute.getOpenType();
+        return constructArrayType(innerOpenType);
+    }
+
+    static ArrayType<?> constructArrayType(OpenType<?> innerOpenType){
         try {
-            return new ArrayType<>(1, inerOpenType);
+            return new ArrayType<>(1, innerOpenType);
         } catch (OpenDataException e) {
             throw new RuntimeException("Unable to create " + ArrayType.class
-                    + " with inner element of type " + inerOpenType, e);
+                    + " with inner element of type " + innerOpenType, e);
         }
     }
 
diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListDependenciesAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/ListDependenciesAttribute.java
new file mode 100644 (file)
index 0000000..641099a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.yangjmxgenerator.attribute;
+
+import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import java.util.List;
+
+public class ListDependenciesAttribute extends AbstractDependencyAttribute {
+
+    public ListDependenciesAttribute(DataSchemaNode attrNode, ServiceInterfaceEntry sie, boolean mandatory, String nullableDescription) {
+        super(attrNode, sie, mandatory, nullableDescription);
+    }
+
+    @Override
+    public Type getType() {
+        return Types.parameterizedTypeFor(Types.typeForClass(List.class), Types.typeForClass(ObjectName.class));
+    }
+
+    @Override
+    public ArrayType<?> getOpenType() {
+        OpenType<?> innerOpenType = SimpleType.OBJECTNAME;
+        return ListAttribute.constructArrayType(innerOpenType);
+    }
+
+}
index 9665633..6a540b5 100644 (file)
@@ -13,6 +13,8 @@ import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -29,11 +31,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-public class TOAttribute extends AbstractAttribute {
+public class TOAttribute extends AbstractAttribute implements TypedAttribute {
 
     private final String nullableDescription, nullableDefault;
     private final Map<String, AttributeIfc> yangNameToAttributeMap;
     private final Map<String, String> attributeNameMap;
+    private final String packageName;
 
     private static final Set<Class<? extends DataSchemaNode>> ALLOWED_CHILDREN = Sets
             .newHashSet();
@@ -45,7 +48,7 @@ public class TOAttribute extends AbstractAttribute {
     }
 
     public static <T extends DataNodeContainer & AugmentationTarget & DataSchemaNode> TOAttribute create(
-            T containerSchemaNode, TypeProviderWrapper typeProviderWrapper) {
+            T containerSchemaNode, TypeProviderWrapper typeProviderWrapper, String packageName) {
         // Transfer Object: get the leaves
         Map<String, AttributeIfc> map = new HashMap<>();
         Map<String, String> attributeNameMap = new HashMap<>();
@@ -55,18 +58,18 @@ public class TOAttribute extends AbstractAttribute {
                 String yangName = dataSchemaNode.getQName().getLocalName();
                 map.put(yangName,
                         createInnerAttribute(dataSchemaNode,
-                                typeProviderWrapper));
+                                typeProviderWrapper, packageName));
             } catch (IllegalArgumentException e) {
                 throw new IllegalStateException("Unable to create TO", e);
             }
         }
         return new TOAttribute(containerSchemaNode, map, attributeNameMap,
-                containerSchemaNode.getDescription());
+                containerSchemaNode.getDescription(), packageName);
     }
 
     private static AttributeIfc createInnerAttribute(
             DataSchemaNode dataSchemaNode,
-            TypeProviderWrapper typeProviderWrapper) {
+            TypeProviderWrapper typeProviderWrapper, String packageName) {
         Class<? extends DataSchemaNode> type = isAllowedType(dataSchemaNode);
 
         if (type.equals(LeafSchemaNode.class))
@@ -74,13 +77,13 @@ public class TOAttribute extends AbstractAttribute {
                     typeProviderWrapper);
         else if (type.equals(ListSchemaNode.class))
             return ListAttribute.create((ListSchemaNode) dataSchemaNode,
-                    typeProviderWrapper);
+                    typeProviderWrapper, packageName);
         else if (type.equals(LeafListSchemaNode.class))
             return ListAttribute.create((LeafListSchemaNode) dataSchemaNode,
                     typeProviderWrapper);
         else if (type.equals(ContainerSchemaNode.class))
             return TOAttribute.create((ContainerSchemaNode) dataSchemaNode,
-                    typeProviderWrapper);
+                    typeProviderWrapper, packageName);
 
         throw new IllegalStateException("This should never happen");
     }
@@ -98,12 +101,13 @@ public class TOAttribute extends AbstractAttribute {
 
     private TOAttribute(DataSchemaNode attrNode,
             Map<String, AttributeIfc> transferObject,
-            Map<String, String> attributeNameMap, String nullableDescription) {
+            Map<String, String> attributeNameMap, String nullableDescription, String packageName) {
         super(attrNode);
         yangNameToAttributeMap = transferObject;
         this.attributeNameMap = attributeNameMap;
         this.nullableDescription = nullableDescription;
         nullableDefault = null;
+        this.packageName = packageName;
     }
 
     public Map<String, String> getAttributeNameMap() {
@@ -197,6 +201,12 @@ public class TOAttribute extends AbstractAttribute {
                 + yangNameToAttributeMap + '}';
     }
 
+    @Override
+    public Type getType() {
+        // TODO: ReferencedTypeImpl from Types
+        return new ReferencedTypeImpl(packageName, getUpperCaseCammelCase());
+    }
+
     @Override
     public CompositeType getOpenType() {
         String description = getNullableDescription() == null ? getAttributeYangName()
@@ -222,6 +232,10 @@ public class TOAttribute extends AbstractAttribute {
         }
     }
 
+    public String getPackageName() {
+        return packageName;
+    }
+
     private static final class FunctionImpl implements
             Function<Entry<String, AttributeIfc>, OpenType<?>> {
         private final String[] itemNames;
index 661dbd7..e86c876 100644 (file)
@@ -7,38 +7,14 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.SimpleType;
-
+import com.google.common.collect.Sets;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TypedAttribute;
 import org.opendaylight.yangtools.binding.generator.util.Types;
@@ -48,13 +24,37 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 
-import com.google.common.collect.Sets;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.SimpleType;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
 public class ModuleMXBeanEntryTest extends AbstractYangTest {
     public static final String EVENTBUS_MXB_NAME = "eventbus";
     public static final String ASYNC_EVENTBUS_MXB_NAME = "async-eventbus";
     public static final String THREADFACTORY_NAMING_MXB_NAME = "threadfactory-naming";
     public static final String THREADPOOL_DYNAMIC_MXB_NAME = "threadpool-dynamic";
+    public static final String THREADPOOL_REGISTRY_IMPL_NAME = "threadpool-registry-impl";
 
     public static final String BGP_LISTENER_IMPL_MXB_NAME = "bgp-listener-impl";
 
@@ -87,7 +87,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
         assertNotNull(namesToMBEs);
         Set<String> expectedMXBeanNames = Sets.newHashSet(EVENTBUS_MXB_NAME,
                 ASYNC_EVENTBUS_MXB_NAME, THREADFACTORY_NAMING_MXB_NAME,
-                THREADPOOL_DYNAMIC_MXB_NAME);
+                THREADPOOL_DYNAMIC_MXB_NAME, THREADPOOL_REGISTRY_IMPL_NAME);
         assertThat(namesToMBEs.keySet(), is(expectedMXBeanNames));
         return namesToMBEs;
     }
@@ -299,6 +299,15 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
             }
 
         }
+        { // test multiple dependencies
+            ModuleMXBeanEntry threadPoolRegistry = namesToMBEs.get(THREADPOOL_REGISTRY_IMPL_NAME);
+            Map<String, AttributeIfc> attributes = threadPoolRegistry.getAttributes();
+            assertEquals(1, attributes.size());
+            AttributeIfc threadpoolsAttr = attributes.get("threadpools");
+            assertNotNull(threadpoolsAttr);
+            assertTrue(threadpoolsAttr instanceof ListDependenciesAttribute);
+            ListDependenciesAttribute threadpools = (ListDependenciesAttribute) threadpoolsAttr;
+        }
     }
 
 }
index 24c0257..14ec7e0 100644 (file)
@@ -100,10 +100,15 @@ public class SchemaContextTest extends AbstractYangTest {
 
     @Test
     public void testReadingIdentities_threadsJavaModule() {
-        Map<String /* identity name */, Optional<QName>> expectedIdentitiesToBases = ImmutableMap
-                .of("eventbus", Optional.of(MODULE_TYPE_Q_NAME), "async-eventbus", Optional.of(MODULE_TYPE_Q_NAME),
-                        "threadfactory-naming", Optional.of(MODULE_TYPE_Q_NAME), "threadpool-dynamic",
-                        Optional.of(MODULE_TYPE_Q_NAME), "thread-rpc-context", Optional.<QName>absent());
+        Map<String /* identity name */, Optional<QName>> expectedIdentitiesToBases = new HashMap(){{
+            put(ModuleMXBeanEntryTest.EVENTBUS_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME));
+            put(ModuleMXBeanEntryTest.ASYNC_EVENTBUS_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME));
+            put(ModuleMXBeanEntryTest.THREADFACTORY_NAMING_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME));
+            put(ModuleMXBeanEntryTest.THREADPOOL_DYNAMIC_MXB_NAME, Optional.of(MODULE_TYPE_Q_NAME));
+            put("thread-rpc-context", Optional.absent());
+            put(ModuleMXBeanEntryTest.THREADPOOL_REGISTRY_IMPL_NAME, Optional.of(MODULE_TYPE_Q_NAME));
+        }};
+
         assertAllIdentitiesAreExpected(threadsJavaModule,
                 expectedIdentitiesToBases);
     }
index 2972cec..4af5b95 100644 (file)
@@ -241,4 +241,25 @@ module config-threads-java {
             }
         }
     }
+
+    identity threadpool-registry-impl {
+        base config:module-type;
+        config:java-name-prefix ThreadPoolRegistryImpl;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case threadpool-registry-impl {
+            when "/config:modules/config:module/config:type = 'threadpool-registry-impl'";
+
+            // list of dependencies:
+            list threadpools {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity th2:threadpool;
+                    }
+                }
+            }
+        }
+    }
 }
index ba5021e..bd83a4c 100644 (file)
@@ -242,6 +242,15 @@ module config-test-impl {
                     }
                 }
             }
+
+            list testing-deps {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity test:testing;
+                    }
+                }
+            }
         }
     }
 
index de75977..3ec9f84 100644 (file)
@@ -836,21 +836,14 @@ public class FlowConfig implements Serializable {
                 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
                 if (sstr.matches()) {
                     for (String t : sstr.group(1).split(",")) {
-                        Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
-                        if (n.matches()) {
-                            String port = n.group(1);
-                            if (port != null) {
-                                if (!isPortValid(sw, port)) {
-                                    String msg = String.format("Output port %s is not valid for this switch", port);
-                                    if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
-                                        msg += " in Container " + containerName;
-                                    }
-                                    return new Status(StatusCode.BADREQUEST, msg);
+                        if (t != null) {
+                            if (!isPortValid(sw, t)) {
+                                String msg = String.format("Output port %s is not valid for this switch", t);
+                                if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
+                                    msg += " in Container " + containerName;
                                 }
+                                return new Status(StatusCode.BADREQUEST, msg);
                             }
-                        } else {
-                            String msg = String.format("Output port %s is not valid", t);
-                            return new Status(StatusCode.BADREQUEST, msg);
                         }
                     }
                     continue;
@@ -859,21 +852,15 @@ public class FlowConfig implements Serializable {
                 sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp);
                 if (sstr.matches()) {
                     for (String t : sstr.group(1).split(",")) {
-                        Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
-                        if (n.matches()) {
-                            if (n.group(1) != null) {
-                                String port = n.group(1).split(":")[0];
-                                if (!isPortValid(sw, port)) {
-                                    String msg = String.format("Output port %d is not valid for this switch", port);
-                                    if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
-                                        msg += " in Container " + containerName;
-                                    }
-                                    return new Status(StatusCode.BADREQUEST, msg);
+                        if (t != null) {
+                            String port = t.split(":")[0];
+                            if (!isPortValid(sw, port)) {
+                                String msg = String.format("Output port %d is not valid for this switch", port);
+                                if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
+                                    msg += " in Container " + containerName;
                                 }
+                                return new Status(StatusCode.BADREQUEST, msg);
                             }
-                        } else {
-                            String msg = String.format("Enqueue port %s is not valid", t);
-                            return new Status(StatusCode.BADREQUEST, msg);
                         }
                     }
                     continue;
@@ -1102,12 +1089,9 @@ public class FlowConfig implements Serializable {
                 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
                 if (sstr.matches()) {
                     for (String t : sstr.group(1).split(",")) {
-                        Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
-                        if (n.matches()) {
-                            if (n.group(1) != null) {
-                                String nc = String.format("%s|%s@%s", node.getType(), n.group(1), node.toString());
-                                actionList.add(new Output(NodeConnector.fromString(nc)));
-                            }
+                        if (t != null) {
+                            String nc = String.format("%s|%s@%s", node.getType(), t, node.toString());
+                            actionList.add(new Output(NodeConnector.fromString(nc)));
                         }
                     }
                     continue;
@@ -1116,17 +1100,14 @@ public class FlowConfig implements Serializable {
                 sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
                 if (sstr.matches()) {
                     for (String t : sstr.group(1).split(",")) {
-                        Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
-                        if (n.matches()) {
-                            if (n.group(1) != null) {
-                                String parts[] = n.group(1).split(":");
-                                String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
-                                if (parts.length == 1) {
-                                    actionList.add(new Enqueue(NodeConnector.fromString(nc)));
-                                } else {
-                                    actionList
-                                            .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
-                                }
+                        if (t != null) {
+                            String parts[] = t.split(":");
+                            String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
+                            if (parts.length == 1) {
+                                actionList.add(new Enqueue(NodeConnector.fromString(nc)));
+                            } else {
+                                actionList
+                                .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
                             }
                         }
                     }
index a1a24eb..5da084e 100644 (file)
@@ -1,14 +1,15 @@
 package org.opendaylight.controller.config.yang.md.sal.binding.statistics;\r
 \r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.Data;\r
 import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeMXBean;\r
 import org.opendaylight.controller.config.yang.md.sal.binding.impl.Transactions;\r
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;\r
 \r
 public class DataBrokerRuntimeMXBeanImpl extends DataBrokerImpl implements DataBrokerImplRuntimeMXBean {\r
     \r
-    private Transactions transactions = new Transactions();\r
+    private final Transactions transactions = new Transactions();\r
+    private final Data data = new Data();\r
     \r
-    @Override\r
     public Transactions getTransactions() {\r
         transactions.setCreated(getCreatedTransactionsCount().get());\r
         transactions.setSubmitted(getSubmittedTransactionsCount().get());\r
@@ -16,4 +17,14 @@ public class DataBrokerRuntimeMXBeanImpl extends DataBrokerImpl implements DataB
         transactions.setFailed(getFailedTransactionsCount().get());\r
         return transactions;\r
     }\r
+\r
+    @Override\r
+    public Data getData() {\r
+        transactions.setCreated(getCreatedTransactionsCount().get());\r
+        transactions.setSubmitted(getSubmittedTransactionsCount().get());\r
+        transactions.setSuccessful(getFinishedTransactionsCount().get());\r
+        transactions.setFailed(getFailedTransactionsCount().get());\r
+        data.setTransactions(transactions);\r
+        return data;\r
+    }\r
 }\r
index 9da073f..b040aa0 100644 (file)
@@ -121,7 +121,9 @@ module opendaylight-sal-binding-broker-impl {
     augment "/config:modules/config:module/config:state" {
         case binding-data-broker {
             when "/config:modules/config:module/config:type = 'binding-data-broker'";
-            uses common:data-state;
+            container data {
+                uses common:data-state;
+            }
         }
     }
     augment "/config:modules/config:module/config:state" {
index 050966f..9a2a904 100644 (file)
@@ -9,10 +9,12 @@
 */
 package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 
+import org.opendaylight.controller.config.yang.md.sal.dom.statistics.DomBrokerRuntimeMXBeanImpl;
 import org.opendaylight.controller.sal.core.api.data.DataStore;
 import org.opendaylight.controller.sal.dom.broker.BrokerConfigActivator;
 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
 import org.osgi.framework.BundleContext;
+
 import static com.google.common.base.Preconditions.*;
 
 /**
@@ -37,14 +39,15 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi
         checkArgument(getDataStore() != null, "Data Store needs to be provided for DomBroker");
     }
     
-    
-
     @Override
     public java.lang.AutoCloseable createInstance() {
-        BrokerImpl broker = new BrokerImpl();
-        BrokerConfigActivator activator = new BrokerConfigActivator();
-        DataStore store = getDataStoreDependency();
-        activator.start(broker, store,getBundleContext());
+        final BrokerImpl broker = new BrokerImpl();
+        final BrokerConfigActivator activator = new BrokerConfigActivator();
+        final DataStore store = getDataStoreDependency();
+        activator.start(broker, store, getBundleContext());
+        
+        final DomBrokerImplRuntimeMXBean domBrokerRuntimeMXBean = new DomBrokerRuntimeMXBeanImpl(activator.getDataService());
+        getRootRuntimeBeanRegistratorWrapper().register(domBrokerRuntimeMXBean);
         return broker;
     }
 
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/statistics/DomBrokerRuntimeMXBeanImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/statistics/DomBrokerRuntimeMXBeanImpl.java
new file mode 100644 (file)
index 0000000..bc13979
--- /dev/null
@@ -0,0 +1,36 @@
+package org.opendaylight.controller.config.yang.md.sal.dom.statistics;
+
+import org.opendaylight.controller.config.yang.md.sal.dom.impl.Data;
+import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplRuntimeMXBean;
+import org.opendaylight.controller.config.yang.md.sal.dom.impl.Transactions;
+import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
+
+public class DomBrokerRuntimeMXBeanImpl implements
+        DomBrokerImplRuntimeMXBean {
+    
+    private final DataBrokerImpl dataService;
+    private final Transactions transactions = new Transactions();
+    private final Data data = new Data();
+    
+    public DomBrokerRuntimeMXBeanImpl(DataBrokerImpl dataService) {
+        this.dataService = dataService; 
+    }
+
+    public Transactions getTransactions() {
+        transactions.setCreated(dataService.getCreatedTransactionsCount().get());
+        transactions.setSubmitted(dataService.getSubmittedTransactionsCount().get());
+        transactions.setSuccessful(dataService.getFinishedTransactionsCount().get());
+        transactions.setFailed(dataService.getFailedTransactionsCount().get());
+        return transactions;
+    }
+
+    @Override
+    public Data getData() {
+        transactions.setCreated(dataService.getCreatedTransactionsCount().get());
+        transactions.setSubmitted(dataService.getSubmittedTransactionsCount().get());
+        transactions.setSuccessful(dataService.getFinishedTransactionsCount().get());
+        transactions.setFailed(dataService.getFailedTransactionsCount().get());
+        data.setTransactions(transactions);
+        return data;
+    }
+}
index da7cccb..482cfa9 100644 (file)
@@ -19,15 +19,16 @@ class BrokerConfigActivator implements AutoCloseable {
     
     
     private static val ROOT = InstanceIdentifier.builder().toInstance();
+
+    @Property
+    private var DataBrokerImpl dataService;
     
     private var ServiceRegistration<SchemaService> schemaReg;
     private var ServiceRegistration<DataBrokerService> dataReg;
     private var ServiceRegistration<DataProviderService> dataProviderReg;
     private var ServiceRegistration<MountService> mountReg;
     private var ServiceRegistration<MountProvisionService> mountProviderReg;
-    
     private var SchemaServiceImpl schemaService;
-    private var DataBrokerImpl dataService;
     private var MountPointManagerImpl mountService;
     
     SchemaAwareDataStoreAdapter wrappedStore
index ac5313a..56eae97 100644 (file)
@@ -2,7 +2,6 @@ package org.opendaylight.controller.sal.dom.broker;
 
 import java.util.concurrent.atomic.AtomicLong;
 
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
@@ -15,17 +14,23 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
 public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier, CompositeNode, DataChangeListener> implements
-        DataProviderService {
+        DataProviderService, AutoCloseable {
 
+    private AtomicLong nextTransaction = new AtomicLong();
+    private final AtomicLong createdTransactionsCount = new AtomicLong();
+    
     public DataBrokerImpl() {
         setDataReadRouter(new DataReaderRouter());
     }
-
-    private AtomicLong nextTransaction = new AtomicLong();
+    
+    public AtomicLong getCreatedTransactionsCount() {
+        return createdTransactionsCount;
+    }
     
     @Override
     public DataTransactionImpl beginTransaction() {
         String transactionId = "DOM-" + nextTransaction.getAndIncrement();
+        createdTransactionsCount.getAndIncrement();
         return new DataTransactionImpl(transactionId,this);
     }
 
@@ -66,4 +71,9 @@ public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier, Compo
         throw new UnsupportedOperationException("Deprecated");
     }
 
+    @Override
+    public void close() throws Exception {
+        
+    }
+
 }
\ No newline at end of file
index bf12ac4..9ae9c9c 100644 (file)
@@ -5,6 +5,7 @@ module opendaylight-sal-dom-broker-impl {
 
        import config { prefix config; revision-date 2013-04-05; }
        import opendaylight-md-sal-dom {prefix sal;}
+       import opendaylight-md-sal-common {prefix common;}
 
     description
         "Service definition for Binding Aware MD-SAL.";
@@ -18,7 +19,7 @@ module opendaylight-sal-dom-broker-impl {
         base config:module-type;
         config:provided-service sal:dom-broker-osgi-registry;
         config:java-name-prefix DomBrokerImpl;
-    }
+    }    
     
     identity hash-map-data-store {
         base config:module-type;
@@ -58,4 +59,12 @@ module opendaylight-sal-dom-broker-impl {
         }
     }
     
+    augment "/config:modules/config:module/config:state" {
+        case dom-broker-impl {
+            when "/config:modules/config:module/config:type = 'dom-broker-impl'";
+            container data {
+                uses common:data-state;
+            } 
+        }
+    }
 }
\ No newline at end of file
index 4b6dcfd..2b6f862 100644 (file)
@@ -12,6 +12,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIf
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 
 import javax.management.openmbean.ArrayType;
@@ -37,7 +38,9 @@ public abstract class AttributeIfcSwitchStatement<T> {
         } else if (attributeIfc instanceof DependencyAttribute) {
             return caseDependencyAttribute(((DependencyAttribute) attributeIfc).getOpenType());
         } else if (attributeIfc instanceof ListAttribute) {
-            return caseListAttribute(((ListAttribute) attributeIfc).getOpenType());
+            return caseListAttribute((ArrayType<?>) attributeIfc.getOpenType());
+        } else if (attributeIfc instanceof ListDependenciesAttribute) {
+            return caseListDependeciesAttribute((ArrayType<?>) attributeIfc.getOpenType());
         } else if (attributeIfc instanceof TOAttribute) {
             return caseTOAttribute(((TOAttribute) attributeIfc).getOpenType());
         }
@@ -45,6 +48,7 @@ public abstract class AttributeIfcSwitchStatement<T> {
         throw getIllegalArgumentException(attributeIfc);
     }
 
+
     private IllegalArgumentException getIllegalArgumentException(AttributeIfc attributeIfc) {
         return new IllegalArgumentException("Unknown attribute type " + attributeIfc.getClass() + ", " + attributeIfc
                 + " with open type:" + attributeIfc.getOpenType());
@@ -74,6 +78,7 @@ public abstract class AttributeIfcSwitchStatement<T> {
 
     protected abstract T caseListAttribute(ArrayType<?> openType);
 
+    protected abstract T caseListDependeciesAttribute(ArrayType<?> openType);
 
     private static class UnknownOpenTypeException extends RuntimeException {
         public UnknownOpenTypeException(String message) {
index bc3c74a..e2ea404 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
 
@@ -86,4 +87,11 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadin
         return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
     }
 
+    @Override
+    protected AttributeReadingStrategy caseListDependeciesAttribute(ArrayType<?> openType) {
+        Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+        AttributeReadingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME);
+        return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
+    }
+
 }
index 853197c..6e5bd0d 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
@@ -121,4 +122,10 @@ public class ObjectMapper extends AttributeIfcSwitchStatement<AttributeMappingSt
                 prepareStrategy(((ListAttribute) lastAttribute).getInnerAttribute()));
     }
 
+    @Override
+    protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseListDependeciesAttribute(ArrayType<?> openType) {
+        Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+        return new ArrayAttributeMappingStrategy(openType, caseDependencyAttribute(SimpleType.OBJECTNAME));
+    }
+
 }
index c321164..f5a2511 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
@@ -109,4 +110,10 @@ public class ObjectResolver extends AttributeIfcSwitchStatement<AttributeResolvi
         return new ArrayAttributeResolvingStrategy(prepareStrategy(innerAttribute), openType);
     }
 
+    @Override
+    protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseListDependeciesAttribute(ArrayType<?> openType) {
+        Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+        return new ArrayAttributeResolvingStrategy(caseDependencyAttribute(SimpleType.OBJECTNAME), openType);
+    }
+
 }
index 99e9699..ad587ea 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
 import org.w3c.dom.Document;
@@ -96,4 +97,11 @@ public class ObjectXmlWriter extends AttributeIfcSwitchStatement<AttributeWritin
         return new ArrayAttributeWritingStrategy(innerStrategy);
     }
 
+    @Override
+    protected AttributeWritingStrategy caseListDependeciesAttribute(ArrayType<?> openType) {
+        Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+        AttributeWritingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME);
+        return new ArrayAttributeWritingStrategy(innerStrategy);
+    }
+
 }
index e4fa6f5..f522668 100644 (file)
@@ -284,8 +284,13 @@ public final class Services {
         public static ServiceInstance fromString(String instanceId) {
             instanceId = instanceId.trim();
             Matcher matcher = p.matcher(instanceId);
+            if(matcher.matches() == false) {
+                matcher = pDeprecated.matcher(instanceId);
+            }
+
             Preconditions.checkArgument(matcher.matches(), "Unexpected format for provider, expected " + p.toString()
-                    + " but was " + instanceId);
+                    + " or " + pDeprecated.toString() + " but was " + instanceId);
+
             String factoryName = matcher.group(1);
             String instanceName = matcher.group(2);
             return new ServiceInstance(factoryName, instanceName);
@@ -310,16 +315,25 @@ public final class Services {
             return instanceName;
         }
 
-        private static final String blueprint = "/" + XmlNetconfConstants.CONFIG_KEY + "/"
+        private static final String blueprint = "/"
                 + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "["
-                + XmlNetconfConstants.NAME_KEY + "='%s']/" + XmlNetconfConstants.INSTANCE_KEY + "["
+                + XmlNetconfConstants.TYPE_KEY + "='%s']["
                 + XmlNetconfConstants.NAME_KEY + "='%s']";
 
-        private static final String blueprintR = "/" + XmlNetconfConstants.CONFIG_KEY + "/"
+        // TODO unify with xpath in RuntimeRpc
+
+        // Previous version of xpath, needs to be supported for backwards compatibility (persisted configs by config-persister)
+        private static final String blueprintRDeprecated = "/" + XmlNetconfConstants.CONFIG_KEY + "/"
                 + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "\\["
                 + XmlNetconfConstants.NAME_KEY + "='%s'\\]/" + XmlNetconfConstants.INSTANCE_KEY + "\\["
                 + XmlNetconfConstants.NAME_KEY + "='%s'\\]";
 
+        private static final String blueprintR = "/"
+                + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "\\["
+                + XmlNetconfConstants.TYPE_KEY + "='%s'\\]\\["
+                + XmlNetconfConstants.NAME_KEY + "='%s'\\]";
+
+        private static final Pattern pDeprecated = Pattern.compile(String.format(blueprintRDeprecated, "(.+)", "(.+)"));
         private static final Pattern p = Pattern.compile(String.format(blueprintR, "(.+)", "(.+)"));
 
         @Override
index d91e38d..35fa042 100644 (file)
@@ -132,10 +132,12 @@ public class NetconfMappingTest extends AbstractConfigTest {
         // check after edit
         commit();
         Element response = getConfigRunning();
+        System.err.println(XmlUtil.toString(response));
 
         checkBinaryLeafEdited(response);
         checkTypeConfigAttribute(response);
         checkTypedefs(response);
+        checkTestingDeps(response);
         checkEnum(response);
         checkBigDecimal(response);
 
@@ -163,11 +165,6 @@ public class NetconfMappingTest extends AbstractConfigTest {
         verifyNoMoreInteractions(netconfOperationRouter);
     }
 
-    private void checkBigDecimal(Element response) {
-        int size = response.getElementsByTagName("sleep-factor").getLength();
-        assertEquals(1, size);
-    }
-
     private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException,
             IOException {
         DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID);
@@ -394,6 +391,17 @@ public class NetconfMappingTest extends AbstractConfigTest {
         fail("Enum attribute " + enumName + ":" + enumContent + " not present in " + XmlUtil.toString(response));
     }
 
+    private void checkTestingDeps(Element response) {
+        int testingDepsSize = response.getElementsByTagName("testing-deps").getLength();
+        assertEquals(2, testingDepsSize);
+    }
+
+    private void checkBigDecimal(Element response) {
+        int size = response.getElementsByTagName("sleep-factor").getLength();
+        assertEquals(1, size);
+    }
+
+
     private void checkTypeConfigAttribute(Element response) {
 
         XmlElement modulesElement = XmlElement.fromDomElement(response).getOnlyChildElement("data")
index 99b7ee6..1c3ac7a 100644 (file)
@@ -8,45 +8,22 @@
 
 package org.opendaylight.controller.netconf.persist.impl;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetSocketAddress;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServerConnection;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
-import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
 import org.opendaylight.controller.netconf.api.jmx.DefaultCommitOperationMXBean;
 import org.opendaylight.controller.netconf.api.jmx.NetconfJMXNotification;
 import org.opendaylight.controller.netconf.client.NetconfClient;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
-import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
-import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
+
+import javax.annotation.concurrent.ThreadSafe;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.regex.Pattern;
 
 /**
  * Responsible for listening for notifications from netconf containing latest
@@ -57,163 +34,27 @@ import org.xml.sax.SAXException;
 public class ConfigPersisterNotificationHandler implements NotificationListener, Closeable {
 
     private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterNotificationHandler.class);
-    private static final int NETCONF_SEND_ATTEMPT_MS_DELAY = 1000;
-    private static final int NETCONF_SEND_ATTEMPTS = 20;
-
-    private final InetSocketAddress address;
-    private final EventLoopGroup nettyThreadgroup;
-
-    private NetconfClientDispatcher netconfClientDispatcher;
-    private NetconfClient netconfClient;
-
-    private final Persister persister;
-    private final MBeanServerConnection mbeanServer;
-
-
-    private final ObjectName on = DefaultCommitOperationMXBean.objectName;
-
-    public static final long DEFAULT_TIMEOUT = 120000L;// 120 seconds until netconf must be stable
-    private final long timeout;
+    private final MBeanServerConnection mBeanServerConnection;
+    private final NetconfClient netconfClient;
+    private final PersisterAggregator persisterAggregator;
     private final Pattern ignoredMissingCapabilityRegex;
 
-    public ConfigPersisterNotificationHandler(Persister persister, InetSocketAddress address,
-            MBeanServerConnection mbeanServer, Pattern ignoredMissingCapabilityRegex) {
-        this(persister, address, mbeanServer, DEFAULT_TIMEOUT, ignoredMissingCapabilityRegex);
-
-    }
-
-    public ConfigPersisterNotificationHandler(Persister persister, InetSocketAddress address,
-            MBeanServerConnection mbeanServer, long timeout, Pattern ignoredMissingCapabilityRegex) {
-        this.persister = persister;
-        this.address = address;
-        this.mbeanServer = mbeanServer;
-        this.timeout = timeout;
-
-        this.nettyThreadgroup = new NioEventLoopGroup();
+    public ConfigPersisterNotificationHandler(MBeanServerConnection mBeanServerConnection, NetconfClient netconfClient,
+                                              PersisterAggregator persisterAggregator, Pattern ignoredMissingCapabilityRegex) {
+        this.mBeanServerConnection = mBeanServerConnection;
+        this.netconfClient = netconfClient;
+        this.persisterAggregator = persisterAggregator;
         this.ignoredMissingCapabilityRegex = ignoredMissingCapabilityRegex;
     }
 
-    public void init() throws InterruptedException {
-        Optional<ConfigSnapshotHolder> maybeConfig = loadLastConfig();
-
-        if (maybeConfig.isPresent()) {
-            logger.debug("Last config found {}", persister);
-            ConflictingVersionException lastException = null;
-            pushLastConfigWithRetries(maybeConfig, lastException);
-
-        } else {
-            // this ensures that netconf is initialized, this is first
-            // connection
-            // this means we can register as listener for commit
-            registerToNetconf(Collections.<String>emptySet());
-
-            logger.info("No last config provided by backend storage {}", persister);
-        }
+    public void init() {
         registerAsJMXListener();
     }
 
-    private void pushLastConfigWithRetries(Optional<ConfigSnapshotHolder> maybeConfig, ConflictingVersionException lastException) throws InterruptedException {
-        int maxAttempts = 30;
-        for(int i = 0 ; i < maxAttempts; i++) {
-            registerToNetconf(maybeConfig.get().getCapabilities());
-
-            final String configSnapshot = maybeConfig.get().getConfigSnapshot();
-            logger.trace("Pushing following xml to netconf {}", configSnapshot);
-            try {
-                pushLastConfig(XmlUtil.readXmlToElement(configSnapshot));
-                return;
-            } catch(ConflictingVersionException e) {
-                closeClientAndDispatcher(netconfClient, netconfClientDispatcher);
-                lastException = e;
-                Thread.sleep(1000);
-            } catch (SAXException | IOException e) {
-                throw new IllegalStateException("Unable to load last config", e);
-            }
-        }
-        throw new IllegalStateException("Failed to push configuration, maximum attempt count has been reached: "
-                + maxAttempts, lastException);
-    }
-
-    private synchronized long registerToNetconf(Set<String> expectedCaps) throws InterruptedException {
-
-        Set<String> currentCapabilities = Sets.newHashSet();
-
-        // TODO think about moving capability subset check to netconf client
-        // could be utilized by integration tests
-
-        long pollingStart = System.currentTimeMillis();
-        int delay = 5000;
-
-        int attempt = 0;
-
-        long deadline = pollingStart + timeout;
-        while (System.currentTimeMillis() < deadline) {
-            attempt++;
-            netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup);
-            try {
-                netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher);
-            } catch (IllegalStateException e) {
-                logger.debug("Netconf {} was not initialized or is not stable, attempt {}", address, attempt, e);
-                netconfClientDispatcher.close();
-                Thread.sleep(delay);
-                continue;
-            }
-            currentCapabilities = netconfClient.getCapabilities();
-
-            if (isSubset(currentCapabilities, expectedCaps)) {
-                logger.debug("Hello from netconf stable with {} capabilities", currentCapabilities);
-                long currentSessionId = netconfClient.getSessionId();
-                logger.info("Session id received from netconf server: {}", currentSessionId);
-                return currentSessionId;
-            }
-
-
-
-            logger.debug("Polling hello from netconf, attempt {}, capabilities {}", attempt, currentCapabilities);
-
-            closeClientAndDispatcher(netconfClient, netconfClientDispatcher);
-
-            Thread.sleep(delay);
-        }
-        Set<String> allNotFound = new HashSet<>(expectedCaps);
-        allNotFound.removeAll(currentCapabilities);
-        logger.error("Netconf server did not provide required capabilities. Expected but not found: {}, all expected {}, current {}",
-                allNotFound, expectedCaps ,currentCapabilities);
-        throw new RuntimeException("Netconf server did not provide required capabilities. Expected but not found:" + allNotFound);
-
-    }
-
-    private static void closeClientAndDispatcher(Closeable client, Closeable dispatcher) {
-        Exception fromClient = null;
-        try {
-            client.close();
-        } catch (Exception e) {
-            fromClient = e;
-        } finally {
-            try {
-                dispatcher.close();
-            } catch (Exception e) {
-                if (fromClient != null) {
-                    e.addSuppressed(fromClient);
-                }
-
-                throw new RuntimeException("Error closing temporary client ", e);
-            }
-        }
-    }
-
-    private boolean isSubset(Set<String> currentCapabilities, Set<String> expectedCaps) {
-        for (String exCap : expectedCaps) {
-            if (currentCapabilities.contains(exCap) == false)
-                return false;
-        }
-        return true;
-    }
-
     private void registerAsJMXListener() {
         logger.trace("Called registerAsJMXListener");
         try {
-            mbeanServer.addNotificationListener(on, this, null, null);
+            mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.objectName, this, null, null);
         } catch (InstanceNotFoundException | IOException e) {
             throw new RuntimeException("Cannot register as JMX listener to netconf", e);
         }
@@ -242,7 +83,7 @@ public class ConfigPersisterNotificationHandler implements NotificationListener,
 
     private void handleAfterCommitNotification(final CommitJMXNotification notification) {
         try {
-            persister.persistConfig(new CapabilityStrippingConfigSnapshotHolder(notification.getConfigSnapshot(),
+            persisterAggregator.persistConfig(new CapabilityStrippingConfigSnapshotHolder(notification.getConfigSnapshot(),
                     notification.getCapabilities(), ignoredMissingCapabilityRegex));
             logger.info("Configuration persisted successfully");
         } catch (IOException e) {
@@ -250,137 +91,21 @@ public class ConfigPersisterNotificationHandler implements NotificationListener,
         }
     }
 
-    private Optional<ConfigSnapshotHolder> loadLastConfig() {
-        Optional<ConfigSnapshotHolder> maybeConfigElement;
-        try {
-            maybeConfigElement = persister.loadLastConfig();
-        } catch (IOException e) {
-            throw new RuntimeException("Unable to load configuration", e);
-        }
-        return maybeConfigElement;
-    }
-
-    private synchronized void pushLastConfig(Element xmlToBePersisted) throws ConflictingVersionException {
-        logger.info("Pushing last configuration to netconf");
-        StringBuilder response = new StringBuilder("editConfig response = {");
-
-
-        NetconfMessage message = createEditConfigMessage(xmlToBePersisted, "/netconfOp/editConfig.xml");
-
-        // sending message to netconf
-        NetconfMessage responseMessage = netconfClient.sendMessage(message, NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY);
-
-        XmlElement element = XmlElement.fromDomDocument(responseMessage.getDocument());
-        Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
-        element = element.getOnlyChildElement();
-
-        checkIsOk(element, responseMessage);
-        response.append(XmlUtil.toString(responseMessage.getDocument()));
-        response.append("}");
-        responseMessage = netconfClient.sendMessage(getNetconfMessageFromResource("/netconfOp/commit.xml"), NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY);
-
-        element = XmlElement.fromDomDocument(responseMessage.getDocument());
-        Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
-        element = element.getOnlyChildElement();
-
-        checkIsOk(element, responseMessage);
-        response.append("commit response = {");
-        response.append(XmlUtil.toString(responseMessage.getDocument()));
-        response.append("}");
-        logger.info("Last configuration loaded successfully");
-        logger.trace("Detailed message {}", response);
-    }
-
-    static void checkIsOk(XmlElement element, NetconfMessage responseMessage) throws ConflictingVersionException {
-        if (element.getName().equals(XmlNetconfConstants.OK)) {
-            return;
-        }
-
-        if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) {
-            logger.warn("Can not load last configuration, operation failed");
-            // is it ConflictingVersionException ?
-            XPathExpression xPathExpression = XMLNetconfUtil.compileXPath("/netconf:rpc-reply/netconf:rpc-error/netconf:error-info/netconf:error");
-            String error = (String) XmlUtil.evaluateXPath(xPathExpression, element.getDomElement(), XPathConstants.STRING);
-            if (error!=null && error.contains(ConflictingVersionException.class.getCanonicalName())) {
-                throw new ConflictingVersionException(error);
-            }
-            throw new IllegalStateException("Can not load last configuration, operation failed: "
-                    + XmlUtil.toString(responseMessage.getDocument()));
-        }
-
-        logger.warn("Can not load last configuration. Operation failed.");
-        throw new IllegalStateException("Can not load last configuration. Operation failed: "
-                + XmlUtil.toString(responseMessage.getDocument()));
-    }
-
-    private static NetconfMessage createEditConfigMessage(Element dataElement, String editConfigResourcename) {
-        try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcename)) {
-            Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcename);
-
-            Document doc = XmlUtil.readXmlToDocument(stream);
-
-            doc.getDocumentElement();
-            XmlElement editConfigElement = XmlElement.fromDomDocument(doc).getOnlyChildElement();
-            XmlElement configWrapper = editConfigElement.getOnlyChildElement(XmlNetconfConstants.CONFIG_KEY);
-            editConfigElement.getDomElement().removeChild(configWrapper.getDomElement());
-            for (XmlElement el : XmlElement.fromDomElement(dataElement).getChildElements()) {
-                configWrapper.appendChild((Element) doc.importNode(el.getDomElement(), true));
-            }
-            editConfigElement.appendChild(configWrapper.getDomElement());
-            return new NetconfMessage(doc);
-        } catch (IOException | SAXException e) {
-            throw new RuntimeException("Unable to parse message from resources " + editConfigResourcename, e);
-        }
-    }
-
-    private NetconfMessage getNetconfMessageFromResource(String resource) {
-        try (InputStream stream = getClass().getResourceAsStream(resource)) {
-            Preconditions.checkNotNull(stream, "Unable to load resource " + resource);
-            return new NetconfMessage(XmlUtil.readXmlToDocument(stream));
-        } catch (SAXException | IOException e) {
-            throw new RuntimeException("Unable to parse message from resources " + resource, e);
-        }
-    }
-
     @Override
     public synchronized void close() {
-        // TODO persister is received from constructor, should not be closed
-        // here
-        try {
-            persister.close();
-        } catch (Exception e) {
-            logger.warn("Unable to close config persister {}", persister, e);
-        }
-
-        if (netconfClient != null) {
-            try {
-                netconfClient.close();
-            } catch (Exception e) {
-                logger.warn("Unable to close connection to netconf {}", netconfClient, e);
-            }
-        }
-
-        if (netconfClientDispatcher != null) {
-            try {
-                netconfClientDispatcher.close();
-            } catch (Exception e) {
-                logger.warn("Unable to close connection to netconf {}", netconfClientDispatcher, e);
-            }
-        }
-
-        try {
-            nettyThreadgroup.shutdownGracefully();
-        } catch (Exception e) {
-            logger.warn("Unable to close netconf client thread group {}", netconfClientDispatcher, e);
-        }
-
         // unregister from JMX
+        ObjectName on = DefaultCommitOperationMXBean.objectName;
         try {
-            if (mbeanServer.isRegistered(on)) {
-                mbeanServer.removeNotificationListener(on, this);
+            if (mBeanServerConnection.isRegistered(on)) {
+                mBeanServerConnection.removeNotificationListener(on, this);
             }
         } catch (Exception e) {
             logger.warn("Unable to unregister {} as listener for {}", this, on, e);
         }
     }
+
+    public NetconfClient getNetconfClient() {
+        return netconfClient;
+    }
+
 }
diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
new file mode 100644 (file)
index 0000000..044346e
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * 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.netconf.persist.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import io.netty.channel.EventLoopGroup;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClient;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import javax.annotation.concurrent.Immutable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Immutable
+public class ConfigPusher {
+    private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterNotificationHandler.class);
+    private static final int NETCONF_SEND_ATTEMPT_MS_DELAY = 1000;
+    private static final int NETCONF_SEND_ATTEMPTS = 20;
+
+    private final InetSocketAddress address;
+    private final EventLoopGroup nettyThreadgroup;
+
+
+    public static final long DEFAULT_TIMEOUT = 120000L;// 120 seconds until netconf must be stable
+    private final long timeout;
+
+    public ConfigPusher(InetSocketAddress address, EventLoopGroup nettyThreadgroup) {
+        this(address, DEFAULT_TIMEOUT, nettyThreadgroup);
+
+    }
+
+    public ConfigPusher(InetSocketAddress address, long timeout, EventLoopGroup nettyThreadgroup) {
+        this.address = address;
+        this.timeout = timeout;
+
+        this.nettyThreadgroup = nettyThreadgroup;
+    }
+
+    public synchronized NetconfClient init(List<ConfigSnapshotHolder> configs) throws InterruptedException {
+        logger.debug("Last config snapshots to be pushed to netconf: {}", configs);
+        return pushAllConfigs(configs);
+    }
+
+    private synchronized NetconfClient pushAllConfigs(List<ConfigSnapshotHolder> configs) throws InterruptedException {
+        NetconfClient netconfClient = makeNetconfConnection(Collections.<String>emptySet(), Optional.<NetconfClient>absent());
+        for (ConfigSnapshotHolder configSnapshotHolder: configs){
+            netconfClient = pushSnapshotWithRetries(configSnapshotHolder, Optional.of(netconfClient));
+        }
+        return netconfClient;
+    }
+
+    private synchronized NetconfClient pushSnapshotWithRetries(ConfigSnapshotHolder configSnapshotHolder,
+                                                               Optional<NetconfClient> oldClientForPossibleReuse)
+            throws InterruptedException {
+
+        ConflictingVersionException lastException = null;
+        int maxAttempts = 30;
+        for(int i = 0 ; i < maxAttempts; i++) {
+            NetconfClient netconfClient = makeNetconfConnection(configSnapshotHolder.getCapabilities(), oldClientForPossibleReuse);
+            final String configSnapshot = configSnapshotHolder.getConfigSnapshot();
+            logger.trace("Pushing following xml to netconf {}", configSnapshot);
+            try {
+                pushLastConfig(configSnapshotHolder, netconfClient);
+                return netconfClient;
+            } catch(ConflictingVersionException e) {
+                Util.closeClientAndDispatcher(netconfClient);
+                lastException = e;
+                Thread.sleep(1000);
+            } catch (SAXException | IOException e) {
+                throw new IllegalStateException("Unable to load last config", e);
+            }
+        }
+        throw new IllegalStateException("Failed to push configuration, maximum attempt count has been reached: "
+                + maxAttempts, lastException);
+    }
+
+    /**
+     * @param expectedCaps capabilities that server hello must contain. Will retry until all are found or throws RuntimeException.
+     *                     If empty set is provided, will only make sure netconf client successfuly connected to the server.
+     * @param oldClientForPossibleReuse if present, try to get expected capabilities from it before closing it and retrying with
+     *                                  new client connection.
+     * @return NetconfClient that has all required capabilities from server.
+     */
+    private synchronized NetconfClient makeNetconfConnection(Set<String> expectedCaps,
+                                                             Optional<NetconfClient> oldClientForPossibleReuse)
+            throws InterruptedException {
+
+        if (oldClientForPossibleReuse.isPresent()) {
+            NetconfClient oldClient = oldClientForPossibleReuse.get();
+            if (Util.isSubset(oldClient, expectedCaps)) {
+                return oldClient;
+            } else {
+                Util.closeClientAndDispatcher(oldClient);
+            }
+        }
+
+        // TODO think about moving capability subset check to netconf client
+        // could be utilized by integration tests
+
+        long pollingStart = System.currentTimeMillis();
+        int delay = 5000;
+
+        int attempt = 0;
+
+        long deadline = pollingStart + timeout;
+
+        Set<String> latestCapabilities = new HashSet<>();
+        while (System.currentTimeMillis() < deadline) {
+            attempt++;
+            NetconfClientDispatcher netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup);
+            NetconfClient netconfClient;
+            try {
+                netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher);
+            } catch (IllegalStateException e) {
+                logger.debug("Netconf {} was not initialized or is not stable, attempt {}", address, attempt, e);
+                netconfClientDispatcher.close();
+                Thread.sleep(delay);
+                continue;
+            }
+            latestCapabilities = netconfClient.getCapabilities();
+            if (Util.isSubset(netconfClient, expectedCaps)) {
+                logger.debug("Hello from netconf stable with {} capabilities", latestCapabilities);
+                logger.info("Session id received from netconf server: {}", netconfClient.getClientSession());
+                return netconfClient;
+            }
+            logger.debug("Polling hello from netconf, attempt {}, capabilities {}", attempt, latestCapabilities);
+            Util.closeClientAndDispatcher(netconfClient);
+            Thread.sleep(delay);
+        }
+        Set<String> allNotFound = new HashSet<>(expectedCaps);
+        allNotFound.removeAll(latestCapabilities);
+        logger.error("Netconf server did not provide required capabilities. Expected but not found: {}, all expected {}, current {}",
+                allNotFound, expectedCaps, latestCapabilities);
+        throw new RuntimeException("Netconf server did not provide required capabilities. Expected but not found:" + allNotFound);
+    }
+
+
+    private synchronized void pushLastConfig(ConfigSnapshotHolder configSnapshotHolder, NetconfClient netconfClient)
+            throws ConflictingVersionException, IOException, SAXException {
+
+        Element xmlToBePersisted = XmlUtil.readXmlToElement(configSnapshotHolder.getConfigSnapshot());
+        logger.info("Pushing last configuration to netconf: {}", configSnapshotHolder);
+        StringBuilder response = new StringBuilder("editConfig response = {");
+
+
+        NetconfMessage message = createEditConfigMessage(xmlToBePersisted, "/netconfOp/editConfig.xml");
+
+        // sending message to netconf
+        NetconfMessage responseMessage = netconfClient.sendMessage(message, NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY);
+
+        XmlElement element = XmlElement.fromDomDocument(responseMessage.getDocument());
+        Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
+        element = element.getOnlyChildElement();
+
+        Util.checkIsOk(element, responseMessage);
+        response.append(XmlUtil.toString(responseMessage.getDocument()));
+        response.append("}");
+        responseMessage = netconfClient.sendMessage(getNetconfMessageFromResource("/netconfOp/commit.xml"), NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY);
+
+        element = XmlElement.fromDomDocument(responseMessage.getDocument());
+        Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
+        element = element.getOnlyChildElement();
+
+        Util.checkIsOk(element, responseMessage);
+        response.append("commit response = {");
+        response.append(XmlUtil.toString(responseMessage.getDocument()));
+        response.append("}");
+        logger.info("Last configuration loaded successfully");
+        logger.trace("Detailed message {}", response);
+    }
+
+    private static NetconfMessage createEditConfigMessage(Element dataElement, String editConfigResourcename) {
+        try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcename)) {
+            Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcename);
+
+            Document doc = XmlUtil.readXmlToDocument(stream);
+
+            doc.getDocumentElement();
+            XmlElement editConfigElement = XmlElement.fromDomDocument(doc).getOnlyChildElement();
+            XmlElement configWrapper = editConfigElement.getOnlyChildElement(XmlNetconfConstants.CONFIG_KEY);
+            editConfigElement.getDomElement().removeChild(configWrapper.getDomElement());
+            for (XmlElement el : XmlElement.fromDomElement(dataElement).getChildElements()) {
+                configWrapper.appendChild((Element) doc.importNode(el.getDomElement(), true));
+            }
+            editConfigElement.appendChild(configWrapper.getDomElement());
+            return new NetconfMessage(doc);
+        } catch (IOException | SAXException e) {
+            throw new RuntimeException("Unable to parse message from resources " + editConfigResourcename, e);
+        }
+    }
+
+    private static NetconfMessage getNetconfMessageFromResource(String resource) {
+        try (InputStream stream = ConfigPusher.class.getResourceAsStream(resource)) {
+            Preconditions.checkNotNull(stream, "Unable to load resource " + resource);
+            return new NetconfMessage(XmlUtil.readXmlToDocument(stream));
+        } catch (SAXException | IOException e) {
+            throw new RuntimeException("Unable to parse message from resources " + resource, e);
+        }
+    }
+}
index b37c145..27f9309 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.controller.netconf.persist.impl;
 
-import com.google.common.base.Optional;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.persist.api.PropertiesProvider;
@@ -17,6 +16,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 public class NoOpStorageAdapter implements StorageAdapter, Persister {
     private static final Logger logger = LoggerFactory.getLogger(NoOpStorageAdapter.class);
@@ -33,9 +34,9 @@ public class NoOpStorageAdapter implements StorageAdapter, Persister {
     }
 
     @Override
-    public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
+    public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
         logger.debug("loadLastConfig called");
-        return Optional.absent();
+        return Collections.emptyList();
     }
 
     @Override
index e109ebe..7e9dce6 100644 (file)
@@ -9,7 +9,6 @@
 package org.opendaylight.controller.netconf.persist.impl;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.persist.api.StorageAdapter;
@@ -20,6 +19,7 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -48,7 +48,7 @@ import java.util.ListIterator;
  </pre>
  * During server startup {@link ConfigPersisterNotificationHandler} requests last snapshot from underlying storages.
  * Each storage can respond by giving snapshot or absent response.
- * The {@link #loadLastConfig()} will search for first non-absent response from storages ordered backwards as user
+ * The {@link #loadLastConfigs()} will search for first non-absent response from storages ordered backwards as user
  * specified (first '3', then '2').
  *
  * When a commit notification is received, '2' will be omitted because readonly flag is set to true, so
@@ -154,19 +154,29 @@ public final class PersisterAggregator implements Persister {
         }
     }
 
+    /**
+     * @return last non-empty result from input persisters
+     */
     @Override
-    public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
+    public List<ConfigSnapshotHolder> loadLastConfigs()  {
         // iterate in reverse order
         ListIterator<PersisterWithConfiguration> li = persisterWithConfigurations.listIterator(persisterWithConfigurations.size());
         while(li.hasPrevious()) {
             PersisterWithConfiguration persisterWithConfiguration = li.previous();
-            Optional<ConfigSnapshotHolder> configSnapshotHolderOptional = persisterWithConfiguration.storage.loadLastConfig();
-            if (configSnapshotHolderOptional.isPresent()) {
-                return configSnapshotHolderOptional;
+            List<ConfigSnapshotHolder> configs = null;
+            try {
+                configs = persisterWithConfiguration.storage.loadLastConfigs();
+            } catch (IOException e) {
+                throw new RuntimeException("Error while calling loadLastConfig on " +  persisterWithConfiguration, e);
+            }
+            if (configs.isEmpty() == false) {
+                logger.debug("Found non empty configs using {}:{}", persisterWithConfiguration, configs);
+                return configs;
             }
         }
         // no storage had an answer
-        return Optional.absent();
+        logger.debug("No non-empty list of configuration snapshots found");
+        return Collections.emptyList();
     }
 
     @VisibleForTesting
index b173091..811ba38 100644 (file)
@@ -8,24 +8,79 @@
 
 package org.opendaylight.controller.netconf.persist.impl;
 
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadFactory;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClient;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import java.util.Set;
 
 public final class Util {
+    private static final Logger logger = LoggerFactory.getLogger(Util.class);
+
+
+    public static boolean isSubset(NetconfClient netconfClient, Set<String> expectedCaps) {
+        return isSubset(netconfClient.getCapabilities(), expectedCaps);
+
+    }
+
+    private static boolean isSubset(Set<String> currentCapabilities, Set<String> expectedCaps) {
+        for (String exCap : expectedCaps) {
+            if (currentCapabilities.contains(exCap) == false)
+                return false;
+        }
+        return true;
+    }
+
+
+    // TODO: check if closing in correct order
+    public static void closeClientAndDispatcher(NetconfClient client) {
+        NetconfClientDispatcher dispatcher = client.getNetconfClientDispatcher();
+        Exception fromClient = null;
+        try {
+            client.close();
+        } catch (Exception e) {
+            fromClient = e;
+        } finally {
+            try {
+                dispatcher.close();
+            } catch (Exception e) {
+                if (fromClient != null) {
+                    e.addSuppressed(fromClient);
+                }
+                throw new RuntimeException("Error closing temporary client ", e);
+            }
+        }
+    }
 
-    public static ScheduledExecutorService getExecutorServiceWithThreadName(final String threadNamePrefix,
-            int threadCount) {
-        return Executors.newScheduledThreadPool(threadCount, new ThreadFactory() {
 
-            private int i = 1;
+    public static void checkIsOk(XmlElement element, NetconfMessage responseMessage) throws ConflictingVersionException {
+        if (element.getName().equals(XmlNetconfConstants.OK)) {
+            return;
+        }
 
-            @Override
-            public Thread newThread(Runnable r) {
-                Thread thread = new Thread(r);
-                thread.setName(threadNamePrefix + ":" + i++);
-                return thread;
+        if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) {
+            logger.warn("Can not load last configuration, operation failed");
+            // is it ConflictingVersionException ?
+            XPathExpression xPathExpression = XMLNetconfUtil.compileXPath("/netconf:rpc-reply/netconf:rpc-error/netconf:error-info/netconf:error");
+            String error = (String) XmlUtil.evaluateXPath(xPathExpression, element.getDomElement(), XPathConstants.STRING);
+            if (error!=null && error.contains(ConflictingVersionException.class.getCanonicalName())) {
+                throw new ConflictingVersionException(error);
             }
-        });
+            throw new IllegalStateException("Can not load last configuration, operation failed: "
+                    + XmlUtil.toString(responseMessage.getDocument()));
+        }
+
+        logger.warn("Can not load last configuration. Operation failed.");
+        throw new IllegalStateException("Can not load last configuration. Operation failed: "
+                + XmlUtil.toString(responseMessage.getDocument()));
     }
 }
index e7916c2..6560911 100644 (file)
@@ -8,8 +8,13 @@
 
 package org.opendaylight.controller.netconf.persist.impl.osgi;
 
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import org.opendaylight.controller.netconf.client.NetconfClient;
 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
+import org.opendaylight.controller.netconf.persist.impl.ConfigPusher;
 import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator;
+import org.opendaylight.controller.netconf.persist.impl.Util;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -28,14 +33,19 @@ public class ConfigPersisterActivator implements BundleActivator {
     private final static MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
     private static final String IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX = "ignoredMissingCapabilityRegex";
 
-    private ConfigPersisterNotificationHandler configPersisterNotificationHandler;
+    public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister";
 
-    private Thread initializationThread;
+    public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass";
 
-    public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister";
-    public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX =  "storageAdapterClass";
     public static final String DEFAULT_IGNORED_REGEX = "^urn:ietf:params:xml:ns:netconf:base:1.0";
 
+
+    private volatile ConfigPersisterNotificationHandler jmxNotificationHandler;
+    private volatile NetconfClient netconfClient;
+    private Thread initializationThread;
+    private EventLoopGroup nettyThreadgroup;
+    private PersisterAggregator persisterAggregator;
+
     @Override
     public void start(final BundleContext context) throws Exception {
         logger.debug("ConfigPersister starting");
@@ -49,20 +59,24 @@ public class ConfigPersisterActivator implements BundleActivator {
         } else {
             regex = DEFAULT_IGNORED_REGEX;
         }
-        Pattern ignoredMissingCapabilityRegex = Pattern.compile(regex);
-        PersisterAggregator persister = PersisterAggregator.createFromProperties(propertiesProvider);
+        final Pattern ignoredMissingCapabilityRegex = Pattern.compile(regex);
+        nettyThreadgroup = new NioEventLoopGroup();
+
+        persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider);
+        final InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, "Netconf is not configured, persister is not operational", true);
+        final ConfigPusher configPusher = new ConfigPusher(address, nettyThreadgroup);
 
-        InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
-                "Netconf is not configured, persister is not operational",true);
-        configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(persister, address,
-                platformMBeanServer, ignoredMissingCapabilityRegex);
 
         // offload initialization to another thread in order to stop blocking activator
         Runnable initializationRunnable = new Runnable() {
             @Override
             public void run() {
                 try {
-                    configPersisterNotificationHandler.init();
+                    netconfClient = configPusher.init(persisterAggregator.loadLastConfigs());
+                    jmxNotificationHandler = new ConfigPersisterNotificationHandler(
+                            platformMBeanServer, netconfClient, persisterAggregator,
+                            ignoredMissingCapabilityRegex);
+                    jmxNotificationHandler.init();
                 } catch (InterruptedException e) {
                     logger.info("Interrupted while waiting for netconf connection");
                 }
@@ -75,6 +89,18 @@ public class ConfigPersisterActivator implements BundleActivator {
     @Override
     public void stop(BundleContext context) throws Exception {
         initializationThread.interrupt();
-        configPersisterNotificationHandler.close();
+        if (jmxNotificationHandler != null) {
+            jmxNotificationHandler.close();
+        }
+        if (netconfClient != null) {
+            netconfClient = jmxNotificationHandler.getNetconfClient();
+            try {
+                Util.closeClientAndDispatcher(netconfClient);
+            } catch (Exception e) {
+                logger.warn("Unable to close connection to netconf {}", netconfClient, e);
+            }
+        }
+        nettyThreadgroup.shutdownGracefully();
+        persisterAggregator.close();
     }
 }
index 6c45c9c..a124d85 100644 (file)
@@ -24,7 +24,7 @@ public class ConfigPersisterNotificationHandlerTest {
     public void testConflictingVersionDetection() throws Exception {
         Document document = XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/conflictingVersionResponse.xml"));
         try{
-            ConfigPersisterNotificationHandler.checkIsOk(XmlElement.fromDomDocument(document).getOnlyChildElement(), new NetconfMessage(document));
+            Util.checkIsOk(XmlElement.fromDomDocument(document).getOnlyChildElement(), new NetconfMessage(document));
             fail();
         }catch(ConflictingVersionException e){
             assertThat(e.getMessage(), containsString("Optimistic lock failed. Expected parent version 21, was 18"));
index 7a11b9c..e824b58 100644 (file)
@@ -7,13 +7,14 @@
  */
 package org.opendaylight.controller.netconf.persist.impl;
 
-import com.google.common.base.Optional;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 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 java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 
 public class DummyAdapter implements StorageAdapter, Persister {
 
@@ -27,9 +28,9 @@ public class DummyAdapter implements StorageAdapter, Persister {
     static int load = 0;
 
     @Override
-    public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
+    public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
         load++;
-        return Optional.absent();
+        return Collections.emptyList();
     }
 
     static int props = 0;
index d9fa7ba..227018b 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.controller.netconf.persist.impl;
 
-import com.google.common.base.Optional;
 import org.junit.Test;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.config.persist.api.Persister;
@@ -18,14 +17,14 @@ import org.opendaylight.controller.netconf.persist.impl.osgi.PropertiesProviderB
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Properties;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.fail;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 import static org.junit.matchers.JUnitMatchers.containsString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -79,9 +78,9 @@ public class PersisterAggregatorTest {
         assertFalse(persister.isReadOnly());
 
         persisterAggregator.persistConfig(null);
-        persisterAggregator.loadLastConfig();
+        persisterAggregator.loadLastConfigs();
         persisterAggregator.persistConfig(null);
-        persisterAggregator.loadLastConfig();
+        persisterAggregator.loadLastConfigs();
 
         assertEquals(2, DummyAdapter.persist);
         assertEquals(2, DummyAdapter.load);
@@ -110,29 +109,41 @@ public class PersisterAggregatorTest {
         }
     }
 
+    private ConfigSnapshotHolder mockHolder(String name){
+        ConfigSnapshotHolder result = mock(ConfigSnapshotHolder.class);
+        doReturn("mock:" + name).when(result).toString();
+        return result;
+    }
+
+    private Persister mockPersister(String name){
+        Persister result = mock(Persister.class);
+        doReturn("mock:" + name).when(result).toString();
+        return result;
+    }
+
     @Test
     public void loadLastConfig() throws Exception {
         List<PersisterWithConfiguration> persisterWithConfigurations = new ArrayList<>();
         PersisterWithConfiguration first = new PersisterWithConfiguration(mock(Persister.class), false);
 
-        ConfigSnapshotHolder ignored = mock(ConfigSnapshotHolder.class);
-        doReturn(Optional.of(ignored)).when(first.getStorage()).loadLastConfig(); // should be ignored
+        ConfigSnapshotHolder ignored = mockHolder("ignored");
+        doReturn(Arrays.asList(ignored)).when(first.getStorage()).loadLastConfigs(); // should be ignored
 
-        ConfigSnapshotHolder used = mock(ConfigSnapshotHolder.class);
-        PersisterWithConfiguration second = new PersisterWithConfiguration(mock(Persister.class), false);
-        doReturn(Optional.of(used)).when(second.getStorage()).loadLastConfig(); // should be used
 
-        PersisterWithConfiguration third = new PersisterWithConfiguration(mock(Persister.class), false);
-        doReturn(Optional.absent()).when(third.getStorage()).loadLastConfig();
+        ConfigSnapshotHolder used = mockHolder("used");
+        PersisterWithConfiguration second = new PersisterWithConfiguration(mockPersister("p1"), false);
+        doReturn(Arrays.asList(used)).when(second.getStorage()).loadLastConfigs(); // should be used
+
+        PersisterWithConfiguration third = new PersisterWithConfiguration(mockPersister("p2"), false);
+        doReturn(Arrays.asList()).when(third.getStorage()).loadLastConfigs();
 
         persisterWithConfigurations.add(first);
         persisterWithConfigurations.add(second);
         persisterWithConfigurations.add(third);
 
         PersisterAggregator persisterAggregator = new PersisterAggregator(persisterWithConfigurations);
-        Optional<ConfigSnapshotHolder> configSnapshotHolderOptional = persisterAggregator.loadLastConfig();
-        assertTrue(configSnapshotHolderOptional.isPresent());
-        assertEquals(used, configSnapshotHolderOptional.get());
+        List<ConfigSnapshotHolder> configSnapshotHolderOptional = persisterAggregator.loadLastConfigs();
+        assertEquals(1, configSnapshotHolderOptional.size());
+        assertEquals(used, configSnapshotHolderOptional.get(0));
     }
-
 }
index d959774..d644cdd 100644 (file)
@@ -100,6 +100,10 @@ public class NetconfClient implements Closeable {
         clientSession.close();
     }
 
+    public NetconfClientDispatcher getNetconfClientDispatcher() {
+        return dispatch;
+    }
+
     private static ReconnectStrategy getReconnectStrategy(int connectionAttempts, int attemptMsTimeout) {
         return new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, attemptMsTimeout, 1000, 1.0, null,
                 Long.valueOf(connectionAttempts), null);
index ccc7c85..c61dab7 100644 (file)
@@ -8,23 +8,41 @@
 
 package org.opendaylight.controller.netconf.it;
 
-import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import static java.util.Collections.emptyList;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
+
 import junit.framework.Assert;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
-import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
@@ -49,8 +67,6 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFact
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
-import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
-import org.opendaylight.controller.netconf.persist.impl.osgi.ConfigPersisterActivator;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.ExiParameters;
@@ -64,28 +80,11 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
 
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
+import ch.ethz.ssh2.Connection;
+import ch.ethz.ssh2.Session;
 
-import static java.util.Collections.emptyList;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 public class NetconfITTest extends AbstractConfigTest {
 
@@ -220,14 +219,18 @@ public class NetconfITTest extends AbstractConfigTest {
         }
     }
 
+
+    //TODO: test persister actually
+    @Ignore
     @Test(timeout = 10000)
     public void testPersister() throws Exception {
-        Persister persister = mock(Persister.class);
-        doReturn("mockPersister").when(persister).toString();
-        doReturn(Optional.absent()).when(persister).loadLastConfig();
-        ConfigPersisterNotificationHandler h =
-                new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer(), Pattern.compile(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX));
-        h.init();
+//        Persister persister = mock(Persister.class);
+//        doReturn("mockPersister").when(persister).toString();
+//        doReturn(Collections.emptyList()).when(persister).loadLastConfigs();
+//        ConfigPersisterNotificationHandler h =
+//                new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer(),
+//                        Pattern.compile(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX));
+//        h.init();
     }
 
     @Ignore
index caa0094..dc522d2 100644 (file)
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                         <name>ref_dep</name>
                     </testing-dep>
+
+                    <testing-deps>
+                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                        <name>ref_dep</name>
+                    </testing-deps>
+                    <testing-deps>
+                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                        <name>ref_dep_2</name>
+                    </testing-deps>
                 </module>
 
                 <module>
 
                     <testing-dep>
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
+                        <name>ref_dep_2</name>
                     </testing-dep>
                 </module>
             </modules>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>
index c825536..388aa4f 100644 (file)
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_dep_2</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
+                        <provider>/modules/module[type='impl-dep'][name='dep2']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>
index 82c218d..4d94d9e 100644 (file)
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_dep_2</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
+                        <provider>/modules/module[type='impl-dep'][name='dep2']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>
index 7c19b9f..c399c19 100644 (file)
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_dep_2</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
+                        <provider>/modules/module[type='impl-dep'][name='dep2']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>
index 84ae575..47b82c6 100644 (file)
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_dep_2</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
+                        <provider>/modules/module[type='impl-dep'][name='dep2']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>
index 2d9e9ed..0e70e13 100644 (file)
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_dep_2</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
+                        <provider>/modules/module[type='impl-dep'][name='dep2']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>
index 9407dd0..bc05d63 100644 (file)
@@ -27,7 +27,7 @@
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                 </service>
index 233ad23..f20d9ff 100644 (file)
@@ -28,7 +28,7 @@
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                 </service>
index 4593887..ff0bd9f 100644 (file)
@@ -29,7 +29,7 @@
 
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                 </service>
index 81c4137..906367b 100644 (file)
@@ -29,7 +29,7 @@
                     <instance>
                         <name>ref_dep</name>
                         <unknownAttribute>error</unknownAttribute>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                 </service>
index 528d5b0..b05046d 100644 (file)
@@ -26,7 +26,7 @@
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                 </service>
index a1e304b..d03bb08 100644 (file)
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_dep_2</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
+                        <provider>/modules/module[type='impl-dep'][name='dep2']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>
index 812882a..3722973 100644 (file)
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
                         <name>ref_dep</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep']
+                        <provider>/modules/module[type='impl-dep'][name='dep']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_dep_2</name>
-                        <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
+                        <provider>/modules/module[type='impl-dep'][name='dep2']
                         </provider>
                     </instance>
                     <instance>
                         <name>ref_test1</name>
-                        <provider>/config/modules/module[name='impl-netconf']/instance[name='test1']
+                        <provider>
+                            /modules/module[type='impl-netconf'][name='test1']
                         </provider>
                     </instance>
                 </service>