<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>
<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"/>
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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> {
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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> {
+
+}
+++ /dev/null
-/*
- * 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);
- }
-}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
<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>
--- /dev/null
+/*
+ * 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;
+ }
+}
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();
}
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;
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
}
@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));
}
@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;
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;
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";
@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;
- }
}
final ComponentInstance newInstance = contextFactory.newInstance(
- OSGiEffectiveModelImpl.props(nextGeneration(), newSnapshot));
+ OSGiModuleInfoSnapshotImpl.props(nextGeneration(), newSnapshot));
if (currentInstance != null) {
currentInstance.dispose();
}
</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>