Fix bug in hello message: module with more revisions. 05/4505/1
authorTomas Olvecky <tolvecky@cisco.com>
Tue, 21 Jan 2014 14:26:39 +0000 (15:26 +0100)
committerTomas Olvecky <tolvecky@cisco.com>
Tue, 21 Jan 2014 14:36:53 +0000 (15:36 +0100)
When yang store discovers new yang files, it should keep all modules
provided by the parser. The old behavior was that only only one
module instance was chosen. This change results in hello message
containing all revisions of all modules.

Change-Id: I5f580042303573fb4fd2d592846763d46bbb1d66
Signed-off-by: Tomas Olvecky <tolvecky@cisco.com>
opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/api/YangStoreSnapshot.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/ExtenderYangTracker.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/MbeParser.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangStoreCache.java [new file with mode: 0644]
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangStoreSnapshotImpl.java
opendaylight/config/yang-store-impl/src/test/java/org/opendaylight/controller/config/yang/store/impl/ExtenderYangTrackerCustomizerTest.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java

index da8b5e4..b912b0c 100644 (file)
@@ -7,21 +7,50 @@
  */
 package org.opendaylight.controller.config.yang.store.api;
 
-import java.util.Map;
-import java.util.Map.Entry;
-
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
+import java.util.Map;
+import java.util.Set;
+
 public interface YangStoreSnapshot extends AutoCloseable {
 
+    /**
+     * @deprecated Use {@link #getQNamesToIdentitiesToModuleMXBeanEntries()} instead. This method return only one
+     * module representation even if multiple revisions are available.
+     */
+    @Deprecated
     Map<String/* Namespace from yang file */,
             Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> getModuleMXBeanEntryMap();
 
-    Map<String, Entry<Module, String>> getModuleMap();
 
+    Map<QName, Map<String /* identity local name */, ModuleMXBeanEntry>> getQNamesToIdentitiesToModuleMXBeanEntries();
+
+    /**
+     * Get number of parsed ModuleMXBeanEntry instances.
+     */
     int countModuleMXBeanEntries();
 
+    /**
+     * Get all modules discovered when this snapshot was created.
+     * @return all modules discovered. If one module exists with two different revisions, return both.
+     */
+    Set<Module> getModules();
+
+    /**
+     * Get all modules together with their yang sources.
+     */
+    Map<Module, String> getModulesToSources();
+
+    /**
+     * Retrieve source of module as it appeared during creation of this snapshot.
+     * @param module
+     * @return yang source of given module
+     * @throws java.lang.IllegalArgumentException if module does not belong to this snapshot
+     */
+    String getModuleSource(Module module);
+
     @Override
     void close();
 }
index 0d704a8..b5efc51 100644 (file)
@@ -14,12 +14,9 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
 import org.opendaylight.controller.config.yang.store.api.YangStoreService;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
-import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
-import org.opendaylight.yangtools.yang.model.api.Module;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
@@ -36,8 +33,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -220,78 +215,3 @@ public class ExtenderYangTracker extends BundleTracker<Object> implements YangSt
         cache.invalidate();
     }
 }
