Merge "Resolve Bug:853 - remove groovy from config code generator."
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / ServiceReferenceRegistryImpl.java
index 0faa32b7dc4e181962802d8d5e1345472d8378d9..ceea99415471d1ecd48a0d2cd17f469174aa792a 100644 (file)
@@ -7,6 +7,17 @@
  */
 package org.opendaylight.controller.config.manager.impl;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.LookupRegistry;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
@@ -26,17 +37,7 @@ import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, SearchableServiceReferenceWritableRegistry {
     private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class);
 
     private final Map<String, ModuleFactory> factories;
@@ -46,8 +47,11 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
     private final ServiceReferenceRegistrator serviceReferenceRegistrator;
     // helper method for getting QName of SI from namespace + local name
     private final Map<String /* namespace */, Map<String /* local name */, ServiceInterfaceAnnotation>> namespacesToAnnotations;
+    private final Map<String /* service qName */, ServiceInterfaceAnnotation> serviceQNamesToAnnotations;
     // all Service Interface qNames for sanity checking
     private final Set<String /* qName */> allQNames;
+    Map<ModuleIdentifier, Map<String /* service ref name */, ServiceInterfaceAnnotation >> modulesToServiceRef = new HashMap<>();
+
 
     // actual reference database
     private final Map<ServiceReference, ModuleIdentifier> refNames = new HashMap<>();
@@ -124,7 +128,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
     /**
      * Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data.
      */
-    public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
+    public static SearchableServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
                                                     ConfigTransactionLookupRegistry txLookupRegistry,
                                                     Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
 
@@ -195,46 +199,55 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
 
         this.serviceReferenceRegistrator = serviceReferenceRegistratorFactory.create();
 
-        Map<String, Set<String /* QName */>> factoryNamesToQNames = new HashMap<>();
+        Map<String, Set<String /* QName */>> modifiableFactoryNamesToQNames = new HashMap<>();
         Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
         Set<String /* qName */> allQNames = new HashSet<>();
+
+
         for (Entry<String, ModuleFactory> entry : factories.entrySet()) {
             if (entry.getKey().equals(entry.getValue().getImplementationName()) == false) {
                 logger.error("Possible error in code: Mismatch between supplied and actual name of {}", entry);
                 throw new IllegalArgumentException("Possible error in code: Mismatch between supplied and actual name of " + entry);
             }
             Set<ServiceInterfaceAnnotation> siAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(entry.getValue());
-            Set<String> qNames = new HashSet<>();
-            for (ServiceInterfaceAnnotation sia: siAnnotations) {
-                qNames.add(sia.value());
-            }
+            Set<String> qNames = InterfacesHelper.getQNames(siAnnotations);
             allAnnotations.addAll(siAnnotations);
             allQNames.addAll(qNames);
-            factoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
+            modifiableFactoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
         }
-        this.factoryNamesToQNames = Collections.unmodifiableMap(factoryNamesToQNames);
+        this.factoryNamesToQNames = Collections.unmodifiableMap(modifiableFactoryNamesToQNames);
         this.allQNames = Collections.unmodifiableSet(allQNames);
         // fill namespacesToAnnotations
-        Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> namespacesToAnnotations =
+        Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> modifiableNamespacesToAnnotations =
                 new HashMap<>();
+        Map<String /* service qName*/, ServiceInterfaceAnnotation> modifiableServiceQNamesToAnnotations = new HashMap<>();
         for (ServiceInterfaceAnnotation sia : allAnnotations) {
-            Map<String, ServiceInterfaceAnnotation> ofNamespace = namespacesToAnnotations.get(sia.namespace());
+            Map<String, ServiceInterfaceAnnotation> ofNamespace = modifiableNamespacesToAnnotations.get(sia.namespace());
             if (ofNamespace == null) {
                 ofNamespace = new HashMap<>();
-                namespacesToAnnotations.put(sia.namespace(), ofNamespace);
+                modifiableNamespacesToAnnotations.put(sia.namespace(), ofNamespace);
             }
             if (ofNamespace.containsKey(sia.localName())) {
                 logger.error("Cannot construct namespacesToAnnotations map, conflict between local names in {}, offending local name: {}, map so far {}",
-                        sia.namespace(), sia.localName(), namespacesToAnnotations);
+                        sia.namespace(), sia.localName(), modifiableNamespacesToAnnotations);
                 throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName());
             }
             ofNamespace.put(sia.localName(), sia);
+            modifiableServiceQNamesToAnnotations.put(sia.value(), sia);
         }
