import org.opendaylight.controller.sal.binding.api.BindingAwareService;
/**
- *
* Marker interface for MD-SAL services which are available for users of MD-SAL.
*
+ * <p>
* BindingService is marker interface for infrastructure services provided by
* the SAL. These services may be session-specific, and wrapped by custom
* delegator patterns in order to introduce additional semantics / checks
* to the system.
*
+ * <p>
* This interface extends {@link BindingAwareService}, order to be make
* new services available via
* {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext}
/**
* A chain of transactions.
+ *
* <p>
* For more information about transaction chaining and transaction chains
* see {@link TransactionChain}.
* @see TransactionChain
*
*/
-public interface BindingTransactionChain extends TransactionFactory, TransactionChain<InstanceIdentifier<?>, DataObject> {
- /**
- * {@inheritDoc}
- */
+public interface BindingTransactionChain extends TransactionFactory,
+ TransactionChain<InstanceIdentifier<?>, DataObject> {
@Override
ReadOnlyTransaction newReadOnlyTransaction();
- /**
- * {@inheritDoc}
- */
@Override
ReadWriteTransaction newReadWriteTransaction();
- /**
- * {@inheritDoc}
- */
@Override
WriteTransaction newWriteOnlyTransaction();
}
/**
* ClusteredDataTreeChangeListener is a marker interface to enable data tree change notifications on all
* instances in a cluster where this listener is registered.
+ *
* <p>
* Applications should implement ClusteredDataTreeChangeListener instead of {@link DataTreeChangeListener},
* if they want to listen for data tree change notifications on any node of a clustered data store.
/**
* Provides access to a conceptual data tree store and also provides the ability to
* subscribe for changes to data under a given branch of the tree.
+ *
* <p>
* For more information on usage, please see the documentation in {@link AsyncDataBroker}.
*
* @see TransactionChainFactory
*/
public interface DataBroker extends AsyncDataBroker<InstanceIdentifier<?>, DataObject, DataChangeListener>,
- TransactionChainFactory<InstanceIdentifier<?>, DataObject>, TransactionFactory, BindingService, DataTreeChangeService {
- /**
- * {@inheritDoc}
- */
+ TransactionChainFactory<InstanceIdentifier<?>, DataObject>, TransactionFactory, BindingService,
+ DataTreeChangeService {
@Override
ReadOnlyTransaction newReadOnlyTransaction();
- /**
- * {@inheritDoc}
- */
@Override
ReadWriteTransaction newReadWriteTransaction();
- /**
- * {@inheritDoc}
- */
@Override
WriteTransaction newWriteOnlyTransaction();
- /**
- * {@inheritDoc}
- */
@Override
ListenerRegistration<DataChangeListener> registerDataChangeListener(LogicalDatastoreType store,
InstanceIdentifier<?> path, DataChangeListener listener, DataChangeScope triggeringScope);
- /**
- * {@inheritDoc}
- */
@Override
BindingTransactionChain createTransactionChain(TransactionChainListener listener);
}
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
/**
- * Modified Data Object.
- *
- * Represents modification of Data Object.
- *
+ * Represents a modification of DataObject.
*/
-public interface DataObjectModification<T extends DataObject> extends org.opendaylight.yangtools.concepts.Identifiable<PathArgument> {
+public interface DataObjectModification<T extends DataObject>
+ extends org.opendaylight.yangtools.concepts.Identifiable<PathArgument> {
enum ModificationType {
/**
- *
* Child node (direct or indirect) was modified.
*
*/
SUBTREE_MODIFIED,
+
/**
- *
* Node was explicitly created / overwritten.
*
*/
+
WRITE,
/**
- *
* Node was deleted.
*
*/
@Nonnull Class<T> getDataType();
/**
- *
- * Returns type of modification
+ * Returns type of modification.
*
* @return type Type of performed modification.
*/
@Nonnull Collection<DataObjectModification<? extends DataObject>> getModifiedChildren();
/**
- * Returns container child modification if {@code child} was modified by this
- * modification.
+ * Returns container child modification if {@code child} was modified by this modification.
*
+ * <p>
* For accessing all modified list items consider iterating over {@link #getModifiedChildren()}.
*
* @param child Type of child - must be only container
* @throws IllegalArgumentException If supplied {@code child} class is not valid child according
* to generated model.
*/
- @Nullable <C extends ChildOf<? super T>> DataObjectModification<C> getModifiedChildContainer(@Nonnull Class<C> child);
+ @Nullable <C extends ChildOf<? super T>> DataObjectModification<C> getModifiedChildContainer(
+ @Nonnull Class<C> child);
/**
- * Returns augmentation child modification if {@code augmentation} was modified by this
- * modification.
+ * Returns augmentation child modification if {@code augmentation} was modified by this modification.
*
+ * <p>
* For accessing all modified list items consider iterating over {@link #getModifiedChildren()}.
*
* @param augmentation Type of augmentation - must be only container
* @throws IllegalArgumentException If supplied {@code augmentation} class is not valid augmentation
* according to generated model.
*/
- @Nullable <C extends Augmentation<T> & DataObject> DataObjectModification<C> getModifiedAugmentation(@Nonnull Class<C> augmentation);
+ @Nullable <C extends Augmentation<T> & DataObject> DataObjectModification<C> getModifiedAugmentation(
+ @Nonnull Class<C> augmentation);
/**
* @throws IllegalArgumentException If supplied {@code listItem} class is not valid child according
* to generated model.
*/
- <C extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<C>> DataObjectModification<C> getModifiedChildListItem(
- @Nonnull Class<C> listItem,@Nonnull K listKey);
+ <C extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<C>> DataObjectModification<C>
+ getModifiedChildListItem(@Nonnull Class<C> listItem,@Nonnull K listKey);
/**
* Returns a child modification if a node identified by {@code childArgument} was modified by
*
*/
@Nullable DataObjectModification<? extends DataObject> getModifiedChild(PathArgument childArgument);
-
}
* data tree changes. This interface differs from {@link DataChangeListener}
* in that it provides a cursor-based view of the change, which has potentially
* lower overhead and allow more flexible consumption of change event.
+ *
* <p>
* Note: this interface enables notifications only at the leader of the data store, if clustered. If you want
* notifications on all instances in a cluster, use the {@link ClusteredDataTreeChangeListener}.
* to recover from such events. Event producers are expected to exert reasonable
* effort to suppress such events.
*
+ * <p>
* In other words, it is completely acceptable to observe
* a {@link DataObjectModification}, while the state observed before and
* after- data items compare as equal.
* Registers a {@link DataTreeChangeListener} 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 DataTreeIdentifier}.
- * <p>
*
+ * <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.
+ *
* <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
* 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
* your listener using {@link ListenerRegistration#close()} to stop
* delivery of change events.
*/
- @Nonnull <T extends DataObject,L extends DataTreeChangeListener<T>> ListenerRegistration<L> registerDataTreeChangeListener(@Nonnull DataTreeIdentifier<T> treeId, @Nonnull L listener);
+ @Nonnull <T extends DataObject,L extends DataTreeChangeListener<T>> ListenerRegistration<L>
+ registerDataTreeChangeListener(@Nonnull DataTreeIdentifier<T> treeId, @Nonnull L listener);
}
* A unique identifier for a particular subtree. It is composed of the logical
* data store type and the instance identifier of the root node.
*/
-public final class DataTreeIdentifier<T extends DataObject> implements Immutable, Path<DataTreeIdentifier<?>>, Serializable {
+public final class DataTreeIdentifier<T extends DataObject> implements Immutable,
+ Path<DataTreeIdentifier<?>>, Serializable {
private static final long serialVersionUID = 1L;
private final InstanceIdentifier<T> rootIdentifier;
private final LogicalDatastoreType datastoreType;
@Override
public String toString() {
- return getClass().getSimpleName() + "{datastoreType = " + datastoreType + ", rootIdentifier = " +
- rootIdentifier + "}";
+ return getClass().getSimpleName() + "{datastoreType = " + datastoreType + ", rootIdentifier = "
+ + rootIdentifier + "}";
}
}
import com.google.common.collect.ForwardingObject;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.ListenableFuture;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
public Object getIdentifier() {
return delegate.getIdentifier();
}
-
}
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-public interface MountPoint extends Identifiable<InstanceIdentifier<?>>{
-
+public interface MountPoint extends Identifiable<InstanceIdentifier<?>> {
<T extends BindingService> Optional<T> getService(Class<T> service);
-
}
* - {@link #offerNotification(Notification, int, TimeUnit)}, which may block
* for specified time if resources are thin.
*
+ * <p>
* The actual delivery to listeners is asynchronous and implementation-specific.
* Users of this interface should not make any assumptions as to whether the
* notification has or has not been seen.
* Well-known value indicating that the binding-aware implementation is currently not
* able to accept a notification.
*/
- ListenableFuture<Object> REJECTED = Futures.immediateFailedFuture(new NotificationRejectedException("Rejected due to resource constraints."));
+ ListenableFuture<Object> REJECTED = Futures.immediateFailedFuture(new NotificationRejectedException(
+ "Rejected due to resource constraints."));
/**
* Publishes a notification to subscribed listeners. This initiates
* listeners can happen asynchronously, potentially after a call to
* this method returns.
*
+ * <p>
* Still guaranteed not to block. Returns Listenable Future which will complete once.
*
* @param notification
* the notification to publish.
* @return A listenable future which will report completion when the service has finished
- * propagating the notification to its immediate registrants, or {@link #REJECTED} if resource
- * constraints prevent
+ * propagating the notification to its immediate registrants, or {@link #REJECTED} if resource
+ * constraints prevent
* @throws NullPointerException if the notification is null
*/
ListenableFuture<?> offerNotification(Notification notification);
* @param unit a TimeUnit determining how to interpret the
* timeout parameter
* @return A listenable future which will report completion when the service has finished
- * propagating the notification to its immediate registrants, or {@link #REJECTED} if resource
- * constraints prevent
+ * propagating the notification to its immediate registrants, or {@link #REJECTED} if resource
+ * constraints prevent
* @throws InterruptedException if interrupted while waiting
* @throws NullPointerException if the notification or unit is null
* @throws IllegalArgumentException if timeout is negative.
/**
* Notification broker which allows clients to subscribe for and publish YANG-modeled notifications.
*
+ * <p>
* Each YANG module which defines notifications results in a generated interface <code>{ModuleName}Listener</code>
* which handles all the notifications defined in the YANG model. Each notification type translates to
* a specific method of the form <code>on{NotificationType}</code> on the generated interface.
* The generated interface also extends the
* {@link org.opendaylight.yangtools.yang.binding.NotificationListener} interface and implementations
- * are registered using {@link #registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)}
- * method.
+ * are registered using
+ * {@link #registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)} method.
*
* <h3>Dispatch Listener Example</h3>
+ *
* <p>
* Lets assume we have following YANG model:
*
* }
* </pre>
*
+ * <p>
* The generated interface will be:
* {@code
* public interface ExampleListener extends NotificationListener {
/**
* A transaction that provides a stateful read-only view of the data tree.
+ *
* <p>
* For more information on usage and examples, please see the documentation in
* {@link org.opendaylight.controller.md.sal.common.api.data.AsyncReadTransaction}.
*/
-public interface ReadOnlyTransaction extends ReadTransaction, AsyncReadOnlyTransaction<InstanceIdentifier<?>, DataObject> {
-
+public interface ReadOnlyTransaction extends ReadTransaction, AsyncReadOnlyTransaction<InstanceIdentifier<?>,
+ DataObject> {
}
*/
package org.opendaylight.controller.md.sal.binding.api;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.controller.md.sal.common.api.data.AsyncReadTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
/**
* A transaction that provides read access to a logical data store.
+ *
* <p>
* For more information on usage and examples, please see the documentation in {@link AsyncReadTransaction}.
*/
/**
* A transaction that enables combined read/write capabilities.
+ *
* <p>
* For more information on usage and examples, please see the documentation in {@link AsyncReadWriteTransaction}.
*/
-public interface ReadWriteTransaction extends ReadTransaction, WriteTransaction, AsyncReadWriteTransaction<InstanceIdentifier<?>, DataObject> {
-
+public interface ReadWriteTransaction extends ReadTransaction, WriteTransaction,
+ AsyncReadWriteTransaction<InstanceIdentifier<?>, DataObject> {
}
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-public interface TransactionFactory extends AsyncDataTransactionFactory<InstanceIdentifier<?>, DataObject>{
-
+public interface TransactionFactory extends AsyncDataTransactionFactory<InstanceIdentifier<?>, DataObject> {
@Override
ReadOnlyTransaction newReadOnlyTransaction();
@Override
WriteTransaction newWriteOnlyTransaction();
-
}
/**
* A transaction that provides mutation capabilities on a data tree.
+ *
* <p>
* For more information on usage and examples, please see the documentation in {@link AsyncWriteTransaction}.
*/
import org.osgi.framework.BundleContext;
@Deprecated
-public abstract class AbstractBindingAwareConsumer extends AbstractBrokerAwareActivator implements BindingAwareConsumer {
-
+public abstract class AbstractBindingAwareConsumer extends AbstractBrokerAwareActivator
+ implements BindingAwareConsumer {
@Override
protected final void onBrokerAvailable(BindingAwareBroker broker, BundleContext context) {
broker.registerConsumer(this, context);
}
-
}
*/
package org.opendaylight.controller.sal.binding.api;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.osgi.framework.BundleContext;
@Deprecated
-public abstract class AbstractBindingAwareProvider extends AbstractBrokerAwareActivator implements BindingAwareProvider {
-
+public abstract class AbstractBindingAwareProvider extends AbstractBrokerAwareActivator
+ implements BindingAwareProvider {
@Override
protected final void onBrokerAvailable(BindingAwareBroker broker, BundleContext context) {
- ProviderContext ctx = broker.registerProvider(this, context);
+ broker.registerProvider(this, context);
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public abstract class AbstractBrokerAwareActivator implements BundleActivator {
- private static final ExecutorService mdActivationPool = Executors.newCachedThreadPool();
+ private static final ExecutorService MD_ACTIVATION_POOL = Executors.newCachedThreadPool();
private BundleContext context;
private ServiceTracker<BindingAwareBroker, BindingAwareBroker> tracker;
private BindingAwareBroker broker;
- private ServiceTrackerCustomizer<BindingAwareBroker, BindingAwareBroker> customizer = new ServiceTrackerCustomizer<BindingAwareBroker, BindingAwareBroker>() {
+ private final ServiceTrackerCustomizer<BindingAwareBroker, BindingAwareBroker> customizer =
+ new ServiceTrackerCustomizer<BindingAwareBroker, BindingAwareBroker>() {
@Override
public BindingAwareBroker addingService(ServiceReference<BindingAwareBroker> reference) {
broker = context.getService(reference);
- mdActivationPool.execute(() -> onBrokerAvailable(broker, context));
+ MD_ACTIVATION_POOL.execute(() -> onBrokerAvailable(broker, context));
return broker;
}
@Override
public void removedService(ServiceReference<BindingAwareBroker> reference, BindingAwareBroker service) {
broker = context.getService(reference);
- mdActivationPool.execute(() -> onBrokerRemoved(broker, context));
+ MD_ACTIVATION_POOL.execute(() -> onBrokerRemoved(broker, context));
}
};
@Override
- public final void start(BundleContext context) throws Exception {
- this.context = context;
- startImpl(context);
- tracker = new ServiceTracker<>(context, BindingAwareBroker.class, customizer);
+ public final void start(BundleContext bundleContext) throws Exception {
+ this.context = bundleContext;
+ startImpl(bundleContext);
+ tracker = new ServiceTracker<>(bundleContext, BindingAwareBroker.class, customizer);
tracker.open();
}
@Override
- public final void stop(BundleContext context) throws Exception {
+ public final void stop(BundleContext bundleContext) throws Exception {
tracker.close();
- stopImpl(context);
+ stopImpl(bundleContext);
}
-
/**
* Called when this bundle is started (before
* {@link BindingAwareProvider#onSessionInitiated(ProviderContext)} so the Framework can perform
* <p>
* This method must complete and return to its caller in a timely manner.
*
- * @param context
+ * @param bundleContext
* The execution context of the bundle being started.
* @throws RuntimeException
* If this method throws an exception, this bundle is marked as
* listeners, unregister all services registered by this bundle,
* and release all services used by this bundle.
*/
- protected void startImpl(BundleContext context) {
+ protected void startImpl(BundleContext bundleContext) {
// NOOP
}
* <p>
* This method must complete and return to its caller in a timely manner.
*
- * @param context The execution context of the bundle being stopped.
+ * @param bundleContext The execution context of the bundle being stopped.
* @throws RuntimeException If this method throws an exception, the bundle is still
* marked as stopped, and the Framework will remove the bundle's
* listeners, unregister all services registered by the bundle, and
* release all services used by the bundle.
*/
- protected void stopImpl(BundleContext context) {
+ protected void stopImpl(BundleContext bundleContext) {
// NOOP
}
+ protected abstract void onBrokerAvailable(BindingAwareBroker bindingBroker, BundleContext bundleContext);
- protected abstract void onBrokerAvailable(BindingAwareBroker broker, BundleContext context);
-
- protected void onBrokerRemoved(BindingAwareBroker broker, BundleContext context) {
- stopImpl(context);
+ protected void onBrokerRemoved(BindingAwareBroker bindingBroker, BundleContext bundleContext) {
+ stopImpl(bundleContext);
}
}
/**
* Binding-aware core of the SAL layer responsible for wiring the SAL consumers.
*
+ * <p>
* The responsibility of the broker is to maintain registration of SAL
* functionality Consumers and Providers, store provider and
* consumer specific context and functionality registration via
* {@link ConsumerContext} and provide access to infrastructure services, which
* removes direct dependencies between providers and consumers.
*
+ * <p>
* The Binding-aware broker is also responsible for translation from Java
* classes modeling the functionality and data to binding-independent form which
* is used in SAL Core.
*
- *
* <h3>Infrastructure services</h3> Some examples of infrastructure services:
*
* <ul>
* {@link NotificationProviderService}
* </ul>
*
+ * <p>
* The services are exposed via session.
*
* <h3>Session-based access</h3>
*
+ * <p>
* The providers and consumers needs to register in order to use the
* binding-independent SAL layer and to expose functionality via SAL layer.
*
+ * <p>
* For more information about session-based access see {@link ConsumerContext}
* and {@link ProviderContext}
*/
interface ConsumerContext extends RpcConsumerRegistry {
/**
- * Returns a session specific instance (implementation) of requested
- * binding-aware infrastructural service
+ * Returns a session specific instance (implementation) of requested binding-aware infrastructure service.
*
* @param service
* Broker service
RoutedRegistration<Class<? extends BaseIdentity>, InstanceIdentifier<?>, T> {
/**
- * Register particular instance identifier to be processed by this
- * RpcService
- *
- * Deprecated in favor of RoutedRegistration#registerPath(Object, Object).
+ * Register particular instance identifier to be processed by this RpcService.
*
- * @param context
- * @param instance
+ * @deprecated in favor of RoutedRegistration#registerPath(Object, Object).
*/
@Deprecated
void registerInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance);
/**
- * Unregister particular instance identifier to be processed by this
- * RpcService
- *
- * Deprecated in favor of RoutedRegistration#unregisterPath(Class, InstanceIdentifier).
+ * Unregister particular instance identifier to be processed by this RpcService.
*
- * @param context
- * @param instance
+ * @deprecated in favor of RoutedRegistration#unregisterPath(Class, InstanceIdentifier).
*/
@Deprecated
void unregisterInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance);
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
/**
-*
-* A developer implemented component that gets registered with the Broker.
-*
-* Semantically, a consumer may:
-*
-* <ol>
-* <li>Subscribe for Notifications </li>
-* <li>Invoke RPCs</li>
-* <li>Read from either the operational or config data tree</li>
-* <li>Write to the config data tree</li>
-* </ol>
-* If you need to:
-* <ol>
-* <li> Emit Notifications</li>
-* <li> Provide the implementation of RPCs </li>
-* <li> Write to the operational data tree </li>
-* </ol>
-*
-* Consider using a BindingAwareProvider
-*
-* Examples:
-*
-* To get a NotificationService:
-*
-* {code
-* public void onSessionInitiated(ProviderContext session) {
-* NotificationProviderService notificationService = session.getSALService(NotificationProviderService.class);
-* notificationService.publish(notification)
-* }
-* where notification is an instance of a modeled Notification.
-* For more information on sending notifications via the NotificationProviderService
-* @see org.opendaylight.controller.sal.binding.api.NotificationProviderService
-*
-*
-* A consumer can *invoke* and RPC ( ie, call foo(fooArgs)) but it cannot register an RPC
-* implementation with the MD-SAL that others can invoke(call).
-* To get an invokable RPC:
-*
-* {code
-* public void onSessionInitiated(ProviderContext session) {
-* MyService rpcFlowSalService = session.getRpcService(MyService.class);
-* }
-*
-* Where MyService.class is a Service interface generated from a yang model with RPCs modeled in it. The returned
-* rpcFlowSalService can be used like any other object by invoking its methods. Note, nothing special needs to be done
-* for RoutedRPCs. They just work.
-*
-* To get a DataBroker to allow access to the data tree:
-*
-* {code
-* public void onSessionInitiated(final ProviderContext session) {
-* DataBroker databroker = session.getSALService(BindingDataBroker.class);
-* }
-* }
+ * A developer implemented component that gets registered with the Broker.
+ *
+ * <p>
+ * Semantically, a consumer may:
+ *
+ * <ol>
+ * <li>Subscribe for Notifications </li>
+ * <li>Invoke RPCs</li>
+ * <li>Read from either the operational or config data tree</li>
+ * <li>Write to the config data tree</li>
+ * </ol>
+ * If you need to:
+ * <ol>
+ * <li> Emit Notifications</li>
+ * <li> Provide the implementation of RPCs </li>
+ * <li> Write to the operational data tree </li>
+ * </ol>
+ *
+ * <p>
+ * Consider using a BindingAwareProvider
+ *
+ * <p>
+ * Examples:
+ *
+ * <p>
+ * To get a NotificationService:
+ *
+ * <p>
+ * {code
+ * public void onSessionInitiated(ProviderContext session) {
+ * NotificationProviderService notificationService = session.getSALService(NotificationProviderService.class);
+ * notificationService.publish(notification)
+ * }
+ * where notification is an instance of a modeled Notification.
+ * For more information on sending notifications via the NotificationProviderService
+ * see org.opendaylight.controller.sal.binding.api.NotificationProviderService
+ *
+ * <p>
+ * A consumer can *invoke* and RPC ( ie, call foo(fooArgs)) but it cannot register an RPC
+ * implementation with the MD-SAL that others can invoke(call).
+ * To get an invokable RPC:
+ *
+ * <p>
+ * {code
+ * public void onSessionInitiated(ProviderContext session) {
+ * MyService rpcFlowSalService = session.getRpcService(MyService.class);
+ * }
+ *
+ * <p>
+ * Where MyService.class is a Service interface generated from a yang model with RPCs modeled in it. The returned
+ * rpcFlowSalService can be used like any other object by invoking its methods. Note, nothing special needs to be done
+ * for RoutedRPCs. They just work.
+ *
+ * <p>
+ * To get a DataBroker to allow access to the data tree:
+ *
+ * <p>
+ * {code
+ * public void onSessionInitiated(final ProviderContext session) {
+ * DataBroker databroker = session.getSALService(BindingDataBroker.class);
+ * }
+ * }
*/
public interface BindingAwareConsumer {
/**
* Callback signaling initialization of the consumer session to the SAL.
*
+ * <p>
* The consumer MUST use the session for all communication with SAL or
* retrieving SAL infrastructure services.
*
- * This method is invoked by
- * {@link BindingAwareBroker#registerConsumer(BindingAwareConsumer)}
+ * <p>
+ * This method is invoked by {@link BindingAwareBroker#registerConsumer(BindingAwareConsumer)}
*
* @param session
* Unique session between consumer and SAL.
*/
void onSessionInitialized(ConsumerContext session);
-
}
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
/**
- *
* A developer implemented component that gets registered with the Broker.
*
+ * <p>
* Semantically, a provider may:
*
* <ol>
* <li> Write to the operational data tree </li>
* </ol>
*
+ * <p>
* If a class is not doing at least one of those three, consider using
* a BindingAwareConsumer instead:
- * @see org.opendaylight.controller.sal.binding.api.BindingAwareConsumer
+ * see {@link org.opendaylight.controller.sal.binding.api.BindingAwareConsumer}
*
* <p>
- *
- *In addition, a BindingAwareProvider can in pursuit of its goals:
- *
+ * In addition, a BindingAwareProvider can in pursuit of its goals:
* <ol>
* <li>Subscribe for Notifications </li>
* <li>Invoke RPCs</li>
* </ol>
* (All of the above are things a Consumer can also do).
*
- *<p>
- *
+ * <p>
* Examples:
*
*<p>
- *
* To get a NotificationService:
*
* {@code
* }
* }
* For more information on sending notifications via the NotificationProviderService
- * @see org.opendaylight.controller.sal.binding.api.NotificationProviderService
+ * see {@link org.opendaylight.controller.sal.binding.api.NotificationProviderService}
*
+ * <p>
* To register an RPC implementation:
*
* {@code
* }
*
* <p>
- * Where MyService.class is a Service interface generated from a yang model with RPCs modeled in it and myImplementationInstance
- * is an instance of a class that implements MyService.
+ * Where MyService.class is a Service interface generated from a yang model with RPCs modeled in it and
+ * myImplementationInstance is an instance of a class that implements MyService.
*
+ * <p>
* To register a Routed RPC Implementation:
* {@code
* public void onSessionInitiated(ProviderContext session) {
- * RoutedRpcRegistration<SalFlowService> flowRegistration = session.addRoutedRpcImplementation(SalFlowService.class, salFlowServiceImplementationInstance);
+ * RoutedRpcRegistration<SalFlowService> flowRegistration = session.addRoutedRpcImplementation(SalFlowService.class,
+ * salFlowServiceImplementationInstance);
flowRegistration.registerPath(NodeContext.class, nodeInstanceId);
* }
* }
*
- * Where SalFlowService.class is a Service interface generated from a yang model with RPCs modeled in it and salFlowServiceImplementationInstance is an instance
- * of a class that implements SalFlowService.
+ * <p>
+ * Where SalFlowService.class is a Service interface generated from a yang model with RPCs modeled in it and
+ * salFlowServiceImplementationInstance is an instance of a class that implements SalFlowService.
+ *
* <p>
* The line:
* {@code
* flowRegistration.registerPath(NodeContext.class, nodeInstanceId);
* }
- * Is indicating that the RPC implementation is registered to handle RPC invocations that have their NodeContext pointing to the node with instance id nodeInstanceId.
- * This bears a bit of further explanation. RoutedRPCs can be 'routed' to an implementation based upon 'context'. 'context' is a pointer (instanceId) to some place
- * in the data tree. In this example, the 'context' is a pointer to a Node. In this way, a provider can register its ability to provide a service for a particular
- * Node, but not *all* Nodes. The Broker routes the RPC by 'context' to the correct implementation, without the caller having to do extra work. Because of this when
- * a RoutedRPC is registered, it needs to also be able to indicate for which 'contexts' it is providing an implementation.
+ * Is indicating that the RPC implementation is registered to handle RPC invocations that have their NodeContext
+ * pointing to the node with instance id nodeInstanceId. This bears a bit of further explanation. RoutedRPCs can be
+ * 'routed' to an implementation based upon 'context'. 'context' is a pointer (instanceId) to some place in the data
+ * tree. In this example, the 'context' is a pointer to a Node. In this way, a provider can register its ability to
+ * provide a service for a particular Node, but not *all* Nodes. The Broker routes the RPC by 'context' to the correct
+ * implementation, without the caller having to do extra work. Because of this when a RoutedRPC is registered, it
+ * needs to also be able to indicate for which 'contexts' it is providing an implementation.
*
- * An example of a Routed RPC would be an updateFlow(node, flow) that would be routed based on node to the provider which had registered to provide
- * it *for that node*.
+ * <p>
+ * An example of a Routed RPC would be an updateFlow(node, flow) that would be routed based on node to the provider
+ * which had registered to provide it *for that node*.
*
*<p>
- *
* To get a DataBroker to allow access to the data tree:
*
* {@code
/**
* Callback signaling initialization of the consumer session to the SAL.
*
+ * <p>
* The consumer MUST use the session for all communication with SAL or
* retrieving SAL infrastructure services.
*
+ * <p>
* This method is invoked by
* {@link BindingAwareBroker#registerProvider(BindingAwareProvider)}
*
* instance of the service with it's own context.
*
* <p>
- * The consumer's (or provider's) instance of specific service could be obtained
- * by invoking {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext#getSALService(Class)} method on session
- * assigned to the consumer.
+ * The consumer's (or provider's) instance of specific service could be obtained by invoking
+ * {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext#getSALService(Class)}
+ * method on session assigned to the consumer.
*
* <p>
- * {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext} and {@link BindingAwareProvider} may seem
- * similar, but provider provides YANG model-based functionality and
+ * {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext}
+ * and {@link BindingAwareProvider} may seem similar, but provider provides YANG model-based functionality and
* {@link BindingAwareProvider} exposes the necessary supporting functionality
* to implement specific functionality of YANG and to reuse it in the
* development of {@link BindingAwareConsumer}s and {@link BindingAwareProvider}s.
public interface NotificationListener<T extends Notification> extends EventListener {
/**
* Invoked to deliver a notification.
+ *
* <p>
* Note that this method may be invoked from a shared thread pool, so implementations SHOULD NOT
* perform CPU-intensive operations and MUST NOT invoke any potentially blocking operations.
@Deprecated
public interface NotificationProviderService extends NotificationService, NotificationPublishService<Notification> {
- /**
- * {@inheritDoc}
- */
@Override
void publish(Notification notification);
- /**
- * {@inheritDoc}
- */
@Override
void publish(Notification notification, ExecutorService executor);
* Registers a listener to be notified about notification subscriptions. This
* enables a component to know when there is a notification listener subscribed
* for a particular notification type.
+ *
* <p>
* On registration of this listener, the
* {@link NotificationInterestListener#onNotificationSubscribtion(Class)} method
interface NotificationInterestListener extends EventListener {
/**
- * Callback that is invoked when a notification listener subscribes for a
- * particular notification type.
+ * Callback that is invoked when a notification listener subscribes for a particular notification type.
+ *
* <p>
* This method is only called for the first subscription that occurs for a
* particular notification type. Subsequent subscriptions for the same
* notification type do not trigger invocation of this method.
+ *
* <p>
* <b>Note:</b>This callback is delivered from thread not owned by this listener,
* all processing should be as fast as possible and implementations should
* </ul>
*
* <h3>Generic Listener</h3>
+ *
* <p>
* A generic listener implements the {@link NotificationListener} interface which has one callback method
* <code>onNotification</code> that is invoked for any notification type the listener is subscribed to.
+ *
* <p>
* A generic listener is subscribed using the {@link #registerNotificationListener(Class, NotificationListener)}
* method by which you specify the type of notification to receive. A generic listener may be registered for
* multiple notification types via multiple subscriptions.
+ *
* <p>
* Generic listeners allow for a more flexible approach, allowing you to subscribe for just
* one type of notification from a YANG model. You could also have a general subscription
* </pre>
*
* <h3>Dispatch Listener</h3>
+ *
* <p>
* A dispatch listener implements a YANG-generated module interface <code>{ModuleName}Listener</code>
* which handles all the notifications defined in the YANG model. Each notification type translates to
* a specific method of the form <code>on{NotificationType}</code> on the generated interface.
* The generated interface also extends the
* {@link org.opendaylight.yangtools.yang.binding.NotificationListener} interface and implementations
- * are registered using {@link #registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)}
- * method.
+ * are registered using
+ * {@link #registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)} method.
*
* <h4>Dispatch Listener Example</h4>
+ *
* <p>
* Lets assume we have following YANG model:
*
* }
* }
*
+ * <p>
* The generated interface will be:
* {@code
* public interface ExampleListener extends NotificationListener {
/**
* Provides access to registered Remote Procedure Call (RPC) service implementations. The RPCs are
* defined in YANG models.
+ *
* <p>
* RPC implementations are registered using the {@link RpcProviderRegistry}.
*
* RPC methods may be implemented asynchronously, callers should avoid blocking on the
* {@link java.util.concurrent.Future Future} result. Instead, it is recommended to use
* {@link com.google.common.util.concurrent.JdkFutureAdapters#listenInPoolThread(java.util.concurrent.Future)}
- * or {@link com.google.common.util.concurrent.JdkFutureAdapters#listenInPoolThread(java.util.concurrent.Future, java.util.concurrent.Executor)}
+ * or {@link com.google.common.util.concurrent.JdkFutureAdapters#listenInPoolThread(java.util.concurrent.Future,
+ * java.util.concurrent.Executor)}
* to listen for Rpc Result. This will asynchronously listen for future result in executor and
* will not block current thread.
*
* {@code
* final Future<RpcResult<SomeRpcOutput>> future = someRpcService.someRpc( ... );
- * Futures.addCallback(JdkFutureAdapters.listenInThreadPool(future), new FutureCallback<RpcResult<SomeRpcOutput>>() {
- *
- * public void onSuccess(RpcResult<SomeRpcOutput> result) {
- * // process result ...
- * }
+ * Futures.addCallback(JdkFutureAdapters.listenInThreadPool(future),
+ * new FutureCallback<RpcResult<SomeRpcOutput>>() {
+ * public void onSuccess(RpcResult<SomeRpcOutput> result) {
+ * // process result ...
+ * }
*
- * public void onFailure(Throwable t) {
- * // RPC failed
- * }
- * );
- * }
- * }
+ * public void onFailure(Throwable t) {
+ * // RPC failed
+ * }
+ * });
+ * }
*
* @param serviceInterface the interface of the RPC Service. Typically this is an interface generated
* from a YANG model.
/**
* Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are
* defined in YANG models.
+ *
* <p>
* There are 2 types of RPCs:
* <ul>
* </ul>
*
* <h2>Global RPC</h2>
+ *
* <p>
* An RPC is global if there is intended to be only 1 registered implementation. A global RPC is not
* explicitly declared as such, essentially any RPC that is not defined to be routed is considered global.
+ *
* <p>
* Global RPCs are registered using the
* {@link #addRpcImplementation(Class, RpcService)} method.
*
* <h2>Routed RPC</h2>
+ *
* <p>
* MD-SAL supports routing of RPC between multiple implementations where the appropriate
* implementation is selected at run time based on the content of the RPC message as described in
* YANG model.
+ *
* <p>
* RPC routing is based on:
* <ul>
* </ul>
*
* <h3>Context type</h3>
+ *
* <p>
* A context type is modeled in YANG using a combination of a YANG <code>identity</code>
* and Opendaylight specific extensions from <code>yang-ext</code> module. These extensions are:
* <code>instance-identifier</code> or a type derived from <code>instance-identifier</code>.</li>
* </ul>
*
- *
- * <h3>Routed RPC example</h3>
- * <p>
+ * <p><br>
* <h4>1. Defining a Context Type</h4>
+ *
* <p>
* The following snippet declares a simple YANG <code>identity</code> named <code>example-context</code>:
*
* ...
* }
* }
+ *
* <p>
* We then use the declared identity to define a context type by using it in combination
* with the <code>context-instance</code> YANG extension. We'll associate the context type
* with a list element in the data tree. This defines the set of nodes whose instance
* identifiers are valid for the <code>example-context</code> context type.
+ *
* <p>
* The following YANG snippet imports the <code>yang-ext</code> module and defines the list
* element named <code>item</code> inside a container named <code>foo</code>:
* ...
* }
* }
+ *
* <p>
* The statement <code>ext:context-instance "example-context";</code> inside the list element
* declares that any instance identifier referencing <code>item</code> in the data
* InstanceIdentifier.create(Example.class)
* </pre>
* is not valid.
+ *
* <p>
* So using an <code>identity</code> in combination with <code>context-instance</code> we
* have effectively defined a context type that can be referenced in a YANG RPC input.
*
+ * <p>
* <h5>2. Defining an RPC to use the Context Type</h5>
+ *
* <p>
* To define an RPC to be routed based on the context type we need to add an input leaf element
* that references the context type which will hold an instance identifier value to be
* used to route the RPC.
+ *
* <p>
* The following snippet defines an RPC named <code>show-item</code> with 2 leaf elements
* as input: <code>item</code> of type <code>instance-identifier</code> and <code>description</code>:
* }
* }
* </pre>
+ *
* <p>
* We mark the <code>item</code> leaf with a <code>context-reference</code> statement that
* references the <code>example-context</code> context type. RPC calls will then be routed
* based on the instance identifier value contained in <code>item</code>. Only instance
* identifiers that point to a <code>foo/item</code> node are valid as input.
+ *
* <p>
* The generated RPC Service interface for the module is:
*
* Future<RpcResult<Void>> showItem(ShowItemInput input);
* }
* </pre>
+ *
* <p>
* For constructing the RPC input, there are generated classes ShowItemInput and ShowItemInputBuilder.
*
* <h5>3. Registering a routed RPC implementation</h5>
+ *
* <p>
* To register a routed implementation for the <code>show-item</code> RPC, we must use the
* {@link #addRoutedRpcImplementation(Class, RpcService)} method. This
* will return a {@link RoutedRpcRegistration} instance which can then be used to register /
* unregister routed paths associated with the registered implementation.
+ *
* <p>
* The following snippet registers <code>myImpl</code> as the RPC implementation for an
* <code>item</code> with key <code>"foo"</code>:
* // YANG-generated class for the example-context identity.
* reg.registerPath(ExampleContext.class, path);
* </pre>
+ *
* <p>
* It is also possible to register the same implementation for multiple paths:
*
* arguments in ShowItemInput, extract the InstanceIdentifier value of the <code>item</code> leaf and select
* the implementation whose registered path matches the InstanceIdentifier value of the <code>item</code> leaf.
*
+ * <p><br>
* <h2>Notes for RPC Implementations</h2>
*
+ * <p>
* <h3>RpcResult</h3>
+ *
* <p>
* The generated interfaces require implementors to return
- * {@link java.util.concurrent.Future Future}<{@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}<{RpcName}Output>> instances.
+ * {@link java.util.concurrent.Future Future}<{@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
+ * <{RpcName}Output>> instances.
*
+ * <p>
* Implementations should do processing of RPC calls asynchronously and update the
* returned {@link java.util.concurrent.Future Future} instance when processing is complete.
* However using {@link com.google.common.util.concurrent.Futures#immediateFuture(Object) Futures.immediateFuture}
* or completely fail. This is intended to provide additional human readable information
* for users of the API and to transfer warning / error information across the system
* so it may be visible via other external APIs such as Restconf.
+ *
* <p>
* It is recommended to use the {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
* for conveying appropriate error information
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.RpcService;
-public final class RpcContextIdentifier implements Immutable{
+public final class RpcContextIdentifier implements Immutable {
public final Class<? extends RpcService> rpcService;
public final Class<? extends BaseIdentity> routingContext;
return routingContext;
}
- public static final RpcContextIdentifier contextForGlobalRpc(Class<? extends RpcService> serviceType) {
+ public static RpcContextIdentifier contextForGlobalRpc(Class<? extends RpcService> serviceType) {
return new RpcContextIdentifier(serviceType, null);
}
- public static final RpcContextIdentifier contextFor(Class<? extends RpcService> serviceType,Class<? extends BaseIdentity> routingContext) {
+ public static RpcContextIdentifier contextFor(Class<? extends RpcService> serviceType,
+ Class<? extends BaseIdentity> routingContext) {
return new RpcContextIdentifier(serviceType, routingContext);
}
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((routingContext == null) ? 0 : routingContext.hashCode());
- result = prime * result + ((rpcService == null) ? 0 : rpcService.hashCode());
+ result = prime * result + (routingContext == null ? 0 : routingContext.hashCode());
+ result = prime * result + (rpcService == null ? 0 : rpcService.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
RpcContextIdentifier other = (RpcContextIdentifier) obj;
if (routingContext == null) {
- if (other.routingContext != null)
+ if (other.routingContext != null) {
return false;
- } else if (!routingContext.equals(other.routingContext))
+ }
+ } else if (!routingContext.equals(other.routingContext)) {
return false;
+ }
if (rpcService == null) {
- if (other.rpcService != null)
+ if (other.rpcService != null) {
return false;
- } else if (!rpcService.equals(other.rpcService))
+ }
+ } else if (!rpcService.equals(other.rpcService)) {
return false;
+ }
return true;
}
-
}
public interface RpcRoutingContext<C extends BaseIdentity,S extends RpcService> {
Class<C> getContextType();
+
Class<S> getServiceType();
}