Refactor NetconfDeviceSchemas
[netconf.git] / plugins / netconf-client-mdsal / src / main / java / org / opendaylight / netconf / client / mdsal / impl / DefaultDeviceNetconfSchemaProvider.java
index 9bbf63f550d6724ea5a93efe0642bd52ef9d2606..54c7cce74e022b3574b354d632457ffd0b247967 100644 (file)
@@ -10,16 +10,11 @@ package org.opendaylight.netconf.client.mdsal.impl;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.util.HashSet;
 import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.netconf.client.mdsal.LibraryModulesSchemas;
-import org.opendaylight.netconf.client.mdsal.LibrarySchemaSourceProvider;
-import org.opendaylight.netconf.client.mdsal.NetconfStateSchemasResolverImpl;
 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchema;
 import org.opendaylight.netconf.client.mdsal.api.DeviceNetconfSchema;
 import org.opendaylight.netconf.client.mdsal.api.DeviceNetconfSchemaProvider;
@@ -31,6 +26,7 @@ import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
+import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
 import org.slf4j.Logger;
@@ -41,7 +37,7 @@ public final class DefaultDeviceNetconfSchemaProvider implements DeviceNetconfSc
     private static final Logger LOG = LoggerFactory.getLogger(DefaultDeviceNetconfSchemaProvider.class);
 
     // FIXME: resolver seems to be a useless indirection
-    private final NetconfDeviceSchemasResolver resolver;
+    private final NetconfDeviceSchemasResolver resolver = new NetconfStateSchemasResolverImpl();
     private final @NonNull EffectiveModelContextFactory contextFactory;
     private final @NonNull SchemaSourceRegistry registry;
     private final @NonNull SchemaRepository repository;
@@ -49,67 +45,33 @@ public final class DefaultDeviceNetconfSchemaProvider implements DeviceNetconfSc
 
     DefaultDeviceNetconfSchemaProvider(final SharedSchemaRepository repository) {
         this(repository, repository,
-            repository.createEffectiveModelContextFactory(SchemaContextFactoryConfiguration.getDefault()),
-            new NetconfStateSchemasResolverImpl());
+            repository.createEffectiveModelContextFactory(SchemaContextFactoryConfiguration.getDefault()));
     }
 
     @VisibleForTesting
     public DefaultDeviceNetconfSchemaProvider(final SchemaSourceRegistry registry, final SchemaRepository repository,
-            final EffectiveModelContextFactory contextFactory, final NetconfDeviceSchemasResolver resolver) {
+            final EffectiveModelContextFactory contextFactory) {
         this.registry = requireNonNull(registry);
         this.repository = requireNonNull(repository);
         this.contextFactory = requireNonNull(contextFactory);
-        this.resolver = requireNonNull(resolver);
     }
 
     @Override
     public ListenableFuture<DeviceNetconfSchema> deviceNetconfSchemaFor(final RemoteDeviceId deviceId,
             final NetconfSessionPreferences sessionPreferences, final NetconfRpcService deviceRpc,
             final BaseNetconfSchema baseSchema, final Executor processingExecutor) {
-
-        // Acquire schemas
-        final var futureSchemas = resolver.resolve(deviceRpc, sessionPreferences, deviceId, baseSchema.modelContext());
-
-        // Convert to sources
-        final var sourceResolverFuture = Futures.transform(futureSchemas, availableSchemas -> {
-            final var providedSources = availableSchemas.getAvailableYangSchemasQNames();
-            LOG.debug("{}: Schemas exposed by ietf-netconf-monitoring: {}", deviceId, providedSources);
-
-            final var requiredSources = new HashSet<>(sessionPreferences.moduleBasedCaps().keySet());
-            final var requiredSourcesNotProvided = Sets.difference(requiredSources, providedSources);
-            if (!requiredSourcesNotProvided.isEmpty()) {
-                LOG.warn("{}: Netconf device does not provide all yang models reported in hello message capabilities,"
-                        + " required but not provided: {}", deviceId, requiredSourcesNotProvided);
-                LOG.warn("{}: Attempting to build schema context from required sources", deviceId);
-            }
-
-            // Here all the sources reported in netconf monitoring are merged with those reported in hello.
-            // It is necessary to perform this since submodules are not mentioned in hello but still required.
-            // This clashes with the option of a user to specify supported yang models manually in configuration
-            // for netconf-connector and as a result one is not able to fully override yang models of a device.
-            // It is only possible to add additional models.
-            final var providedSourcesNotRequired = Sets.difference(providedSources, requiredSources);
-            if (!providedSourcesNotRequired.isEmpty()) {
-                LOG.warn("{}: Netconf device provides additional yang models not reported in "
-                        + "hello message capabilities: {}", deviceId, providedSourcesNotRequired);
-                LOG.warn("{}: Adding provided but not required sources as required to prevent failures", deviceId);
-                LOG.debug("{}: Netconf device reported in hello: {}", deviceId, requiredSources);
-                requiredSources.addAll(providedSourcesNotRequired);
-            }
-
-            // FIXME: this instanceof check is quite bad
-            final var sourceProvider = availableSchemas instanceof LibraryModulesSchemas libraryModule
-                ? new LibrarySchemaSourceProvider(libraryModule.getAvailableModels())
-                    : new MonitoringSchemaSourceProvider(deviceId, deviceRpc);
-            return new DeviceSources(requiredSources, providedSources, sourceProvider);
-        }, MoreExecutors.directExecutor());
+        // Acquire sources
+        final var sourceResolverFuture = resolver.resolve(deviceId, sessionPreferences, deviceRpc,
+            baseSchema.modelContext());
 
         // Set up the EffectiveModelContext for the device
         return Futures.transformAsync(sourceResolverFuture, deviceSources -> {
             LOG.debug("{}: Resolved device sources to {}", deviceId, deviceSources);
 
             // Register all sources with repository and start resolution
-            final var registrations = deviceSources.register(registry);
+            final var registrations = deviceSources.providedSources().stream()
+                .flatMap(sources -> sources.registerWith(registry, Costs.REMOTE_IO.getValue()))
+                .collect(Collectors.toUnmodifiableList());
             final var future = new SchemaSetup(repository, contextFactory, deviceId, deviceSources, sessionPreferences)
                 .startResolution();