Bug 5403 - Support yang-library schema resolution 06/40606/3
authorJakub Morvay <jmorvay@cisco.com>
Tue, 21 Jun 2016 11:23:03 +0000 (13:23 +0200)
committerJakub Morvay <jmorvay@cisco.com>
Tue, 28 Jun 2016 09:53:27 +0000 (09:53 +0000)
Change-Id: I3599d3cf857cbb7b40c17aafadc9db7c83c4b09d
Signed-off-by: Jakub Morvay <jmorvay@cisco.com>
13 files changed:
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/NetconfDeviceSchemas.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/NetconfDeviceSchemasResolver.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/LibraryModulesSchemas.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfStateSchemas.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfStateSchemasResolverImpl.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDeviceTest.java
netconf/sal-netconf-connector/src/test/resources/yang-library-fail.xml
netconf/sal-netconf-connector/src/test/resources/yang-library.json
netconf/sal-netconf-connector/src/test/resources/yang-library.xml
netconf/tools/netconf-cli/src/main/java/org/opendaylight/netconf/cli/NetconfDeviceConnectionManager.java

index 6d5cdf898b68539ecef02d8ed7fc64e214651a2d..b75efc080fee8dca556fedce879a860b5294e49a 100644 (file)
@@ -48,7 +48,7 @@ import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemas;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
@@ -150,7 +150,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin
         schemaResourcesDTOs.put(DEFAULT_CACHE_DIRECTORY,
                 new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY,
                         DEFAULT_SCHEMA_CONTEXT_FACTORY,
-                        new NetconfStateSchemas.NetconfStateSchemasResolverImpl()));
+                        new NetconfStateSchemasResolverImpl()));
         DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE);
         DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
                 TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
@@ -372,7 +372,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin
 
         if (schemaResourcesDTO == null) {
             schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory,
-                    new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+                    new NetconfStateSchemasResolverImpl());
         }
 
         return schemaResourcesDTO;
@@ -394,7 +394,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin
                 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
         repository.registerSchemaSourceListener(deviceCache);
         return new NetconfDevice.SchemaResourcesDTO(repository, schemaContextFactory,
-                new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+                new NetconfStateSchemasResolverImpl());
     }
 
     /**
index 79a439c0ebc5984f00c0a70616fcbd7cc9920833..96cb688e45b55b4a2e2279e579e03b60a5bf8fe5 100644 (file)
@@ -40,7 +40,7 @@ import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemas;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
@@ -134,7 +134,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         schemaResourcesDTOs.put(DEFAULT_CACHE_DIRECTORY,
                 new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY,
                         DEFAULT_SCHEMA_CONTEXT_FACTORY,
-                        new NetconfStateSchemas.NetconfStateSchemasResolverImpl()));
+                        new NetconfStateSchemasResolverImpl()));
         DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE);
         DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
                 TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
@@ -284,7 +284,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
 
         if (schemaResourcesDTO == null) {
             schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory,
-                    new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+                    new NetconfStateSchemasResolverImpl());
         }
 
         final NetconfDevice device = new NetconfDeviceBuilder()
@@ -330,7 +330,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
                 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
         repository.registerSchemaSourceListener(deviceCache);
         return new NetconfDevice.SchemaResourcesDTO(repository, schemaContextFactory,
-                new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+                new NetconfStateSchemasResolverImpl());
     }
 
     /**
diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/NetconfDeviceSchemas.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/NetconfDeviceSchemas.java
new file mode 100644 (file)
index 0000000..54c4135
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 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.netconf.sal.connect.api;
+
+import java.util.Set;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemas;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
+
+public interface NetconfDeviceSchemas {
+
+    Set<QName> getAvailableYangSchemasQNames();
+}
diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/NetconfDeviceSchemasResolver.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/NetconfDeviceSchemasResolver.java
new file mode 100644 (file)
index 0000000..c1a465e
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016 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.netconf.sal.connect.api;
+
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+
+/**
+ * Factory for netconf device schemas
+ */
+public interface NetconfDeviceSchemasResolver {
+    NetconfDeviceSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id);
+}
index dd6f855d7a7c654df667f688ce501f2209bf094b..adb95c554093b0d0e9816e3f5b8a7ef5ac8ea5e6 100644 (file)
@@ -8,23 +8,36 @@
 package org.opendaylight.netconf.sal.connect.netconf;
 
 import static javax.xml.bind.DatatypeConverter.printBase64Binary;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toId;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
 import com.google.gson.stream.JsonReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.AbstractMap;
 import java.util.Collections;
 import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
 import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.ModulesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.module.list.Module;
 import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
