*
*
*/
- public interface ConsumerContext {
+ public interface ConsumerContext extends RpcConsumerRegistry {
/**
* Returns a session specific instance (implementation) of requested
*/
<T extends BindingAwareService> T getSALService(Class<T> service);
- /**
- * Returns a session specific instance (implementation) of requested
- * YANG module implentation / service provided by consumer.
- *
- * @param service
- * Broker service
- * @return Session specific implementation of service
- */
- <T extends RpcService> T getRpcService(Class<T> module);
+
}
/**
* functionality provided by other {@link BindingAwareConsumer}s.
*
*/
- public interface ProviderContext extends ConsumerContext {
- /**
- * Registers an global RpcService implementation.
- *
- * @param type
- * @param implementation
- * @return
- */
- <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
- throws IllegalStateException;
-
- <T extends RpcService> RpcRegistration<T> addMountRpcImplementation(Class<T> type, InstanceIdentifier<?> mount,
- T implementation) throws IllegalStateException;
-
- <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type, T implementation)
- throws IllegalStateException;
+ public interface ProviderContext extends ConsumerContext, RpcProviderRegistry {
+ @Deprecated
void registerFunctionality(ProviderFunctionality functionality);
+ @Deprecated
void unregisterFunctionality(ProviderFunctionality functionality);
}
public interface NotificationProviderService extends NotificationService, NotificationPublishService<Notification> {
+ /**
+ * Deprecated. Use {@link #publish(Notification)}.
+ *
+ * @param notification
+ */
@Deprecated
void notify(Notification notification);
+ /**
+ * Deprecated. Use {@link #publish(Notification,ExecutorService)}.
+ *
+ * @param notification
+ */
@Deprecated
void notify(Notification notification, ExecutorService service);
+ /**
+ * Publishes a notification.
+ *
+ * @param Notification notification to publish.
+ *
+ */
@Override
void publish(Notification notification);
+ /**
+ * Publishes a notification, listener calls are done in provided executor.
+ *
+ */
@Override
void publish(Notification notification, ExecutorService service);
-
- @Override
- public <T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(
- Class<T> notificationType, NotificationListener<T> listener);
-
- @Override
- public Registration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(
- org.opendaylight.yangtools.yang.binding.NotificationListener listener);
}
package org.opendaylight.controller.sal.binding.api;
import org.opendaylight.controller.md.sal.common.api.notify.NotificationSubscriptionService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.Notification;
public interface NotificationService extends BindingAwareService {
-
+ /**
+ *
+ * Deprecated: use {@link #addNotificationListener(Class, NotificationListener)} istead.
+ *
+ * @param listener
+ */
@Deprecated
<T extends Notification> void addNotificationListener(Class<T> notificationType, NotificationListener<T> listener);
+ /**
+ *
+ * Deprecated: use {@link #addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)} istead.
+ *
+ * @param listener
+ */
@Deprecated
void addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener);
+ /**
+ * Deprecated: use {@link Registration#close()} istead.
+ * @param listener
+ */
@Deprecated
void removeNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener);
+ /**
+ * Deprecated: use {@link Registration#close()} istead.
+ * @param listener
+ */
@Deprecated
<T extends Notification> void removeNotificationListener(Class<T> notificationType, NotificationListener<T> listener);
+
+ /**
+ * Register a generic listener for specified notification type only.
+ *
+ * @param notificationType
+ * @param listener
+ * @return Registration for listener. To unregister listener invoke {@link Registration#close()} method.
+ */
<T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(
Class<T> notificationType, NotificationListener<T> listener);
+ /**
+ * Register a listener which implements generated notification interfaces derived from
+ * {@link org.opendaylight.yangtools.yang.binding.NotificationListener}.
+ * Listener is registered for all notifications present in implemented interfaces.
+ *
+ * @param listener
+ * @return Registration for listener. To unregister listener invoke {@link Registration#close()} method.
+ */
Registration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(
org.opendaylight.yangtools.yang.binding.NotificationListener listener);
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.api;
+
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+/**
+ * Base interface defining contract for retrieving MD-SAL
+ * version of RpcServices
+ *
+ */
+public interface RpcConsumerRegistry {
+ /**
+ * Returns a session specific instance (implementation) of requested
+ * YANG module implentation / service provided by consumer.
+ *
+ * @param service
+ * Broker service
+ * @return Session specific implementation of service
+ */
+ <T extends RpcService> T getRpcService(Class<T> module);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.api;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+/**
+ * Interface defining provider's access to the Rpc Registry
+ * which could be used to register their implementations of service to the MD-SAL.
+ *
+ * @author ttkacik
+ *
+ */
+public interface RpcProviderRegistry extends RpcConsumerRegistry {
+ /**
+ * Registers an global RpcService implementation.
+ *
+ * @param type
+ * @param implementation
+ * @return
+ */
+ <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
+ throws IllegalStateException;
+
+ /**
+ *
+ * Register an Routed RpcService where routing is determined on annotated (in YANG model)
+ * context-reference and value of annotated leaf.
+ *
+ * @param type Type of RpcService, use generated interface class, not your implementation clas
+ * @param implementation Implementation of RpcService
+ * @return Registration object for routed Rpc which could be used to close an
+ *
+ * @throws IllegalStateException
+ */
+ <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type, T implementation)
+ throws IllegalStateException;
+}
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
import org.opendaylight.controller.sal.binding.api.BindingAwareService;
import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.DataRoot;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@Deprecated
public void unregisterChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener changeListener);
+ /**
+ * Reads data subtree from configurational store.
+ * (Store which is populated by consumer, which is usually used to
+ * inject state into providers. E.g. Flow configuration)-
+ *
+ */
+ @Override
+ public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path);
+
+ /**
+ * Reads data subtree from operational store.
+ * (Store which is populated by providers, which is usually used to
+ * capture state of providers. E.g. Topology)
+ *
+ */
+ @Override
+ public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path);
+
+ /**
+ * Register a data change listener for particular subtree.
+ *
+ * Callback is invoked each time data in subtree changes.
+ *
+ */
+ @Override
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(
+ InstanceIdentifier<? extends DataObject> path, DataChangeListener listener);
}
package org.opendaylight.controller.sal.binding.api.data;
import java.util.EventListener;
+import java.util.concurrent.Future;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
public interface DataModificationTransaction extends DataModification<InstanceIdentifier<? extends DataObject>, DataObject> {
+ /**
+ * Returns an unique identifier for transaction
+ *
+ */
+ @Override
+ public Object getIdentifier();
+
+ /**
+ * Initiates a two-phase commit of candidate data.
+ *
+ * <p>
+ * The {@link Consumer} could initiate a commit of candidate data
+ *
+ * <p>
+ * The successful commit changes the state of the system and may affect
+ * several components.
+ *
+ * <p>
+ * The effects of successful commit of data are described in the
+ * specifications and YANG models describing the {@link Provider} components
+ * of controller. It is assumed that {@link Consumer} has an understanding
+ * of this changes.
+ *
+ *
+ * @see DataCommitHandler for further information how two-phase commit is
+ * processed.
+ * @param store
+ * Identifier of the store, where commit should occur.
+ * @return Result of the commit, containing success information or list of
+ * encountered errors, if commit was not successful.
+ */
+ @Override
+ public Future<RpcResult<TransactionStatus>> commit();
+
+
+
+ /**
+ * Register a listener for transaction
+ *
+ * @param listener
+ * @return
+ */
ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener);
- //FIXME: After 0.6 Release of YANG-Binding
- //public <T extends DataObject> T readOperationalData(InstanceIdentifier<T> path);
- //public <T extends DataObject> T readConfigurationData(InstanceIdentifier<T> path);
+ /**
+ * Listener for transaction state changes
+ *
+ *
+ */
public interface DataTransactionListener extends EventListener {
+ /**
+ * Callback is invoked after each transaction status change.
+ *
+ * @param transaction Transaction
+ * @param status New status
+ */
void onStatusUpdated(DataModificationTransaction transaction,TransactionStatus status);
}
}
import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
+/**
+ * DataProviderService is common access point for {@link BindingAwareProvider} providers
+ * to access data trees described by the YANG model.
+ *
+ */
public interface DataProviderService extends DataBrokerService, DataProvisionService<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ /**
+ * Registers a data reader for particular subtree of overal YANG data tree.
+ *
+ * Registered data reader is called if anyone tries to read data from
+ * paths which are nested to provided path.
+ *
+ * @param path Subpath which is handled by registered data reader
+ * @param reader Instance of reader which
+ * @return Registration object for reader. Invoking {@link Registration#close()} will unregister reader.
+ */
+ Registration<DataReader<InstanceIdentifier<? extends DataObject>,DataObject>> registerDataReader(InstanceIdentifier<? extends DataObject> path,DataReader<InstanceIdentifier<? extends DataObject>,DataObject> reader);
}
import org.opendaylight.yangtools.yang.binding.DataRoot;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Utility interface which does type capture for BindingAware DataReader.
+ *
+ * @author
+ *
+ */
public interface RuntimeDataProvider extends ProviderFunctionality,DataReader<InstanceIdentifier<? extends DataObject>, DataObject> {
package org.opendaylight.controller.sal.binding.api.mount;
import org.opendaylight.controller.sal.binding.api.NotificationService;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
-public interface MountInstance extends NotificationService, DataBrokerService {
-
- <T extends RpcService> T getRpcService(Class<T> rpcService);
+public interface MountInstance //
+ extends //
+ RpcConsumerRegistry, //
+ Identifiable<InstanceIdentifier<?>>, //
+ NotificationService, //
+ DataBrokerService {
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.api.mount;
+
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+
+/**
+ * Provider's version of Mount Point, this version allows access to MD-SAL
+ * services specific for this mountpoint and registration / provision of
+ * interfaces for mount point.
+ *
+ * @author ttkacik
+ *
+ */
+public interface MountProviderInstance //
+ extends //
+ MountInstance, //
+ DataProviderService, //
+ RpcProviderRegistry, //
+ NotificationProviderService {
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.api.mount;
+
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Provider MountProviderService, this version allows access to MD-SAL
+ * services specific for this mountpoint and registration / provision of
+ * interfaces for mount point.
+ *
+ * @author ttkacik
+ *
+ */
+public interface MountProviderService extends MountInstance {
+
+ MountProviderInstance createMountPoint(InstanceIdentifier<?> path);
+}
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
import org.opendaylight.controller.sal.binding.spi.RpcRouter;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcImplementation;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.sal.binding.codegen.impl
-
-import org.opendaylight.yangtools.yang.binding.BaseIdentity
-import javassist.CtMethod
-import java.lang.reflect.Method
-
-@Data
-class RoutingPair {
-
- @Property
- val Class<? extends BaseIdentity> context;
- @Property
- val CtMethod getter;
-
- @Property
- val boolean encapsulated;
-}
import java.util.Set
import java.util.HashMap
import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable
-import org.opendaylight.yangtools.yang.binding.DataObject
import static org.opendaylight.controller.sal.binding.codegen.impl.XtendHelper.*
+import org.opendaylight.yangtools.yang.binding.DataContainer
+import org.opendaylight.yangtools.yang.binding.RpcImplementation
class RpcRouterCodegenInstance<T extends RpcService> implements RpcRouter<T> {
val T invocationProxy
@Property
- val Class<T> rpcServiceType
+ val RpcImplementation invokerDelegate;
+
+ @Property
+ val Class<T> serviceType
@Property
val Set<Class<? extends BaseIdentity>> contexts
- val routingTables = new HashMap<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, ?>>;
+ @Property
+ val Set<Class<? extends DataContainer>> supportedInputs;
+
+ val routingTables = new HashMap<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, ? extends RpcService>>;
@Property
var T defaultService
- new(Class<T> type, T routerImpl, Set<Class<? extends BaseIdentity>> contexts) {
- _rpcServiceType = type
+ new(Class<T> type, T routerImpl, Set<Class<? extends BaseIdentity>> contexts,
+ Set<Class<? extends DataContainer>> inputs) {
+ _serviceType = type
_invocationProxy = routerImpl
+ _invokerDelegate = routerImpl as RpcImplementation
_contexts = contexts
+ _supportedInputs = inputs;
for (ctx : contexts) {
val table = XtendHelper.createRoutingTable(ctx)
val table = getRoutingTable(context);
return table.getRoute(path);
}
+
+ override <T extends DataContainer> invoke(Class<T> type, T input) {
+ return invokerDelegate.invoke(type, input);
+ }
+
}
import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
import java.util.HashSet
-import java.io.ObjectOutputStream.PutField
import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.*
-import javax.xml.ws.spi.Invoker
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker
import java.util.Set
-import java.util.Collections
import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper
import java.util.WeakHashMap
import javassist.ClassClassPath
+import org.opendaylight.yangtools.yang.binding.annotations.QName
+import org.opendaylight.yangtools.yang.binding.DataContainer
+import org.opendaylight.yangtools.yang.binding.RpcImplementation
class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory {
override <T extends RpcService> getRouterFor(Class<T> iface) {
val contexts = new HashSet<Class<? extends BaseIdentity>>
- val instance = <T>withClassLoader(iface.classLoader) [ |
+ val instance = <RpcRouterCodegenInstance<T>>withClassLoader(iface.classLoader) [ |
val supertype = iface.asCtClass
+ val metadata = supertype.rpcMetadata;
val targetCls = createClass(iface.routerName, supertype) [
- //field(ROUTING_TABLE_FIELD,Map)
+ addInterface(RpcImplementation.asCtClass)
+
field(DELEGATE_FIELD, iface)
- val ctxMap = new HashMap<String, Class<? extends BaseIdentity>>();
- // We search for routing pairs and add fields
- supertype.methods.filter[declaringClass == supertype && parameterTypes.size === 1].forEach [ method |
- val routingPair = method.routingContextInput;
- if (routingPair !== null) {
- ctxMap.put(routingPair.context.routingTableField, routingPair.context);
- contexts.add(routingPair.context)
- }
- ]
- for (ctx : ctxMap.entrySet) {
- field(ctx.key, Map)
+ //field(REMOTE_INVOKER_FIELD,iface);
+
+ for (ctx : metadata.contexts) {
+ field(ctx.routingTableField, Map)
}
implementMethodsFrom(supertype) [
if (parameterTypes.size === 1) {
- val routingPair = routingContextInput;
+ val rpcMeta = metadata.rpcMethods.get(name);
val bodyTmp = '''
{
- final «InstanceIdentifier.name» identifier = $1.«routingPair.getter.name»()«IF routingPair.
- encapsulated».getValue()«ENDIF»;
- «supertype.name» instance = («supertype.name») «routingPair.context.routingTableField».get(identifier);
+ final «InstanceIdentifier.name» identifier = $1.«rpcMeta.inputRouteGetter.name»()«IF rpcMeta.
+ routeEncapsulated».getValue()«ENDIF»;
+ «supertype.name» instance = («supertype.name») «rpcMeta.context.routingTableField».get(identifier);
if(instance == null) {
instance = «DELEGATE_FIELD»;
}
body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);'''
}
]
+ implementMethodsFrom(RpcImplementation.asCtClass) [
+ switch (name) {
+ case "getSupportedInputs":
+ body = '''
+ {
+ throw new java.lang.UnsupportedOperationException("Not implemented yet");
+ return ($r) null;
+ }'''
+ case "invoke": {
+ val tmpBody = '''
+ {
+ «FOR input : metadata.supportedInputs SEPARATOR " else "»
+ «val rpcMetadata = metadata.rpcInputs.get(input)»
+ if(«input.name».class.equals($1)) {
+ return ($r) this.«rpcMetadata.methodName»((«input.name») $2);
+ }
+ «ENDFOR»
+ throw new java.lang.IllegalArgumentException("Not supported message type");
+ return ($r) null;
+ }
+ '''
+ body = tmpBody
+ }
+ }
+ ]
]
- return targetCls.toClass(iface.classLoader).newInstance as T
+ val instance = targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as T
+ return new RpcRouterCodegenInstance(iface, instance, metadata.contexts,metadata.supportedInputs);
];
- return new RpcRouterCodegenInstance(iface, instance, contexts);
+ return instance;
+ }
+
+ private def RpcServiceMetadata getRpcMetadata(CtClass iface) {
+ val metadata = new RpcServiceMetadata;
+
+ iface.methods.filter[declaringClass == iface && parameterTypes.size === 1].forEach [ method |
+ val routingPair = method.rpcMetadata;
+ if (routingPair !== null) {
+ metadata.contexts.add(routingPair.context)
+ metadata.rpcMethods.put(method.name,routingPair)
+ val input = routingPair.inputType.javaClass as Class<? extends DataContainer>;
+ metadata.supportedInputs.add(input);
+ metadata.rpcInputs.put(input,routingPair);
+ }
+ ]
+ return metadata;
+ }
+
+ private def getRpcMetadata(CtMethod method) {
+ val inputClass = method.parameterTypes.get(0);
+ return inputClass.rpcMethodMetadata(inputClass,method.name);
+ }
+
+ private def RpcMetadata rpcMethodMetadata(CtClass dataClass,CtClass inputClass,String rpcMethod) {
+ for (method : dataClass.methods) {
+ if (method.name.startsWith("get") && method.parameterTypes.size === 0) {
+ for (annotation : method.availableAnnotations) {
+ if (annotation instanceof RoutingContext) {
+ val encapsulated = !method.returnType.equals(InstanceIdentifier.asCtClass);
+ return new RpcMetadata(null,rpcMethod,(annotation as RoutingContext).value, method, encapsulated,inputClass);
+ }
+ }
+ }
+ }
+ for (iface : dataClass.interfaces) {
+ val ret = rpcMethodMetadata(iface,inputClass,rpcMethod);
+ if(ret != null) return ret;
+ }
+ return null;
+ }
+
+ private def getJavaClass(CtClass cls) {
+ Thread.currentThread.contextClassLoader.loadClass(cls.name)
+ }
+
+ override getInvokerFactory() {
+ return this;
+ }
+
+ override invokerFor(NotificationListener instance) {
+ val cls = instance.class
+ val prototype = resolveInvokerClass(cls);
+
+ return new RuntimeGeneratedInvoker(instance, prototype)
}
protected def generateListenerInvoker(Class<? extends NotificationListener> iface) {
val supportedNotification = callbacks.map[parameterTypes.get(0) as Class<? extends Notification>].toSet;
- val targetCls = createClass(iface.invokerName,BROKER_NOTIFICATION_LISTENER ) [
+ val targetCls = createClass(iface.invokerName, BROKER_NOTIFICATION_LISTENER) [
field(DELEGATE_FIELD, iface)
implementMethodsFrom(BROKER_NOTIFICATION_LISTENER) [
body = '''
{
«FOR callback : callbacks SEPARATOR " else "»
- «val cls = callback.parameterTypes.get(0).name»
- if($1 instanceof «cls») {
- «DELEGATE_FIELD».«callback.name»((«cls») $1);
- return null;
- }
+ «val cls = callback.parameterTypes.get(0).name»
+ if($1 instanceof «cls») {
+ «DELEGATE_FIELD».«callback.name»((«cls») $1);
+ return null;
+ }
«ENDFOR»
return null;
}
'''
]
]
- val finalClass = targetCls.toClass(iface.classLoader,iface.protectionDomain)
+ val finalClass = targetCls.toClass(iface.classLoader, iface.protectionDomain)
return new RuntimeGeneratedInvokerPrototype(supportedNotification,
finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener>);
}
- def void method(CtClass it, Class<?> returnType, String name, Class<?> parameter, MethodGenerator function1) {
+ private def void method(CtClass it, Class<?> returnType, String name, Class<?> parameter, MethodGenerator function1) {
val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it);
function1.process(method);
it.addMethod(method);
}
- private def routingContextInput(CtMethod method) {
- val inputClass = method.parameterTypes.get(0);
- return inputClass.contextInstance;
- }
-
- private def RoutingPair getContextInstance(CtClass dataClass) {
- for (method : dataClass.methods) {
- if (method.name.startsWith("get") && method.parameterTypes.size === 0) {
- for (annotation : method.availableAnnotations) {
- if (annotation instanceof RoutingContext) {
- val encapsulated = !method.returnType.equals(InstanceIdentifier.asCtClass);
-
- return new RoutingPair((annotation as RoutingContext).value, method, encapsulated);
- }
- }
- }
- }
- for (iface : dataClass.interfaces) {
- val ret = getContextInstance(iface);
- if(ret != null) return ret;
- }
- return null;
- }
-
private def void implementMethodsFrom(CtClass target, CtClass source, MethodGenerator function1) {
for (method : source.methods) {
if (method.declaringClass == source) {
}
}
- override getInvokerFactory() {
- return this;
- }
-
- override invokerFor(NotificationListener instance) {
- val cls = instance.class
- val prototype = resolveInvokerClass(cls);
-
- return new RuntimeGeneratedInvoker(instance,prototype)
- }
-
- def resolveInvokerClass(Class<? extends NotificationListener> class1) {
+ protected def resolveInvokerClass(Class<? extends NotificationListener> class1) {
val invoker = invokerClasses.get(class1);
if (invoker !== null) {
return invoker;
}
@Data
-class RuntimeGeneratedInvoker implements NotificationInvoker {
-
+package class RuntimeGeneratedInvoker implements NotificationInvoker {
+
@Property
val NotificationListener delegate;
-
@Property
var org.opendaylight.controller.sal.binding.api.NotificationListener invocationProxy;
@Property
var RuntimeGeneratedInvokerPrototype prototype;
- new(NotificationListener delegate,RuntimeGeneratedInvokerPrototype prototype) {
+ new(NotificationListener delegate, RuntimeGeneratedInvokerPrototype prototype) {
_delegate = delegate;
_prototype = prototype;
_invocationProxy = prototype.protoClass.newInstance;
}
override close() {
-
}
}
@Data
-class RuntimeGeneratedInvokerPrototype {
+package class RuntimeGeneratedInvokerPrototype {
@Property
val Set<Class<? extends Notification>> supportedNotifications;
@Property
val Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener> protoClass;
}
+
+package class RpcServiceMetadata {
+
+ @Property
+ val contexts = new HashSet<Class<? extends BaseIdentity>>();
+
+ @Property
+ val rpcMethods = new HashMap<String, RpcMetadata>();
+
+ @Property
+ val rpcInputs = new HashMap<Class<? extends DataContainer>, RpcMetadata>();
+
+
+ @Property
+ val supportedInputs = new HashSet<Class<? extends DataContainer>>();
+}
+
+@Data
+package class RpcMetadata {
+
+ @Property
+ val QName qname;
+
+ @Property
+ val String methodName;
+
+ @Property
+ val Class<? extends BaseIdentity> context;
+ @Property
+ val CtMethod inputRouteGetter;
+
+ @Property
+ val boolean routeEncapsulated;
+
+ @Property
+ val CtClass inputType;
+}
private val clsPool = ClassPool.getDefault()
private var RuntimeCodeGenerator generator;
+
/**
* Map of all Managed Direct Proxies
*/
private val Map<Class<? extends RpcService>, RpcRouter<? extends RpcService>> rpcRouters = new ConcurrentHashMap();
+ @Property
private var NotificationBrokerImpl notifyBroker
+
+ @Property
private var DataBrokerImpl dataBroker
+
private var ServiceRegistration<NotificationProviderService> notifyBrokerRegistration
@Property
notifyBroker = new NotificationBrokerImpl(executor);
notifyBroker.invokerFactory = generator.invokerFactory;
dataBroker = new DataBrokerImpl();
+ dataBroker.executor = executor;
val brokerProperties = newProperties();
notifyBrokerRegistration = brokerBundleContext.registerService(NotificationProviderService, notifyBroker,
brokerProperties)
brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties)
brokerBundleContext.registerService(DataProviderService, dataBroker, brokerProperties)
brokerBundleContext.registerService(DataBrokerService, dataBroker, brokerProperties)
+
+
}
import java.util.Hashtable;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
private static final Logger log = LoggerFactory.getLogger(BrokerActivator.class);
private BindingAwareBrokerImpl baSal;
private ServiceRegistration<BindingAwareBroker> baSalRegistration;
-
+ private HashMapDataStore store = new HashMapDataStore();
+ private InstanceIdentifier<?> root = InstanceIdentifier.builder().toInstance();
+
@Override
public void start(BundleContext context) throws Exception {
log.info("Binding Aware Broker initialized");
baSal = new BindingAwareBrokerImpl();
baSal.setBrokerBundleContext(context);
baSal.start();
+ baSal.getDataBroker().registerDataReader(root, store);
+ baSal.getDataBroker().registerCommitHandler(root, store);
BindingAwareBroker baSalService = baSal;
Hashtable<String, String> properties = new Hashtable<>();
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.DataRoot
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-class DataBrokerImpl implements DataProviderService {
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus
+import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
+import org.opendaylight.yangtools.concepts.ListenerRegistration
+import static extension org.opendaylight.controller.sal.binding.impl.util.MapUtils.*;
+import java.util.Collection
+import java.util.Map.Entry
+import java.util.HashSet
+import java.util.Set
+import com.google.common.collect.Multimap
+import static com.google.common.base.Preconditions.*;
+import java.util.List
+import java.util.LinkedList
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
+import com.google.common.collect.HashMultimap
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Callable
+import org.opendaylight.yangtools.yang.common.RpcResult
+import org.opendaylight.controller.sal.common.util.Rpcs
+import java.util.Collections
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import java.util.ArrayList
+import org.opendaylight.controller.sal.common.util.RpcErrors
+
+class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService {
+
+ @Property
+ var ExecutorService executor;
+
+ Multimap<InstanceIdentifier, DataReaderRegistration> configReaders = HashMultimap.create();
+ Multimap<InstanceIdentifier, DataReaderRegistration> operationalReaders = HashMultimap.create();
+ Multimap<InstanceIdentifier, DataChangeListenerRegistration> listeners = HashMultimap.create();
+ Multimap<InstanceIdentifier, DataCommitHandlerRegistration> commitHandlers = HashMultimap.create();
override beginTransaction() {
+ return new DataTransactionImpl(this);
}
- override commit(DataStoreIdentifier store) {
- throw new UnsupportedOperationException("Deprecated")
+ override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+ val readers = configReaders.getAllChildren(path);
+ return readers.readConfiguration(path);
}
- override editCandidateData(DataStoreIdentifier store, DataRoot changeSet) {
- throw new UnsupportedOperationException("Deprecated")
+ override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+ val readers = operationalReaders.getAllChildren(path);
+ return readers.readOperational(path);
}
- override <T extends DataRoot> getCandidateData(DataStoreIdentifier store, Class<T> rootType) {
- throw new UnsupportedOperationException("Deprecated")
+ override registerCommitHandler(InstanceIdentifier<? extends DataObject> path,
+ DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
+ val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
+ commitHandlers.put(path,registration)
+ return registration;
}
- override <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, T filter) {
- throw new UnsupportedOperationException("Deprecated")
+ override registerDataChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener listener) {
+ val reg = new DataChangeListenerRegistration(path, listener, this);
+ listeners.put(path, reg);
+ return reg;
}
- override getConfigurationData(InstanceIdentifier<?> data) {
- throw new UnsupportedOperationException("Deprecated")
+ override registerDataReader(InstanceIdentifier<? extends DataObject> path,
+ DataReader<InstanceIdentifier<? extends DataObject>, DataObject> provider) {
+ val ret = new DataReaderRegistration(provider, this);
+ ret.paths.add(path);
+ configReaders.put(path, ret);
+ operationalReaders.put(path, ret);
+ return ret;
}
- override <T extends DataRoot> getData(DataStoreIdentifier store, Class<T> rootType) {
- throw new UnsupportedOperationException("Deprecated")
+ protected def removeReader(DataReaderRegistration reader) {
+ for (path : reader.paths) {
+ operationalReaders.remove(path, reader);
+ configReaders.remove(path, reader);
+ }
}
- override <T extends DataRoot> T getData(DataStoreIdentifier store, T filter) {
- throw new UnsupportedOperationException("Deprecated")
+ protected def removeListener(DataChangeListenerRegistration registration) {
+ listeners.remove(registration.path, registration);
}
- override getData(InstanceIdentifier<? extends DataObject> path) {
- return readOperationalData(path);
+ protected def removeCommitHandler(DataCommitHandlerRegistration registration) {
+ commitHandlers.remove(registration.path, registration);
}
- override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+ protected def DataObject readConfiguration(
+ Collection<Entry<? extends InstanceIdentifier, ? extends DataReaderRegistration>> entries,
+ InstanceIdentifier<? extends DataObject> path) {
+
+ val List<DataObject> partialResults = new LinkedList();
+ for (entry : entries) {
+ partialResults.add(entry.value.instance.readConfigurationData(path))
+ }
+ return merge(path, partialResults);
}
- override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+ protected def DataObject readOperational(
+ Collection<Entry<? extends InstanceIdentifier, ? extends DataReaderRegistration>> entries,
+ InstanceIdentifier<? extends DataObject> path) {
+
+ val List<DataObject> partialResults = new LinkedList();
+ for (entry : entries) {
+ partialResults.add(entry.value.instance.readOperationalData(path))
+ }
+ return merge(path, partialResults);
}
- override registerChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener changeListener) {
+ protected def DataObject merge(InstanceIdentifier<? extends DataObject> identifier, List<DataObject> objects) {
+
+ // FIXME: implement real merge
+ if (objects.size > 0) {
+ return objects.get(0);
+ }
+ }
+
+ protected def getActiveCommitHandlers() {
+
+ return commitHandlers.entries.map[ value.instance].toSet
}
- override registerCommitHandler(InstanceIdentifier<? extends DataObject> path,
- DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
+ protected def commit(DataTransactionImpl transaction) {
+ checkNotNull(transaction);
+ transaction.changeStatus(TransactionStatus.SUBMITED);
+ val task = new TwoPhaseCommit(transaction, this);
+ return executor.submit(task);
}
- override registerDataChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener listener) {
+}
+
+package class DataReaderRegistration extends //
+AbstractObjectRegistration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> {
+
+ DataBrokerImpl dataBroker;
+
+ @Property
+ val Set<InstanceIdentifier<? extends DataObject>> paths;
+
+ new(DataReader<InstanceIdentifier<? extends DataObject>, DataObject> instance, DataBrokerImpl broker) {
+ super(instance)
+ dataBroker = broker;
+ _paths = new HashSet();
}
- override unregisterChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener changeListener) {
+ override protected removeRegistration() {
+ dataBroker.removeReader(this);
}
}
+
+package class DataChangeListenerRegistration extends AbstractObjectRegistration<DataChangeListener> implements ListenerRegistration<DataChangeListener> {
+
+ DataBrokerImpl dataBroker;
+
+ @Property
+ val InstanceIdentifier<?> path;
+
+ new(InstanceIdentifier<?> path, DataChangeListener instance, DataBrokerImpl broker) {
+ super(instance)
+ dataBroker = broker;
+ _path = path;
+ }
+
+ override protected removeRegistration() {
+ dataBroker.removeListener(this);
+ dataBroker = null;
+ }
+
+}
+
+package class DataCommitHandlerRegistration //
+extends AbstractObjectRegistration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> {
+
+ DataBrokerImpl dataBroker;
+
+ @Property
+ val InstanceIdentifier<?> path;
+
+ new(InstanceIdentifier<?> path, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> instance,
+ DataBrokerImpl broker) {
+ super(instance)
+ dataBroker = broker;
+ _path = path;
+ }
+
+ override protected removeRegistration() {
+ dataBroker.removeCommitHandler(this);
+ dataBroker = null;
+ }
+
+}
+
+package class TwoPhaseCommit implements Callable<RpcResult<TransactionStatus>> {
+
+ val DataTransactionImpl transaction;
+ val DataBrokerImpl dataBroker;
+
+ new(DataTransactionImpl transaction, DataBrokerImpl broker) {
+ this.transaction = transaction;
+ this.dataBroker = broker;
+ }
+
+ override call() throws Exception {
+
+ val Iterable<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> commitHandlers = dataBroker.activeCommitHandlers;
+
+ // requesting commits
+ val List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> handlerTransactions = new ArrayList();
+ try {
+ for (handler : commitHandlers) {
+ handlerTransactions.add(handler.requestCommit(transaction));
+ }
+ } catch (Exception e) {
+ return rollback(handlerTransactions,e);
+ }
+ val List<RpcResult<Void>> results = new ArrayList();
+ try {
+ for (subtransaction : handlerTransactions) {
+ results.add(subtransaction.finish());
+ }
+ } catch (Exception e) {
+ return rollback(handlerTransactions,e);
+ }
+
+ return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
+ }
+
+ def rollback(List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> transactions,Exception e) {
+ for (transaction : transactions) {
+ transaction.rollback()
+ }
+ // FIXME return encoutered error.
+ return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
+import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class DataTransactionImpl extends AbstractDataModification<InstanceIdentifier<? extends DataObject>, DataObject>
+ implements DataModificationTransaction {
+
+ private final Object identifier;
+
+ private TransactionStatus status;
+ private ListenerRegistry<DataTransactionListener> listeners;
+
+ final DataBrokerImpl broker;
+
+ public DataTransactionImpl(DataBrokerImpl dataBroker) {
+ identifier = new Object();
+ broker = dataBroker;
+ status = TransactionStatus.NEW;
+ listeners = new ListenerRegistry<>();
+ }
+
+ @Override
+ public Future<RpcResult<TransactionStatus>> commit() {
+ return broker.commit(this);
+ }
+
+ @Override
+ public DataObject readConfigurationData(
+ org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
+ return broker.readConfigurationData(path);
+ }
+
+ @Override
+ public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+ return broker.readOperationalData(path);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((broker == null) ? 0 : broker.hashCode());
+ result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DataTransactionImpl other = (DataTransactionImpl) obj;
+ if (broker == null) {
+ if (other.broker != null)
+ return false;
+ } else if (!broker.equals(other.broker))
+ return false;
+ if (identifier == null) {
+ if (other.identifier != null)
+ return false;
+ } else if (!identifier.equals(other.identifier))
+ return false;
+ return true;
+ }
+
+ @Override
+ public TransactionStatus getStatus() {
+ return status;
+ }
+
+ @Override
+ public Object getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener) {
+ return listeners.register(listener);
+ }
+
+ public void changeStatus(TransactionStatus status) {
+ this.status = status;
+ Iterable<ListenerRegistration<DataTransactionListener>> listenersToNotify = listeners.getListeners();
+ for (ListenerRegistration<DataTransactionListener> listenerRegistration : listenersToNotify) {
+ listenerRegistration.getInstance().onStatusUpdated(this, status);
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.controller.sal.common.DataStoreIdentifier
+import org.opendaylight.yangtools.yang.binding.DataRoot
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
+
+abstract class DeprecatedDataAPISupport implements DataProviderService {
+
+ @Deprecated
+ override commit(DataStoreIdentifier store) {
+ throw new UnsupportedOperationException("Deprecated")
+ }
+
+ @Deprecated
+ override editCandidateData(DataStoreIdentifier store, DataRoot changeSet) {
+ throw new UnsupportedOperationException("Deprecated")
+ }
+
+ @Deprecated
+ override <T extends DataRoot> getCandidateData(DataStoreIdentifier store, Class<T> rootType) {
+ throw new UnsupportedOperationException("Deprecated")
+ }
+
+ @Deprecated
+ override <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, T filter) {
+ throw new UnsupportedOperationException("Deprecated")
+ }
+
+ @Deprecated
+ override getConfigurationData(InstanceIdentifier<?> data) {
+ throw new UnsupportedOperationException("Deprecated")
+ }
+
+ @Deprecated
+ override <T extends DataRoot> getData(DataStoreIdentifier store, Class<T> rootType) {
+ throw new UnsupportedOperationException("Deprecated")
+ }
+
+ @Deprecated
+ override <T extends DataRoot> T getData(DataStoreIdentifier store, T filter) {
+ throw new UnsupportedOperationException("Deprecated")
+ }
+
+ @Deprecated
+ override getData(InstanceIdentifier<? extends DataObject> path) {
+ return readOperationalData(path);
+ }
+
+ override registerChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener changeListener) {
+ }
+
+ override unregisterChangeListener(InstanceIdentifier<? extends DataObject> path,
+ DataChangeListener changeListener) {
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import org.opendaylight.yangtools.yang.common.RpcResult
+import java.util.Map
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.controller.sal.common.util.Rpcs
+import java.util.Collections
+
+class HashMapDataStore //
+implements //
+RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ val Map<InstanceIdentifier<? extends DataObject>,DataObject> configuration = new ConcurrentHashMap();
+ val Map<InstanceIdentifier<? extends DataObject>,DataObject> operational = new ConcurrentHashMap();
+
+
+ override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+ configuration.get(path);
+ }
+
+ override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+ operational.get(path);
+ }
+
+ override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ return new HashMapDataStoreTransaction(modification,this);
+ }
+
+ def RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
+ return Rpcs.getRpcResult(true,null,Collections.emptySet);
+ }
+
+ def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
+ val modification = transaction.modification;
+ configuration.putAll(modification.updatedConfigurationData);
+ operational.putAll(modification.updatedOperationalData);
+
+ for(removal : modification.removedConfigurationData) {
+ configuration.remove(removal);
+ }
+ for(removal : modification.removedOperationalData) {
+ operational.remove(removal);
+ }
+ return Rpcs.getRpcResult(true,null,Collections.emptySet);
+ }
+
+}
+
+class HashMapDataStoreTransaction implements //
+DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+ @Property
+ val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification
+
+ @Property
+ val HashMapDataStore datastore;
+
+
+ new(
+ DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modify,
+ HashMapDataStore store
+ ) {
+ _modification = modify;
+ _datastore = store;
+ }
+
+ override finish() throws IllegalStateException {
+ datastore.finish(this);
+
+ }
+
+ override getModification() {
+ this._modification;
+ }
+
+ override rollback() throws IllegalStateException {
+ datastore.rollback(this);
+ }
+}
return salReg;
}
- override <T extends RpcService> addMountRpcImplementation(Class<T> type, InstanceIdentifier<?> mount, T implementation) throws IllegalStateException {
- checkNotNull(type, "Service type should not be null")
- checkNotNull(mount,"Path to the mount should not be null")
- checkNotNull(implementation, "Service instance should not be null")
-
- val properties = new Hashtable<String, String>();
- properties.salServiceType = SAL_SERVICE_TYPE_PROVIDER
-
- // Fill requirements
- val salReg = broker.registerMountedRpcImplementation(type, implementation, mount, this)
- registeredServices.put(type, salReg)
- return salReg;
- }
-
override <T extends RpcService> addRoutedRpcImplementation(Class<T> type, T implementation) throws IllegalStateException {
checkNotNull(type, "Service type should not be null")
checkNotNull(implementation, "Service type should not be null")
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.util
+
+import java.util.Map.Entry
+import org.opendaylight.yangtools.concepts.Path
+import java.util.Map
+import java.util.Set
+import java.util.Collection
+import java.util.HashSet
+import com.google.common.collect.Multimap
+
+class MapUtils {
+
+ public static def <P extends Path<P>, V> Collection<Entry<? extends P, ? extends V>> getAllChildren(
+ Multimap<? extends P, ? extends V> map, P path) {
+ val ret = new HashSet();
+ val entries = map.entries;
+
+ for (entry : entries) {
+ val currentPath = entry.key;
+ // If the registered reader processes nested elements
+ if (path.contains(currentPath)) {
+ ret.add(entry);
+ } else if(currentPath.contains(path)) {
+ // If the registered reader is parent of entry
+ ret.add(entry);
+ }
+ }
+
+ return ret;
+ }
+}
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcImplementation;
import org.opendaylight.yangtools.yang.binding.RpcService;
/**
* Type of RpcService for which router provides routing information
* and route selection.
*/
-public interface RpcRouter<T extends RpcService> {
+public interface RpcRouter<T extends RpcService> extends RpcImplementation{
/**
* Returns a type of RpcService which is served by this instance of router.
*
* @return type of RpcService which is served by this instance of router.
*/
- Class<T> getRpcServiceType();
+ Class<T> getServiceType();
/**
* @return type of RpcService which is served by this instance of router.
*/
T getInvocationProxy();
-
/**
* Returns a routing table for particular route context
--- /dev/null
+package org.opendaylight.controller.sal.binding.spi.remote;
+
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+public interface RemoteRpcRouter {
+
+
+
+
+
+
+ ListenerRegistration<RouteChangeListener> registerRouteChangeListener(RouteChangeListener listener);
+
+
+
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.spi.remote;
+
+import java.util.EventListener;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface RouteChangeListener extends EventListener {
+
+ void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change);
+
+}
import org.opendaylight.controller.sal.binding.test.mock.FooListener;
import org.opendaylight.controller.sal.binding.test.mock.FooService;
import org.opendaylight.controller.sal.binding.test.mock.FooUpdate;
+import org.opendaylight.controller.sal.binding.test.mock.InheritedContextInput;
import org.opendaylight.controller.sal.binding.test.mock.ReferencableObject;
import org.opendaylight.controller.sal.binding.test.mock.ReferencableObjectKey;
import org.opendaylight.controller.sal.binding.test.mock.SimpleInput;
assertNotNull(product);
assertNotNull(product.getInvocationProxy());
+ assertNotNull(product.getSupportedInputs());
+ assertTrue(product.getSupportedInputs().contains(SimpleInput.class));
+ assertTrue(product.getSupportedInputs().contains(InheritedContextInput.class));
assertEquals("2 fields should be generated.", 2, product.getInvocationProxy().getClass().getFields().length);
verifyRouting(product);
Future<RpcResult<Void>> simple(SimpleInput obj);
- Future<RpcResult<Void>> inheritedContextInput(InheritedContextInput obj);
+ Future<RpcResult<Void>> inheritedContext(InheritedContextInput obj);
}
<artifactId>model-flow-service</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
</dependency>
</dependencies>
</project>
mavenBundle(YANGTOOLS, "yang-common").versionAsInProject(), //
mavenBundle(CONTROLLER, "sal-common").versionAsInProject(), //
mavenBundle(CONTROLLER, "sal-common-api").versionAsInProject(), //
+ mavenBundle(CONTROLLER, "sal-common-impl").versionAsInProject(), //
mavenBundle("com.google.guava", "guava").versionAsInProject(), //
mavenBundle(YANGTOOLS + ".thirdparty", "xtend-lib-osgi").versionAsInProject() //
);
public static Option junitAndMockitoBundles() {
return new DefaultCompositeOption(
- // Repository required to load harmcrest (OSGi-fied version).
+ // Repository required to load harmcrest (OSGi-fied version).
repository("http://repository.springsource.com/maven/bundles/external").id(
"com.springsource.repository.bundles.external"),
// BASE Models
baseModelBundles(), flowCapableModelBundles(), junitAndMockitoBundles());
}
+
}
--- /dev/null
+package org.opendaylight.controller.test.sal.binding.it;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class DataServiceTest extends AbstractTest {
+
+ protected DataBrokerService consumerDataService;
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @Test
+ public void test() throws Exception {
+ BindingAwareConsumer consumer1 = new BindingAwareConsumer() {
+
+ @Override
+ public void onSessionInitialized(ConsumerContext session) {
+ consumerDataService = session.getSALService(DataBrokerService.class);
+ }
+ };
+ broker.registerConsumer(consumer1, getBundleContext());
+
+ assertNotNull(consumerDataService);
+
+
+ DataModificationTransaction transaction = consumerDataService.beginTransaction();
+ assertNotNull(transaction);
+
+ NodeRef node1 = createNodeRef("0");
+ DataObject node = consumerDataService.readConfigurationData(node1.getValue());
+ assertNull(node);
+ Node nodeData1 = createNode("0");
+
+ transaction.putConfigurationData(node1.getValue(), nodeData1);
+ Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
+ assertNotNull(commitResult);
+
+ RpcResult<TransactionStatus> result = commitResult.get();
+
+ assertNotNull(result);
+ assertNotNull(result.getResult());
+ assertEquals(TransactionStatus.COMMITED, result.getResult());
+
+ DataObject readedData = consumerDataService.readConfigurationData(node1.getValue());
+ assertNotNull(readedData);
+ assertEquals(nodeData1, readedData);
+
+
+ DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
+ assertNotNull(transaction);
+
+ transaction2.removeConfigurationData(node1.getValue());
+
+ Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
+ assertNotNull(commitResult2);
+
+ RpcResult<TransactionStatus> result2 = commitResult2.get();
+
+ assertNotNull(result2);
+ assertNotNull(result2.getResult());
+ assertEquals(TransactionStatus.COMMITED, result2.getResult());
+
+ DataObject readedData2 = consumerDataService.readConfigurationData(node1.getValue());
+ assertNull(readedData2);
+
+
+ }
+
+
+ private static NodeRef createNodeRef(String string) {
+ NodeKey key = new NodeKey(new NodeId(string));
+ InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
+ .toInstance();
+
+ return new NodeRef(path);
+ }
+
+ private static Node createNode(String string) {
+ NodeBuilder ret = new NodeBuilder();
+ ret.setId(new NodeId(string));
+ return ret.build();
+ }
+}
// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
// import org.opendaylight.yangtools.concepts.Path;
+/**
+ * Reader for reading YANG subtrees based on their path.
+ *
+ * Reader is requested to return object at specified path and all it's subnodes
+ * known to the reader or null if node is not found in this reader.
+ *
+ * @param <P> Path Type
+ * @param <D> Data Type
+ */
public interface DataReader<P/* extends Path<P> */,D> {
/**
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>sal-common-impl</artifactId>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
- </scm>
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-common-impl</artifactId>
+ <packaging>bundle</packaging>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.lib</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>org.opendaylight.controller.md.sal.common.impl</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- </dependencies>
- <packaging>bundle</packaging>
</project>
import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW;
-public abstract class AbstractDataModification<P extends Path<P>, D> implements DataModification<P, D> {
+public abstract class AbstractDataModification<P /*extends Path<P>*/, D> implements DataModification<P, D> {
- private final Map<P,D> configurationUpdate;
- private final Map<P,D> operationalUpdate;
+ private final Map<P, D> configurationUpdate;
+ private final Map<P, D> operationalUpdate;
private final Set<P> configurationRemove;
private final Set<P> operationalRemove;
-
+
private final Map<P, D> unmodifiable_configurationUpdate;
private final Map<P, D> unmodifiable_operationalUpdate;
private final Set<P> unmodifiable_configurationRemove;
private final Set<P> unmodifiable_OperationalRemove;
-
-
public AbstractDataModification(Map<P, D> configurationUpdate, Map<P, D> operationalUpdate,
Set<P> configurationRemove, Set<P> operationalRemove) {
this.configurationUpdate = configurationUpdate;
this.operationalUpdate = operationalUpdate;
this.configurationRemove = configurationRemove;
this.operationalRemove = operationalRemove;
-
+
unmodifiable_configurationUpdate = Collections.unmodifiableMap(configurationUpdate);
unmodifiable_operationalUpdate = Collections.unmodifiableMap(operationalUpdate);
unmodifiable_configurationRemove = Collections.unmodifiableSet(configurationRemove);
unmodifiable_OperationalRemove = Collections.unmodifiableSet(operationalRemove);
}
-
+
public AbstractDataModification() {
- this(new HashMap<P,D>(), new HashMap<P,D>(), new HashSet<P>(), new HashSet<P>());
+ this(new HashMap<P, D>(), new HashMap<P, D>(), new HashSet<P>(), new HashSet<P>());
}
@Override
configurationUpdate.put(path, data);
configurationRemove.remove(path);
}
-
+
@Override
public final void putRuntimeData(P path, D data) {
checkMutable();
operationalUpdate.put(path, data);
operationalRemove.remove(path);
}
-
+
@Override
public final void removeRuntimeData(P path) {
checkMutable();
operationalUpdate.remove(path);
operationalRemove.add(path);
}
-
+
@Override
public final void removeConfigurationData(P path) {
checkMutable();
}
private final void checkMutable() {
- if(!NEW.equals(this.getStatus())) throw new IllegalStateException("Transaction was already submitted");
+ if (!NEW.equals(this.getStatus()))
+ throw new IllegalStateException("Transaction was already submitted");
}
@Override
public Map<P, D> getUpdatedConfigurationData() {
-
+
return unmodifiable_configurationUpdate;
}
public Set<P> getRemovedConfigurationData() {
return unmodifiable_configurationRemove;
}
-
+
@Override
public Set<P> getRemovedOperationalData() {
return unmodifiable_OperationalRemove;
--- /dev/null
+package org.opendaylight.controller.md.sal.common.impl;
+
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.google.common.base.Preconditions.*;
+
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+public class ListenerRegistry<T extends EventListener> {
+
+ final Set<ListenerRegistration<T>> listeners;
+ final Set<ListenerRegistration<T>> unmodifiableView;
+
+ public ListenerRegistry() {
+ listeners = new HashSet<>();
+ unmodifiableView = Collections.unmodifiableSet(listeners);
+ }
+
+ public Iterable<ListenerRegistration<T>> getListeners() {
+ return unmodifiableView;
+ }
+
+
+ public ListenerRegistration<T> register(T listener) {
+ checkNotNull(listener, "Listener should not be null.");
+ ListenerRegistrationImpl<T> ret = new ListenerRegistrationImpl<T>(listener);
+ listeners.add(ret);
+ return ret;
+ }
+
+
+ @SuppressWarnings("rawtypes")
+ private void remove(ListenerRegistrationImpl registration) {
+ listeners.remove(registration);
+ }
+
+ private class ListenerRegistrationImpl<P extends EventListener> //
+ extends AbstractObjectRegistration<P> //
+ implements ListenerRegistration<P> {
+
+ public ListenerRegistrationImpl(P instance) {
+ super(instance);
+ }
+
+ @Override
+ protected void removeRegistration() {
+ ListenerRegistry.this.remove(this);
+ }
+ }
+}
this.session = session;
NotificationService notificationService = session.getSALService(NotificationService.class);
notificationService.addNotificationListener(ToastDone.class, this);
-
-
}
@Override
mavenBundle(ODL, "sal-binding-api").versionAsInProject(), //
mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject(), //
mavenBundle(ODL, "sal-common").versionAsInProject(), //
- mavenBundle(ODL, "sal-common-api").versionAsInProject(),
+ mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
+ mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
mavenBundle(SAMPLE, "sample-toaster").versionAsInProject(), //
mavenBundle(SAMPLE, "sample-toaster-consumer").versionAsInProject(), //