Fixup yanglib-mdsal-writer 52/110852/3
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 18 Mar 2024 15:10:59 +0000 (16:10 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 19 Mar 2024 06:28:48 +0000 (07:28 +0100)
yanglib-mdsal-writer does not write out module-state by default, which
our CSIT expects. We also should be friendly to RFC7895 clients and have
this content by default.

Furthermore the @Inject needs to be separated from @Activate, as we do
not have OSGi configuration in javax.inject world. Use a compatible
writeLegacy=true default and Optional for URL provider.

Moreover there is a bug where the initial update would not be written if
the listener is executed before registration is stored into the object
field. Fix that by using an explicit boolean to track the closed state.

Finally enable multiple Urls to be reported in the RFC8525 container.
For RFC7895 compatibility we pick the first Url in iteration order.

JIRA: NETCONF-1277
Change-Id: I8cbb2af5e4e7b8ec713126bad981fb5a38c4240f
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
apps/yanglib-mdsal-writer/pom.xml
apps/yanglib-mdsal-writer/src/main/java/org/opendaylight/netconf/yanglib/writer/YangLibraryContentBuilderUtil.java
apps/yanglib-mdsal-writer/src/main/java/org/opendaylight/netconf/yanglib/writer/YangLibrarySchemaSourceUrlProvider.java
apps/yanglib-mdsal-writer/src/main/java/org/opendaylight/netconf/yanglib/writer/YangLibraryWriter.java
apps/yanglib-mdsal-writer/src/test/java/org/opendaylight/netconf/yanglib/writer/YangLibraryWriterTest.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/RestconfSchemaSourceUrlProvider.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/server/mdsal/RestconfSchemaSourceUrlProviderTest.java

index 20a3afa1465cd1eb3396e0ca602c2572bd361cbf..905b7670dd322aefcb844bbe15727072e6f144c7 100644 (file)
     <dependencies>
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
-            <artifactId>mdsal-dom-api</artifactId>
+            <artifactId>mdsal-binding-api</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
-            <artifactId>mdsal-binding-api</artifactId>
+            <artifactId>mdsal-dom-api</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
             <artifactId>jakarta.annotation-api</artifactId>
             <optional>true</optional>
         </dependency>
+
         <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-dom-spi</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-test-util</artifactId>
index aefbe5d51a3e4f72efcc5d8b4424fea9235a5978..c469259b207a55c0fe5fcd552ded21c0d1094865 100644 (file)
@@ -15,10 +15,10 @@ import com.google.common.collect.ImmutableSet;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.datastores.rev180214.Operational;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
@@ -51,6 +51,7 @@ import org.opendaylight.yangtools.yang.model.api.ModuleLike;
 //  https://jira.opendaylight.org/browse/MDSAL-833
 //  https://jira.opendaylight.org/browse/MDSAL-835
 final class YangLibraryContentBuilderUtil {
+    @Deprecated
     private static final CommonLeafs.Revision EMPTY_REVISION = new CommonLeafs.Revision("");
 
     static final String DEFAULT_MODULE_SET_NAME = "ODL_modules";
@@ -64,11 +65,12 @@ final class YangLibraryContentBuilderUtil {
      * Builds ietf-yang-library content based on model context.
      *
      * @param context effective model context
-     * @param urlProvider optional schema source URL provider
+     * @param urlProvider schema source URL provider
      * @return content as YangLibrary object
      */
-    static YangLibrary buildYangLibrary(final @NonNull EffectiveModelContext context,
-            final @NonNull String contentId, final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider) {
+    @NonNullByDefault
+    static YangLibrary buildYangLibrary(final EffectiveModelContext context, final String contentId,
+            final YangLibrarySchemaSourceUrlProvider urlProvider) {
         final var deviationsMap = getDeviationsMap(context);
         return new YangLibraryBuilder()
             .setModuleSet(BindingMap.of(new ModuleSetBuilder()
@@ -93,20 +95,20 @@ final class YangLibraryContentBuilderUtil {
     private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104
         .module.set.parameters.@NonNull Module buildModule(final @NonNull Module module,
             final @NonNull  Map<QNameModule, Set<Module>> deviationsMap,
-            final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider) {
+            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
         return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
             .rev190104.module.set.parameters.ModuleBuilder()
             .setName(buildModuleKeyName(module))
             .setRevision(buildRevision(module))
             .setNamespace(new Uri(module.getNamespace().toString()))
-            .setFeature(buildFeatures(module).orElse(null))
-            .setDeviation(buildDeviations(module, deviationsMap).orElse(null))
-            .setLocation(buildSchemaSourceUrl(module, urlProvider).map(Set::of).orElse(null))
+            .setFeature(buildFeatures(module))
+            .setDeviation(buildDeviations(module, deviationsMap))
+            .setLocation(buildSchemaSourceUrls(module, urlProvider))
             .setSubmodule(module.getSubmodules().stream()
                 .map(subModule -> new SubmoduleBuilder()
                     .setName(buildModuleKeyName(subModule))
                     .setRevision(buildRevision(subModule))
-                    .setLocation(buildSchemaSourceUrl(subModule, urlProvider).map(Set::of).orElse(null))
+                    .setLocation(buildSchemaSourceUrls(subModule, urlProvider))
                     .build())
                 .collect(BindingMap.toMap()))
             .build();
@@ -116,13 +118,13 @@ final class YangLibraryContentBuilderUtil {
      * Builds ietf-yang-library legacy content based on model context.
      *
      * @param context effective model context
-     * @param urlProvider optional schema source URL provider
+     * @param urlProvider schema source URL provider
      * @return content as ModulesState object
      * @deprecated due to model update via RFC 8525, the functionality serves backward compatibility.
      */
     @Deprecated
     static ModulesState buildModuleState(final @NonNull EffectiveModelContext context,
-            final @NonNull String moduleSetId, final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider) {
+            final @NonNull String moduleSetId, final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
         final var deviationsMap = getDeviationsMap(context);
         return new ModulesStateBuilder()
             .setModule(context.getModules().stream()
@@ -132,26 +134,27 @@ final class YangLibraryContentBuilderUtil {
             .build();
     }
 
+    @Deprecated
     private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
         .rev190104.module.list.@NonNull Module buildLegacyModule(final @NonNull Module module,
             final @NonNull  Map<QNameModule, Set<Module>> deviationsMap,
-            final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider) {
+            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
 
         return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
             .rev190104.module.list.ModuleBuilder()
             .setName(buildModuleKeyName(module))
             .setRevision(buildLegacyRevision(module))
             .setNamespace(new Uri(module.getNamespace().toString()))
-            .setFeature(buildFeatures(module).orElse(null))
-            .setSchema(buildSchemaSourceUrl(module, urlProvider).orElse(null))
+            .setFeature(buildFeatures(module))
+            .setSchema(buildSchemaSourceUrl(module, urlProvider))
             .setConformanceType(hasDeviations(module) ? Implement : Import)
-            .setDeviation(buildLegacyDeviations(module, deviationsMap).orElse(null))
+            .setDeviation(buildLegacyDeviations(module, deviationsMap))
             .setSubmodule(module.getSubmodules().stream()
                 .map(subModule -> new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library
                     .rev190104.module.list.module.SubmoduleBuilder()
                     .setName(buildModuleKeyName(subModule))
                     .setRevision(buildLegacyRevision(subModule))
-                    .setSchema(buildSchemaSourceUrl(subModule, urlProvider).orElse(null))
+                    .setSchema(buildSchemaSourceUrl(subModule, urlProvider))
                     .build())
                 .collect(BindingMap.toMap()))
             .build();
@@ -162,6 +165,7 @@ final class YangLibraryContentBuilderUtil {
         return revision != null ? new RevisionIdentifier(revision.toString()) : null;
     }
 
+    @Deprecated
     private static CommonLeafs.Revision buildLegacyRevision(final ModuleLike module) {
         final var revision = module.getQNameModule().revision();
         return revision != null ? new CommonLeafs.Revision(new RevisionIdentifier(revision.toString()))
@@ -174,16 +178,24 @@ final class YangLibraryContentBuilderUtil {
             new YangIdentifier(module.getName() + "_" + revision);
     }
 
-    private static @NonNull Optional<Uri> buildSchemaSourceUrl(final @NonNull ModuleLike module,
-            final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider) {
-        return urlProvider == null ? Optional.empty() :
-            urlProvider.getSchemaSourceUrl(DEFAULT_MODULE_SET_NAME, module.getName(),
-                module.getRevision().orElse(null));
+    @Deprecated
+    private static @Nullable Uri buildSchemaSourceUrl(final @NonNull ModuleLike module,
+            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
+        final var uris = buildSchemaSourceUrls(module, urlProvider);
+        return uris == null ? null : uris.iterator().next();
     }
 
-    private static Optional<Set<YangIdentifier>> buildFeatures(final ModuleLike module) {
-        if (module.getFeatures() == null || module.getFeatures().isEmpty()) {
-            return Optional.empty();
+    private static @Nullable Set<Uri> buildSchemaSourceUrls(final @NonNull ModuleLike module,
+            final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider) {
+        final var uris = urlProvider.getSchemaSourceUrl(DEFAULT_MODULE_SET_NAME, module.getName(),
+            module.getRevision().orElse(null));
+        return uris.isEmpty() ? null : uris;
+    }
+
+    private static @Nullable Set<YangIdentifier> buildFeatures(final ModuleLike module) {
+        final var moduleFeatures = module.getFeatures();
+        if (moduleFeatures == null || moduleFeatures.isEmpty()) {
+            return null;
         }
         final var namespace = module.getQNameModule();
         final var features = module.getFeatures().stream()
@@ -192,36 +204,31 @@ final class YangLibraryContentBuilderUtil {
             .filter(featureName -> namespace.equals(featureName.getModule()))
             .map(featureName -> new YangIdentifier(featureName.getLocalName()))
             .collect(Collectors.toUnmodifiableSet());
-        return features.isEmpty() ? Optional.empty() : Optional.of(features);
+        return features.isEmpty() ? null : features;
     }
 
     private static boolean hasDeviations(final Module module) {
         return module.getDeviations() != null && !module.getDeviations().isEmpty();
     }
 
-    private static Optional<Set<YangIdentifier>> buildDeviations(final Module module,
+    private static @Nullable Set<YangIdentifier> buildDeviations(final Module module,
             final Map<QNameModule, Set<Module>> deviationsMap) {
         final var deviationModules = deviationsMap.get(module.getQNameModule());
-        if (deviationModules == null) {
-            return Optional.empty();
-        }
-        return Optional.of(deviationModules.stream()
+        return deviationModules == null ? null : deviationModules.stream()
             .map(devModule -> new YangIdentifier(buildModuleKeyName(devModule)))
-            .collect(ImmutableSet.toImmutableSet()));
+            .collect(ImmutableSet.toImmutableSet());
     }
 
-    private static Optional<Map<DeviationKey, Deviation>> buildLegacyDeviations(final Module module,
+    @Deprecated
+    private static @Nullable Map<DeviationKey, Deviation> buildLegacyDeviations(final Module module,
             final Map<QNameModule, Set<Module>> deviationsMap) {
         final var deviationModules = deviationsMap.get(module.getQNameModule());
-        if (deviationModules == null) {
-            return Optional.empty();
-        }
-        return Optional.of(deviationModules.stream()
+        return deviationModules == null ? null : deviationModules.stream()
             .map(devModule -> new DeviationBuilder()
                 .setName(buildModuleKeyName(devModule))
                 .setRevision(buildLegacyRevision(devModule))
                 .build())
-            .collect(BindingMap.toMap()));
+            .collect(BindingMap.toMap());
     }
 
     private static @NonNull Map<QNameModule, Set<Module>> getDeviationsMap(final EffectiveModelContext context) {
index f230a8a3b531a75cfe9ce8a4e11d6a4d8fc92037..c83c179ec1bdd5a9e31d3d3b2bd4eafb0ddf0c0e 100644 (file)
@@ -7,30 +7,28 @@
  */
 package org.opendaylight.netconf.yanglib.writer;
 
-import java.util.Optional;
+import java.util.Set;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yangtools.yang.common.Revision;
 
 /**
- * The service providing URLs to yang schema sources.
+ * The service providing URLs to YANG schema sources.
  */
 // TODO: current interface is a part of integration with YangLibrarySupport and expected
 //  to be removed once the similar interface is implemented there.
 //  Addresses https://jira.opendaylight.org/browse/MDSAL-833
 public interface YangLibrarySchemaSourceUrlProvider {
-
     /**
      * Provides yang schema source URL where it can be downloaded from.
      *
      * @param moduleSetName the module set name the requested resource belongs to
      * @param moduleName referenced module or submodule name
      * @param revision optional revision
-     *
-     * @return optional of URL to requested resource
+     * @return List of URLs to requested resource
      */
-    Optional<Uri> getSchemaSourceUrl(@NonNull String moduleSetName, @NonNull String moduleName,
+    @NonNull Set<Uri> getSchemaSourceUrl(@NonNull String moduleSetName, @NonNull String moduleName,
         @Nullable Revision revision);
 }
 
index 0436dca8f61a2266ca7794a3b67a9315a3635615..f75619386ee59bbb26720b0cb437f7e14545303b 100644 (file)
@@ -12,12 +12,16 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.MoreExecutors;
+import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
@@ -32,6 +36,7 @@ import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
 import org.osgi.service.metatype.annotations.AttributeDefinition;
 import org.osgi.service.metatype.annotations.Designate;
 import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@@ -48,45 +53,70 @@ import org.slf4j.LoggerFactory;
 public final class YangLibraryWriter implements AutoCloseable {
     @ObjectClassDefinition
     public @interface Configuration {
-        @AttributeDefinition(description = "Enables legacy content to be written")
-        boolean write$_$legacy() default false;
+        @AttributeDefinition(description = "Maintain RFC7895-compatible modules-state container. Defaults to true.")
+        boolean write$_$legacy() default true;
     }
 
     private static final Logger LOG = LoggerFactory.getLogger(YangLibraryWriter.class);
     private static final InstanceIdentifier<YangLibrary> YANG_LIBRARY_INSTANCE_IDENTIFIER =
         InstanceIdentifier.create(YangLibrary.class);
+    @Deprecated
     private static final InstanceIdentifier<ModulesState> MODULES_STATE_INSTANCE_IDENTIFIER =
         InstanceIdentifier.create(ModulesState.class);
 
-    private final AtomicLong idCounter = new AtomicLong(0L);
+    private final AtomicLong idCounter = new AtomicLong();
+    private final AtomicBoolean closed = new AtomicBoolean();
+    private final @NonNull YangLibrarySchemaSourceUrlProvider urlProvider;
     private final DataBroker dataBroker;
     private final boolean writeLegacy;
+    private final Registration reg;
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL)
-    volatile YangLibrarySchemaSourceUrlProvider schemaSourceUrlProvider;
+    public YangLibraryWriter(final DOMSchemaService schemaService, final DataBroker dataBroker,
+            final boolean writeLegacy, final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider) {
+        this.dataBroker = requireNonNull(dataBroker);
+        this.urlProvider = orEmptyProvider(urlProvider);
+        this.writeLegacy = writeLegacy;
+        reg = schemaService.registerSchemaContextListener(this::onModelContextUpdated);
+        LOG.info("ietf-yang-library writer started with modules-state {}", writeLegacy ? "enabled" : "disabled");
+    }
 
-    @GuardedBy("this")
-    private Registration reg;
+    public YangLibraryWriter(final DOMSchemaService schemaService, final DataBroker dataBroker,
+            final boolean writeLegacy) {
+        this(schemaService, dataBroker, writeLegacy, null);
+    }
 
     @Inject
+    public YangLibraryWriter(final DOMSchemaService schemaService, final DataBroker dataBroker,
+            final Optional<YangLibrarySchemaSourceUrlProvider> urlProvider) {
+        this(schemaService, dataBroker, true, urlProvider.orElse(null));
+    }
+
     @Activate
-    public YangLibraryWriter(final @Reference DOMSchemaService schemaService,
-            final @Reference DataBroker dataBroker, final Configuration configuration) {
-        this.dataBroker = requireNonNull(dataBroker);
-        writeLegacy = configuration.write$_$legacy();
-        reg = schemaService.registerSchemaContextListener(this::onModelContextUpdated);
+    public YangLibraryWriter(final @Reference DOMSchemaService schemaService, @Reference final DataBroker dataBroker,
+            @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
+                final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider,
+            final Configuration configuration) {
+        this(schemaService, dataBroker, configuration.write$_$legacy(), urlProvider);
+    }
+
+    private static @NonNull YangLibrarySchemaSourceUrlProvider orEmptyProvider(
+            final @Nullable YangLibrarySchemaSourceUrlProvider urlProvider) {
+        return urlProvider != null ? urlProvider : emptyProvider();
+    }
+
+    private static @NonNull YangLibrarySchemaSourceUrlProvider emptyProvider() {
+        return (moduleSetName, moduleName, revision) -> Set.of();
     }
 
     @Deactivate
     @PreDestroy
     @Override
     public synchronized void close() throws InterruptedException, ExecutionException {
-        if (reg == null) {
+        if (!closed.compareAndSet(false, true)) {
             // Already shut down
             return;
         }
         reg.close();
-        reg = null;
 
         // FIXME: we should be using a transaction chain for this, but, really, this should be a dynamically-populated
         //        shard (i.e. no storage whatsoever)!
@@ -100,12 +130,12 @@ public final class YangLibraryWriter implements AutoCloseable {
         future.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo info) {
-                LOG.debug("YANG library cleared successfully");
+                LOG.info("ietf-yang-library writer stopped");
             }
 
             @Override
             public void onFailure(final Throwable throwable) {
-                LOG.warn("Unable to clear YANG library", throwable);
+                LOG.warn("ietf-yang-library writer stopped uncleanly", throwable);
             }
         }, MoreExecutors.directExecutor());
 
@@ -122,28 +152,31 @@ public final class YangLibraryWriter implements AutoCloseable {
     }
 
     private synchronized void updateYangLibrary(final EffectiveModelContext context) {
-        if (reg == null) {
+        if (closed.get()) {
             // Already shut down, do not do anything
+            LOG.debug("ietf-yang-library writer closed, skipping update");
             return;
         }
+
         final var nextId = String.valueOf(idCounter.incrementAndGet());
+        LOG.debug("ietf-yang-library writer starting update to {}", nextId);
         final var tx = dataBroker.newWriteOnlyTransaction();
         tx.put(LogicalDatastoreType.OPERATIONAL, YANG_LIBRARY_INSTANCE_IDENTIFIER,
-            YangLibraryContentBuilderUtil.buildYangLibrary(context, nextId, schemaSourceUrlProvider));
+            YangLibraryContentBuilderUtil.buildYangLibrary(context, nextId, urlProvider));
         if (writeLegacy) {
             tx.put(LogicalDatastoreType.OPERATIONAL, MODULES_STATE_INSTANCE_IDENTIFIER,
-                YangLibraryContentBuilderUtil.buildModuleState(context, nextId, schemaSourceUrlProvider));
+                YangLibraryContentBuilderUtil.buildModuleState(context, nextId, urlProvider));
         }
 
         tx.commit().addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
-                LOG.debug("Yang library updated successfully");
+                LOG.debug("ietf-yang-library updated successfully");
             }
 
             @Override
             public void onFailure(final Throwable throwable) {
-                LOG.warn("Failed to update yang library", throwable);
+                LOG.warn("Failed to update ietf-yang-library", throwable);
             }
         }, MoreExecutors.directExecutor());
     }
index e1b013439ea364525bbbba3ca3abc77864123fa9..5af36dfd193a9cb1c74f61e094d9740e43823887 100644 (file)
@@ -22,7 +22,6 @@ import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang
 import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.Module.ConformanceType.Import;
 import static org.opendaylight.yangtools.yang.test.util.YangParserTestUtils.parseYangResources;
 
-import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Stream;
 import org.junit.jupiter.api.BeforeEach;
@@ -40,6 +39,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.datastores.rev180214.Operational;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.LegacyRevisionUtils;
@@ -64,9 +64,10 @@ import org.opendaylight.yangtools.yang.binding.util.BindingMap;
 @ExtendWith(MockitoExtension.class)
 class YangLibraryWriterTest {
     private static final YangLibrarySchemaSourceUrlProvider URL_PROVIDER = (moduleSetName, moduleName, revision) ->
-            Optional.of(new Uri("/url/to/" + moduleName + (revision == null ? "" : "/" + revision)));
+            Set.of(new Uri("/url/to/" + moduleName + (revision == null ? "" : "/" + revision)));
     private static final InstanceIdentifier<YangLibrary> YANG_LIBRARY_PATH =
         InstanceIdentifier.create(YangLibrary.class);
+    @Deprecated
     private static final InstanceIdentifier<ModulesState> MODULES_STATE_PATH =
         InstanceIdentifier.create(ModulesState.class);
     private static final boolean WITH_LEGACY = true;
@@ -82,8 +83,6 @@ class YangLibraryWriterTest {
     private WriteTransaction writeTransaction;
     @Mock
     private Registration registration;
-    @Mock
-    private YangLibraryWriter.Configuration config;
     @Captor
     private ArgumentCaptor<YangLibrary> yangLibraryCaptor;
     @Captor
@@ -92,20 +91,13 @@ class YangLibraryWriterTest {
 
     @BeforeEach
     void beforeEach() {
-        doReturn(registration).when(schemaService).registerSchemaContextListener(any());
-    }
-
-    private YangLibraryWriter.Configuration setupConfig(final boolean writeLegacy) {
-        doReturn(writeLegacy).when(config).write$_$legacy();
-        return config;
     }
 
     @Test
     @DisplayName("No update bc context has no ietf-yang-library")
     void noUpdate() {
-        writer = new YangLibraryWriter(schemaService, dataBroker, setupConfig(NO_LEGACY));
-        writer.onModelContextUpdated(parseYangResources(YangLibraryWriterTest.class,
-            "/test-module.yang", "/test-submodule.yang"));
+        writer = new YangLibraryWriter(new FixedDOMSchemaService(parseYangResources(YangLibraryWriterTest.class,
+            "/test-module.yang", "/test-submodule.yang")), dataBroker, NO_LEGACY);
         verifyNoInteractions(dataBroker);
     }
 
@@ -116,13 +108,10 @@ class YangLibraryWriterTest {
         doReturn(writeTransaction).when(dataBroker).newWriteOnlyTransaction();
         doReturn(emptyFluentFuture()).when(writeTransaction).commit();
 
-        writer = new YangLibraryWriter(schemaService, dataBroker, setupConfig(writeLegacy));
-        if (withUrls) {
-            writer.schemaSourceUrlProvider = URL_PROVIDER;
-        }
-        writer.onModelContextUpdated(parseYangResources(YangLibraryWriterTest.class,
+        writer = new YangLibraryWriter(new FixedDOMSchemaService(parseYangResources(YangLibraryWriterTest.class,
             "/test-module.yang", "/test-submodule.yang", "/test-more.yang", "/ietf-yang-library@2019-01-04.yang",
-            "/ietf-datastores@2018-02-14.yang", "/ietf-yang-types.yang", "/ietf-inet-types.yang"));
+            "/ietf-datastores@2018-02-14.yang", "/ietf-yang-types.yang", "/ietf-inet-types.yang")), dataBroker,
+            writeLegacy, withUrls ? URL_PROVIDER : null);
 
         verify(writeTransaction).put(eq(OPERATIONAL), eq(YANG_LIBRARY_PATH), yangLibraryCaptor.capture());
         assertEquals(expectedData, yangLibraryCaptor.getValue());
@@ -148,8 +137,9 @@ class YangLibraryWriterTest {
     void clearOnClose(final boolean writeLegacy) throws Exception {
         doReturn(writeTransaction).when(dataBroker).newWriteOnlyTransaction();
         doReturn(emptyFluentFuture()).when(writeTransaction).commit();
+        doReturn(registration).when(schemaService).registerSchemaContextListener(any());
 
-        new YangLibraryWriter(schemaService, dataBroker, setupConfig(writeLegacy)).close();
+        new YangLibraryWriter(schemaService, dataBroker, writeLegacy).close();
         verify(writeTransaction).delete(OPERATIONAL, YANG_LIBRARY_PATH);
         if (writeLegacy) {
             verify(writeTransaction).delete(OPERATIONAL, MODULES_STATE_PATH);
@@ -217,6 +207,7 @@ class YangLibraryWriterTest {
             .build();
     }
 
+    @Deprecated
     private static ModulesState buildModulesState(final boolean withUrls) {
         return new ModulesStateBuilder()
             .setModule(BindingMap.of(
index d30a9d8c569d29a6c071db034625c6e49a155f0c..3dc94290f1cd6013c8ddf1e1c15a7de69fd69ad9 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.restconf.server.mdsal;
 
-import java.util.Optional;
+import java.util.Set;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.netconf.yanglib.writer.YangLibrarySchemaSourceUrlProvider;
@@ -40,15 +40,15 @@ public final class RestconfSchemaSourceUrlProvider implements YangLibrarySchemaS
     }
 
     @Override
-    public Optional<Uri> getSchemaSourceUrl(final String moduleSetName, final String moduleName,
+    public Set<Uri> getSchemaSourceUrl(final String moduleSetName, final String moduleName,
             final Revision revision) {
         if ("ODL_modules".equals(moduleSetName)) {
             final var sb = new StringBuilder(modulesPath).append(moduleName);
             if (revision != null) {
                 sb.append("?" + URLConstants.MODULES_REVISION_QUERY + "=").append(revision);
             }
-            return Optional.of(new Uri(sb.toString()));
+            return Set.of(new Uri(sb.toString()));
         }
-        return Optional.empty();
+        return Set.of();
     }
 }
index 51927aa69cc3e986a126f015356de4a5fd43ea55..fee66c8408279cf1ca7077f231c163e68946a1e2 100644 (file)
@@ -12,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.doReturn;
 
 import java.util.List;
-import java.util.Optional;
+import java.util.Set;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
@@ -50,7 +50,7 @@ class RestconfSchemaSourceUrlProviderTest {
     @MethodSource
     void getSchemaSourceUrl(final String moduleName, final Revision revision, final Uri expected) {
         final var result = urlProvider.getSchemaSourceUrl("ODL_modules", moduleName, revision);
-        assertEquals(Optional.of(expected), result);
+        assertEquals(Set.of(expected), result);
     }
 
     private static List<Arguments> getSchemaSourceUrl() {