-        this.namespacesToAnnotations = Collections.unmodifiableMap(namespacesToAnnotations);
-        // copy refNames
+        this.namespacesToAnnotations = Collections.unmodifiableMap(modifiableNamespacesToAnnotations);
+        this.serviceQNamesToAnnotations = Collections.unmodifiableMap(modifiableServiceQNamesToAnnotations);
         logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
     }
 
+    @Override
+    public Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier) {
+        Map<String, ServiceInterfaceAnnotation> result = modulesToServiceRef.get(moduleIdentifier);
+        if (result == null) {
+            return Collections.emptyMap();
+        }
+        return Collections.unmodifiableMap(result);
+    }
 
     @Override
     public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
@@ -271,7 +284,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
     public synchronized Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
         Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> result = new HashMap<>();
         for (Entry<ServiceReference, ModuleIdentifier> entry: refNames.entrySet()) {
-            String qName = entry.getKey().getServiceInterfaceName();
+            String qName = entry.getKey().getServiceInterfaceQName();
             Map<String /* refName */, ObjectName> innerMap = result.get(qName);
             if (innerMap == null) {
                 innerMap = new HashMap<>();
@@ -379,9 +392,9 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
             throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + moduleIdentifier.getFactoryName());
         }
         // supplied serviceInterfaceName must exist in this collection
-        if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
-            logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
-            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName() + " within factory " + moduleIdentifier.getFactoryName());
+        if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceQName()) == false) {
+            logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceQName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName() + " within factory " + moduleIdentifier.getFactoryName());
         }
 
 
@@ -404,6 +417,15 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
         }
         // save to refNames
         refNames.put(serviceReference, moduleIdentifier);
+        Map<String, ServiceInterfaceAnnotation> refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier);
+        if (refNamesToAnnotations == null){
+            refNamesToAnnotations = new HashMap<>();
+            modulesToServiceRef.put(moduleIdentifier, refNamesToAnnotations);
+        }
+
+        ServiceInterfaceAnnotation annotation = serviceQNamesToAnnotations.get(serviceReference.getServiceInterfaceQName());
+        checkNotNull(annotation, "Possible error in code, cannot find annotation for " + serviceReference);
+        refNamesToAnnotations.put(serviceReference.getRefName(), annotation);
         return result;
     }
 
@@ -430,9 +452,9 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
     private ObjectName getServiceON(ServiceReference serviceReference) {
         if (writable) {
             return ObjectNameUtil.createTransactionServiceON(serviceReferenceRegistrator.getNullableTransactionName(),
-                    serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+                    serviceReference.getServiceInterfaceQName(), serviceReference.getRefName());
         } else {
-            return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+            return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceQName(), serviceReference.getRefName());
         }
     }
 
@@ -446,13 +468,13 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
         logger.debug("Removing service reference {} from {}", serviceReference, this);
         assertWritable();
         // is the qName known?
-        if (allQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
-            logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceName(), allQNames);
-            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName());
+        if (allQNames.contains(serviceReference.getServiceInterfaceQName()) == false) {
+            logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceQName(), allQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName());
         }
         ModuleIdentifier removed = refNames.remove(serviceReference);
         if (removed == null){
-            throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceName());
+            throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceQName());
         }
         Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> entry = mBeans.remove(serviceReference);
         if (entry == null) {
@@ -475,21 +497,28 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
 
     @Override
     public synchronized boolean removeServiceReferences(ObjectName moduleObjectName) throws InstanceNotFoundException {
+        lookupRegistry.checkConfigBeanExists(moduleObjectName);
+        String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
+        // check that service interface name exist
+        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
+        return removeServiceReferences(moduleObjectName, serviceInterfaceQNames);
+    }
+
+
+    private boolean removeServiceReferences(ObjectName moduleObjectName, Set<String> qNames) throws InstanceNotFoundException {
+        ObjectNameUtil.checkType(moduleObjectName, ObjectNameUtil.TYPE_MODULE);
         assertWritable();
-        Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName);
+        Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName, qNames);
         for (ServiceReference sr : serviceReferencesLinkingTo) {
             removeServiceReference(sr);
         }
         return serviceReferencesLinkingTo.isEmpty() == false;
     }
 
-    private synchronized Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName)  throws InstanceNotFoundException {
-        lookupRegistry.checkConfigBeanExists(moduleObjectName);
+    private Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName, Set<String> serviceInterfaceQNames) {
         String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
-        // check that service interface name exist
-        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
         if (serviceInterfaceQNames == null) {
-            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
+            logger.warn("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
             throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
         }
         String instanceName = ObjectNameUtil.getInstanceName(moduleObjectName);
@@ -503,7 +532,6 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
         return result;
     }
 
-
     @Override
     public String toString() {
         return "ServiceReferenceRegistryImpl{" +