Rehost BindingReflections.loadModuleInfos() 77/104877/4
authorOleksandr Panasiuk <oleksandr.panasiuk@pantheon.tech>
Tue, 14 Mar 2023 16:06:33 +0000 (18:06 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 19 Jun 2023 11:19:28 +0000 (13:19 +0200)
Use ServiceLoader to locate all module infos instead. This reduces the
proliferation of BindingReflections just a tiny bit.

JIRA: MDSAL-803
Change-Id: I5d76f6c8eddc1d689ebd8fcbe9cbf23350b465cf
Signed-off-by: Oleksandr Panasiuk <oleksandr.panasiuk@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/util/BindingTestContext.java
binding/mdsal-binding-runtime-spi/src/main/java/module-info.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/BindingRuntimeHelpers.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ModuleInfoSnapshotBuilder.java
binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java
binding/mdsal-binding-spec-util/src/test/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflectionsTest.java

index dd06d7e63ff56d9d1def584ac178c3c5f837ce67..c57b2f87466a98ad6c8ff61dcd2d62ae4d5270f7 100644 (file)
@@ -11,7 +11,6 @@ import static com.google.common.base.Preconditions.checkState;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Set;
@@ -29,7 +28,6 @@ import org.opendaylight.mdsal.binding.dom.adapter.BindingDOMNotificationServiceA
 import org.opendaylight.mdsal.binding.dom.adapter.BindingDOMRpcProviderServiceAdapter;
 import org.opendaylight.mdsal.binding.dom.adapter.BindingDOMRpcServiceAdapter;
 import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
-import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
@@ -184,8 +182,7 @@ public class BindingTestContext implements AutoCloseable {
     }
 
     public void loadYangSchemaFromClasspath() {
-        final ImmutableSet<YangModuleInfo> moduleInfos = BindingReflections.loadModuleInfos();
-        updateYangSchema(moduleInfos);
+        updateYangSchema(BindingRuntimeHelpers.loadModuleInfos());
     }
 
     public DOMRpcProviderService getDomRpcRegistry() {
index ea8a90c818298540bb2df1efe494f5faa8557538..73b77f818befd9c634648e61bcefc6b6ee4d3048 100644 (file)
@@ -18,6 +18,7 @@ module org.opendaylight.mdsal.binding.runtime.spi {
     requires org.opendaylight.mdsal.binding.spec.util;
     requires org.slf4j;
 
+    uses org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
     uses org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
     uses org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeGenerator;
 
index d724dd498f0e5699ef7d93f646df969fd2a3ac39..0e5a488318624a6e6b387313b02756d240038fee 100644 (file)
@@ -7,10 +7,13 @@
  */
 package org.opendaylight.mdsal.binding.runtime.spi;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import com.google.common.annotations.Beta;
-import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.ServiceLoader;
 import java.util.stream.Collectors;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
@@ -18,6 +21,7 @@ import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeGenerator;
 import org.opendaylight.mdsal.binding.runtime.api.DefaultBindingRuntimeContext;
 import org.opendaylight.mdsal.binding.runtime.api.ModuleInfoSnapshot;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
@@ -31,7 +35,7 @@ import org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
 @Beta
 public final class BindingRuntimeHelpers {
     private BindingRuntimeHelpers() {
-
+        // Hidden on purpose
     }
 
     public static @NonNull EffectiveModelContext createEffectiveModel(final Class<?>... classes) {
@@ -57,8 +61,7 @@ public final class BindingRuntimeHelpers {
     public static @NonNull BindingRuntimeContext createRuntimeContext() {
         final ModuleInfoSnapshot infos;
         try {
-            infos = prepareContext(ServiceLoaderState.ParserFactory.INSTANCE,
-                BindingReflections.loadModuleInfos());
+            infos = prepareContext(ServiceLoaderState.ParserFactory.INSTANCE, loadModuleInfos());
         } catch (YangParserException e) {
             throw new IllegalStateException("Failed to parse models", e);
         }
@@ -102,13 +105,29 @@ public final class BindingRuntimeHelpers {
         return new DefaultBindingRuntimeContext(generator.generateTypeMapping(infos.getEffectiveModelContext()), infos);
     }
 
-    @SuppressWarnings("checkstyle:IllegalCatch")
-    private static @NonNull YangModuleInfo extractYangModuleInfo(final Class<?> clazz) {
-        try {
-            return BindingReflections.getModuleInfo(clazz);
-        } catch (Exception e) {
-            Throwables.throwIfUnchecked(e);
-            throw new IllegalStateException("Failed to extract module info from " + clazz, e);
+    public static @NonNull YangModuleInfo extractYangModuleInfo(final Class<?> clazz) {
+        final var namespace = BindingReflections.findQName(clazz).getNamespace();
+        return loadModuleInfos().stream()
+            .filter(info -> namespace.equals(info.getName().getNamespace()))
+            .findFirst()
+            .orElseThrow(() -> new IllegalStateException("Failed to extract module info from " + clazz));
+    }
+
+    public static @NonNull ImmutableSet<YangModuleInfo> loadModuleInfos() {
+        final var moduleInfoSet = ImmutableSet.<YangModuleInfo>builder();
+        for (var bindingProvider : ServiceLoader.load(YangModelBindingProvider.class)) {
+            var moduleInfo = bindingProvider.getModuleInfo();
+            checkState(moduleInfo != null, "Module Info for %s is not available.", bindingProvider.getClass());
+            collectYangModuleInfo(bindingProvider.getModuleInfo(), moduleInfoSet);
+        }
+        return moduleInfoSet.build();
+    }
+
+    private static void collectYangModuleInfo(final YangModuleInfo moduleInfo,
+            final ImmutableSet.Builder<YangModuleInfo> moduleInfoSet) {
+        moduleInfoSet.add(moduleInfo);
+        for (var dependency : moduleInfo.getImportedModules()) {
+            collectYangModuleInfo(dependency, moduleInfoSet);
         }
     }
 
index 457397cd60d08d62aa898558ebc84858585d3126..89dd34d983e4649f4302077c0ca0c40ba824f0fc 100644 (file)
@@ -52,7 +52,7 @@ public final class ModuleInfoSnapshotBuilder {
     public @NonNull ModuleInfoSnapshotBuilder add(final Class<? extends BindingObject> clazz) {
         final YangModuleInfo moduleInfo;
         try {
-            moduleInfo = BindingReflections.getModuleInfo(clazz);
+            moduleInfo = BindingRuntimeHelpers.extractYangModuleInfo(clazz);
         } catch (Exception e) {
             Throwables.throwIfUnchecked(e);
             throw new IllegalStateException("Failed to introspect " + clazz, e);
index 34ce3e23bd37d079460e4cbcd24db12a9a90d915..847ca2d97b52c3cad91a23ddd3999f4a63ed7b8d 100644 (file)
@@ -231,16 +231,6 @@ public final class BindingReflections {
         return Notification.class.isAssignableFrom(potentialNotification);
     }
 
-    /**
-     * Loads {@link YangModuleInfo} infos available on current classloader. This method is shorthand for
-     * {@link #loadModuleInfos(ClassLoader)} with {@link Thread#getContextClassLoader()} for current thread.
-     *
-     * @return Set of {@link YangModuleInfo} available for current classloader.
-     */
-    public static @NonNull ImmutableSet<YangModuleInfo> loadModuleInfos() {
-        return loadModuleInfos(Thread.currentThread().getContextClassLoader());
-    }
-
     /**
      * Loads {@link YangModuleInfo} infos available on supplied classloader.
      *
index e04eee6b45bf38b61c5b9590ab3455727c1e4c08..6d4e55635daa938b09d6bdde2d0ffd8dbf260f6a 100644 (file)
@@ -12,7 +12,6 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Collections;
 import java.util.List;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
@@ -27,8 +26,6 @@ public class BindingReflectionsTest {
     public void testBindingWithDummyObject() throws Exception {
         assertEquals("ModuleInfoClassName should be equal to string", "test.$YangModuleInfoImpl",
                 BindingReflections.getModuleInfoClassName("test"));
-        assertEquals("Module info should be empty Set", Collections.emptySet(),
-                BindingReflections.loadModuleInfos());
         assertFalse("Should not be RpcType", BindingReflections.isRpcType(DataObject.class));
         assertTrue("Should be BindingClass", BindingReflections.isBindingClass(DataObject.class));
         assertFalse("Should not be Notification", BindingReflections.isNotification(DataObject.class));