}
@Override
- protected ActionProviderService createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected ActionProviderService createInstance(final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new ActionProviderServiceAdapter(adapterContext(),
delegates.getInstance(DOMActionProviderService.class));
}
@Override
- public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<? extends Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMActionProviderService.class);
}
}
}
@Override
- public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<? extends Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMActionService.class);
}
@Override
- protected ActionService createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected ActionService createInstance(final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new ActionServiceAdapter(adapterContext(), delegates.getInstance(DOMActionService.class));
}
}
@Override
public Optional<T> load(final Class<? extends T> key) {
-
- final AdapterBuilder<? extends T, D> builder = createBuilder(key);
- for (final Class<? extends D> reqDeleg : builder.getRequiredDelegates()) {
- final D deleg = getDelegate(reqDeleg);
+ final var builder = createBuilder(key);
+ for (var reqDeleg : builder.getRequiredDelegates()) {
+ final var deleg = getDelegate(reqDeleg);
if (deleg != null) {
builder.addDelegate(reqDeleg, deleg);
} else {
import org.opendaylight.mdsal.binding.api.BindingService;
import org.opendaylight.mdsal.dom.api.DOMService;
-abstract class BindingDOMAdapterBuilder<T extends BindingService> extends AdapterBuilder<T, DOMService> {
+abstract class BindingDOMAdapterBuilder<T extends BindingService> extends AdapterBuilder<T, DOMService<?, ?>> {
@FunctionalInterface
interface Factory<T extends BindingService> {
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableMap;
-import java.util.Map;
import org.opendaylight.mdsal.binding.api.ActionProviderService;
import org.opendaylight.mdsal.binding.api.ActionService;
import org.opendaylight.mdsal.binding.api.BindingService;
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
import org.opendaylight.mdsal.binding.api.NotificationService;
import org.opendaylight.mdsal.binding.api.RpcService;
-import org.opendaylight.mdsal.binding.dom.adapter.BindingDOMAdapterBuilder.Factory;
import org.opendaylight.mdsal.dom.api.DOMService;
-public abstract class BindingDOMAdapterLoader extends AdapterLoader<BindingService, DOMService> {
- private static final Map<Class<?>,BindingDOMAdapterBuilder.Factory<?>> FACTORIES =
- ImmutableMap.<Class<?>, BindingDOMAdapterBuilder.Factory<?>>builder()
+public abstract class BindingDOMAdapterLoader extends AdapterLoader<BindingService, DOMService<?, ?>> {
+ private static final ImmutableMap<Class<?>, BindingDOMAdapterBuilder.Factory<?>> FACTORIES =
+ ImmutableMap.<Class<?>, BindingDOMAdapterBuilder.Factory<?>>builder()
.put(NotificationService.class, BindingDOMNotificationServiceAdapter.BUILDER_FACTORY)
.put(NotificationPublishService.class, BindingDOMNotificationPublishServiceAdapter.BUILDER_FACTORY)
.put(DataBroker.class, BindingDOMDataBrokerAdapter.BUILDER_FACTORY)
.put(ActionService.class, ActionServiceAdapter.BUILDER_FACTORY)
.put(ActionProviderService.class, ActionProviderServiceAdapter.BUILDER_FACTORY)
.put(InstanceNotificationService.class, InstanceNotificationServiceAdapter.BUILDER_FACTORY)
- .put(InstanceNotificationPublishService.class,
- InstanceNotificationPublishServiceAdapter.BUILDER_FACTORY)
+ .put(InstanceNotificationPublishService.class, InstanceNotificationPublishServiceAdapter.BUILDER_FACTORY)
.build();
private final AdapterContext codec;
- public BindingDOMAdapterLoader(final AdapterContext codec) {
+ protected BindingDOMAdapterLoader(final AdapterContext codec) {
this.codec = requireNonNull(codec);
}
@Override
- protected final AdapterBuilder<? extends BindingService, DOMService> createBuilder(
- final Class<? extends BindingService> key) {
- final Factory<?> factory = FACTORIES.get(key);
+ protected final AdapterBuilder<? extends BindingService, DOMService<?, ?>> createBuilder(
+ final Class<? extends BindingService> key) {
+ final var factory = FACTORIES.get(key);
checkArgument(factory != null, "Unsupported service type %s", key);
return factory.newBuilder(codec);
}
public BindingDOMDataBrokerAdapter(final AdapterContext adapterContext, final DOMDataBroker domDataBroker) {
super(adapterContext, domDataBroker);
- final DOMDataTreeChangeService domTreeChange = domDataBroker.getExtensions()
- .getInstance(DOMDataTreeChangeService.class);
+ final var domTreeChange = domDataBroker.extension(DOMDataTreeChangeService.class);
treeChangeService = domTreeChange == null ? null
: new BindingDOMDataTreeChangeServiceAdapter(adapterContext, domTreeChange);
}
}
@Override
- public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<? extends Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMDataBroker.class);
}
@Override
- protected DataBroker createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected DataBroker createInstance(final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new BindingDOMDataBrokerAdapter(adapterContext(), delegates.getInstance(DOMDataBroker.class));
}
}
}
@Override
- public Set<Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMNotificationPublishService.class);
}
@Override
- protected NotificationPublishService createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected NotificationPublishService createInstance(final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new BindingDOMNotificationPublishServiceAdapter(adapterContext(),
delegates.getInstance(DOMNotificationPublishService.class));
}
}
@Override
- protected NotificationService createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected NotificationService createInstance(final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new BindingDOMNotificationServiceAdapter(adapterContext(),
delegates.getInstance(DOMNotificationService.class));
}
@Override
- public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<? extends Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMNotificationService.class);
}
}
}
@Override
- public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<? extends Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMRpcService.class);
}
@Override
- protected RpcService createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected RpcService createInstance(final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new BindingDOMRpcServiceAdapter(adapterContext(), delegates.getInstance(DOMRpcService.class));
}
}
identifier = codec.currentSerializer().fromYangInstanceIdentifier(domMountPoint.getIdentifier());
services = CacheBuilder.newBuilder().build(new BindingDOMAdapterLoader(codec) {
@Override
- protected DOMService getDelegate(final Class<? extends DOMService> reqDeleg) {
- return domMountPoint.getService(reqDeleg).orElse(null);
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected DOMService<?, ?> getDelegate(final Class<? extends DOMService<?, ?>> reqDeleg) {
+ return reqDeleg.cast(domMountPoint.getService((Class) reqDeleg).orElse(null));
}
});
}
}
@Override
- public Set<Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMInstanceNotificationPublishService.class);
}
@Override
- protected InstanceNotificationPublishService createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected InstanceNotificationPublishService createInstance(
+ final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new InstanceNotificationPublishServiceAdapter(adapterContext(),
delegates.getInstance(DOMInstanceNotificationPublishService.class));
}
}
@Override
- protected InstanceNotificationService createInstance(final ClassToInstanceMap<DOMService> delegates) {
+ protected InstanceNotificationService createInstance(final ClassToInstanceMap<DOMService<?, ?>> delegates) {
return new InstanceNotificationServiceAdapter(adapterContext(),
delegates.getInstance(DOMInstanceNotificationService.class));
}
@Override
- public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+ public Set<? extends Class<? extends DOMService<?, ?>>> getRequiredDelegates() {
return ImmutableSet.of(DOMInstanceNotificationService.class);
}
}
* @param <B> BindingService type
* @author Robert Varga
*/
-final class AdaptingTracker<D extends DOMService, B extends BindingService>
+final class AdaptingTracker<D extends DOMService<?, ?>, B extends BindingService>
extends ServiceTracker<D, AdaptingTracker.ComponentHolder<B>> {
static final class ComponentHolder<B extends BindingService> {
final B binding;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import com.google.common.collect.ImmutableClassToInstanceMap;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
@Before
public void setUp() {
- doReturn(ImmutableClassToInstanceMap.of()).when(domService).getExtensions();
bindingDOMAdapterLoader = new BindingDOMAdapterLoader(mockContext) {
@Override
- protected DOMService getDelegate(final Class<? extends DOMService> reqDeleg) {
+ protected DOMService<?, ?> getDelegate(final Class<? extends DOMService<?, ?>> reqDeleg) {
return domService;
}
};
@RunWith(Parameterized.class)
public class BindingDOMTransactionChainAdapterTest {
- enum TransactionChainType implements BiFunction<DataBroker, TransactionChainListener, TransactionChain> {
+ public enum TransactionChainType implements BiFunction<DataBroker, TransactionChainListener, TransactionChain> {
NORMAL {
@Override
public TransactionChain apply(final DataBroker broker, final TransactionChainListener listener) {
@Before
public void setUp() {
- doCallRealMethod().when(domService).getExtensions();
doReturn(transactionChain).when(domService).createTransactionChain(any());
if (type == TransactionChainType.MERGING) {
doCallRealMethod().when(domService).createMergingTransactionChain(any());
BindingDOMAdapterLoader bindingDOMAdapterLoader = new BindingDOMAdapterLoader(
new ConstantAdapterContext(mockCodecRegistry)) {
@Override
- protected DOMService getDelegate(final Class<? extends DOMService> reqDeleg) {
+ protected DOMService<?, ?> getDelegate(final Class<? extends DOMService<?, ?>> reqDeleg) {
return domService;
}
};
}
public NotificationService createNotificationService() {
- return new BindingDOMNotificationServiceAdapter(schemaService, domNotificationRouter);
+ return new BindingDOMNotificationServiceAdapter(schemaService, domNotificationRouter.notificationService());
}
public NotificationPublishService createNotificationPublishService() {
- return new BindingDOMNotificationPublishServiceAdapter(schemaService, domNotificationRouter);
+ return new BindingDOMNotificationPublishServiceAdapter(schemaService,
+ domNotificationRouter.notificationPublishService());
}
public abstract ListeningExecutorService getCommitCoordinatorExecutor();
public void startBindingNotificationBroker() {
checkState(executor != null);
- final DOMNotificationRouter router = new DOMNotificationRouter(16);
- domPublishService = router;
- domListenService = router;
+ final var router = new DOMNotificationRouter(16);
+ domPublishService = router.notificationPublishService();
+ domListenService = router.notificationService();
publishService = new BindingDOMNotificationPublishServiceAdapter(mockSchemaService, domPublishService);
listenService = new BindingDOMNotificationServiceAdapter(mockSchemaService, domListenService);
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
import java.util.ServiceLoader;
import org.opendaylight.mdsal.binding.dom.adapter.AdapterContext;
import org.opendaylight.mdsal.binding.dom.adapter.CurrentAdapterSerializer;
import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.opendaylight.mdsal.dom.api.DOMSchemaServiceExtension;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
return schemaContext;
}
- @Override
- public ClassToInstanceMap<DOMSchemaServiceExtension> getExtensions() {
- return ImmutableClassToInstanceMap.of();
- }
-
public synchronized void changeSchema(final BindingRuntimeContext newContext) {
serializer = new CurrentAdapterSerializer(CODEC_CACHE.getUnchecked(newContext));
schemaContext = newContext.getEffectiveModelContext();
@Beta
@NonNullByDefault
public interface DOMActionProviderService
- extends DOMExtensibleService<DOMActionProviderService, DOMActionProviderServiceExtension> {
+ extends DOMService<DOMActionProviderService, DOMActionProviderServiceExtension> {
/**
* Register an {@link DOMActionImplementation} object with this service, servicing specified action instances.
*
/**
* Marker interface for extensions of {@link DOMActionProviderService}.
- *
- * @author Robert Varga
*/
@Beta
@NonNullByDefault
public interface DOMActionProviderServiceExtension
- extends DOMServiceExtension<DOMActionProviderService, DOMActionProviderServiceExtension> {
+ extends DOMService.Extension<DOMActionProviderService, DOMActionProviderServiceExtension> {
}
/**
* A {@link DOMService} which allows clients to invoke Actions. The conceptual model of this service is that
* of a dynamic router, where the set of available Action services can change dynamically.
- *
- * @author Robert Varga
*/
@Beta
@NonNullByDefault
-public interface DOMActionService extends DOMExtensibleService<DOMActionService, DOMActionServiceExtension> {
+public interface DOMActionService extends DOMService<DOMActionService, DOMActionServiceExtension> {
/**
* Initiate invocation of an Action. This method is guaranteed to not block on any external resources.
*
/**
* Marker interface for extensions of {@link DOMActionService}.
- *
- * @author Robert Varga
*/
@Beta
@NonNullByDefault
-public interface DOMActionServiceExtension
- extends DOMServiceExtension<DOMActionService, DOMActionServiceExtension> {
+public interface DOMActionServiceExtension extends DOMService.Extension<DOMActionService, DOMActionServiceExtension> {
}
* <b>Implementation Note:</b> This interface is not intended to be implemented by users of MD-SAL,
* but only to be consumed by them.
*/
-public interface DOMDataBroker extends DOMTransactionFactory,
- DOMExtensibleService<DOMDataBroker, DOMDataBrokerExtension> {
+public interface DOMDataBroker extends DOMService<DOMDataBroker, DOMDataBrokerExtension>, DOMTransactionFactory {
/**
* Create a new transaction chain. The chain will be initialized to read from its backing datastore, with
* no outstanding transaction. Listener will be registered to handle chain-level events.
package org.opendaylight.mdsal.dom.api;
/**
- * Type capture of a {@link DOMServiceExtension} applicable to {@link DOMDataBroker}
- * implementations.
+ * Type capture of a {@link DOMService.Extension} applicable to {@link DOMDataBroker} implementations.
*/
-public interface DOMDataBrokerExtension extends DOMServiceExtension<DOMDataBroker, DOMDataBrokerExtension> {
-
+public interface DOMDataBrokerExtension extends DOMService.Extension<DOMDataBroker, DOMDataBrokerExtension> {
+ // Marker interface
}
import org.opendaylight.yangtools.concepts.ListenerRegistration;
/**
- * A {@link DOMServiceExtension} which allows users to register for changes to a
- * subtree.
+ * A {@link DOMDataBrokerExtension} which allows users to register for changes to a subtree.
*/
public interface DOMDataTreeChangeService extends DOMDataBrokerExtension {
/**
- * Registers a {@link DOMDataTreeChangeListener} to receive notifications when data changes
- * under a given path in the conceptual data tree.
+ * Registers a {@link DOMDataTreeChangeListener} to receive notifications when data changes under a given path in
+ * the conceptual data tree.
*
* <p>
- * You are able to register for notifications for any node or subtree which can be represented
- * using {@link DOMDataTreeIdentifier}.
+ * You are able to register for notifications for any node or subtree which can be represented using
+ * {@link DOMDataTreeIdentifier}.
*
* <p>
- * You are able to register for data change notifications for a subtree or leaf even if it does
- * not exist. You will receive notification once that node is created.
+ * You are able to register for data change notifications for a subtree or leaf even if it does not exist. You will
+ * receive notification once that node is created.
*
* <p>
- * If there is any pre-existing data in the data tree for the path for which you are
- * registering, you will receive an initial data change event, which will contain all
- * pre-existing data, marked as created.
+ * If there is any pre-existing data in the data tree for the path for which you are registering, you will receive
+ * an initial data change event, which will contain all pre-existing data, marked as created.
*
* <p>
- * This method returns a {@link ListenerRegistration} object. To "unregister" your listener for
- * changes call the {@link ListenerRegistration#close()} method on the returned object.
+ * This method returns a {@link ListenerRegistration} object. To "unregister" your listener for changes call
+ * the {@link ListenerRegistration#close()} method on the returned object.
*
* <p>
- * You MUST explicitly unregister your listener when you no longer want to receive
- * notifications. This is especially true in OSGi environments, where failure to do so during
- * bundle shutdown can lead to stale listeners being still registered.
+ * You MUST explicitly unregister your listener when you no longer want to receive notifications. This is especially
+ * true in OSGi environments, where failure to do so during bundle shutdown can lead to stale listeners being still
+ * registered.
*
* @param treeId Data tree identifier of the subtree which should be watched for changes.
* @param listener Listener instance which is being registered
* {@link ListenerRegistration#close()} to stop delivery of change events.
* @throws NullPointerException if any of the arguments is null
*/
+ // FIXME: just Registration
<L extends DOMDataTreeChangeListener> @NonNull ListenerRegistration<L> registerDataTreeChangeListener(
@NonNull DOMDataTreeIdentifier treeId, @NonNull L listener);
}
+++ /dev/null
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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.api;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
-import org.eclipse.jdt.annotation.NonNull;
-
-/**
- * Marker interface for services which can support {@link DOMServiceExtension}. Aside for marking
- * these, they also provide runtime query to detect whether a particular trait is in fact available.
- *
- * @param <T> Base {@link DOMService}
- * @param <E> Extension type
- */
-@Beta
-public interface DOMExtensibleService<T extends DOMExtensibleService<T, E>,
- E extends DOMServiceExtension<T, E>> extends DOMService {
- /**
- * Return a map of currently-supported extensions, along with accessor services which provide access to the specific
- * functionality bound to this service. Default implementation reports no extensions.
- *
- * @return A map of supported functionality.
- */
- default @NonNull ClassToInstanceMap<E> getExtensions() {
- return ImmutableClassToInstanceMap.of();
- }
-}
* </ul>
*/
@Beta
-public interface DOMInstanceNotificationPublishService extends DOMService {
+public interface DOMInstanceNotificationPublishService extends
+ DOMService<DOMInstanceNotificationPublishService, DOMInstanceNotificationPublishService.Extension> {
+ /**
+ * Marker interface for an extension to {@link DOMInstanceNotificationPublishService}.
+ */
+ interface Extension extends DOMService.Extension<DOMInstanceNotificationPublishService, Extension> {
+ // Marker interface
+ }
+
/**
* Well-known value indicating that the implementation is currently not
* able to accept a notification.
*/
@Beta
@NonNullByDefault
-public interface DOMInstanceNotificationService extends DOMService {
+public interface DOMInstanceNotificationService
+ extends DOMService<DOMInstanceNotificationService, DOMInstanceNotificationService.Extension> {
+ /**
+ * Marker interface for an extension to {@link DOMInstanceNotificationService}.
+ */
+ interface Extension extends DOMService.Extension<DOMInstanceNotificationService, Extension> {
+ // Marker interface
+ }
+
/**
* Register a {@link DOMInstanceNotificationListener} for a particular {@code path} and notification {@code type}.
*
public interface DOMMountPoint extends Identifiable<YangInstanceIdentifier> {
- <T extends DOMService> Optional<T> getService(Class<T> cls);
+ <T extends DOMService<T, E>, E extends DOMService.Extension<T, E>> Optional<T> getService(Class<T> cls);
}
* 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.api;
import java.util.Optional;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-public interface DOMMountPointService extends DOMService {
+public interface DOMMountPointService extends DOMService<DOMMountPointService, DOMMountPointService.Extension> {
+ /**
+ * Marker interface for an extension to {@link DOMMountPointService}.
+ */
+ interface Extension extends DOMService.Extension<DOMMountPointService, Extension> {
+ // Marker interface
+ }
Optional<DOMMountPoint> getMountPoint(YangInstanceIdentifier path);
DOMMountPointBuilder createMountPoint(YangInstanceIdentifier path);
+ // FIXME: just Registration
ListenerRegistration<DOMMountPointListener> registerProvisionListener(DOMMountPointListener listener);
interface DOMMountPointBuilder {
- <T extends DOMService> DOMMountPointBuilder addService(Class<T> type,T impl);
+ <T extends DOMService<T, E>, E extends DOMService.Extension<T, E>> DOMMountPointBuilder addService(
+ Class<T> type, T impl);
+ // FIXME: just Registration
ObjectRegistration<DOMMountPoint> register();
}
}
* should never wait, or put an upper bound on how long it is going to wait</li>
* </ul>
*/
-public interface DOMNotificationPublishService extends DOMService {
+public interface DOMNotificationPublishService
+ extends DOMService<DOMNotificationPublishService, DOMNotificationPublishService.Extension> {
+ /**
+ * Marker interface for an extension to {@link DOMNotificationPublishService}.
+ */
+ interface Extension extends DOMService.Extension<DOMNotificationPublishService, Extension> {
+ // Marker interface
+ }
+
/**
* Well-known value indicating that the implementation is currently not able to accept a notification.
*/
*/
package org.opendaylight.mdsal.dom.api;
-import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
/**
* A {@link DOMService} which allows its users to subscribe to receive top-level (YANG 1.0) {@link DOMNotification}s.
*/
-public interface DOMNotificationService extends DOMService {
+public interface DOMNotificationService extends DOMService<DOMNotificationService, DOMNotificationService.Extension> {
+ /**
+ * Marker interface for an extension to {@link DOMNotificationService}.
+ */
+ interface Extension extends DOMService.Extension<DOMNotificationService, Extension> {
+ // Marker interface
+ }
+
/**
* Register a {@link DOMNotificationListener} to receive a set of notifications. As with other
* {@link ListenerRegistration}-based interfaces, registering an instance multiple times results in
* null or a schema node identifier which does not represent a valid {@link DOMNotification} type.
* @throws NullPointerException if either of the arguments is null
*/
+ // FIXME: just Registration and default implementation forwarding to Map-based thing
<T extends DOMNotificationListener> @NonNull ListenerRegistration<T>
registerNotificationListener(@NonNull T listener, @NonNull Collection<Absolute> types);
* null or a schema node identifier which does not represent a valid {@link DOMNotification} type.
* @throws NullPointerException if listener is null
*/
+ // FIXME: just Registration
default <T extends DOMNotificationListener> @NonNull ListenerRegistration<T>
registerNotificationListener(@NonNull final T listener, final Absolute... types) {
- return registerNotificationListener(listener, Arrays.asList(types));
+ return registerNotificationListener(listener, List.of(types));
}
/**
* A {@link DOMService} which allows registration of RPC implementations with a conceptual router. The client
* counterpart of this service is {@link DOMRpcService}.
*/
-public interface DOMRpcProviderService extends DOMService {
+public interface DOMRpcProviderService extends DOMService<DOMRpcProviderService, DOMRpcProviderService.Extension> {
+ /**
+ * Marker interface for an extension to {@link DOMRpcProviderService}.
+ */
+ interface Extension extends DOMService.Extension<DOMRpcProviderService, Extension> {
+ // Marker interface
+ }
+
/**
* Register an {@link DOMRpcImplementation} object with this service.
*
* @throws NullPointerException if implementation or types is null
* @throws IllegalArgumentException if types is empty or contains a null element.
*/
+ // FIXME: just Registration and forward to set
+ // FIXME: single-instance specialization
@NonNull <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T>
registerRpcImplementation(@NonNull T implementation, @NonNull DOMRpcIdentifier... rpcs);
* @throws NullPointerException if implementation or types is null
* @throws IllegalArgumentException if types is empty or contains a null element.
*/
+ // FIXME: just Registration and forward to set
@NonNull <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T>
registerRpcImplementation(@NonNull T implementation, @NonNull Set<DOMRpcIdentifier> rpcs);
* to track the process of RPCs becoming available.
*/
// FIXME: once we have a DOMOperationService implementation, deprecate this interface
-public interface DOMRpcService extends DOMService {
+public interface DOMRpcService extends DOMService<DOMRpcService, DOMRpcService.Extension> {
+ /**
+ * Marker interface for an extension to {@link DOMRpcService}.
+ */
+ interface Extension extends DOMService.Extension<DOMRpcService, Extension> {
+ // Marker interface
+ }
+
/**
* Initiate invocation of an RPC. This method is guaranteed to not block on any external
* resources.
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextListener;
-public interface DOMSchemaService extends DOMExtensibleService<DOMSchemaService, DOMSchemaServiceExtension> {
+public interface DOMSchemaService extends DOMService<DOMSchemaService, DOMSchemaServiceExtension> {
/**
* Returns global schema context.
*
package org.opendaylight.mdsal.dom.api;
/**
- * Type capture of a {@link DOMServiceExtension} applicable to {@link DOMSchemaService}
- * implementations.
+ * Type capture of a {@link DOMService.Extension} applicable to {@link DOMSchemaService} implementations.
*/
-public interface DOMSchemaServiceExtension extends DOMServiceExtension<DOMSchemaService, DOMSchemaServiceExtension> {
-
+public interface DOMSchemaServiceExtension extends DOMService.Extension<DOMSchemaService, DOMSchemaServiceExtension> {
+ // Marker interface
}
*/
package org.opendaylight.mdsal.dom.api;
+import org.opendaylight.yangtools.concepts.ExtensibleObject;
+import org.opendaylight.yangtools.concepts.ObjectExtension;
+
/**
- * Marker interface for services which can be obtained from a {@link DOMMountPoint}
- * instance. No further semantics are implied.
+ * Marker interface for services which can be obtained from a {@link DOMMountPoint} instance. The only further semantics
+ * implied are that each service can also host related {@link Extension}s supported via the {@link ExtensibleObject}
+ * contract.
+ *
+ * @param <T> Concrete service type
+ * @param <E> Extension type
*/
-public interface DOMService {
-
+public interface DOMService<T extends DOMService<T, E>, E extends DOMService.Extension<T, E>>
+ extends ExtensibleObject<T, E> {
+ /**
+ * Extension to a concrete {@link DOMService}.
+ *
+ * @param <T> Concrete service type
+ * @param <E> Extension type
+ */
+ interface Extension<T extends DOMService<T, E>, E extends Extension<T, E>> extends ObjectExtension<T, E> {
+ // Only a marker interface
+ }
}
+++ /dev/null
-/*
- * Copyright (c) 2017 Pantheon Technologies, 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.api;
-
-import com.google.common.annotations.Beta;
-
-/**
- * Marker interface for services which expose additional functionality on top
- * of some base {@link DOMService}.
- */
-@Beta
-public interface DOMServiceExtension<T extends DOMExtensibleService<T, E>, E extends DOMServiceExtension<T, E>> {
-
-}
import com.google.common.base.Preconditions;
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.ImmutableClassToInstanceMap;
+import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
}
@Override
- public ClassToInstanceMap<DOMDataBrokerExtension> getExtensions() {
- return extensions;
+ public final Collection<DOMDataBrokerExtension> supportedExtensions() {
+ return extensions.values();
}
@Override
*/
package org.opendaylight.mdsal.dom.broker;
-import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
import com.google.common.collect.MutableClassToInstanceMap;
}
private static void checkNotExists(final YangInstanceIdentifier id, final DOMMountPoint mountPoint) {
- checkState(mountPoint == null, "Mount point %s already exists as %s", id, mountPoint);
+ if (mountPoint != null) {
+ throw new IllegalStateException("Mount point " + id + " already exists as " + mountPoint);
+ }
}
private final class DOMMountPointBuilderImpl implements DOMMountPointBuilder {
- private final MutableClassToInstanceMap<DOMService> services = MutableClassToInstanceMap.create();
+ private final MutableClassToInstanceMap<DOMService<?, ?>> services = MutableClassToInstanceMap.create();
private final YangInstanceIdentifier path;
private SimpleDOMMountPoint mountPoint;
}
@Override
- public <T extends DOMService> DOMMountPointBuilder addService(final Class<T> type, final T impl) {
- services.putInstance(requireNonNull(type), requireNonNull(impl));
+ public <T extends DOMService<T, E>, E extends DOMService.Extension<T, E>> DOMMountPointBuilder addService(
+ final Class<T> type, final T impl) {
+ services.putInstance(type, requireNonNull(impl));
return this;
}
@Override
public ObjectRegistration<DOMMountPoint> register() {
- checkState(mountPoint == null, "Mount point is already built.");
+ if (mountPoint != null) {
+ throw new IllegalStateException("Mount point is already built");
+ }
mountPoint = SimpleDOMMountPoint.create(path, services);
return registerMountPoint(mountPoint);
}
* Internal implementation one by using a {@link QueuedNotificationManager}.
*</p>
*/
-@Component(immediate = true, configurationPid = "org.opendaylight.mdsal.dom.notification", service = {
- DOMNotificationService.class, DOMNotificationPublishService.class,
- DOMNotificationSubscriptionListenerRegistry.class
+@Component(configurationPid = "org.opendaylight.mdsal.dom.notification", service = {
+ DOMNotificationRouter.class, DOMNotificationSubscriptionListenerRegistry.class
})
@Designate(ocd = DOMNotificationRouter.Config.class)
// Non-final for testing
-public class DOMNotificationRouter implements AutoCloseable, DOMNotificationPublishService,
- DOMNotificationService, DOMNotificationSubscriptionListenerRegistry {
+public class DOMNotificationRouter implements DOMNotificationSubscriptionListenerRegistry, AutoCloseable {
@ObjectClassDefinition()
public @interface Config {
@AttributeDefinition(name = "notification-queue-depth")
}
}
+ private final class PublishFacade implements DOMNotificationPublishService {
+ @Override
+ public ListenableFuture<? extends Object> putNotification(final DOMNotification notification)
+ throws InterruptedException {
+ return putNotificationImpl(notification);
+ }
+
+ @Override
+ public ListenableFuture<? extends Object> offerNotification(final DOMNotification notification) {
+ final var subscribers = listeners.get(notification.getType());
+ return subscribers.isEmpty() ? NO_LISTENERS : publish(notification, subscribers);
+ }
+
+ @Override
+ public ListenableFuture<? extends Object> offerNotification(final DOMNotification notification,
+ final long timeout, final TimeUnit unit) throws InterruptedException {
+ final var subscribers = listeners.get(notification.getType());
+ if (subscribers.isEmpty()) {
+ return NO_LISTENERS;
+ }
+ // Attempt to perform a non-blocking publish first
+ final var noBlock = publish(notification, subscribers);
+ if (!DOMNotificationPublishService.REJECTED.equals(noBlock)) {
+ return noBlock;
+ }
+
+ try {
+ final var publishThread = Thread.currentThread();
+ final var timerTask = observer.schedule(publishThread::interrupt, timeout, unit);
+ final var withBlock = putNotificationImpl(notification);
+ timerTask.cancel(true);
+ if (observer.getQueue().size() > 50) {
+ observer.purge();
+ }
+ return withBlock;
+ } catch (InterruptedException e) {
+ return DOMNotificationPublishService.REJECTED;
+ }
+ }
+ }
+
+ private final class SubscribeFacade implements DOMNotificationService {
+ @Override
+ public <T extends DOMNotificationListener> ListenerRegistration<T> registerNotificationListener(
+ final T listener, final Collection<Absolute> types) {
+ synchronized (DOMNotificationRouter.this) {
+ final var reg = new SingleReg<>(listener);
+
+ if (!types.isEmpty()) {
+ final var b = ImmutableMultimap.<Absolute, Reg<?>>builder();
+ b.putAll(listeners);
+
+ for (var t : types) {
+ b.put(t, reg);
+ }
+
+ replaceListeners(b.build());
+ }
+
+ return reg;
+ }
+ }
+
+ @Override
+ public synchronized Registration registerNotificationListeners(
+ final Map<Absolute, DOMNotificationListener> typeToListener) {
+ synchronized (DOMNotificationRouter.this) {
+ final var b = ImmutableMultimap.<Absolute, Reg<?>>builder();
+ b.putAll(listeners);
+
+ final var tmp = new HashMap<DOMNotificationListener, ComponentReg>();
+ for (var e : typeToListener.entrySet()) {
+ b.put(e.getKey(), tmp.computeIfAbsent(e.getValue(), ComponentReg::new));
+ }
+ replaceListeners(b.build());
+
+ final var regs = List.copyOf(tmp.values());
+ return new AbstractRegistration() {
+ @Override
+ protected void removeRegistration() {
+ regs.forEach(ComponentReg::close);
+ removeRegistrations(regs);
+ }
+ };
+ }
+ }
+ }
+
private static final Logger LOG = LoggerFactory.getLogger(DOMNotificationRouter.class);
private static final @NonNull ListenableFuture<?> NO_LISTENERS = Futures.immediateFuture(Empty.value());
ListenerRegistry.create();
private final EqualityQueuedNotificationManager<AbstractListenerRegistration<? extends DOMNotificationListener>,
DOMNotificationRouterEvent> queueNotificationManager;
+ private final @NonNull DOMNotificationPublishService notificationPublishService = new PublishFacade();
+ private final @NonNull DOMNotificationService notificationService = new SubscribeFacade();
private final ScheduledThreadPoolExecutor observer;
private final ExecutorService executor;
this(config.queueDepth());
}
- @Override
- public synchronized <T extends DOMNotificationListener> ListenerRegistration<T> registerNotificationListener(
- final T listener, final Collection<Absolute> types) {
- final var reg = new SingleReg<>(listener);
-
- if (!types.isEmpty()) {
- final var b = ImmutableMultimap.<Absolute, Reg<?>>builder();
- b.putAll(listeners);
-
- for (var t : types) {
- b.put(t, reg);
- }
-
- replaceListeners(b.build());
- }
-
- return reg;
+ public @NonNull DOMNotificationService notificationService() {
+ return notificationService;
}
- @Override
- public synchronized Registration registerNotificationListeners(
- final Map<Absolute, DOMNotificationListener> typeToListener) {
- final var b = ImmutableMultimap.<Absolute, Reg<?>>builder();
- b.putAll(listeners);
-
- final var tmp = new HashMap<DOMNotificationListener, ComponentReg>();
- for (var e : typeToListener.entrySet()) {
- b.put(e.getKey(), tmp.computeIfAbsent(e.getValue(), ComponentReg::new));
- }
- replaceListeners(b.build());
-
- final var regs = List.copyOf(tmp.values());
- return new AbstractRegistration() {
- @Override
- protected void removeRegistration() {
- regs.forEach(ComponentReg::close);
- removeRegistrations(regs);
- }
- };
+ public @NonNull DOMNotificationPublishService notificationPublishService() {
+ return notificationPublishService;
}
private synchronized void removeRegistration(final SingleReg<?> reg) {
return subscriptionListeners.register(listener);
}
+ @VisibleForTesting
+ @NonNull ListenableFuture<? extends Object> putNotificationImpl(final DOMNotification notification)
+ throws InterruptedException {
+ final var subscribers = listeners.get(notification.getType());
+ return subscribers.isEmpty() ? NO_LISTENERS : publish(notification, subscribers);
+ }
+
@VisibleForTesting
@NonNull ListenableFuture<?> publish(final DOMNotification notification, final Collection<Reg<?>> subscribers) {
final var futures = new ArrayList<ListenableFuture<?>>(subscribers.size());
MoreExecutors.directExecutor());
}
- @Override
- public ListenableFuture<? extends Object> putNotification(final DOMNotification notification)
- throws InterruptedException {
- final var subscribers = listeners.get(notification.getType());
- return subscribers.isEmpty() ? NO_LISTENERS : publish(notification, subscribers);
- }
-
- @Override
- public ListenableFuture<? extends Object> offerNotification(final DOMNotification notification) {
- final var subscribers = listeners.get(notification.getType());
- return subscribers.isEmpty() ? NO_LISTENERS : publish(notification, subscribers);
- }
-
- @Override
- public ListenableFuture<? extends Object> offerNotification(final DOMNotification notification, final long timeout,
- final TimeUnit unit) throws InterruptedException {
- final var subscribers = listeners.get(notification.getType());
- if (subscribers.isEmpty()) {
- return NO_LISTENERS;
- }
- // Attempt to perform a non-blocking publish first
- final var noBlock = publish(notification, subscribers);
- if (!DOMNotificationPublishService.REJECTED.equals(noBlock)) {
- return noBlock;
- }
-
- try {
- final var publishThread = Thread.currentThread();
- final var timerTask = observer.schedule(publishThread::interrupt, timeout, unit);
- final var withBlock = putNotification(notification);
- timerTask.cancel(true);
- if (observer.getQueue().size() > 50) {
- observer.purge();
- }
- return withBlock;
- } catch (InterruptedException e) {
- return DOMNotificationPublishService.REJECTED;
- }
- }
-
@PreDestroy
@Deactivate
@Override
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableTable;
}
@NonNullByDefault
- private final class ActionAvailabilityFacade implements DOMActionAvailabilityExtension {
+ private final class ActionServiceFacade implements DOMActionService, DOMActionAvailabilityExtension {
@Override
- public <T extends AvailabilityListener> ListenerRegistration<T> registerAvailabilityListener(final T listener) {
- synchronized (DOMRpcRouter.this) {
- final ActionRegistration<T> ret = new ActionRegistration<>(DOMRpcRouter.this, listener,
- actionRoutingTable.getOperations(listener));
- actionListeners = ImmutableList.<ActionRegistration<?>>builder()
- .addAll(actionListeners)
- .add(ret)
- .build();
-
- listenerNotifier.execute(ret::initialTable);
- return ret;
- }
- }
- }
-
- @NonNullByDefault
- private final class ActionServiceFacade implements DOMActionService {
- private final ClassToInstanceMap<DOMActionServiceExtension> extensions = ImmutableClassToInstanceMap.of(
- DOMActionAvailabilityExtension.class, new ActionAvailabilityFacade());
-
- @Override
- public ClassToInstanceMap<DOMActionServiceExtension> getExtensions() {
- return extensions;
+ public Collection<DOMActionServiceExtension> supportedExtensions() {
+ return List.of(this);
}
@Override
: Futures.immediateFailedFuture(
new DOMActionNotAvailableException("No implementation of Action %s available", type));
}
+
+ @Override
+ public <T extends AvailabilityListener> ListenerRegistration<T> registerAvailabilityListener(final T listener) {
+ synchronized (DOMRpcRouter.this) {
+ final ActionRegistration<T> ret = new ActionRegistration<>(DOMRpcRouter.this, listener,
+ actionRoutingTable.getOperations(listener));
+ actionListeners = ImmutableList.<ActionRegistration<?>>builder()
+ .addAll(actionListeners)
+ .add(ret)
+ .build();
+
+ listenerNotifier.execute(ret::initialTable);
+ return ret;
+ }
+ }
}
@NonNullByDefault
--- /dev/null
+/*
+ * Copyright (c) 2023 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.broker;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.dom.api.DOMNotificationService;
+import org.opendaylight.mdsal.dom.spi.ForwardingDOMNotificationService;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Singleton
+@Component(service = DOMNotificationService.class)
+public final class RouterDOMNotificationService extends ForwardingDOMNotificationService {
+ private final @NonNull DOMNotificationService delegate;
+
+ @Inject
+ @Activate
+ public RouterDOMNotificationService(@Reference final DOMNotificationRouter router) {
+ delegate = router.notificationService();
+ }
+
+ @Override
+ protected DOMNotificationService delegate() {
+ return delegate;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.broker;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.mdsal.dom.spi.ForwardingDOMNotificationPublishService;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Singleton
+@Component(service = DOMNotificationPublishService.class)
+public final class RouterDOMPublishNotificationService extends ForwardingDOMNotificationPublishService {
+ private final @NonNull DOMNotificationPublishService delegate;
+
+ @Inject
+ @Activate
+ public RouterDOMPublishNotificationService(@Reference final DOMNotificationRouter router) {
+ delegate = router.notificationPublishService();
+ }
+
+ @Override
+ protected DOMNotificationPublishService delegate() {
+ return delegate;
+ }
+}
}
private DOMDataTreeChangeService getDOMDataTreeChangeService() {
- return domBroker.getExtensions().getInstance(DOMDataTreeChangeService.class);
+ return domBroker.extension(DOMDataTreeChangeService.class);
}
static class CommitExecutorService extends ForwardingExecutorService {
import org.opendaylight.mdsal.dom.api.DOMNotificationListener;
import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
import org.opendaylight.mdsal.dom.spi.DOMNotificationSubscriptionListener;
-import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
try (var domNotificationRouter = new DOMNotificationRouter(1024)) {
final var domNotificationListener = mock(DOMNotificationListener.class);
- domNotificationRouter.registerNotificationListener(domNotificationListener,
+ domNotificationRouter.notificationService().registerNotificationListener(domNotificationListener,
List.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif1"))));
assertEquals(1, domNotificationRouter.listeners().size());
- domNotificationRouter.registerNotificationListener(domNotificationListener,
+ domNotificationRouter.notificationService().registerNotificationListener(domNotificationListener,
List.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif2")),
Absolute.of(QName.create("urn:opendaylight:test-listener", "notif3"))));
assertEquals(3, domNotificationRouter.listeners().size());
final var domNotificationListener1 = mock(DOMNotificationListener.class);
final var domNotificationListener2 = mock(DOMNotificationListener.class);
- domNotificationRouter.registerNotificationListeners(
+ domNotificationRouter.notificationService().registerNotificationListeners(
Map.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif1")), domNotificationListener1,
Absolute.of(QName.create("urn:opendaylight:test-listener", "notif2")), domNotificationListener2));
assertEquals(2, domNotificationRouter.listeners().size());
@SuppressWarnings("checkstyle:IllegalCatch")
@Test
public void complexTest() throws Exception {
- final DOMNotificationSubscriptionListener domNotificationSubscriptionListener =
- mock(DOMNotificationSubscriptionListener.class);
+ final var domNotificationSubscriptionListener = mock(DOMNotificationSubscriptionListener.class);
doNothing().when(domNotificationSubscriptionListener).onSubscriptionChanged(any());
- final CountDownLatch latch = new CountDownLatch(1);
- final DOMNotificationListener domNotificationListener = new TestListener(latch);
- final DOMNotificationRouter domNotificationRouter = new DOMNotificationRouter(1024);
+ final var latch = new CountDownLatch(1);
+ final var domNotificationListener = new TestListener(latch);
+ final var domNotificationRouter = new DOMNotificationRouter(1024);
+ final var notifService = domNotificationRouter.notificationService();
+ final var notifPubService = domNotificationRouter.notificationPublishService();
var listeners = domNotificationRouter.listeners();
assertTrue(listeners.isEmpty());
- assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener,
- Absolute.of(TestModel.TEST_QNAME)));
- assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener,
- Absolute.of(TestModel.TEST2_QNAME)));
+ assertNotNull(notifService.registerNotificationListener(domNotificationListener,
+ List.of(Absolute.of(TestModel.TEST_QNAME))));
+ assertNotNull(notifService.registerNotificationListener(domNotificationListener,
+ List.of(Absolute.of(TestModel.TEST2_QNAME))));
listeners = domNotificationRouter.listeners();
assertFalse(listeners.isEmpty());
- ListenerRegistry<DOMNotificationSubscriptionListener> subscriptionListeners =
- domNotificationRouter.subscriptionListeners();
+ var subscriptionListeners = domNotificationRouter.subscriptionListeners();
assertEquals(0, subscriptionListeners.streamListeners().count());
assertNotNull(domNotificationRouter.registerSubscriptionListener(domNotificationSubscriptionListener));
assertSame(domNotificationSubscriptionListener,
subscriptionListeners.streamListeners().findAny().orElseThrow());
- final DOMNotification domNotification = mock(DOMNotification.class);
+ final var domNotification = mock(DOMNotification.class);
doReturn("test").when(domNotification).toString();
doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
doReturn(TEST_CHILD).when(domNotification).getBody();
- assertNotNull(domNotificationRouter.offerNotification(domNotification));
+ assertNotNull(notifPubService.offerNotification(domNotification));
- try {
- assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
- assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
- } catch (Exception e) {
- // FIXME: what is the point here?!
- assertTrue(e instanceof UnsupportedOperationException);
- }
-
- assertNotNull(domNotificationRouter.putNotification(domNotification));
+ assertNotNull(notifPubService.offerNotification(domNotification, 1, TimeUnit.SECONDS));
+ assertNotNull(notifPubService.offerNotification(domNotification, 1, TimeUnit.SECONDS));
+ assertNotNull(notifPubService.putNotification(domNotification));
}
@Test
public void offerNotification() throws Exception {
try (var domNotificationRouter = new DOMNotificationRouter(1024)) {
- final DOMNotification domNotification = mock(DOMNotification.class);
+ final var domNotification = mock(DOMNotification.class);
doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
doReturn(TEST_CHILD).when(domNotification).getBody();
- assertNotNull(domNotificationRouter.putNotification(domNotification));
- assertNotNull(domNotificationRouter.offerNotification(domNotification));
- assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
+
+ final var notifPubService = domNotificationRouter.notificationPublishService();
+ assertNotNull(notifPubService.putNotification(domNotification));
+ assertNotNull(notifPubService.offerNotification(domNotification));
+ assertNotNull(notifPubService.offerNotification(domNotification, 1, TimeUnit.SECONDS));
}
}
@Test
public void testOfferNotificationWithBlocking() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- final TestListener testListener = new TestListener(latch);
- final DOMNotification domNotification = mock(DOMNotification.class);
+ final var latch = new CountDownLatch(1);
+ final var testListener = new TestListener(latch);
+ final var domNotification = mock(DOMNotification.class);
doReturn("test").when(domNotification).toString();
doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
doReturn(TEST_CHILD).when(domNotification).getBody();
- try (TestRouter testRouter = new TestRouter(1)) {
- assertNotNull(testRouter.registerNotificationListener(testListener, Absolute.of(TestModel.TEST_QNAME)));
- assertNotNull(testRouter.registerNotificationListener(testListener, Absolute.of(TestModel.TEST2_QNAME)));
+ try (var testRouter = new TestRouter(1)) {
+ final var notifService = testRouter.notificationService();
+ final var notifPubService = testRouter.notificationPublishService();
+
+ assertNotNull(notifService.registerNotificationListener(testListener,
+ List.of(Absolute.of(TestModel.TEST_QNAME))));
+ assertNotNull(notifService.registerNotificationListener(testListener,
+ List.of(Absolute.of(TestModel.TEST2_QNAME))));
assertNotEquals(DOMNotificationPublishService.REJECTED,
- testRouter.offerNotification(domNotification, 3, TimeUnit.SECONDS));
+ notifPubService.offerNotification(domNotification, 3, TimeUnit.SECONDS));
assertTrue("Listener was not notified", latch.await(5, TimeUnit.SECONDS));
assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
assertEquals(DOMNotificationPublishService.REJECTED,
- testRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
+ notifPubService.offerNotification(domNotification, 1, TimeUnit.SECONDS));
assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
}
}
}
private static class TestListener implements DOMNotificationListener {
- private final CountDownLatch latch;
private final List<DOMNotification> receivedNotifications = new ArrayList<>();
+ private final CountDownLatch latch;
TestListener(final CountDownLatch latch) {
this.latch = latch;
latch.countDown();
}
- public List<DOMNotification> getReceivedNotifications() {
+ List<DOMNotification> getReceivedNotifications() {
return receivedNotifications;
}
}
ListenableFuture<? extends Object> publish(final DOMNotification notification,
final Collection<Reg<?>> subscribers) {
if (triggerRejected) {
- return REJECTED;
+ return DOMNotificationPublishService.REJECTED;
}
triggerRejected = true;
}
@Override
- public ListenableFuture<? extends Object> putNotification(final DOMNotification notification)
+ public ListenableFuture<? extends Object> putNotificationImpl(final DOMNotification notification)
throws InterruptedException {
Thread.sleep(2000);
- return super.putNotification(notification);
+ return super.putNotificationImpl(notification);
}
}
}
assertEquals(List.of(), rpcRouter.actionListeners());
final var listener = mock(AvailabilityListener.class);
- final var reg = rpcRouter.actionService().getExtensions()
- .getInstance(DOMActionAvailabilityExtension.class).registerAvailabilityListener(listener);
+ final var availability = rpcRouter.actionService().extension(DOMActionAvailabilityExtension.class);
+ assertNotNull(availability);
+ final var reg = availability.registerAvailabilityListener(listener);
assertNotNull(reg);
assertEquals(List.of(reg), rpcRouter.actionListeners());
*/
package org.opendaylight.mdsal.dom.spi;
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
-import org.eclipse.jdt.annotation.NonNullByDefault;
+import java.util.Collection;
+import java.util.List;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.mdsal.dom.api.DOMSchemaServiceExtension;
import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider;
*
* @author Michael Vorburger.ch
*/
-@Beta
-@NonNullByDefault
public abstract class AbstractDOMSchemaService implements DOMSchemaService, EffectiveModelContextProvider {
public abstract static class WithYangTextSources extends AbstractDOMSchemaService
implements DOMYangTextSourceProvider {
@Override
- public ClassToInstanceMap<DOMSchemaServiceExtension> getExtensions() {
- return ImmutableClassToInstanceMap.of(DOMYangTextSourceProvider.class, this);
+ public Collection<? extends DOMSchemaServiceExtension> supportedExtensions() {
+ return List.of(this);
}
}
@Override
public final EffectiveModelContext getEffectiveModelContext() {
- final EffectiveModelContext ret = getGlobalContext();
- checkState(ret != null, "Global context is not available in %s", this);
+ final var ret = getGlobalContext();
+ if (ret == null) {
+ throw new IllegalStateException("Global context is not available in " + this);
+ }
return ret;
}
}
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.mdsal.dom.api.DOMSchemaServiceExtension;
}
@Override
- public ClassToInstanceMap<DOMSchemaServiceExtension> getExtensions() {
- return ImmutableClassToInstanceMap.of(DOMYangTextSourceProvider.class, this);
+ public List<DOMSchemaServiceExtension> supportedExtensions() {
+ return List.of(this);
}
@Override
import com.google.common.annotations.Beta;
import java.util.Set;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.mdsal.dom.api.DOMActionImplementation;
import org.opendaylight.mdsal.dom.api.DOMActionInstance;
import org.opendaylight.mdsal.dom.api.DOMActionProviderService;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
@Beta
+@NonNullByDefault
public abstract class ForwardingDOMActionProviderService
- extends ForwardingDOMExtensibleService<DOMActionProviderService, DOMActionProviderServiceExtension>
+ extends ForwardingDOMService<DOMActionProviderService, DOMActionProviderServiceExtension>
implements DOMActionProviderService {
@Override
- public <T extends @NonNull DOMActionImplementation> ObjectRegistration<T> registerActionImplementation(
- final T implementation, final Set<@NonNull DOMActionInstance> instances) {
+ public <T extends DOMActionImplementation> ObjectRegistration<T> registerActionImplementation(
+ final T implementation, final Set<DOMActionInstance> instances) {
return delegate().registerActionImplementation(implementation, instances);
}
}
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMActionServiceExtension;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
@Beta
+@NonNullByDefault
public abstract class ForwardingDOMActionService
- extends ForwardingDOMExtensibleService<DOMActionService, DOMActionServiceExtension>
- implements DOMActionService {
+ extends ForwardingDOMService<DOMActionService, DOMActionServiceExtension> implements DOMActionService {
@Override
public ListenableFuture<? extends DOMActionResult> invokeAction(final Absolute type,
final DOMDataTreeIdentifier path, final ContainerNode input) {
import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
/**
- * Utility {@link DOMDataBroker} implementation which forwards all interface
- * method invocation to a delegate instance.
+ * Utility {@link DOMDataBroker} implementation which forwards all interface method invocation to a delegate instance.
*/
-public abstract class ForwardingDOMDataBroker
- extends ForwardingDOMExtensibleService<DOMDataBroker, DOMDataBrokerExtension>
+public abstract class ForwardingDOMDataBroker extends ForwardingDOMService<DOMDataBroker, DOMDataBrokerExtension>
implements DOMDataBroker {
@Override
public DOMDataTreeReadTransaction newReadOnlyTransaction() {
+++ /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.spi;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ForwardingObject;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.dom.api.DOMExtensibleService;
-import org.opendaylight.mdsal.dom.api.DOMServiceExtension;
-
-@Beta
-public abstract class ForwardingDOMExtensibleService<T extends DOMExtensibleService<T, E>,
- E extends DOMServiceExtension<T, E>> extends ForwardingObject
- implements DOMExtensibleService<T, E> {
- @Override
- public ClassToInstanceMap<E> getExtensions() {
- return delegate().getExtensions();
- }
-
- @Override
- protected abstract @NonNull T delegate();
-}
--- /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.spi;
+
+import com.google.common.collect.ForwardingObject;
+import java.util.Collection;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.dom.api.DOMService;
+
+public abstract class ForwardingDOMService<T extends DOMService<T, E>, E extends DOMService.Extension<T, E>>
+ extends ForwardingObject implements DOMService<T, E> {
+ @Override
+ @SuppressWarnings("hiding")
+ public final <T extends E> @Nullable T extension(final Class<T> type) {
+ return DOMService.super.extension(type);
+ }
+
+ @Override
+ @SuppressWarnings("hiding")
+ public final <T extends E> Optional<T> findExtension(final Class<T> type) {
+ return DOMService.super.findExtension(type);
+ }
+
+ @Override
+ public final Collection<? extends E> supportedExtensions() {
+ return supportedExtensions(delegate().supportedExtensions());
+ }
+
+ protected @NonNull Collection<? extends E> supportedExtensions(final @NonNull Collection<? extends E> extensions) {
+ return extensions;
+ }
+
+ @Override
+ protected abstract @NonNull T delegate();
+}
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.ImmutableClassToInstanceMap;
import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.mdsal.dom.api.DOMService;
+import org.opendaylight.mdsal.dom.api.DOMService.Extension;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
public final class SimpleDOMMountPoint implements DOMMountPoint {
-
- private final YangInstanceIdentifier identifier;
- private final ClassToInstanceMap<DOMService> services;
+ private final ImmutableClassToInstanceMap<DOMService<?, ?>> services;
+ private final @NonNull YangInstanceIdentifier identifier;
private SimpleDOMMountPoint(final YangInstanceIdentifier identifier,
- final ClassToInstanceMap<DOMService> services) {
+ final ClassToInstanceMap<DOMService<?, ?>> services) {
this.identifier = requireNonNull(identifier);
this.services = ImmutableClassToInstanceMap.copyOf(services);
}
public static SimpleDOMMountPoint create(final YangInstanceIdentifier identifier,
- final ClassToInstanceMap<DOMService> services) {
+ final ClassToInstanceMap<DOMService<?, ?>> services) {
return new SimpleDOMMountPoint(identifier, services);
}
}
@Override
- public <T extends DOMService> Optional<T> getService(final Class<T> cls) {
+ public <T extends DOMService<T, E>, E extends Extension<T, E>> Optional<T> getService(final Class<T> cls) {
return Optional.ofNullable(services.getInstance(cls));
}
}
*/
package org.opendaylight.mdsal.dom.spi;
-import static org.mockito.ArgumentMatchers.any;
+import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-import com.google.common.collect.ImmutableClassToInstanceMap;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataBrokerExtension;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
-@RunWith(MockitoJUnitRunner.StrictStubs.class)
-public class ForwardingDOMDataBrokerTest extends ForwardingDOMDataBroker {
- @Mock(name = "domDataBroker")
- public DOMDataBroker domDataBroker;
+@ExtendWith(MockitoExtension.class)
+class ForwardingDOMDataBrokerTest {
+ private interface Extension extends DOMDataBrokerExtension {
+ // Nothing else
+ }
+
+ @Mock
+ private DOMTransactionChain chain;
+ @Mock
+ private DOMTransactionChainListener chainListener;
+ @Mock
+ private Extension extension;
+ @Mock
+ private DOMDataBroker domDataBroker;
+ @Mock
+ private DOMDataTreeReadTransaction readTx;
+ @Mock
+ private DOMDataTreeWriteTransaction writeTx;
@Test
- public void basicTest() throws Exception {
- doReturn(null).when(domDataBroker).createTransactionChain(any());
- this.createTransactionChain(null);
- verify(domDataBroker).createTransactionChain(any());
-
- doReturn(ImmutableClassToInstanceMap.of()).when(domDataBroker).getExtensions();
- this.getExtensions();
- verify(domDataBroker).getExtensions();
-
- doReturn(null).when(domDataBroker).newReadOnlyTransaction();
- this.newReadOnlyTransaction();
- verify(domDataBroker).newReadOnlyTransaction();
-
- doReturn(null).when(domDataBroker).newWriteOnlyTransaction();
- this.newWriteOnlyTransaction();
- verify(domDataBroker).newWriteOnlyTransaction();
- }
+ void basicTest() throws Exception {
+ final var impl = new ForwardingDOMDataBroker() {
+ @Override
+ protected DOMDataBroker delegate() {
+ return domDataBroker;
+ }
+ };
+
+ doReturn(chain).when(domDataBroker).createTransactionChain(chainListener);
+ assertSame(chain, impl.createTransactionChain(chainListener));
+
+ doReturn(List.of(extension)).when(domDataBroker).supportedExtensions();
+ assertSame(extension, impl.extension(Extension.class));
+
+ doReturn(readTx).when(domDataBroker).newReadOnlyTransaction();
+ assertSame(readTx, impl.newReadOnlyTransaction());
- @Override
- protected DOMDataBroker delegate() {
- return domDataBroker;
+ doReturn(writeTx).when(domDataBroker).newWriteOnlyTransaction();
+ assertSame(writeTx, impl.newWriteOnlyTransaction());
}
}
\ No newline at end of file
*/
package org.opendaylight.mdsal.dom.spi;
+import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier;
import org.opendaylight.mdsal.dom.api.DOMRpcImplementation;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
-@RunWith(MockitoJUnitRunner.StrictStubs.class)
-public class ForwardingDOMRpcImplementationTest extends ForwardingDOMRpcImplementation {
- @Mock(name = "domRpcImplementation")
- public DOMRpcImplementation domRpcImplementation;
+@ExtendWith(MockitoExtension.class)
+class ForwardingDOMRpcImplementationTest {
+ @Mock
+ private DOMRpcImplementation domRpcImplementation;
+ @Mock
+ private DOMRpcIdentifier domRpcIdentifier;
+ @Mock
+ private ListenableFuture<DOMRpcResult> rpcFuture;
@Test
- public void basicTest() throws Exception {
- final DOMRpcIdentifier domRpcIdentifier = mock(DOMRpcIdentifier.class);
+ void basicTest() {
+ var impl = new ForwardingDOMRpcImplementation() {
+ @Override
+ protected DOMRpcImplementation delegate() {
+ return domRpcImplementation;
+ }
+ };
- doReturn(null).when(domRpcImplementation).invokeRpc(domRpcIdentifier, null);
- this.invokeRpc(domRpcIdentifier, null);
- verify(domRpcImplementation).invokeRpc(domRpcIdentifier, null);
- }
-
- @Override
- protected DOMRpcImplementation delegate() {
- return domRpcImplementation;
+ doReturn(rpcFuture).when(domRpcImplementation).invokeRpc(domRpcIdentifier, null);
+ assertSame(rpcFuture, impl.invokeRpc(domRpcIdentifier, null));
}
}
\ No newline at end of file
*/
package org.opendaylight.mdsal.dom.spi;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
import com.google.common.collect.ImmutableClassToInstanceMap;
-import org.junit.Test;
+import java.util.Optional;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.dom.api.DOMService;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-public class SimpleDOMMountPointTest {
- @Test
- public void basicTest() throws Exception {
- final var domService = mock(DOMService.class);
- final var classToInstanceMap = ImmutableClassToInstanceMap.of(DOMService.class, domService);
+@ExtendWith(MockitoExtension.class)
+class SimpleDOMMountPointTest {
+ private interface MockService extends DOMService<MockService, MockService.Extension> {
+ interface Extension extends DOMService.Extension<MockService, Extension> {
+ // Marker
+ }
+ }
- final SimpleDOMMountPoint simpleDOMMountPoint =
- SimpleDOMMountPoint.create(YangInstanceIdentifier.of(), classToInstanceMap);
- assertNotNull(simpleDOMMountPoint);
+ @Mock
+ private MockService service;
+
+ @Test
+ void basicTest() {
+ final var impl = SimpleDOMMountPoint.create(YangInstanceIdentifier.of(),
+ ImmutableClassToInstanceMap.of(MockService.class, service));
+ assertNotNull(impl);
- assertSame(YangInstanceIdentifier.of(), simpleDOMMountPoint.getIdentifier());
- assertTrue(simpleDOMMountPoint.getService(DOMService.class).isPresent());
- assertSame(domService, simpleDOMMountPoint.getService(DOMService.class).orElseThrow());
+ assertSame(YangInstanceIdentifier.of(), impl.getIdentifier());
+ assertEquals(Optional.of(service), impl.getService(MockService.class));
}
}
\ No newline at end of file
final int listenPort, final Duration keepaliveInterval,
final int maxMissedKeepalives) {
LOG.debug("Source {}", enabled ? "enabled" : "disabled");
- final DOMDataTreeChangeService dtcs = broker.getExtensions().getInstance(DOMDataTreeChangeService.class);
+ final var dtcs = broker.extension(DOMDataTreeChangeService.class);
verify(dtcs != null, "Missing DOMDataTreeChangeService in broker %s", broker);
checkArgument(maxMissedKeepalives > 0, "max-missed-keepalives %s must be greater than 0", maxMissedKeepalives);
return enabled ? singleton.registerClusterSingletonService(new SourceSingletonService(bootstrap,
import org.eclipse.jdt.annotation.Nullable;
/**
- * Implementation of {@link CloseTracked} which can be used as a field in
- * another class which implements {@link CloseTracked} and delegates its methods
- * to this.
+ * Implementation of {@link CloseTracked} which can be used as a field in another class which implements
+ * {@link CloseTracked} and delegates its methods to this.
*
- * <p>This is useful if that class already has another parent class.
- * If it does not, then it's typically more convenient to just extend AbstractCloseTracked.
+ * <p>
+ * This is useful if that class already has another parent class. If it does not, then it's typically more convenient to
+ * just extend AbstractCloseTracked.
*
* @author Michael Vorburger.ch
*/
final class CloseTrackedTrait<T extends CloseTracked<T>> implements CloseTracked<T> {
-
// NB: It's important that we keep a Throwable here, and not directly the StackTraceElement[] !
// This is because creating a new Throwable() is a lot less expensive in terms of runtime overhead
// than actually calling its getStackTrace(), which we can delay until we really need to.
if (transactionChainRegistry.isDebugContextEnabled()) {
// NB: We're NOT doing the (expensive) getStackTrace() here just yet (only below)
// TODO When we're on Java 9, then instead use the new java.lang.StackWalker API..
- this.allocationContext = new Throwable();
+ allocationContext = new Throwable();
} else {
- this.allocationContext = null;
+ allocationContext = null;
}
this.realCloseTracked = requireNonNull(realCloseTracked, "realCloseTracked");
- this.closeTrackedRegistry = requireNonNull(transactionChainRegistry, "transactionChainRegistry");
- this.closeTrackedRegistry.add(this);
+ closeTrackedRegistry = requireNonNull(transactionChainRegistry, "transactionChainRegistry");
+ closeTrackedRegistry.add(this);
}
@Override
@SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
public @Nullable StackTraceElement[] getAllocationContextStackTrace() {
- return allocationContext != null ? allocationContext.getStackTrace() : null;
+ final var local = allocationContext;
+ return local != null ? local.getStackTrace() : null;
}
public void removeFromTrackedRegistry() {
import static java.util.Objects.requireNonNull;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.MutableClassToInstanceMap;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.PrintStream;
import java.util.ArrayList;
@SuppressWarnings("checkstyle:JavadocStyle")
//...because otherwise it whines about the elements in the @code block even though it's completely valid Javadoc
-
/**
* TracingBroker logs "write" operations and listener registrations to the md-sal. It logs the instance identifier path,
* the objects themselves, as well as the stack trace of the call invoking the registration or write operation.
* watchRegistrations and allow all registrations to be logged.
* </li>
* </ul>
- *
*/
public class TracingBroker implements TracingDOMDataBroker {
@SuppressFBWarnings("SLF4J_LOGGER_SHOULD_BE_PRIVATE")
}
@Override
- public ClassToInstanceMap<DOMDataBrokerExtension> getExtensions() {
- final ClassToInstanceMap<DOMDataBrokerExtension> delegateExt = delegate.getExtensions();
- final DOMDataTreeChangeService treeChangeSvc = delegateExt.getInstance(DOMDataTreeChangeService.class);
- if (treeChangeSvc == null) {
- return delegateExt;
- }
-
- final ClassToInstanceMap<DOMDataBrokerExtension> res = MutableClassToInstanceMap.create(delegateExt);
- res.put(DOMDataTreeChangeService.class, new DOMDataTreeChangeService() {
- @Override
- public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerDataTreeChangeListener(
- final DOMDataTreeIdentifier domDataTreeIdentifier, final L listener) {
- if (isRegistrationWatched(domDataTreeIdentifier.getRootIdentifier(),
- domDataTreeIdentifier.getDatastoreType())) {
- LOG.warn("{} registration (registerDataTreeChangeListener) for {} from {}.",
+ public <T extends DOMDataBrokerExtension> T extension(final Class<T> type) {
+ final var ext = delegate.extension(type);
+ if (DOMDataTreeChangeService.class.equals(type) && ext instanceof DOMDataTreeChangeService treeChange) {
+ return type.cast(new DOMDataTreeChangeService() {
+ @Override
+ public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerDataTreeChangeListener(
+ final DOMDataTreeIdentifier domDataTreeIdentifier, final L listener) {
+ final var rootId = domDataTreeIdentifier.getRootIdentifier();
+ if (isRegistrationWatched(rootId, domDataTreeIdentifier.getDatastoreType())) {
+ LOG.warn("{} registration (registerDataTreeChangeListener) for {} from {}.",
listener instanceof ClusteredDOMDataTreeChangeListener ? "Clustered" : "Non-clustered",
- toPathString(domDataTreeIdentifier.getRootIdentifier()), getStackSummary());
+ toPathString(rootId), getStackSummary());
+ }
+ return treeChange.registerDataTreeChangeListener(domDataTreeIdentifier, listener);
}
- return treeChangeSvc.registerDataTreeChangeListener(domDataTreeIdentifier, listener);
- }
- });
-
- return res;
+ });
+ }
+ return ext;
}
@Override