Add binding adapter components for data services
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / osgi / AdaptingTracker.java
index 5047134f689cd33fa141982dda3769e8f413f0a9..2413ca9e832ee0d4f9cfa4e53b3ee33b64275304 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -7,12 +7,17 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter.osgi;
 
+import static java.util.Objects.requireNonNull;
+
 import java.util.function.Function;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.BindingService;
 import org.opendaylight.mdsal.dom.api.DOMService;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -24,31 +29,73 @@ import org.slf4j.LoggerFactory;
  * @author Robert Varga
  */
 final class AdaptingTracker<D extends DOMService, B extends BindingService>
-        extends AbstractAdaptingTracker<D, B, ServiceRegistration<B>> {
+        extends ServiceTracker<D, AdaptingTracker.ComponentHolder<B>> {
+    static final class ComponentHolder<B extends BindingService> {
+        final B binding;
+        ComponentInstance component;
+
+        ComponentHolder(final B binding, final ComponentInstance component) {
+            this.binding = requireNonNull(binding);
+            this.component = requireNonNull(component);
+        }
+    }
+
     private static final Logger LOG = LoggerFactory.getLogger(AdaptingTracker.class);
 
+    private final Function<D, B> bindingFactory;
+    private final @NonNull Class<B> bindingClass;
+    private final ComponentFactory componentFactory;
+
     AdaptingTracker(final BundleContext ctx, final Class<D> domClass, final Class<B> bindingClass,
-            final Function<D, B> bindingFactory) {
-        super(ctx, domClass, bindingClass, bindingFactory);
+            final Function<D, B> bindingFactory, final ComponentFactory componentFactory) {
+        super(ctx, domClass, null);
+        this.bindingClass = requireNonNull(bindingClass);
+        this.bindingFactory = requireNonNull(bindingFactory);
+        this.componentFactory = requireNonNull(componentFactory);
     }
 
     @Override
-    ServiceRegistration<B> addingService(final ServiceReference<D> reference, final D dom, final B binding) {
-        final Dict props = Dict.fromReference(reference);
-        final ServiceRegistration<B> reg = context.registerService(bindingClass, binding, props);
-        LOG.debug("Registered {} adapter {} of {} with {} as {}", bindingClass.getName(), binding, dom, props, reg);
-        return reg;
+    public void open(final boolean trackAllServices) {
+        LOG.debug("Starting tracker for {}", bindingClass.getName());
+        super.open(trackAllServices);
+        LOG.debug("Tracker for {} started", bindingClass.getName());
+    }
+
+    @Override
+    public ComponentHolder<B> addingService(final ServiceReference<D> reference) {
+        if (reference == null) {
+            LOG.debug("Null reference for {}, ignoring it", bindingClass.getName());
+            return null;
+        }
+        if (reference.getProperty(ServiceProperties.IGNORE_PROP) != null) {
+            LOG.debug("Ignoring reference {} due to {}", reference, ServiceProperties.IGNORE_PROP);
+            return null;
+        }
+
+        final D dom = context.getService(reference);
+        if (dom == null) {
+            LOG.debug("Could not get {} service from {}, ignoring it", bindingClass.getName(), reference);
+            return null;
+        }
+
+        final B binding = bindingFactory.apply(dom);
+        return new ComponentHolder<>(binding, componentFactory.newInstance(Dict.fromReference(reference, binding)));
     }
 
     @Override
-    void removedService(final ServiceRegistration<B> service) {
-        service.unregister();
+    public void modifiedService(final ServiceReference<D> reference, final ComponentHolder<B> service) {
+        if (service != null && reference != null) {
+            service.component.dispose();
+            service.component = componentFactory.newInstance(Dict.fromReference(reference, service.binding));
+        }
     }
 
     @Override
-    void updatedService(final ServiceReference<D> reference, final ServiceRegistration<B> service) {
-        final Dict newProps = Dict.fromReference(reference);
-        LOG.debug("Updating service {} with properties {}", service, newProps);
-        service.setProperties(newProps);
+    public void removedService(final ServiceReference<D> reference, final ComponentHolder<B> service) {
+        if (service != null) {
+            context.ungetService(reference);
+            service.component.dispose();
+            LOG.debug("Unregistered service {}", service);
+        }
     }
 }