-
-class YangStoreCache {
-    private static final Logger logger = LoggerFactory.getLogger(YangStoreCache.class);
-
-    @GuardedBy("this")
-    private Set<URL> cachedUrls = null;
-    @GuardedBy("this")
-    private Optional<YangStoreSnapshot> cachedYangStoreSnapshot = getInitialSnapshot();
-    @GuardedBy("this")
-    private Collection<URL> inconsistentURLsForReporting = Collections.emptySet();
-
-    synchronized Optional<YangStoreSnapshot> getSnapshotIfPossible(Multimap<Bundle, URL> bundlesToYangURLs) {
-        Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
-
-        if (cachedUrls==null || cachedUrls.equals(urls)) {
-            Preconditions.checkState(cachedYangStoreSnapshot.isPresent());
-            YangStoreSnapshot freshSnapshot = new YangStoreSnapshotImpl(cachedYangStoreSnapshot.get());
-            if (inconsistentURLsForReporting.size() > 0){
-                logger.warn("Some yang URLs are ignored: {}", inconsistentURLsForReporting);
-            }
-            return Optional.of(freshSnapshot);
-        }
-
-        return Optional.absent();
-    }
-
-    private static Set<URL> setFromMultimapValues(
-            Multimap<Bundle, URL> bundlesToYangURLs) {
-        Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
-        Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
-        return urls;
-    }
-
-    synchronized void cacheYangStore(Multimap<Bundle, URL> urls,
-                                     YangStoreSnapshot yangStoreSnapshot) {
-        this.cachedUrls = setFromMultimapValues(urls);
-        this.cachedYangStoreSnapshot = Optional.of(yangStoreSnapshot);
-    }
-
-    synchronized void invalidate() {
-        cachedUrls.clear();
-        if (cachedYangStoreSnapshot.isPresent()){
-            cachedYangStoreSnapshot.get().close();
-            cachedYangStoreSnapshot = Optional.absent();
-        }
-    }
-
-    public synchronized void setInconsistentURLsForReporting(Collection<URL> urls){
-        inconsistentURLsForReporting = urls;
-    }
-
-    private Optional<YangStoreSnapshot> getInitialSnapshot() {
-        YangStoreSnapshot initialSnapshot = new YangStoreSnapshot() {
-            @Override
-            public Map<String, Map<String, ModuleMXBeanEntry>> getModuleMXBeanEntryMap() {
-                return Collections.emptyMap();
-            }
-
-            @Override
-            public Map<String, Map.Entry<Module, String>> getModuleMap() {
-                return Collections.emptyMap();
-            }
-
-            @Override
-            public int countModuleMXBeanEntries() {
-                return 0;
-            }
-
-            @Override
-            public void close() {
-            }
-        };
-        return Optional.of(initialSnapshot);
-    }
-}
index d54996d..dd07c5a 100644 (file)
@@ -21,25 +21,27 @@ import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
 public class MbeParser {
+    private static final Logger logger = LoggerFactory.getLogger(MbeParser.class);
 
-    public YangStoreSnapshotImpl parseYangFiles(
-            Collection<? extends InputStream> allInput)
-            throws YangStoreException {
+    public YangStoreSnapshotImpl parseYangFiles(Collection<? extends InputStream> allInput) throws YangStoreException {
         YangParserImpl parser = YangParserWrapper.getYangParserInstance();
 
         Map<InputStream, Module> allYangModules = YangParserWrapper.parseYangFiles(parser, allInput);
 
         SchemaContext resolveSchemaContext = YangParserWrapper.getSchemaContextFromModules(parser, allYangModules);
-
+        logger.trace("Resolved modules:{}", resolveSchemaContext.getModules());
         // JMX generator
 
         Map<String, String> namespaceToPackageMapping = Maps.newHashMap();
@@ -69,35 +71,47 @@ public class MbeParser {
             }
         }
 
-        Map<String, Map<String, ModuleMXBeanEntry>> retVal = Maps.newHashMap();
-        Map<String, Entry<Module, String>> modulesMap = new HashMap<>();
+        Map<String, Map<String, ModuleMXBeanEntry>> moduleMXBeanEntryMap = Maps.newHashMap();
+        Map<Module, String> modulesToSources = new HashMap<>();
+        Map<QName, Map<String /* identity local name */, ModuleMXBeanEntry>>
+                qNamesToIdentitiesToModuleMXBeanEntries = new HashMap<>();
+
 
         for (Entry<InputStream, Module> moduleEntry : allYangModules.entrySet()) {
-            String packageName = packageTranslator.getPackageName(moduleEntry
-                    .getValue());
+            Module module = moduleEntry.getValue();
+            String packageName = packageTranslator.getPackageName(module);
             TypeProviderWrapper typeProviderWrapper = new TypeProviderWrapper(
                     new TypeProviderImpl(resolveSchemaContext));
-            String yangAsString;
-            try {
-                moduleEntry.getKey().reset();
-                yangAsString = IOUtils.toString(moduleEntry.getKey());
-            } catch (IOException e) {
-                throw new IllegalStateException(e);
-            }
-            modulesMap.put(moduleEntry.getValue().getName(),
-                    Maps.immutableEntry(moduleEntry.getValue(), yangAsString));
-            Map<String /* MB identity local name */, ModuleMXBeanEntry> namesToMBEs = ModuleMXBeanEntry
-                    .create(moduleEntry.getValue(), qNamesToSIEs, resolveSchemaContext, typeProviderWrapper,
-                            packageName);
-            retVal.put(moduleEntry.getValue().getNamespace().toString(),
-                    namesToMBEs);
+            String yangAsString = reReadInputStream(moduleEntry);
+
+            QName qName = new QName(module.getNamespace(), module.getRevision(), module.getName());
+
+            Map<String /* MB identity local name */, ModuleMXBeanEntry> namesToMBEs =
+                    Collections.unmodifiableMap(ModuleMXBeanEntry.create(module, qNamesToSIEs, resolveSchemaContext,
+                            typeProviderWrapper, packageName));
+            moduleMXBeanEntryMap.put(module.getNamespace().toString(), namesToMBEs);
+            modulesToSources.put(module, yangAsString);
+            qNamesToIdentitiesToModuleMXBeanEntries.put(qName, namesToMBEs);
         }
 
-        return new YangStoreSnapshotImpl(retVal, modulesMap);
+        return new YangStoreSnapshotImpl(moduleMXBeanEntryMap, modulesToSources, qNamesToIdentitiesToModuleMXBeanEntries);
+    }
+
+    private String reReadInputStream(Entry<InputStream, Module> moduleEntry) {
+        String yangAsString;
+        try {
+            moduleEntry.getKey().reset();
+            yangAsString = IOUtils.toString(moduleEntry.getKey());
+        } catch (IOException e) {
+            throw new IllegalStateException("Cannot reread " + moduleEntry.getValue(), e);
+        }
+        return yangAsString;
     }
 
-    public Map<Module, String> parseYangFilesToString(
-            Collection<? extends InputStream> allYangs) {
+    @Deprecated
+    public Map<Module, String> parseYangFilesToString(Collection<? extends InputStream> allYangs) {
+
+        logger.error("Using deprecated method that will be removed soon", new UnsupportedOperationException("Deprecated"));
         YangParserImpl parser = YangParserWrapper.getYangParserInstance();
 
         Map<InputStream, Module> allYangModules = parser
diff --git a/opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangStoreCache.java b/opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangStoreCache.java
new file mode 100644 (file)
index 0000000..321ce3a
--- /dev/null
@@ -0,0 +1,110 @@
+package org.opendaylight.controller.config.yang.store.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
+import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.osgi.framework.Bundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.GuardedBy;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+class YangStoreCache {
+    private static final Logger logger = LoggerFactory.getLogger(YangStoreCache.class);
+
+    @GuardedBy("this")
+    private Set<URL> cachedUrls = null;
+    @GuardedBy("this")
+    private Optional<YangStoreSnapshot> cachedYangStoreSnapshot = getInitialSnapshot();
+    @GuardedBy("this")
+    private Collection<URL> inconsistentURLsForReporting = Collections.emptySet();
+
+    synchronized Optional<YangStoreSnapshot> getSnapshotIfPossible(Multimap<Bundle, URL> bundlesToYangURLs) {
+        Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
+
+        if (cachedUrls==null || cachedUrls.equals(urls)) {
+            Preconditions.checkState(cachedYangStoreSnapshot.isPresent());
+            YangStoreSnapshot freshSnapshot = YangStoreSnapshotImpl.copy(cachedYangStoreSnapshot.get());
+            if (inconsistentURLsForReporting.size() > 0){
+                logger.warn("Some yang URLs are ignored: {}", inconsistentURLsForReporting);
+            }
+            return Optional.of(freshSnapshot);
+        }
+
+        return Optional.absent();
+    }
+
+    private static Set<URL> setFromMultimapValues(
+            Multimap<Bundle, URL> bundlesToYangURLs) {
+        Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
+        Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
+        return urls;
+    }
+
+    synchronized void cacheYangStore(Multimap<Bundle, URL> urls,
+                                     YangStoreSnapshot yangStoreSnapshot) {
+        this.cachedUrls = setFromMultimapValues(urls);
+        this.cachedYangStoreSnapshot = Optional.of(yangStoreSnapshot);
+    }
+
+    synchronized void invalidate() {
+        cachedUrls.clear();
+        if (cachedYangStoreSnapshot.isPresent()){
+            cachedYangStoreSnapshot.get().close();
+            cachedYangStoreSnapshot = Optional.absent();
+        }
+    }
+
+    public synchronized void setInconsistentURLsForReporting(Collection<URL> urls){
+        inconsistentURLsForReporting = urls;
+    }
+
+    private Optional<YangStoreSnapshot> getInitialSnapshot() {
+        YangStoreSnapshot initialSnapshot = new YangStoreSnapshot() {
+            @Override
+            public Map<String, Map<String, ModuleMXBeanEntry>> getModuleMXBeanEntryMap() {
+                return Collections.emptyMap();
+            }
+
+            @Override
+            public Map<QName, Map<String, ModuleMXBeanEntry>> getQNamesToIdentitiesToModuleMXBeanEntries() {
+                return Collections.emptyMap();
+            }
+
+            @Override
+            public Set<Module> getModules() {
+                return Collections.emptySet();
+            }
+
+            @Override
+            public Map<Module, String> getModulesToSources() {
+                return Collections.emptyMap();
+            }
+
+            @Override
+            public String getModuleSource(Module module) {
+                throw new IllegalArgumentException("Cannot get sources in empty snapshot");
+            }
+
+            @Override
+            public int countModuleMXBeanEntries() {
+                return 0;
+            }
+
+            @Override
+            public void close() {
+            }
+        };
+        return Optional.of(initialSnapshot);
+    }
+}
index ea709e1..474d754 100644 (file)
@@ -9,29 +9,39 @@ package org.opendaylight.controller.config.yang.store.impl;
 
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.Module;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.Collections;
 import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Set;
 
 public class YangStoreSnapshotImpl implements YangStoreSnapshot {
+    private static final Logger logger = LoggerFactory.getLogger(YangStoreSnapshotImpl.class);
 
+    @Deprecated
     private final Map<String /* Namespace from yang file */,
             Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> moduleMXBeanEntryMap;
 
-    private final Map<String, Entry<Module, String>> moduleMap;
+    private final Map<Module, String> modulesToSources;
+    private final Map<QName, Map<String, ModuleMXBeanEntry>> qNamesToIdentitiesToModuleMXBeanEntries;
+
+    public YangStoreSnapshotImpl(Map<String, Map<String, ModuleMXBeanEntry>> moduleMXBeanEntryMap,
+                                 Map<Module, String> modulesToSources,
+                                 Map<QName, Map<String, ModuleMXBeanEntry>> qNamesToIdentitiesToModuleMXBeanEntries) {
 
-    public YangStoreSnapshotImpl(
-            Map<String, Map<String, ModuleMXBeanEntry>> moduleMXBeanEntryMap,
-            Map<String, Entry<Module, String>> moduleMap) {
         this.moduleMXBeanEntryMap = Collections.unmodifiableMap(moduleMXBeanEntryMap);
-        this.moduleMap = Collections.unmodifiableMap(moduleMap);
+        this.modulesToSources = Collections.unmodifiableMap(modulesToSources);
+        this.qNamesToIdentitiesToModuleMXBeanEntries = Collections.unmodifiableMap(qNamesToIdentitiesToModuleMXBeanEntries);
     }
 
-    public YangStoreSnapshotImpl(YangStoreSnapshot yangStoreSnapshot) {
-        this.moduleMXBeanEntryMap = yangStoreSnapshot.getModuleMXBeanEntryMap();
-        this.moduleMap = yangStoreSnapshot.getModuleMap();
+    public static YangStoreSnapshotImpl copy(YangStoreSnapshot yangStoreSnapshot) {
+        return new YangStoreSnapshotImpl(
+                yangStoreSnapshot.getModuleMXBeanEntryMap(),
+                yangStoreSnapshot.getModulesToSources(),
+                yangStoreSnapshot.getQNamesToIdentitiesToModuleMXBeanEntries());
     }
 
     /**
@@ -44,8 +54,28 @@ public class YangStoreSnapshotImpl implements YangStoreSnapshot {
     }
 
     @Override
-    public Map<String, Entry<Module, String>> getModuleMap() {
-        return moduleMap;
+    public Map<QName, Map<String, ModuleMXBeanEntry>> getQNamesToIdentitiesToModuleMXBeanEntries() {
+        return qNamesToIdentitiesToModuleMXBeanEntries;
+    }
+
+    @Override
+    public Set<Module> getModules() {
+        return modulesToSources.keySet();
+    }
+
+    @Override
+    public String getModuleSource(Module module) {
+        String result = modulesToSources.get(module);
+        if (result == null) {
+            logger.trace("Cannot find module {} in {}", module, modulesToSources);
+            throw new IllegalArgumentException("Module not found in this snapshot:" + module);
+        }
+        return result;
+    }
+
+    @Override
+    public Map<Module, String> getModulesToSources() {
+        return modulesToSources;
     }
 
     @Override
index b4054c2..8a7b95f 100644 (file)
@@ -30,7 +30,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
-import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyCollectionOf;
 import static org.mockito.Mockito.doNothing;
@@ -82,8 +81,9 @@ public class ExtenderYangTrackerCustomizerTest {
         doReturn(22).when(yangStoreSnapshot).countModuleMXBeanEntries();
         doReturn("mock yang store").when(yangStoreSnapshot).toString();
         doNothing().when(yangStoreSnapshot).close();
-        doReturn(moduleMap).when(yangStoreSnapshot).getModuleMap();
         doReturn(Collections.emptyMap()).when(yangStoreSnapshot).getModuleMXBeanEntryMap();
+        doReturn(Collections.emptyMap()).when(yangStoreSnapshot).getModulesToSources();
+        doReturn(Collections.emptyMap()).when(yangStoreSnapshot).getQNamesToIdentitiesToModuleMXBeanEntries();
     }
 
     @Test
@@ -99,7 +99,6 @@ public class ExtenderYangTrackerCustomizerTest {
 
         returnedStore = tested.getYangStoreSnapshot();
 
-        assertEquals(yangStoreSnapshot.getModuleMap(), returnedStore.getModuleMap());
 
         tested.removedBundle(bundle, null, null);
         tested.getYangStoreSnapshot();
index 7cd43bd..6eabbe6 100644 (file)
@@ -26,8 +26,8 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
-import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -100,16 +100,15 @@ public class NetconfOperationServiceImpl implements NetconfOperationService {
     }
 
     private static Set<Capability> setupCapabilities(YangStoreSnapshot yangStoreSnapshot) {
-        Set<Capability> capabilities = Sets.newHashSet();
-
+        Set<Capability> capabilities = new HashSet<>();
         // [RFC6241] 8.3.  Candidate Configuration Capability
         capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0"));
         // [RFC6241] 8.5.  Rollback-on-Error Capability
         capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:rollback-on-error:1.0"));
 
-        final Collection<Map.Entry<Module, String>> modulesAndContents = yangStoreSnapshot.getModuleMap().values();
-        for (Map.Entry<Module, String> moduleAndContent : modulesAndContents) {
-            capabilities.add(new YangStoreCapability(moduleAndContent));
+        Set<Module> modules = yangStoreSnapshot.getModules();
+        for (Module module : modules) {
+            capabilities.add(new YangStoreCapability(module, yangStoreSnapshot.getModuleSource(module)));
         }
 
         return capabilities;
@@ -161,10 +160,9 @@ public class NetconfOperationServiceImpl implements NetconfOperationService {
         private final String moduleName;
         private final String moduleNamespace;
 
-        public YangStoreCapability(Map.Entry<Module, String> moduleAndContent) {
-            super(getAsString(moduleAndContent.getKey()));
-            this.content = moduleAndContent.getValue();
-            Module module = moduleAndContent.getKey();
+        public YangStoreCapability(Module module, String moduleContent) {
+            super(getAsString(module));
+            this.content = moduleContent;
             this.moduleName = module.getName();
             this.moduleNamespace = module.getNamespace().toString();
             this.revision = Util.writeDate(module.getRevision());
index 8dbdb26..e0d7e31 100644 (file)
@@ -18,9 +18,12 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 public class CapabilityProviderImpl implements CapabilityProvider {
     private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
@@ -31,7 +34,9 @@ public class CapabilityProviderImpl implements CapabilityProvider {
     public CapabilityProviderImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
         this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
         Map<String, Capability> urisToCapabilitiesInternalMap = getCapabilitiesInternal(netconfOperationServiceSnapshot);
-        capabilityURIs = Collections.unmodifiableSet(urisToCapabilitiesInternalMap.keySet());
+        List<String> capabilityURIs = new ArrayList<>(urisToCapabilitiesInternalMap.keySet());
+        Collections.sort(capabilityURIs);
+        this.capabilityURIs = Collections.unmodifiableSet(new TreeSet<>(capabilityURIs));
     }
 
     private static Map<String, Capability> getCapabilitiesInternal(
index 8d3476f..958ac42 100644 (file)
@@ -95,7 +95,6 @@ public class ConcurrentClientsTest {
             final YangStoreSnapshot yStore = mock(YangStoreSnapshot.class);
             doReturn(yStore).when(this.yangStoreService).getYangStoreSnapshot();
             doReturn(Collections.emptyMap()).when(yStore).getModuleMXBeanEntryMap();
-            doReturn(Collections.emptyMap()).when(yStore).getModuleMap();
 
             final ConfigTransactionJMXClient mockedTCl = mock(ConfigTransactionJMXClient.class);
             doReturn(mockedTCl).when(this.jmxClient).getConfigTransactionClient(any(ObjectName.class));