Refactor OSGi ModuleInfoSnapshot/BindingRuntimeContext 04/88204/12
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 2 Mar 2020 07:18:31 +0000 (08:18 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 16 Mar 2020 12:25:44 +0000 (13:25 +0100)
All components acting on EffectiveModel should end up reacting
to new generation by publishing components based on it before
tearing down the previous instance.

Refactor lifecycle by introducing this into both mdsal-dom-schema-osgi
and mdsal-binding-runtime-osgi -- providing the infrastructure for
mdsal-binding-dom-codec doing the same.

This leads to mdsal-binding-dom-codec-osgi to provide atomic updates
of BindingDOMCodecServices (and its constituent services), hence we
no longer want binding-dom-adapter to publish
BindingNormalizedNodeSerializer from its internal service.

JIRA: MDSAL-525
Change-Id: Ia6757b3db8068d585638bd8e2d3d17aaadb08955
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
25 files changed:
artifacts/pom.xml
binding/mdsal-binding-dom-adapter/src/main/resources/org/opendaylight/blueprint/binding-adapter.xml
binding/mdsal-binding-dom-codec-osgi/pom.xml [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/OSGiBindingDOMCodecServices.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/GlobalBindingDOMCodecServices.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OSGiBindingDOMCodec.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OSGiBindingDOMCodecServicesImpl.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-spi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/spi/BindingDOMCodecFactory.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-spi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/spi/ForwardingBindingDOMCodecServices.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DefaultBindingDOMCodecFactory.java [new file with mode: 0644]
binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/OSGiBindingRuntimeContext.java [new file with mode: 0644]
binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/BindingRuntimeContextImpl.java [deleted file]
binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/GlobalBindingRuntimeContext.java [new file with mode: 0644]
binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/OSGiBindingRuntime.java [new file with mode: 0644]
binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/OSGiBindingRuntimeContextImpl.java [new file with mode: 0644]
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/binding/runtime/spi/ForwardingBindingRuntimeContext.java [new file with mode: 0644]
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/binding/runtime/spi/ForwardingModuleInfoSnapshot.java [new file with mode: 0644]
binding/pom.xml
dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/ModelGenerationAware.java [new file with mode: 0644]
dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/OSGiModuleInfoSnapshot.java
dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/impl/OSGiDOMSchemaService.java
dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/impl/OSGiModelRuntime.java
dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/impl/OSGiModuleInfoSnapshotImpl.java [moved from dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/impl/OSGiEffectiveModelImpl.java with 63% similarity]
dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/impl/RegularYangModuleInfoRegistry.java
features/odl-mdsal-binding-runtime/pom.xml

index 59ff6c91cba7cf3da383af80d4032242a579a936..cb5bd0f3a604e8766220ba1b2265a16a345f18ef 100644 (file)
                 <artifactId>mdsal-binding-dom-codec</artifactId>
                 <version>6.0.0-SNAPSHOT</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.mdsal</groupId>
+                <artifactId>mdsal-binding-dom-codec-osgi</artifactId>
+                <version>6.0.0-SNAPSHOT</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.mdsal</groupId>
                 <artifactId>mdsal-binding-runtime-api</artifactId>
index b6a0d46fb6924d1ddaeb597dd3de478c2ecc0659..5f2a73bef66d01684b10a509046322c0444aed16 100644 (file)
     <argument ref="schemaService"/>
   </bean>
 
-  <service ref="mappingCodec" odl:type="default">
-    <interfaces>
-      <value>org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer</value>
-    </interfaces>
-  </service>
-
   <!-- Adapter factory based on the codec -->
   <bean id="adapterFactory" class="org.opendaylight.mdsal.binding.dom.adapter.BindingAdapterFactory">
     <argument ref="mappingCodec"/>
diff --git a/binding/mdsal-binding-dom-codec-osgi/pom.xml b/binding/mdsal-binding-dom-codec-osgi/pom.xml
new file mode 100644 (file)
index 0000000..bc02401
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.mdsal</groupId>
+        <artifactId>dom-parent</artifactId>
+        <version>6.0.0-SNAPSHOT</version>
+        <relativePath>../../dom/dom-parent</relativePath>
+    </parent>
+
+    <artifactId>mdsal-binding-dom-codec-osgi</artifactId>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding-dom-codec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding-runtime-osgi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>mockito-configuration</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding-test-model</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding-generator-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <Automatic-Module-Name>org.opendaylight.mdsal.binding.dom.codec.osgi</Automatic-Module-Name>
+                    <instructions>
+                        <!-- Karaf cannot handle Factory Component requirements, see https://issues.apache.org/jira/browse/KARAF-6625 -->
+                        <_dsannotations-options>norequirements</_dsannotations-options>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/OSGiBindingDOMCodecServices.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/OSGiBindingDOMCodecServices.java
new file mode 100644 (file)
index 0000000..5bbdcdf
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.osgi;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
+import org.opendaylight.mdsal.dom.schema.osgi.ModelGenerationAware;
+
+@Beta
+public interface OSGiBindingDOMCodecServices extends ModelGenerationAware<BindingDOMCodecServices> {
+
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/GlobalBindingDOMCodecServices.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/GlobalBindingDOMCodecServices.java
new file mode 100644 (file)
index 0000000..928d933
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.osgi.impl;
+
+import static com.google.common.base.Verify.verifyNotNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.primitives.UnsignedLong;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingIdentityCodec;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingLazyContainerNode;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeWriterFactory;
+import org.opendaylight.mdsal.binding.dom.codec.osgi.OSGiBindingDOMCodecServices;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
+import org.opendaylight.mdsal.binding.dom.codec.spi.ForwardingBindingDOMCodecServices;
+import org.opendaylight.mdsal.binding.dom.codec.spi.LazyActionInputContainerNode;
+import org.opendaylight.mdsal.binding.dom.codec.spi.LazyActionOutputContainerNode;
+import org.opendaylight.yangtools.yang.binding.Action;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A global {@link BindingDOMCodecServices}. It is injected with latest {@link OSGiBindingDOMCodecServices} generation.
+ */
+@Beta
+@Component(immediate = true,
+           service = {
+                    BindingDOMCodecServices.class,
+                    BindingNormalizedNodeWriterFactory.class,
+                    BindingNormalizedNodeSerializer.class,
+                    BindingCodecTree.class
+           })
+public final class GlobalBindingDOMCodecServices extends ForwardingBindingDOMCodecServices {
+    private static final Logger LOG = LoggerFactory.getLogger(GlobalBindingDOMCodecServices.class);
+
+    @Reference(updated = "update")
+    volatile OSGiBindingDOMCodecServices osgi = null;
+
+    private BindingDOMCodecServices delegate;
+    private UnsignedLong generation;
+
+    @Override
+    public BindingLazyContainerNode<RpcInput> toLazyNormalizedNodeActionInput(
+            final Class<? extends Action<?, ?, ?>> action, final NodeIdentifier identifier, final RpcInput input) {
+        return new LazyActionInputContainerNode(identifier, input, this, action);
+    }
+
+    @Override
+    public BindingLazyContainerNode<RpcOutput> toLazyNormalizedNodeActionOutput(
+            final Class<? extends Action<?, ?, ?>> action, final NodeIdentifier identifier, final RpcOutput output) {
+        return new LazyActionOutputContainerNode(identifier, output, this, action);
+    }
+
+    @Override
+    public <T extends DataObject> BindingDataObjectCodecTreeNode<T> getSubtreeCodec(final InstanceIdentifier<T> path) {
+        return delegate.getSubtreeCodec(path);
+    }
+
+    @Override
+    public BindingCodecTreeNode getSubtreeCodec(final YangInstanceIdentifier path) {
+        return delegate.getSubtreeCodec(path);
+    }
+
+    @Override
+    public BindingCodecTreeNode getSubtreeCodec(final Absolute path) {
+        return delegate.getSubtreeCodec(path);
+    }
+
+    @Override
+    public BindingIdentityCodec getIdentityCodec() {
+        return delegate.getIdentityCodec();
+    }
+
+    @Override
+    public BindingInstanceIdentifierCodec getInstanceIdentifierCodec() {
+        return delegate.getInstanceIdentifierCodec();
+    }
+
+    @Override
+    protected BindingDOMCodecServices delegate() {
+        return verifyNotNull(delegate);
+    }
+
+    void update() {
+        updateDelegate();
+        LOG.info("Global Binding/DOM Codec updated to generation {}", generation);
+    }
+
+    @Activate
+    void activate() {
+        updateDelegate();
+        LOG.info("Global Binding/DOM Codec activated with generation {}", generation);
+    }
+
+    @Deactivate
+    void deactivate() {
+        delegate = null;
+        LOG.info("Global Binding/DOM Codec deactivated");
+    }
+
+    private void updateDelegate() {
+        generation = osgi.getGeneration();
+        delegate = osgi.getService();
+    }
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OSGiBindingDOMCodec.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OSGiBindingDOMCodec.java
new file mode 100644 (file)
index 0000000..53774d1
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.osgi.impl;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecFactory;
+import org.opendaylight.mdsal.binding.runtime.osgi.OSGiBindingRuntimeContext;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(immediate = true)
+public final class OSGiBindingDOMCodec {
+    // TODO: can we get rid of this complexity?
+    private abstract static class AbstractInstances {
+
+        abstract void add(OSGiBindingRuntimeContext runtimeContext);
+
+        abstract void remove(OSGiBindingRuntimeContext runtimeContext);
+
+        abstract @NonNull AbstractInstances toActive(BindingDOMCodecFactory codecFactory, ComponentFactory factory);
+
+        abstract @NonNull AbstractInstances toInactive();
+    }
+
+    private static final class InactiveInstances extends AbstractInstances {
+        private final Set<OSGiBindingRuntimeContext> instances = Collections.newSetFromMap(new IdentityHashMap<>());
+
+        InactiveInstances() {
+
+        }
+
+        InactiveInstances(final Set<OSGiBindingRuntimeContext> keySet) {
+            instances.addAll(keySet);
+        }
+
+        @Override
+        void add(final OSGiBindingRuntimeContext runtimeContext) {
+            verify(instances.add(runtimeContext), "Duplicate instance %s?!", runtimeContext);
+        }
+
+        @Override
+        void remove(final OSGiBindingRuntimeContext runtimeContext) {
+            instances.remove(runtimeContext);
+        }
+
+        @Override
+        AbstractInstances toActive(final BindingDOMCodecFactory codecFactory, final ComponentFactory factory) {
+            final ActiveInstances active = new ActiveInstances(codecFactory, factory);
+            instances.stream()
+                .sorted(Comparator.comparing(OSGiBindingRuntimeContext::getGeneration).reversed())
+                .forEach(active::add);
+            return active;
+        }
+
+        @Override
+        AbstractInstances toInactive() {
+            throw new IllegalStateException("Attempted to deactivate inactive instances");
+        }
+    }
+
+    private static final class ActiveInstances extends AbstractInstances {
+        private final Map<OSGiBindingRuntimeContext, ComponentInstance> instances = new IdentityHashMap<>();
+        private final BindingDOMCodecFactory codecFactory;
+        private final ComponentFactory factory;
+
+        ActiveInstances(final BindingDOMCodecFactory codecFactory, final ComponentFactory factory) {
+            this.codecFactory = requireNonNull(codecFactory);
+            this.factory = requireNonNull(factory);
+        }
+
+        @Override
+        void add(final OSGiBindingRuntimeContext runtimeContext) {
+            final BindingRuntimeContext context = runtimeContext.getService();
+
+            instances.put(runtimeContext, factory.newInstance(OSGiBindingDOMCodecServicesImpl.props(
+                runtimeContext.getGeneration(), runtimeContext.getServiceRanking(),
+                codecFactory.createBindingDOMCodec(context))));
+        }
+
+        @Override
+        void remove(final OSGiBindingRuntimeContext runtimeContext) {
+            final ComponentInstance instance = instances.remove(runtimeContext);
+            if (instance != null) {
+                instance.dispose();
+            } else {
+                LOG.warn("Instance for generation {} not found", runtimeContext.getGeneration());
+            }
+        }
+
+        @Override
+        AbstractInstances toActive(final BindingDOMCodecFactory ignoreCodecFactory,
+                final ComponentFactory ignoreFactory) {
+            throw new IllegalStateException("Attempted to activate active instances");
+        }
+
+        @Override
+        AbstractInstances toInactive() {
+            instances.values().forEach(ComponentInstance::dispose);
+            return new InactiveInstances(instances.keySet());
+        }
+
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(OSGiBindingDOMCodec.class);
+
+    @Reference
+    BindingDOMCodecFactory codecFactory = null;
+
+    @Reference(target = "(component.factory=" + OSGiBindingDOMCodecServicesImpl.FACTORY_NAME + ")")
+    ComponentFactory contextFactory = null;
+
+    @GuardedBy("this")
+    private AbstractInstances instances = new InactiveInstances();
+
+    @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
+    synchronized void addModuleInfoSnapshot(final OSGiBindingRuntimeContext runtimeContext) {
+        instances.add(runtimeContext);
+    }
+
+    synchronized void removeModuleInfoSnapshot(final OSGiBindingRuntimeContext runtimeContext) {
+        instances.remove(runtimeContext);
+    }
+
+    @Activate
+    synchronized void activate() {
+        LOG.info("Binding/DOM Codec activating");
+        instances = instances.toActive(codecFactory, contextFactory);
+        LOG.info("Binding/DOM Codec activated");
+    }
+
+    @Deactivate
+    synchronized void deactivate() {
+        LOG.info("Binding/DOM Codec deactivating");
+        instances = instances.toInactive();
+        LOG.info("Binding/DOM Codec deactivated");
+    }
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OSGiBindingDOMCodecServicesImpl.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OSGiBindingDOMCodecServicesImpl.java
new file mode 100644 (file)
index 0000000..3ecca42
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.osgi.impl;
+
+import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedLong;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
+import org.gaul.modernizer_maven_annotations.SuppressModernizer;
+import org.opendaylight.mdsal.binding.dom.codec.osgi.OSGiBindingDOMCodecServices;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A Factory Component which implements {@link OSGiBindingDOMCodecServices}.
+ */
+@Beta
+@Component(factory = OSGiBindingDOMCodecServicesImpl.FACTORY_NAME, service = OSGiBindingDOMCodecServices.class)
+public final class OSGiBindingDOMCodecServicesImpl implements OSGiBindingDOMCodecServices {
+    // OSGi DS Component Factory name
+    static final String FACTORY_NAME =
+            "org.opendaylight.mdsal.binding.dom.codec.osgi.impl.OSGiBindingDOMCodecServicesImpl";
+
+    // Keys to for activation properties
+    @VisibleForTesting
+    static final String GENERATION = "org.opendaylight.mdsal.binding.dom.codec.osgi.impl.Generation";
+    @VisibleForTesting
+    static final String DELEGATE = "org.opendaylight.mdsal.binding.dom.codec.osgi.impl.BindingDOMCodecServices";
+
+    private static final Logger LOG = LoggerFactory.getLogger(OSGiBindingDOMCodecServicesImpl.class);
+
+    private BindingDOMCodecServices delegate;
+    private UnsignedLong generation;
+
+    @Override
+    public UnsignedLong getGeneration() {
+        return verifyNotNull(generation);
+    }
+
+    @Override
+    public BindingDOMCodecServices getService() {
+        return verifyNotNull(delegate);
+    }
+
+    @Activate
+    void activate(final Map<String, ?> properties) {
+        generation = (UnsignedLong) verifyNotNull(properties.get(GENERATION));
+        delegate = (BindingDOMCodecServices) verifyNotNull(properties.get(DELEGATE));
+        LOG.info("Binding/DOM Codec generation {} activated", generation);
+    }
+
+    @Deactivate
+    void deactivate() {
+        delegate = null;
+        LOG.info("Binding/DOM Codec generation {} deactivated", generation);
+    }
+
+    @SuppressModernizer
+    static Dictionary<String, ?> props(final @NonNull UnsignedLong generation, final @NonNull Integer ranking,
+            final BindingDOMCodecServices delegate) {
+        final Dictionary<String, Object> ret = new Hashtable<>(4);
+        ret.put(Constants.SERVICE_RANKING, ranking);
+        ret.put(GENERATION, generation);
+        ret.put(DELEGATE, requireNonNull(delegate));
+        return ret;
+    }
+}
diff --git a/binding/mdsal-binding-dom-codec-spi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/spi/BindingDOMCodecFactory.java b/binding/mdsal-binding-dom-codec-spi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/spi/BindingDOMCodecFactory.java
new file mode 100644 (file)
index 0000000..64e6842
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.spi;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
+
+@Beta
+@NonNullByDefault
+public interface BindingDOMCodecFactory {
+
+    BindingDOMCodecServices createBindingDOMCodec(BindingRuntimeContext context);
+}
diff --git a/binding/mdsal-binding-dom-codec-spi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/spi/ForwardingBindingDOMCodecServices.java b/binding/mdsal-binding-dom-codec-spi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/spi/ForwardingBindingDOMCodecServices.java
new file mode 100644 (file)
index 0000000..1fe1ccd
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.spi;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ForwardingObject;
+import java.time.Instant;
+import java.util.Map.Entry;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingLazyContainerNode;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.Action;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+@Beta
+public abstract class ForwardingBindingDOMCodecServices extends ForwardingObject implements BindingDOMCodecServices {
+    @Override
+    protected abstract BindingDOMCodecServices delegate();
+
+    @Override
+    public BindingLazyContainerNode<RpcInput> toLazyNormalizedNodeActionInput(
+            final Class<? extends Action<?, ?, ?>> action, final NodeIdentifier identifier, final RpcInput input) {
+        return delegate().toLazyNormalizedNodeActionInput(action, identifier, input);
+    }
+
+    @Override
+    public BindingLazyContainerNode<RpcOutput> toLazyNormalizedNodeActionOutput(
+            final Class<? extends Action<?, ?, ?>> action, final NodeIdentifier identifier, final RpcOutput output) {
+        return delegate().toLazyNormalizedNodeActionOutput(action, identifier, output);
+    }
+
+    @Override
+    public YangInstanceIdentifier toYangInstanceIdentifier(final InstanceIdentifier<?> binding) {
+        return delegate().toYangInstanceIdentifier(binding);
+    }
+
+    @Override
+    public <T extends DataObject> InstanceIdentifier<T> fromYangInstanceIdentifier(final YangInstanceIdentifier dom) {
+        return delegate().getInstanceIdentifierCodec().toBinding(dom);
+    }
+
+    @Override
+    public <T extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?,?>> toNormalizedNode(
+            final InstanceIdentifier<T> path, final T data) {
+        return delegate().toNormalizedNode(path, data);
+    }
+
+    @Override
+    public ContainerNode toNormalizedNodeNotification(final Notification data) {
+        return delegate().toNormalizedNodeNotification(data);
+    }
+
+    @Override
+    public ContainerNode toNormalizedNodeRpcData(final DataContainer data) {
+        return delegate().toNormalizedNodeRpcData(data);
+    }
+
+    @Override
+    public ContainerNode toNormalizedNodeActionInput(final Class<? extends Action<?, ?, ?>> action,
+            final RpcInput input) {
+        return delegate().toNormalizedNodeActionInput(action, input);
+    }
+
+    @Override
+    public ContainerNode toNormalizedNodeActionOutput(final Class<? extends Action<?, ?, ?>> action,
+            final RpcOutput output) {
+        return delegate().toNormalizedNodeActionOutput(action, output);
+    }
+
+    @Override
+    public Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(final YangInstanceIdentifier path,
+            final NormalizedNode<?, ?> data) {
+        return delegate().fromNormalizedNode(path, data);
+    }
+
+    @Override
+    public Notification fromNormalizedNodeNotification(final SchemaPath path, final ContainerNode data) {
+        return delegate().fromNormalizedNodeNotification(path, data);
+    }
+
+    @Override
+    public Notification fromNormalizedNodeNotification(final SchemaPath path, final ContainerNode data,
+            final Instant eventInstant) {
+        return delegate().fromNormalizedNodeNotification(path, data, eventInstant);
+    }
+
+    @Override
+    public DataObject fromNormalizedNodeRpcData(final SchemaPath path, final ContainerNode data) {
+        return delegate().fromNormalizedNodeRpcData(path, data);
+    }
+
+    @Override
+    public <T extends RpcInput> T fromNormalizedNodeActionInput(final Class<? extends Action<?, ?, ?>> action,
+            final ContainerNode input) {
+        return delegate().fromNormalizedNodeActionInput(action, input);
+    }
+
+    @Override
+    public <T extends RpcOutput> T fromNormalizedNodeActionOutput(final Class<? extends Action<?, ?, ?>> action,
+            final ContainerNode output) {
+        return delegate().fromNormalizedNodeActionOutput(action, output);
+    }
+
+    @Override
+    public Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriterAndIdentifier(
+            final InstanceIdentifier<?> path, final NormalizedNodeStreamWriter domWriter) {
+        return delegate().newWriterAndIdentifier(path, domWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newWriter(final InstanceIdentifier<?> path,
+            final NormalizedNodeStreamWriter domWriter) {
+        return delegate().newWriter(path, domWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
+            final NormalizedNodeStreamWriter streamWriter) {
+        return delegate().newNotificationWriter(notification, streamWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newActionInputWriter(final Class<? extends Action<?, ?, ?>> action,
+            final NormalizedNodeStreamWriter domWriter) {
+        return delegate().newActionInputWriter(action, domWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newActionOutputWriter(final Class<? extends Action<?, ?, ?>> action,
+            final NormalizedNodeStreamWriter domWriter) {
+        return delegate().newActionOutputWriter(action, domWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newRpcWriter(final Class<? extends DataContainer> rpcInputOrOutput,
+            final NormalizedNodeStreamWriter streamWriter) {
+        return delegate().newRpcWriter(rpcInputOrOutput,streamWriter);
+    }
+}
diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DefaultBindingDOMCodecFactory.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DefaultBindingDOMCodecFactory.java
new file mode 100644 (file)
index 0000000..fa7f08c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.impl;
+
+import com.google.common.annotations.Beta;
+import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.kohsuke.MetaInfServices;
+import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecFactory;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Beta
+@NonNullByDefault
+@MetaInfServices
+@Singleton
+@Component(immediate = true)
+public final class DefaultBindingDOMCodecFactory implements BindingDOMCodecFactory {
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultBindingDOMCodecFactory.class);
+
+    @Override
+    public BindingDOMCodecServices createBindingDOMCodec(final BindingRuntimeContext context) {
+        return new BindingCodecContext(context);
+    }
+
+    @Activate
+    @SuppressWarnings("static-method")
+    void activate() {
+        LOG.info("Binding/DOM Codec enabled");
+    }
+
+    @Deactivate
+    @SuppressWarnings("static-method")
+    void deactivate() {
+        LOG.info("Binding/DOM Codec disabled");
+    }
+}
diff --git a/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/OSGiBindingRuntimeContext.java b/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/OSGiBindingRuntimeContext.java
new file mode 100644 (file)
index 0000000..c5a15ec
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.osgi;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.dom.schema.osgi.ModelGenerationAware;
+
+@Beta
+public interface OSGiBindingRuntimeContext extends ModelGenerationAware<BindingRuntimeContext> {
+
+}
diff --git a/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/BindingRuntimeContextImpl.java b/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/BindingRuntimeContextImpl.java
deleted file mode 100644 (file)
index f177833..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.runtime.osgi.impl;
-
-import com.google.common.primitives.UnsignedLong;
-import org.opendaylight.binding.runtime.api.AbstractBindingRuntimeContext;
-import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
-import org.opendaylight.binding.runtime.api.BindingRuntimeGenerator;
-import org.opendaylight.binding.runtime.api.BindingRuntimeTypes;
-import org.opendaylight.binding.runtime.api.ClassLoadingStrategy;
-import org.opendaylight.binding.runtime.api.DefaultBindingRuntimeContext;
-import org.opendaylight.mdsal.dom.schema.osgi.OSGiModuleInfoSnapshot;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A Factory Component which implements {@link BindingRuntimeContext}.
- */
-@Component(service = BindingRuntimeContext.class, immediate = true)
-public final class BindingRuntimeContextImpl extends AbstractBindingRuntimeContext {
-    private static final Logger LOG = LoggerFactory.getLogger(BindingRuntimeContextImpl.class);
-
-    @Reference
-    OSGiModuleInfoSnapshot effectiveModel = null;
-    @Reference
-    BindingRuntimeGenerator generator = null;
-
-    private BindingRuntimeContext delegate;
-    private UnsignedLong generation;
-
-    @Override
-    public ClassLoadingStrategy getStrategy() {
-        return delegate.getStrategy();
-    }
-
-    @Override
-    public BindingRuntimeTypes getTypes() {
-        return delegate.getTypes();
-    }
-
-    @Activate
-    void activate() {
-        generation = effectiveModel.getGeneration();
-        delegate = DefaultBindingRuntimeContext.create(
-            generator.generateTypeMapping(effectiveModel.getEffectiveModelContext()), effectiveModel);
-
-        LOG.debug("BindingRuntimeContext generation {} activated", generation);
-    }
-
-    @Deactivate
-    void deactivate() {
-        delegate = null;
-        LOG.debug("BindingRuntimeContext generation {} deactivated", generation);
-    }
-}
diff --git a/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/GlobalBindingRuntimeContext.java b/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/GlobalBindingRuntimeContext.java
new file mode 100644 (file)
index 0000000..049c695
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.osgi.impl;
+
+import static com.google.common.base.Verify.verifyNotNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.primitives.UnsignedLong;
+import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.binding.runtime.spi.ForwardingBindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.osgi.OSGiBindingRuntimeContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A global {@link BindingRuntimeContext}. It is injected with latest {@link OSGiBindingRuntimeContext} generation.
+ */
+@Beta
+@Component(service = BindingRuntimeContext.class, immediate = true)
+public final class GlobalBindingRuntimeContext extends ForwardingBindingRuntimeContext {
+    private static final Logger LOG = LoggerFactory.getLogger(GlobalBindingRuntimeContext.class);
+
+    @Reference
+    OSGiBindingRuntimeContext osgi = null;
+
+    private BindingRuntimeContext delegate;
+    private UnsignedLong generation;
+
+    @Override
+    protected BindingRuntimeContext delegate() {
+        return verifyNotNull(delegate);
+    }
+
+    @Activate
+    void activate() {
+        generation = osgi.getGeneration();
+        delegate = osgi.getService();
+        LOG.info("Global BindingRuntimeContext generation {} activated", generation);
+    }
+
+    @Deactivate
+    void deactivate() {
+        delegate = null;
+        LOG.info("Global BindingRuntimeContext generation {} deactivated", generation);
+    }
+}
diff --git a/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/OSGiBindingRuntime.java b/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/OSGiBindingRuntime.java
new file mode 100644 (file)
index 0000000..1fc662d
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.osgi.impl;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.binding.runtime.api.BindingRuntimeGenerator;
+import org.opendaylight.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.binding.runtime.api.DefaultBindingRuntimeContext;
+import org.opendaylight.binding.runtime.api.ModuleInfoSnapshot;
+import org.opendaylight.mdsal.dom.schema.osgi.OSGiModuleInfoSnapshot;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Beta
+@Component(immediate = true)
+public final class OSGiBindingRuntime {
+    // TODO: can we get rid of this complexity?
+    private abstract static class AbstractInstances {
+
+        abstract void add(OSGiModuleInfoSnapshot snapshot);
+
+        abstract void remove(OSGiModuleInfoSnapshot snapshot);
+
+        abstract @NonNull AbstractInstances toActive(BindingRuntimeGenerator generator, ComponentFactory factory);
+
+        abstract @NonNull AbstractInstances toInactive();
+    }
+
+    private static final class InactiveInstances extends AbstractInstances {
+        private final Set<OSGiModuleInfoSnapshot> instances = Collections.newSetFromMap(new IdentityHashMap<>());
+
+        InactiveInstances() {
+
+        }
+
+        InactiveInstances(final Set<OSGiModuleInfoSnapshot> keySet) {
+            instances.addAll(keySet);
+        }
+
+        @Override
+        void add(final OSGiModuleInfoSnapshot snapshot) {
+            verify(instances.add(snapshot), "Duplicate instance %s?!", snapshot);
+        }
+
+        @Override
+        void remove(final OSGiModuleInfoSnapshot snapshot) {
+            instances.remove(snapshot);
+        }
+
+        @Override
+        AbstractInstances toActive(final BindingRuntimeGenerator generator, final ComponentFactory factory) {
+            final ActiveInstances active = new ActiveInstances(generator, factory);
+            instances.stream()
+                .sorted(Comparator.comparing(OSGiModuleInfoSnapshot::getGeneration).reversed())
+                .forEach(active::add);
+            return active;
+        }
+
+        @Override
+        AbstractInstances toInactive() {
+            throw new IllegalStateException("Attempted to deactivate inactive instances");
+        }
+    }
+
+    private static final class ActiveInstances extends AbstractInstances {
+        private final Map<OSGiModuleInfoSnapshot, ComponentInstance> instances = new IdentityHashMap<>();
+        private final BindingRuntimeGenerator generator;
+        private final ComponentFactory factory;
+
+        ActiveInstances(final BindingRuntimeGenerator generator, final ComponentFactory factory) {
+            this.generator = requireNonNull(generator);
+            this.factory = requireNonNull(factory);
+        }
+
+        @Override
+        void add(final OSGiModuleInfoSnapshot snapshot) {
+            final ModuleInfoSnapshot context = snapshot.getService();
+            final BindingRuntimeTypes types = generator.generateTypeMapping(context.getEffectiveModelContext());
+
+            instances.put(snapshot, factory.newInstance(OSGiBindingRuntimeContextImpl.props(
+                snapshot.getGeneration(), snapshot.getServiceRanking(),
+                DefaultBindingRuntimeContext.create(types, context))));
+        }
+
+        @Override
+        void remove(final OSGiModuleInfoSnapshot snapshot) {
+            final ComponentInstance instance = instances.remove(snapshot);
+            if (instance != null) {
+                instance.dispose();
+            } else {
+                LOG.warn("Instance for generation {} not found", snapshot.getGeneration());
+            }
+        }
+
+        @Override
+        AbstractInstances toActive(final BindingRuntimeGenerator ignoreGenerator,
+                final ComponentFactory ignoreFactory) {
+            throw new IllegalStateException("Attempted to activate active instances");
+        }
+
+        @Override
+        AbstractInstances toInactive() {
+            instances.values().forEach(ComponentInstance::dispose);
+            return new InactiveInstances(instances.keySet());
+        }
+
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(OSGiBindingRuntime.class);
+
+    @Reference
+    BindingRuntimeGenerator generator = null;
+
+    @Reference(target = "(component.factory=" + OSGiBindingRuntimeContextImpl.FACTORY_NAME + ")")
+    ComponentFactory contextFactory = null;
+
+    @GuardedBy("this")
+    private AbstractInstances instances = new InactiveInstances();
+
+    @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
+    synchronized void addModuleInfoSnapshot(final OSGiModuleInfoSnapshot snapshot) {
+        instances.add(snapshot);
+    }
+
+    synchronized void removeModuleInfoSnapshot(final OSGiModuleInfoSnapshot snapshot) {
+        instances.remove(snapshot);
+    }
+
+    @Activate
+    synchronized void activate() {
+        LOG.info("Binding Runtime activating");
+        instances = instances.toActive(generator, contextFactory);
+        LOG.info("Binding Runtime activated");
+    }
+
+    @Deactivate
+    synchronized void deactivate() {
+        LOG.info("Binding Runtime deactivating");
+        instances = instances.toInactive();
+        LOG.info("Binding Runtime deactivated");
+    }
+}
diff --git a/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/OSGiBindingRuntimeContextImpl.java b/binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/OSGiBindingRuntimeContextImpl.java
new file mode 100644 (file)
index 0000000..9fe1a84
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.osgi.impl;
+
+import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedLong;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
+import org.gaul.modernizer_maven_annotations.SuppressModernizer;
+import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.osgi.OSGiBindingRuntimeContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A Factory Component which implements {@link OSGiBindingRuntimeContext}.
+ */
+@Beta
+@Component(factory = OSGiBindingRuntimeContextImpl.FACTORY_NAME, service = OSGiBindingRuntimeContext.class)
+public final class OSGiBindingRuntimeContextImpl implements OSGiBindingRuntimeContext {
+    // OSGi DS Component Factory name
+    static final String FACTORY_NAME = "org.opendaylight.mdsal.binding.runtime.osgi.impl.OSGiBindingRuntimeContextImpl";
+
+    // Keys to for activation properties
+    @VisibleForTesting
+    static final String GENERATION = "org.opendaylight.mdsal.binding.runtime.osgi.impl.Generation";
+    @VisibleForTesting
+    static final String DELEGATE = "org.opendaylight.mdsal.binding.runtime.osgi.impl.BindingRuntimeContext";
+
+    private static final Logger LOG = LoggerFactory.getLogger(OSGiBindingRuntimeContextImpl.class);
+
+    private BindingRuntimeContext delegate;
+    private UnsignedLong generation;
+
+    @Override
+    public UnsignedLong getGeneration() {
+        return verifyNotNull(generation);
+    }
+
+    @Override
+    public BindingRuntimeContext getService() {
+        return verifyNotNull(delegate);
+    }
+
+    @Activate
+    void activate(final Map<String, ?> properties) {
+        generation = (UnsignedLong) verifyNotNull(properties.get(GENERATION));
+        delegate = (BindingRuntimeContext) verifyNotNull(properties.get(DELEGATE));
+        LOG.info("BindingRuntimeContext generation {} activated", generation);
+    }
+
+    @Deactivate
+    void deactivate() {
+        delegate = null;
+        LOG.info("BindingRuntimeContext generation {} deactivated", generation);
+    }
+
+    @SuppressModernizer
+    static Dictionary<String, ?> props(final @NonNull UnsignedLong generation, final @NonNull Integer ranking,
+            final BindingRuntimeContext delegate) {
+        final Dictionary<String, Object> ret = new Hashtable<>(4);
+        ret.put(Constants.SERVICE_RANKING, ranking);
+        ret.put(GENERATION, generation);
+        ret.put(DELEGATE, requireNonNull(delegate));
+        return ret;
+    }
+}
diff --git a/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/binding/runtime/spi/ForwardingBindingRuntimeContext.java b/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/binding/runtime/spi/ForwardingBindingRuntimeContext.java
new file mode 100644 (file)
index 0000000..6935214
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.binding.runtime.spi;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ForwardingObject;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.binding.runtime.api.ClassLoadingStrategy;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.Action;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+@Beta
+public abstract class ForwardingBindingRuntimeContext extends ForwardingObject implements BindingRuntimeContext {
+    @Override
+    protected abstract BindingRuntimeContext delegate();
+
+    @Override
+    public ClassLoadingStrategy getStrategy() {
+        return delegate().getStrategy();
+    }
+
+    @Override
+    public BindingRuntimeTypes getTypes() {
+        return delegate().getTypes();
+    }
+
+    @Override
+    public AugmentationSchemaNode getAugmentationDefinition(final Class<?> augClass) {
+        return delegate().getAugmentationDefinition(augClass);
+    }
+
+    @Override
+    public DataSchemaNode getSchemaDefinition(final Class<?> cls) {
+        return delegate().getSchemaDefinition(cls);
+    }
+
+    @Override
+    public ActionDefinition getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
+        return delegate().getActionDefinition(cls);
+    }
+
+    @Override
+    public Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
+            final DataNodeContainer target, final Class<? extends Augmentation<?>> aug) {
+        return delegate().getResolvedAugmentationSchema(target, aug);
+    }
+
+    @Override
+    public Optional<CaseSchemaNode> getCaseSchemaDefinition(final ChoiceSchemaNode schema, final Class<?> childClass) {
+        return delegate().getCaseSchemaDefinition(schema, childClass);
+    }
+
+    @Override
+    public Entry<GeneratedType, WithStatus> getTypeWithSchema(final Class<?> type) {
+        return delegate().getTypeWithSchema(type);
+    }
+
+    @Override
+    public Map<Type, Entry<Type, Type>> getChoiceCaseChildren(final DataNodeContainer schema) {
+        return delegate().getChoiceCaseChildren(schema);
+    }
+
+    @Override
+    public Set<Class<?>> getCases(final Class<?> choice) {
+        return delegate().getCases(choice);
+    }
+
+    @Override
+    public Class<?> getClassForSchema(final SchemaNode childSchema) {
+        return delegate().getClassForSchema(childSchema);
+    }
+
+    @Override
+    public ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(final DataNodeContainer container) {
+        return delegate().getAvailableAugmentationTypes(container);
+    }
+
+    @Override
+    public Class<?> getIdentityClass(final QName input) {
+        return delegate().getIdentityClass(input);
+    }
+}
diff --git a/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/binding/runtime/spi/ForwardingModuleInfoSnapshot.java b/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/binding/runtime/spi/ForwardingModuleInfoSnapshot.java
new file mode 100644 (file)
index 0000000..9abfb15
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.binding.runtime.spi;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ForwardingObject;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.binding.runtime.api.ModuleInfoSnapshot;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+
+@Beta
+public abstract class ForwardingModuleInfoSnapshot extends ForwardingObject implements ModuleInfoSnapshot {
+    @Override
+    protected abstract ModuleInfoSnapshot delegate();
+
+    @Override
+    public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
+        return delegate().loadClass(fullyQualifiedName);
+    }
+
+    @Override
+    public @NonNull EffectiveModelContext getEffectiveModelContext() {
+        return delegate().getEffectiveModelContext();
+    }
+
+    @Override
+    public ListenableFuture<? extends YangTextSchemaSource> getSource(final SourceIdentifier sourceIdentifier) {
+        return delegate().getSource(sourceIdentifier);
+    }
+}
index 58de728158a3e05ef249fe5032a4d830a9404169..0cde979d173590c4682f0bb7e51f89f493a4de66 100644 (file)
@@ -45,6 +45,7 @@
         <module>mdsal-binding-dom-codec</module>
         <module>mdsal-binding-dom-codec-api</module>
         <module>mdsal-binding-dom-codec-spi</module>
+        <module>mdsal-binding-dom-codec-osgi</module>
 
         <module>mdsal-binding-api</module>
         <module>mdsal-binding-spi</module>
diff --git a/dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/ModelGenerationAware.java b/dom/mdsal-dom-schema-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/osgi/ModelGenerationAware.java
new file mode 100644 (file)
index 0000000..872dd1d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.dom.schema.osgi;
+
+import com.google.common.annotations.Beta;
+import com.google.common.primitives.UnsignedLong;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.osgi.framework.Constants;
+
+/**
+ * Additional interface for exposing linear generation of the backing effective model. Implementations of this interface
+ * are expected to be effectively-immutable.
+ *
+ * @param <S> service type
+ */
+@Beta
+public interface ModelGenerationAware<S> extends Immutable {
+
+    @NonNull UnsignedLong getGeneration();
+
+    @NonNull S getService();
+
+    /**
+     * Get service ranking based on the generation. Higher generation results in a higher ranking.
+     *
+     * @return Ranging for use with {@link Constants#SERVICE_RANKING}
+     */
+    default @NonNull Integer getServiceRanking() {
+        return computeServiceRanking(getGeneration().longValue());
+    }
+
+    /**
+     * Calculate service ranking based on generation. Higher generation results in a higher ranking.
+     *
+     * @param generation generation number, treated as an unsigned long
+     * @return Ranging for use with {@link Constants#SERVICE_RANKING}
+     */
+    static @NonNull Integer computeServiceRanking(final long generation) {
+        return generation >= 0 && generation <= Integer.MAX_VALUE ? (int) generation : Integer.MAX_VALUE;
+    }
+}
index f68b197d554ed0b381a7f350f0471835c05c6244..d12a333818f409f490a9274b4d0cfa25094467bd 100644 (file)
@@ -8,15 +8,12 @@
 package org.opendaylight.mdsal.dom.schema.osgi;
 
 import com.google.common.annotations.Beta;
-import com.google.common.primitives.UnsignedLong;
-import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.binding.runtime.api.ModuleInfoSnapshot;
 
 /**
  * Combination of a {@link ModuleInfoSnapshot} with a linear generation.
  */
 @Beta
-public interface OSGiModuleInfoSnapshot extends ModuleInfoSnapshot {
+public interface OSGiModuleInfoSnapshot extends ModelGenerationAware<ModuleInfoSnapshot> {
 
-    @NonNull UnsignedLong getGeneration();
 }
index 768ad5f27cfec149695f6c626ff59320c55005dd..38e4f2d2a343f0a29d51579228a179a2062444c9 100644 (file)
@@ -12,6 +12,7 @@ import static java.util.Objects.requireNonNull;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.binding.runtime.api.ModuleInfoSnapshot;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
 import org.opendaylight.mdsal.dom.schema.osgi.OSGiModuleInfoSnapshot;
 import org.opendaylight.mdsal.dom.spi.AbstractDOMSchemaService;
@@ -44,11 +45,11 @@ public final class OSGiDOMSchemaService extends AbstractDOMSchemaService {
 
     private final List<SchemaContextListener> listeners = new CopyOnWriteArrayList<>();
 
-    private volatile OSGiModuleInfoSnapshot currentContext;
+    private volatile ModuleInfoSnapshot currentSnapshot;
 
     @Override
     public EffectiveModelContext getGlobalContext() {
-        return currentContext.getEffectiveModelContext();
+        return currentSnapshot.getEffectiveModelContext();
     }
 
     @Override
@@ -58,10 +59,11 @@ public final class OSGiDOMSchemaService extends AbstractDOMSchemaService {
     }
 
     @Reference(fieldOption = FieldOption.REPLACE)
-    void bindContext(final OSGiModuleInfoSnapshot newContext) {
-        final EffectiveModelContext ctx = newContext.getEffectiveModelContext();
-        LOG.trace("Updating context to {}", ctx);
-        currentContext = newContext;
+    void bindSnapshot(final OSGiModuleInfoSnapshot newContext) {
+        LOG.trace("Updating context to generation {}", newContext.getGeneration());
+        final ModuleInfoSnapshot snapshot = newContext.getService();
+        final EffectiveModelContext ctx = snapshot.getEffectiveModelContext();
+        currentSnapshot = snapshot;
         listeners.forEach(listener -> notifyListener(ctx, listener));
     }
 
index c7041d77eb01c96481e9f427defba6d04a063621..b77063f323117a4f016dbe89d02a2707ad2d3471 100644 (file)
@@ -23,7 +23,7 @@ public final class OSGiModelRuntime {
 
     @Reference
     YangParserFactory parserFactory = null;
-    @Reference(target = "(component.factory=" + OSGiEffectiveModelImpl.FACTORY_NAME + ")")
+    @Reference(target = "(component.factory=" + OSGiModuleInfoSnapshotImpl.FACTORY_NAME + ")")
     ComponentFactory contextFactory = null;
 
     private YangModuleInfoScanner bundleTracker = null;
@@ -13,16 +13,13 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.primitives.UnsignedLong;
-import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.Map;
 import org.gaul.modernizer_maven_annotations.SuppressModernizer;
 import org.opendaylight.binding.runtime.api.ModuleInfoSnapshot;
+import org.opendaylight.mdsal.dom.schema.osgi.ModelGenerationAware;
 import org.opendaylight.mdsal.dom.schema.osgi.OSGiModuleInfoSnapshot;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
@@ -31,9 +28,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Beta
-@Component(factory = OSGiEffectiveModelImpl.FACTORY_NAME,
-           service = { OSGiModuleInfoSnapshot.class, ModuleInfoSnapshot.class })
-public final class OSGiEffectiveModelImpl implements OSGiModuleInfoSnapshot {
+@Component(factory = OSGiModuleInfoSnapshotImpl.FACTORY_NAME, service = OSGiModuleInfoSnapshot.class)
+public final class OSGiModuleInfoSnapshotImpl implements OSGiModuleInfoSnapshot {
     // OSGi DS Component Factory name
     static final String FACTORY_NAME = "org.opendaylight.mdsal.dom.schema.osgi.impl.OSGiEffectiveModelImpl";
 
@@ -43,54 +39,40 @@ public final class OSGiEffectiveModelImpl implements OSGiModuleInfoSnapshot {
     @VisibleForTesting
     static final String DELEGATE = "org.opendaylight.mdsal.dom.schema.osgi.impl.ModuleInfoSnapshot";
 
-    private static final Logger LOG = LoggerFactory.getLogger(OSGiEffectiveModelImpl.class);
+    private static final Logger LOG = LoggerFactory.getLogger(OSGiModuleInfoSnapshotImpl.class);
 
     private ModuleInfoSnapshot delegate;
     private UnsignedLong generation;
 
     @Override
     public UnsignedLong getGeneration() {
-        return generation;
+        return verifyNotNull(generation);
     }
 
     @Override
-    public EffectiveModelContext getEffectiveModelContext() {
-        return delegate.getEffectiveModelContext();
-    }
-
-    @Override
-    public ListenableFuture<? extends YangTextSchemaSource> getSource(final SourceIdentifier sourceIdentifier) {
-        return delegate.getSource(sourceIdentifier);
-    }
-
-    @Override
-    public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
-        return delegate.loadClass(fullyQualifiedName);
+    public ModuleInfoSnapshot getService() {
+        return verifyNotNull(delegate);
     }
 
     @Activate
     void activate(final Map<String, ?> properties) {
         generation = (UnsignedLong) verifyNotNull(properties.get(GENERATION));
         delegate = (ModuleInfoSnapshot) verifyNotNull(properties.get(DELEGATE));
-        LOG.debug("ClassLoadingEffectiveModelContext generation {} activated", generation);
+        LOG.info("EffectiveModelContext generation {} activated", generation);
     }
 
     @Deactivate
     void deactivate() {
         delegate = null;
-        LOG.debug("ClassLoadingEffectiveModelContext generation {} deactivated", generation);
+        LOG.info("EffectiveModelContext generation {} deactivated", generation);
     }
 
     @SuppressModernizer
     static Dictionary<String, ?> props(final long generation, final ModuleInfoSnapshot delegate) {
         final Dictionary<String, Object> ret = new Hashtable<>(4);
-        ret.put(Constants.SERVICE_RANKING, ranking(generation));
+        ret.put(Constants.SERVICE_RANKING, ModelGenerationAware.computeServiceRanking(generation));
         ret.put(GENERATION, UnsignedLong.fromLongBits(generation));
         ret.put(DELEGATE, requireNonNull(delegate));
         return ret;
     }
-
-    private static Integer ranking(final long generation) {
-        return generation >= 0 && generation <= Integer.MAX_VALUE ? (int) generation : Integer.MAX_VALUE;
-    }
 }
index aff0e1f8ea5b34cc66604291f5f31df18046ced2..09d922d4a9966f4ffcd90ec6dc260f17791c00d5 100644 (file)
@@ -97,7 +97,7 @@ final class RegularYangModuleInfoRegistry extends YangModuleInfoRegistry {
 
 
         final ComponentInstance newInstance = contextFactory.newInstance(
-            OSGiEffectiveModelImpl.props(nextGeneration(), newSnapshot));
+            OSGiModuleInfoSnapshotImpl.props(nextGeneration(), newSnapshot));
         if (currentInstance != null) {
             currentInstance.dispose();
         }
index 3820001189c1bab506d3267cd166faf118fd219c..2c95927e04fd4b860c62d0f7a7b4d5750d3d6ac3 100644 (file)
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding-dom-codec-osgi</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>mdsal-binding-runtime-osgi</artifactId>