Simplify YangLibProvider
[netconf.git] / netconf / yanglib / src / main / java / org / opendaylight / yanglib / impl / YangLibProvider.java
index d969f0b40fddfeaa1713daccc36104efd8967a7e..5235d7df51281a0a424020e446b274f0557c3d37 100644 (file)
@@ -7,39 +7,45 @@
  */
 package org.opendaylight.yanglib.impl;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.base.Predicate;
 import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.Nullable;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 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.rev160409.ModulesState;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.ModulesStateBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.OptionalRevision;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.RevisionIdentifier;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.module.list.Module;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.module.list.ModuleBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.module.list.ModuleKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.LegacyRevisionUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.ModulesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.ModulesStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.Module;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.ModuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.ModuleKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.YangIdentifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.yanglib.impl.rev141210.YanglibConfig;
+import org.opendaylight.yanglib.api.YangLibService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.Revision;
 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.fs.FilesystemSchemaSourceCache;
 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaListenerRegistration;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceListener;
-import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
+import org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,26 +56,26 @@ import org.slf4j.LoggerFactory;
  * along with source identifier to
  * ietf-netconf-yang-library/modules-state/module list.
  */
-public class YangLibProvider implements AutoCloseable, SchemaSourceListener {
+public class YangLibProvider implements AutoCloseable, SchemaSourceListener, YangLibService {
     private static final Logger LOG = LoggerFactory.getLogger(YangLibProvider.class);
 
-    private static final OptionalRevision NO_REVISION = new OptionalRevision("");
     private static final Predicate<PotentialSchemaSource<?>> YANG_SCHEMA_SOURCE =
         input -> YangTextSchemaSource.class.isAssignableFrom(input.getRepresentation());
 
     private final DataBroker dataBroker;
     private final YanglibConfig yanglibConfig;
+    private final SharedSchemaRepository schemaRepository;
     private SchemaListenerRegistration schemaListenerRegistration;
-    private SharedSchemaRepository schemaRepository;
 
-    public YangLibProvider(final YanglibConfig yanglibConfig, final DataBroker dataBroker) {
-        this.yanglibConfig = Preconditions.checkNotNull(yanglibConfig);
-        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+    public YangLibProvider(final YanglibConfig yanglibConfig, final DataBroker dataBroker,
+            final YangParserFactory parserFactory) {
+        this.yanglibConfig = requireNonNull(yanglibConfig);
+        this.dataBroker = requireNonNull(dataBroker);
+        schemaRepository = new SharedSchemaRepository("yang-library", parserFactory);
     }
 
     @Override
     public void close() {
-        YangLibServiceImpl.setSchemaRepository(null);
         if (schemaListenerRegistration != null) {
             schemaListenerRegistration.close();
         }
@@ -82,17 +88,14 @@ public class YangLibProvider implements AutoCloseable, SchemaSourceListener {
         }
 
         final File cacheFolderFile = new File(yanglibConfig.getCacheFolder());
-        Preconditions.checkArgument(cacheFolderFile.exists(), "cache-folder %s does not exist", cacheFolderFile);
-        Preconditions.checkArgument(cacheFolderFile.isDirectory(), "cache-folder %s is not a directory",
-                cacheFolderFile);
+        checkArgument(cacheFolderFile.exists(), "cache-folder %s does not exist", cacheFolderFile);
+        checkArgument(cacheFolderFile.isDirectory(), "cache-folder %s is not a directory", cacheFolderFile);
 
-        schemaRepository = new SharedSchemaRepository("yang-library");
         final FilesystemSchemaSourceCache<YangTextSchemaSource> cache =
                 new FilesystemSchemaSourceCache<>(schemaRepository, YangTextSchemaSource.class, cacheFolderFile);
         schemaRepository.registerSchemaSourceListener(cache);
 
         schemaListenerRegistration = schemaRepository.registerSchemaSourceListener(this);
-        YangLibServiceImpl.setSchemaRepository(schemaRepository);
 
         LOG.info("Started yang library with sources from {}", cacheFolderFile);
     }
@@ -104,20 +107,20 @@ public class YangLibProvider implements AutoCloseable, SchemaSourceListener {
 
     @Override
     public void schemaSourceRegistered(final Iterable<PotentialSchemaSource<?>> sources) {
-        final List<Module> newModules = new ArrayList<>();
+        final Map<ModuleKey, Module> newModules = new HashMap<>();
 
         for (PotentialSchemaSource<?> potentialYangSource : Iterables.filter(sources, YANG_SCHEMA_SOURCE)) {
-            final YangIdentifier moduleName = new YangIdentifier(potentialYangSource.getSourceIdentifier().getName());
-
-            final OptionalRevision moduleRevision = getRevisionForModule(potentialYangSource.getSourceIdentifier());
+            final YangIdentifier moduleName =
+                new YangIdentifier(potentialYangSource.getSourceIdentifier().name().getLocalName());
 
             final Module newModule = new ModuleBuilder()
                     .setName(moduleName)
-                    .setRevision(moduleRevision)
+                    .setRevision(LegacyRevisionUtils.fromYangCommon(
+                        Optional.ofNullable(potentialYangSource.getSourceIdentifier().revision())))
                     .setSchema(getUrlForModule(potentialYangSource.getSourceIdentifier()))
                     .build();
 
-            newModules.add(newModule);
+            newModules.put(newModule.key(), newModule);
         }
 
         if (newModules.isEmpty()) {
@@ -129,9 +132,9 @@ public class YangLibProvider implements AutoCloseable, SchemaSourceListener {
         tx.merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(ModulesState.class),
                 new ModulesStateBuilder().setModule(newModules).build());
 
-        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+        tx.commit().addCallback(new FutureCallback<CommitInfo>() {
             @Override
-            public void onSuccess(@Nullable final Void result) {
+            public void onSuccess(final CommitInfo result) {
                 LOG.debug("Modules state successfully populated with new modules");
             }
 
@@ -151,16 +154,13 @@ public class YangLibProvider implements AutoCloseable, SchemaSourceListener {
         }
 
         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
-        tx.delete(LogicalDatastoreType.OPERATIONAL,
-                InstanceIdentifier.create(ModulesState.class)
-                        .child(Module.class,
-                                new ModuleKey(
-                                        new YangIdentifier(source.getSourceIdentifier().getName()),
-                                        getRevisionForModule(source.getSourceIdentifier()))));
-
-        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+        tx.delete(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(ModulesState.class)
+            .child(Module.class, new ModuleKey(new YangIdentifier(source.getSourceIdentifier().name().getLocalName()),
+                LegacyRevisionUtils.fromYangCommon(Optional.ofNullable(source.getSourceIdentifier().revision())))));
+
+        tx.commit().addCallback(new FutureCallback<CommitInfo>() {
             @Override
-            public void onSuccess(@Nullable final Void result) {
+            public void onSuccess(final CommitInfo result) {
                 LOG.debug("Modules state successfully updated.");
             }
 
@@ -171,19 +171,35 @@ public class YangLibProvider implements AutoCloseable, SchemaSourceListener {
         }, MoreExecutors.directExecutor());
     }
 
+    @Override
+    public String getSchema(final String name, final String revision) {
+        LOG.debug("Attempting load for schema source {}:{}", name, revision);
+        final SourceIdentifier sourceId = new SourceIdentifier(name, revision.isEmpty() ? null : revision);
+
+        final ListenableFuture<YangTextSchemaSource> sourceFuture = schemaRepository.getSchemaSource(sourceId,
+            YangTextSchemaSource.class);
+
+        final YangTextSchemaSource source;
+        try {
+            source = sourceFuture.get();
+        } catch (InterruptedException | ExecutionException e) {
+            throw new IllegalStateException("Unable to get schema " + sourceId, e);
+        }
 
+        try {
+            return source.asCharSource(StandardCharsets.UTF_8).read();
+        } catch (IOException e) {
+            throw new IllegalStateException("Unable to read schema " + sourceId, e);
+        }
+    }
 
     private Uri getUrlForModule(final SourceIdentifier sourceIdentifier) {
         return new Uri("http://" + yanglibConfig.getBindingAddr() + ':' + yanglibConfig.getBindingPort()
-                + "/yanglib/schemas/" + sourceIdentifier.getName() + '/' + revString(sourceIdentifier));
+                + "/yanglib/schemas/" + sourceIdentifier.name().getLocalName() + '/' + revString(sourceIdentifier));
     }
 
     private static String revString(final SourceIdentifier id) {
-        return id.getRevision().map(Revision::toString).orElse("");
-    }
-
-    private static OptionalRevision getRevisionForModule(final SourceIdentifier sourceIdentifier) {
-        return sourceIdentifier.getRevision().map(rev -> new OptionalRevision(new RevisionIdentifier(rev.toString())))
-                .orElse(NO_REVISION);
+        final var rev = id.revision();
+        return rev != null ? rev.toString() : "";
     }
 }