Resolve Bug:807 - Keep ModuleFactory references shutdown purposes.
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / util / InterfacesHelper.java
index 6cd855450ddec8df16df9431701598fb9084ecd8..a6e9b1ba965b8532eb2e688742ca6ec66c5d5e10 100644 (file)
@@ -7,17 +7,18 @@
  */
 package org.opendaylight.controller.config.manager.impl.util;
 
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+
+import javax.management.JMX;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 
-import javax.management.JMX;
-
-import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
-import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
-import org.opendaylight.controller.config.spi.Module;
-
 public class InterfacesHelper {
 
     public static Set<Class<?>> getAllInterfaces(Class<?> clazz) {
@@ -32,16 +33,25 @@ public class InterfacesHelper {
             // get parent class
             clazz = clazz.getSuperclass();
         }
+        return getAllSuperInterfaces(toBeInspected);
+
+    }
+
+    private static Set<Class<?>> getAllSuperInterfaces(Set<Class<?>> ifcs) {
+        ifcs = new HashSet<>(ifcs); // create copy to modify
         // each interface can extend other interfaces
-        Set<Class<?>> inspected = new HashSet<>();
-        while (toBeInspected.size() > 0) {
-            Iterator<Class<?>> iterator = toBeInspected.iterator();
+        Set<Class<?>> result = new HashSet<>();
+        while (ifcs.size() > 0) {
+            Iterator<Class<?>> iterator = ifcs.iterator();
             Class<?> ifc = iterator.next();
             iterator.remove();
-            toBeInspected.addAll(Arrays.asList(ifc.getInterfaces()));
-            inspected.add(ifc);
+            if (ifc.isInterface() == false)  {
+                throw new IllegalArgumentException(ifc + " should be an interface");
+            }
+            ifcs.addAll(Arrays.asList(ifc.getInterfaces()));
+            result.add(ifc);
         }
-        return inspected;
+        return result;
     }
 
     /**
@@ -80,6 +90,18 @@ public class InterfacesHelper {
         return result;
     }
 
+    public static Set<Class<? extends AbstractServiceInterface>> getAllAbstractServiceClasses(Class<? extends Module> configBeanClass) {
+
+        Set<Class<? extends AbstractServiceInterface>> foundGeneratedSIClasses = new HashSet<>();
+        for (Class<?> clazz : getAllInterfaces(configBeanClass)) {
+            if (AbstractServiceInterface.class.isAssignableFrom(clazz) && AbstractServiceInterface.class.equals(clazz) == false) {
+                foundGeneratedSIClasses.add((Class<? extends AbstractServiceInterface>) clazz);
+            }
+        }
+        return getAllAbstractServiceInterfaceClasses(foundGeneratedSIClasses);
+    }
+
+
     /**
      * Get OSGi registration types under which config bean instance should be
      * registered. This is specified in
@@ -87,6 +109,7 @@ public class InterfacesHelper {
      */
     public static Set<Class<?>> getOsgiRegistrationTypes(
             Class<? extends Module> configBeanClass) {
+        // TODO test with service interface hierarchy
         Set<Class<?>> serviceInterfaces = getServiceInterfaces(configBeanClass);
         Set<Class<?>> result = new HashSet<>();
         for (Class<?> clazz : serviceInterfaces) {
@@ -97,4 +120,44 @@ public class InterfacesHelper {
         return result;
     }
 
+    public static Set<String> getQNames(Set<ServiceInterfaceAnnotation> siAnnotations) {
+        Set<String> qNames = new HashSet<>();
+        for (ServiceInterfaceAnnotation sia: siAnnotations) {
+            qNames.add(sia.value());
+        }
+        return Collections.unmodifiableSet(qNames);
+    }
+
+    public static Set<ServiceInterfaceAnnotation> getServiceInterfaceAnnotations(ModuleFactory factory) {
+        Set<Class<? extends AbstractServiceInterface>> implementedServiceIntefaces = Collections.unmodifiableSet(factory.getImplementedServiceIntefaces());
+        return getServiceInterfaceAnnotations(implementedServiceIntefaces);
+    }
+
+    private static Set<ServiceInterfaceAnnotation> getServiceInterfaceAnnotations(Set<Class<? extends AbstractServiceInterface>> implementedServiceIntefaces) {
+        Set<Class<? extends AbstractServiceInterface>> inspected = getAllAbstractServiceInterfaceClasses(implementedServiceIntefaces);
+        Set<ServiceInterfaceAnnotation> result = new HashSet<>();
+        // SIs can form hierarchies, inspect superclass until it does not extend AbstractSI
+        for (Class<?> clazz : inspected) {
+            ServiceInterfaceAnnotation annotation = clazz.getAnnotation(ServiceInterfaceAnnotation.class);
+            if (annotation != null) {
+                result.add(annotation);
+            }
+        }
+        return Collections.unmodifiableSet(result);
+    }
+
+    static Set<Class<? extends AbstractServiceInterface>> getAllAbstractServiceInterfaceClasses(
+            Set<Class<? extends AbstractServiceInterface>> directlyImplementedAbstractSIs) {
+
+        Set<Class<?>> allInterfaces = getAllSuperInterfaces((Set) directlyImplementedAbstractSIs);
+        Set<Class<? extends AbstractServiceInterface>> result = new HashSet<>();
+        for(Class<?> ifc: allInterfaces){
+            if (AbstractServiceInterface.class.isAssignableFrom(ifc) &&
+                    ifc.equals(AbstractServiceInterface.class) == false) {
+                result.add((Class<? extends AbstractServiceInterface>) ifc);
+            }
+
+        }
+        return result;
+    }
 }