@@ -39,6 +52,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
@@ -54,28 +68,47 @@ import org.xml.sax.SAXException;
  * Holds URLs with YANG schema resources for all yang modules reported in
  * ietf-netconf-yang-library/modules-state/modules node
  */
-public class LibraryModulesSchemas {
+public class LibraryModulesSchemas implements NetconfDeviceSchemas {
 
     private static final Logger LOG = LoggerFactory.getLogger(LibraryModulesSchemas.class);
 
-    private static SchemaContext libraryContext;
-
-    private final Map<SourceIdentifier, URL> availableModels;
+    private static final SchemaContext LIBRARY_CONTEXT;
 
     static {
         final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
         moduleInfoBackedContext.registerModuleInfo(
                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.
                         $YangModuleInfoImpl.getInstance());
-        libraryContext = moduleInfoBackedContext.tryToCreateSchemaContext().get();
+        LIBRARY_CONTEXT = moduleInfoBackedContext.tryToCreateSchemaContext().get();
+    }
+
+    private final Map<QName, URL> availableModels;
+
+    private static final YangInstanceIdentifier MODULES_STATE_MODULE_LIST =
+            YangInstanceIdentifier.builder().node(ModulesState.QNAME).node(Module.QNAME).build();
+
+    private static final ContainerNode GET_MODULES_STATE_MODULE_LIST_RPC;
+
+    static {
+        final DataContainerChild<?, ?> filter =
+                NetconfMessageTransformUtil.toFilterStructure(MODULES_STATE_MODULE_LIST, LIBRARY_CONTEXT);
+        GET_MODULES_STATE_MODULE_LIST_RPC =
+                Builders.containerBuilder().withNodeIdentifier(toId(NETCONF_GET_QNAME)).withChild(filter).build();
     }
 
-    private LibraryModulesSchemas(final Map<SourceIdentifier, URL> availableModels) {
+    private LibraryModulesSchemas(final Map<QName, URL> availableModels) {
         this.availableModels = availableModels;
     }
 
     public Map<SourceIdentifier, URL> getAvailableModels() {
-        return availableModels;
+        final Map<SourceIdentifier, URL> result = Maps.newHashMap();
+        for (final Map.Entry<QName, URL> entry : availableModels.entrySet()) {
+            final SourceIdentifier sId = RevisionSourceIdentifier
+                    .create(entry.getKey().getLocalName(), Optional.fromNullable(entry.getKey().getFormattedRevision()));
+            result.put(sId, entry.getValue());
+        }
+
+        return result;
     }
 
 
@@ -92,22 +125,89 @@ public class LibraryModulesSchemas {
 
             if(connection instanceof HttpURLConnection) {
                 connection.setRequestProperty("Accept", "application/xml");
-                String userpass = username + ":" + password;
-                String basicAuth = "Basic " + printBase64Binary(userpass.getBytes());
+                final String userpass = username + ":" + password;
+                final String basicAuth = "Basic " + printBase64Binary(userpass.getBytes());
 
                 connection.setRequestProperty("Authorization", basicAuth);
             }
 
             return createFromURLConnection(connection);
 
-        } catch (IOException e) {
+        } catch (final IOException e) {
             LOG.warn("Unable to download yang library from {}", url, e);
-            return new LibraryModulesSchemas(Collections.<SourceIdentifier, URL>emptyMap());
+            return new LibraryModulesSchemas(Collections.<QName, URL>emptyMap());
         }
     }
 
 
-    private static LibraryModulesSchemas createFromURLConnection(URLConnection connection) {
+    public static LibraryModulesSchemas create(final NetconfDeviceRpc deviceRpc, final RemoteDeviceId deviceId) {
+        final DOMRpcResult moduleListNodeResult;
+        try {
+            moduleListNodeResult =
+                    deviceRpc.invokeRpc(toPath(NETCONF_GET_QNAME), GET_MODULES_STATE_MODULE_LIST_RPC).get();
+        } catch (final InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException(deviceId + ": Interrupted while waiting for response to "
+                    + MODULES_STATE_MODULE_LIST, e);
+        } catch (final ExecutionException e) {
+            LOG.warn("{}: Unable to detect available schemas, get to {} failed", deviceId, MODULES_STATE_MODULE_LIST, e);
+            return new LibraryModulesSchemas(Collections.<QName, URL>emptyMap());
+        }
+
+        if(moduleListNodeResult.getErrors().isEmpty() == false) {
+            LOG.warn("{}: Unable to detect available schemas, get to {} failed, {}",
+                    deviceId, MODULES_STATE_MODULE_LIST, moduleListNodeResult.getErrors());
+            return new LibraryModulesSchemas(Collections.<QName, URL>emptyMap());
+        }
+
+
+        final Optional<? extends NormalizedNode<?, ?>> modulesStateNode =
+                findModulesStateNode(moduleListNodeResult.getResult());
+        if(modulesStateNode.isPresent()) {
+            Preconditions.checkState(modulesStateNode.get() instanceof ContainerNode,
+                    "Expecting container containing schemas, but was %s", modulesStateNode.get());
+            return create(((ContainerNode) modulesStateNode.get()));
+        } else {
+            LOG.warn("{}: Unable to detect available schemas, get to {} was empty", deviceId, toId(ModulesState.QNAME));
+            return new LibraryModulesSchemas(Collections.<QName, URL>emptyMap());
+        }
+    }
+
+    private static Optional<? extends NormalizedNode<?, ?>> findModulesStateNode(final NormalizedNode<?, ?> result) {
+        if(result == null) {
+            return Optional.absent();
+        }
+        final Optional<DataContainerChild<?, ?>> dataNode = ((DataContainerNode<?>) result).getChild(toId(NETCONF_DATA_QNAME));
+        if(dataNode.isPresent() == false) {
+            return Optional.absent();
+        }
+
+       return ((DataContainerNode<?>) dataNode.get()).getChild(toId(ModulesState.QNAME));
+    }
+
+    private static LibraryModulesSchemas create(final ContainerNode modulesStateNode) {
+        final YangInstanceIdentifier.NodeIdentifier moduleListNodeId =
+                new YangInstanceIdentifier.NodeIdentifier(Module.QNAME);
+        final Optional<DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?>> moduleListNode =
+                modulesStateNode.getChild(moduleListNodeId);
+        Preconditions.checkState(moduleListNode.isPresent(),
+                "Unable to find list: %s in %s", moduleListNodeId, modulesStateNode);
+        Preconditions.checkState(moduleListNode.get() instanceof MapNode,
+                "Unexpected structure for container: %s in : %s. Expecting a list",
+                moduleListNodeId, modulesStateNode);
+
+        final ImmutableMap.Builder<QName, URL> schemasMapping = new ImmutableMap.Builder<>();
+        for (final MapEntryNode moduleNode : ((MapNode) moduleListNode.get()).getValue()) {
+            final Optional<Map.Entry<QName, URL>> schemaMappingEntry = createFromEntry(moduleNode);
+            if (schemaMappingEntry.isPresent()) {
+                schemasMapping.put(createFromEntry(moduleNode).get());
+            }
+        }
+
+        return new LibraryModulesSchemas(schemasMapping.build());
+    }
+
+    private static LibraryModulesSchemas createFromURLConnection(final URLConnection connection) {
 
         String contentType = connection.getContentType();
 
@@ -124,7 +224,7 @@ public class LibraryModulesSchemas {
                     contentType.equals("application/json") ? readJson(in) : readXml(in);
 
             if (!optionalModulesStateNode.isPresent()) {
-                return new LibraryModulesSchemas(Collections.<SourceIdentifier, URL>emptyMap());
+                return new LibraryModulesSchemas(Collections.<QName, URL>emptyMap());
             }
 
             final NormalizedNode<?, ?> modulesStateNode = optionalModulesStateNode.get();
@@ -143,18 +243,18 @@ public class LibraryModulesSchemas {
                     "Unexpected structure for container: %s in : %s. Expecting a list",
                     moduleListNodeId, modulesStateNode);
 
-            final ImmutableMap.Builder<SourceIdentifier, URL> schemasMapping = new ImmutableMap.Builder<>();
+            final ImmutableMap.Builder<QName, URL> schemasMapping = new ImmutableMap.Builder<>();
             for (final MapEntryNode moduleNode : ((MapNode) moduleListNode.get()).getValue()) {
-                final Optional<Map.Entry<SourceIdentifier, URL>> schemaMappingEntry = createFromEntry(moduleNode);
+                final Optional<Map.Entry<QName, URL>> schemaMappingEntry = createFromEntry(moduleNode);
                 if (schemaMappingEntry.isPresent()) {
                     schemasMapping.put(createFromEntry(moduleNode).get());
                 }
             }
 
             return new LibraryModulesSchemas(schemasMapping.build());
-        } catch (IOException e) {
+        } catch (final IOException e) {
             LOG.warn("Unable to download yang library from {}", connection.getURL(), e);
-            return new LibraryModulesSchemas(Collections.<SourceIdentifier, URL>emptyMap());
+            return new LibraryModulesSchemas(Collections.<QName, URL>emptyMap());
         }
     }
 
@@ -175,9 +275,9 @@ public class LibraryModulesSchemas {
 
             return createFromURLConnection(connection);
 
-        } catch (IOException e) {
+        } catch (final IOException e) {
             LOG.warn("Unable to download yang library from {}", url, e);
-            return new LibraryModulesSchemas(Collections.<SourceIdentifier, URL>emptyMap());
+            return new LibraryModulesSchemas(Collections.<QName, URL>emptyMap());
         }
     }
 
@@ -195,7 +295,7 @@ public class LibraryModulesSchemas {
         final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
         final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
 
-        final JsonParserStream jsonParser = JsonParserStream.create(writer, libraryContext);
+        final JsonParserStream jsonParser = JsonParserStream.create(writer, LIBRARY_CONTEXT);
         final JsonReader reader = new JsonReader(new InputStreamReader(in));
 
         jsonParser.parse(reader);
@@ -207,12 +307,12 @@ public class LibraryModulesSchemas {
 
     private static Optional<NormalizedNode<?, ?>> readXml(final InputStream in) {
         final DomToNormalizedNodeParserFactory parserFactory =
-                DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, libraryContext);
+                DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, LIBRARY_CONTEXT);
 
         try {
             final NormalizedNode<?, ?> parsed =
                     parserFactory.getContainerNodeParser().parse(Collections.singleton(XmlUtil.readXmlToElement(in)),
-                            (ContainerSchemaNode) libraryContext.getDataChildByName(ModulesState.QNAME));
+                            (ContainerSchemaNode) LIBRARY_CONTEXT.getDataChildByName(ModulesState.QNAME));
             return Optional.of(parsed);
         } catch (IOException|SAXException e) {
             LOG.warn("Unable to parse yang library xml content", e);
@@ -221,7 +321,7 @@ public class LibraryModulesSchemas {
         return Optional.<NormalizedNode<?, ?>>absent();
     }
 
-    private static Optional<Map.Entry<SourceIdentifier, URL>> createFromEntry(final MapEntryNode moduleNode) {
+    private static Optional<Map.Entry<QName, URL>> createFromEntry(final MapEntryNode moduleNode) {
         Preconditions.checkArgument(
                 moduleNode.getNodeType().equals(Module.QNAME), "Wrong QName %s", moduleNode.getNodeType());
 
@@ -234,7 +334,7 @@ public class LibraryModulesSchemas {
         if(revision.isPresent()) {
             if(!SourceIdentifier.REVISION_PATTERN.matcher(revision.get()).matches()) {
                 LOG.warn("Skipping library schema for {}. Revision {} is in wrong format.", moduleNode, revision.get());
-                return Optional.<Map.Entry<SourceIdentifier, URL>>absent();
+                return Optional.<Map.Entry<QName, URL>>absent();
             }
         }
 
@@ -243,18 +343,20 @@ public class LibraryModulesSchemas {
         childNodeId = new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "schema"));
         final Optional<String> schemaUriAsString = getSingleChildNodeValue(moduleNode, childNodeId);
 
+        childNodeId = new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "namespace"));
+        final String moduleNameSpace = getSingleChildNodeValue(moduleNode, childNodeId).get();
 
-        final SourceIdentifier sourceId = revision.isPresent()
-                ? RevisionSourceIdentifier.create(moduleName, revision.get())
-                : RevisionSourceIdentifier.create(moduleName);
+        final QName moduleQName = revision.isPresent()
+                ? QName.create(moduleNameSpace, revision.get(), moduleName)
+                : QName.create(URI.create(moduleNameSpace), null, moduleName);
 
         try {
-            return Optional.<Map.Entry<SourceIdentifier, URL>>of(new AbstractMap.SimpleImmutableEntry<>(
-                    sourceId, new URL(schemaUriAsString.get())));
-        } catch (MalformedURLException e) {
+            return Optional.<Map.Entry<QName, URL>>of(new AbstractMap.SimpleImmutableEntry<>(
+                    moduleQName, new URL(schemaUriAsString.get())));
+        } catch (final MalformedURLException e) {
             LOG.warn("Skipping library schema for {}. URL {} representing yang schema resource is not valid",
                     moduleNode, schemaUriAsString.get());
-            return Optional.<Map.Entry<SourceIdentifier, URL>>absent();
+            return Optional.<Map.Entry<QName, URL>>absent();
         }
     }
 
@@ -273,4 +375,8 @@ public class LibraryModulesSchemas {
                 ? Optional.<String>absent() : Optional.of(value.toString().trim());
     }
 
+    @Override
+    public Set<QName> getAvailableYangSchemasQNames() {
+        return null;
+    }
 }
index 4070c96750519ba3ae9f71bd7a720c5653db3861..69efd2858e4f681f21ec5fbf8dbd46460df6443f 100644 (file)
@@ -32,6 +32,8 @@ import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas;
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemasResolver;
 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
@@ -40,6 +42,7 @@ import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommun
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
 import org.opendaylight.netconf.sal.connect.netconf.schema.NetconfRemoteSchemaYangSourceProvider;
+import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseSchema;
 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
@@ -56,6 +59,7 @@ import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
 import org.slf4j.Logger;
@@ -83,7 +87,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
     private final RemoteDeviceHandler<NetconfSessionPreferences> salFacade;
     private final ListeningExecutorService processingExecutor;
     protected final SchemaSourceRegistry schemaRegistry;
-    private final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver;
+    private final NetconfDeviceSchemasResolver stateSchemasResolver;
     private final NotificationHandler notificationHandler;
     protected final List<SchemaSourceRegistration<? extends SchemaSourceRepresentation>> sourceRegistrations = Lists.newArrayList();
 
@@ -94,7 +98,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
      * Create rpc implementation capable of handling RPC for monitoring and notifications even before the schemas of remote device are downloaded
      */
     static NetconfDeviceRpc getRpcForInitialization(final NetconfDeviceCommunicator listener, final boolean notificationSupport) {
-        BaseSchema baseSchema = notificationSupport ?
+        final BaseSchema baseSchema = notificationSupport ?
                 BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS :
                 BaseSchema.BASE_NETCONF_CTX;
 
@@ -134,7 +138,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
         final FutureCallback<DeviceSources> resolvedSourceCallback = new FutureCallback<DeviceSources>() {
             @Override
             public void onSuccess(final DeviceSources result) {
-                addProvidedSourcesToSchemaRegistry(initRpc, result);
+                addProvidedSourcesToSchemaRegistry(result);
                 setUpSchema(result);
             }
 
@@ -193,7 +197,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
     }
 
     protected void handleSalInitializationSuccess(final SchemaContext result, final NetconfSessionPreferences remoteSessionCapabilities, final DOMRpcService deviceRpc) {
-        BaseSchema baseSchema =
+        final BaseSchema baseSchema =
                 remoteSessionCapabilities.isNotificationsSupported() ?
                 BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS :
                 BaseSchema.BASE_NETCONF_CTX;
@@ -225,8 +229,8 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
         messageTransformer = transformer;
     }
 
-    private void addProvidedSourcesToSchemaRegistry(final NetconfDeviceRpc deviceRpc, final DeviceSources deviceSources) {
-        final NetconfRemoteSchemaYangSourceProvider yangProvider = new NetconfRemoteSchemaYangSourceProvider(id, deviceRpc);
+    private void addProvidedSourcesToSchemaRegistry(final DeviceSources deviceSources) {
+        final SchemaSourceProvider<YangTextSchemaSource> yangProvider = deviceSources.getSourceProvider();
         for (final SourceIdentifier sourceId : deviceSources.getProvidedSources()) {
             sourceRegistrations.add(schemaRegistry.registerSchemaSource(yangProvider,
                     PotentialSchemaSource.create(sourceId, YangTextSchemaSource.class, PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
@@ -260,12 +264,14 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
     public static class SchemaResourcesDTO {
         private final SchemaSourceRegistry schemaRegistry;
         private final SchemaContextFactory schemaContextFactory;
-        private final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver;
+        private final NetconfDeviceSchemasResolver stateSchemasResolver;
 
-        public SchemaResourcesDTO(final SchemaSourceRegistry schemaRegistry, final SchemaContextFactory schemaContextFactory, final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver) {
+        public SchemaResourcesDTO(final SchemaSourceRegistry schemaRegistry,
+                                  final SchemaContextFactory schemaContextFactory,
+                                  final NetconfDeviceSchemasResolver deviceSchemasResolver) {
             this.schemaRegistry = Preconditions.checkNotNull(schemaRegistry);
             this.schemaContextFactory = Preconditions.checkNotNull(schemaContextFactory);
-            this.stateSchemasResolver = Preconditions.checkNotNull(stateSchemasResolver);
+            this.stateSchemasResolver = Preconditions.checkNotNull(deviceSchemasResolver);
         }
 
         public SchemaSourceRegistry getSchemaRegistry() {
@@ -276,7 +282,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
             return schemaContextFactory;
         }
 
-        public NetconfStateSchemas.NetconfStateSchemasResolver getStateSchemasResolver() {
+        public NetconfDeviceSchemasResolver getStateSchemasResolver() {
             return stateSchemasResolver;
         }
     }
@@ -289,23 +295,23 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
         private final NetconfDeviceRpc deviceRpc;
         private final NetconfSessionPreferences remoteSessionCapabilities;
         private final RemoteDeviceId id;
-        private final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver;
+        private final NetconfDeviceSchemasResolver stateSchemasResolver;
 
         DeviceSourcesResolver(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities,
-                                     final RemoteDeviceId id, final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver) {
+                                     final RemoteDeviceId id, final NetconfDeviceSchemasResolver stateSchemasResolver) {
             this.deviceRpc = deviceRpc;
             this.remoteSessionCapabilities = remoteSessionCapabilities;
             this.id = id;
             this.stateSchemasResolver = stateSchemasResolver;
         }
 
-        public DeviceSourcesResolver(final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id, final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver, final NetconfDeviceRpc rpcForMonitoring) {
+        public DeviceSourcesResolver(final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id, final NetconfDeviceSchemasResolver stateSchemasResolver, final NetconfDeviceRpc rpcForMonitoring) {
             this(rpcForMonitoring, remoteSessionCapabilities, id, stateSchemasResolver);
         }
 
         @Override
         public DeviceSources call() throws Exception {
-            final NetconfStateSchemas availableSchemas = stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id);
+            final NetconfDeviceSchemas availableSchemas = stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id);
             LOG.debug("{}: Schemas exposed by ietf-netconf-monitoring: {}", id, availableSchemas.getAvailableYangSchemasQNames());
 
             final Set<QName> requiredSources = Sets.newHashSet(remoteSessionCapabilities.getModuleBasedCaps());
@@ -331,7 +337,15 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
                 requiredSources.addAll(providedSourcesNotRequired);
             }
 
-            return new DeviceSources(requiredSources, providedSources);
+            final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
+            if(availableSchemas instanceof LibraryModulesSchemas) {
+                sourceProvider = new YangLibrarySchemaYangSourceProvider(id,
+                        ((LibraryModulesSchemas) availableSchemas).getAvailableModels());
+            } else {
+                sourceProvider = new NetconfRemoteSchemaYangSourceProvider(id, deviceRpc);
+            }
+
+            return new DeviceSources(requiredSources, providedSources, sourceProvider);
         }
     }
 
@@ -341,10 +355,13 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
     private static final class DeviceSources {
         private final Set<QName> requiredSources;
         private final Set<QName> providedSources;
+        private final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
 
-        public DeviceSources(final Set<QName> requiredSources, final Set<QName> providedSources) {
+        public DeviceSources(final Set<QName> requiredSources, final Set<QName> providedSources,
+                             final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
             this.requiredSources = requiredSources;
             this.providedSources = providedSources;
+            this.sourceProvider = sourceProvider;
         }
 
         public Set<QName> getRequiredSourcesQName() {
@@ -363,6 +380,9 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
             return Collections2.transform(providedSources, QNAME_TO_SOURCE_ID_FUNCTION);
         }
 
+        public SchemaSourceProvider<YangTextSchemaSource> getSourceProvider() {
+            return sourceProvider;
+        }
     }
 
     /**
@@ -401,7 +421,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
                     capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps());
                     handleSalInitializationSuccess(result, remoteSessionCapabilities, getDeviceSpecificRpc(result));
                     return;
-                } catch (Throwable t) {
+                } catch (final Throwable t) {
                     if (t instanceof MissingSchemaSourceException){
                         requiredSources = handleMissingSchemaSourceException(requiredSources, (MissingSchemaSourceException) t);
                     } else if (t instanceof SchemaResolutionException) {
@@ -426,7 +446,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
             salFacade.onDeviceFailed(cause);
         }
 
-        private Collection<SourceIdentifier> handleMissingSchemaSourceException(Collection<SourceIdentifier> requiredSources, final MissingSchemaSourceException t) {
+        private Collection<SourceIdentifier> handleMissingSchemaSourceException(final Collection<SourceIdentifier> requiredSources, final MissingSchemaSourceException t) {
             // In case source missing, try without it
             final SourceIdentifier missingSource = t.getSourceId();
             LOG.warn("{}: Unable to build schema context, missing source {}, will reattempt without it", id, missingSource);
@@ -438,7 +458,7 @@ public class NetconfDevice implements RemoteDevice<NetconfSessionPreferences, Ne
             return stripMissingSource(requiredSources, missingSource);
         }
 
-        private Collection<SourceIdentifier> handleSchemaResolutionException(Collection<SourceIdentifier> requiredSources, final SchemaResolutionException resolutionException) {
+        private Collection<SourceIdentifier> handleSchemaResolutionException(final Collection<SourceIdentifier> requiredSources, final SchemaResolutionException resolutionException) {
             // In case resolution error, try only with resolved sources
             final Set<SourceIdentifier> unresolvedSources = resolutionException.getUnsatisfiedImports().keySet();
             capabilities.addUnresolvedCapabilities(getQNameFromSourceIdentifiers(unresolvedSources), UnavailableCapability.FailureReason.UnableToResolve);
index b738ed69de782c7daa767f04b312dffc0f3f282a..7f4ecd96db2df88ac1bf9958d4e25cd6fef1a201 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseSchema;
@@ -51,28 +52,10 @@ import org.slf4j.LoggerFactory;
 /**
  * Holds QNames for all yang modules reported by ietf-netconf-monitoring/state/schemas
  */
-public final class NetconfStateSchemas {
+public final class NetconfStateSchemas implements NetconfDeviceSchemas {
 
     private static final Logger LOG = LoggerFactory.getLogger(NetconfStateSchemas.class);
 
-    /**
-     * Factory for NetconfStateSchemas
-     */
-    public interface NetconfStateSchemasResolver {
-        NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id);
-    }
-
-    /**
-     * Default implementation resolving schemas QNames from netconf-state
-     */
-    public static final class NetconfStateSchemasResolverImpl implements NetconfStateSchemasResolver {
-
-        @Override
-        public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
-            return NetconfStateSchemas.create(deviceRpc, remoteSessionCapabilities, id);
-        }
-    }
-
     public static final NetconfStateSchemas EMPTY = new NetconfStateSchemas(Collections.<RemoteYangSchema>emptySet());
 
     private static final YangInstanceIdentifier STATE_SCHEMAS_IDENTIFIER =
@@ -96,6 +79,7 @@ public final class NetconfStateSchemas {
         return availableYangSchemas;
     }
 
+    @Override
     public Set<QName> getAvailableYangSchemasQNames() {
         return Sets.newHashSet(Collections2.transform(getAvailableYangSchemas(), new Function<RemoteYangSchema, QName>() {
             @Override
@@ -108,7 +92,7 @@ public final class NetconfStateSchemas {
     /**
      * Issue get request to remote device and parse response to find all schemas under netconf-state/schemas
      */
-    private static NetconfStateSchemas create(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
+    static NetconfStateSchemas create(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
         if(remoteSessionCapabilities.isMonitoringSupported() == false) {
             // TODO - need to search for get-schema support, not just ietf-netconf-monitoring support
             // issue might be a deviation to ietf-netconf-monitoring where get-schema is unsupported...
@@ -199,7 +183,7 @@ public final class NetconfStateSchemas {
 
             QName childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_FORMAT;
 
-            String formatAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+            final String formatAsString = getSingleChildNodeValue(schemaNode, childNode).get();
 
             if(formatAsString.equals(Yang.QNAME.toString()) == false) {
                 LOG.debug("{}: Ignoring schema due to unsupported format: {}", id, formatAsString);
diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfStateSchemasResolverImpl.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfStateSchemasResolverImpl.java
new file mode 100644 (file)
index 0000000..6931cf8
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 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.netconf.sal.connect.netconf;
+
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas;
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemasResolver;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.ModulesState;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * Default implementation resolving schemas QNames from netconf-state or from modules-state
+ */
+public final class NetconfStateSchemasResolverImpl implements NetconfDeviceSchemasResolver {
+
+    @Override
+    public NetconfDeviceSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
+        if (remoteSessionCapabilities.isMonitoringSupported()) {
+            return NetconfStateSchemas.create(deviceRpc, remoteSessionCapabilities, id);
+        } else if (remoteSessionCapabilities.containsModuleCapability(QName.create(ModulesState.QNAME, "ietf-yang-library"))) {
+            return LibraryModulesSchemas.create(deviceRpc, id);
+        }
+        return NetconfStateSchemas.EMPTY;
+    }
+}
index 23e86f3aed93d0971927d86410eb06637d0dc2af..c8be625f0b32653704c0245ce1d685f2d576d68a 100644 (file)
@@ -44,6 +44,8 @@ import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas;
+import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemasResolver;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
@@ -101,10 +103,10 @@ public class NetconfDeviceTest {
             RevisionSourceIdentifier.create(TEST_MODULE + "2", Optional.of(TEST_REVISION));
     public static final String TEST_CAPABILITY2 = TEST_NAMESPACE + "?module=" + TEST_MODULE + "2" + "&amp;revision=" + TEST_REVISION;
 
-    private static final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver = new NetconfStateSchemas.NetconfStateSchemasResolver() {
+    private static final NetconfDeviceSchemasResolver stateSchemasResolver = new NetconfDeviceSchemasResolver() {
 
         @Override
-        public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
+        public NetconfDeviceSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
             return NetconfStateSchemas.EMPTY;
         }
     };
@@ -166,9 +168,9 @@ public class NetconfDeviceTest {
             }
         }).when(schemaFactory).createSchemaContext(anyCollectionOf(SourceIdentifier.class));
 
-        final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver = new NetconfStateSchemas.NetconfStateSchemasResolver() {
+        final NetconfDeviceSchemasResolver stateSchemasResolver = new NetconfDeviceSchemasResolver() {
             @Override
-            public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
+            public NetconfDeviceSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
                 final Module first = Iterables.getFirst(schema.getModules(), null);
                 final QName qName = QName.create(first.getQNameModule(), first.getName());
                 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
index ef1feea975b08b6427ac27bb728181d906d513de..eb54f1cb37a88f21a942ba9834f2c2a610c3e1aa 100644 (file)
@@ -2,6 +2,7 @@
     <module>
         <name>module-with-bad-url</name>
         <revision></revision>
+        <namespace>b</namespace>
         <schema>
             badurl
         </schema>
     <module>
         <name>module-bad-revision</name>
         <revision>bad-revision</revision>
+        <namespace>bbb</namespace>
     </module>
     <module>
         <name>good-ol-module</name>
         <revision></revision>
         <schema>http://www.example.com</schema>
+        <namespace>bbbds</namespace>
     </module>
 </modules>
\ No newline at end of file
index d0f55528211ab5f29915261c328a7eaf82ed67b5..0b08c0d705ea5bbd84f1b95089b6b579facbaaf7 100644 (file)
@@ -4,16 +4,19 @@
       {
         "name": "module-with-revision",
         "revision": "2014-04-08",
-        "schema": "http://localhost:8181/yanglib/schemas/module-with-revision/2014-04-08"
+        "schema": "http://localhost:8181/yanglib/schemas/module-with-revision/2014-04-08",
+        "namespace": "bla"
       },
       {
         "name": "another-module-with-revision",
         "revision": "2014-06-08",
+        "namespace": "test",
         "schema": "http://localhost:8181/yanglib/schemas/another-module-with-revision/2013-10-21"
       },
       {
         "name": "module-without-revision",
         "revision": "",
+        "namespace": "namespace:module-without-revision",
         "schema": "http://localhost:8181/yanglib/schemas/module-without-revision/2013-10-21"
       }
     ]
index 704ec670a2360b7a241e6cce1d224c09181c0daf..c60345093317ca6821214df8d827899ddb540587 100644 (file)
@@ -2,6 +2,7 @@
     <module>
         <name>module-with-revision</name>
         <revision>2014-04-08</revision>
+        <namespace>namespace</namespace>
         <schema>
             http://localhost:8181/yanglib/schemas/module-with-revision/2014-04-08
         </schema>
     <module>
         <name>another-module-with-revision</name>
         <revision>2013-10-21</revision>
+        <namespace>another-module-with-revision:namespace</namespace>
         <schema>
             http://localhost:8181/yanglib/schemas/another-module-with-revision/2013-10-21
         </schema>
     </module>
     <module>
         <name>module-without-revision</name>
+        <namespace>module-without-revision:namespace</namespace>
         <revision></revision>
         <schema>
             http://localhost:8181/yanglib/schemas/module-without-revision/
index 4bbbc11dfcdf62b2fcbc69e40718e9583c41565a..a3e98b31dad5fc96c2ede181fbe14290cbe1f7e5 100644 (file)
@@ -24,7 +24,7 @@ import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemas.NetconfStateSchemasResolverImpl;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;