Updated implementation of broker (data services, generated code), added Integration... 14/2114/5
authorTony Tkacik <ttkacik@cisco.com>
Wed, 23 Oct 2013 17:13:35 +0000 (19:13 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 25 Oct 2013 03:21:57 +0000 (03:21 +0000)
  - Added Javadoc to Bidning Aware APIs
  - Updated implementation of data services
- Added default data store for integration testing
        - added integration test for data modifications and reads
  - Updated implementation of generated RpcRouters to get rid of reflection in cases
    where invoker does not known RPC name, only payload.

Change-Id: I30b8d8b5b4b35ff1879d0a67c2f8717294841063
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
39 files changed:
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcConsumerRegistry.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataBrokerService.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataModificationTransaction.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataProviderService.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/RuntimeDataProvider.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/mount/MountInstance.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/mount/MountProviderInstance.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/mount/MountProviderService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeGenerator.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BrokerActivator.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DeprecatedDataAPISupport.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcRouter.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/remote/RemoteRpcRouter.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/remote/RouteChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataReader.java
opendaylight/md-sal/sal-common-impl/pom.xml
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/ListenerRegistry.java [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/toaster/provider/impl/ToastConsumerImpl.java
opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java

index 84e0561..19ca06a 100644 (file)
@@ -126,7 +126,7 @@ public interface BindingAwareBroker {
      * 
      * 
      */
-    public interface ConsumerContext {
+    public interface ConsumerContext extends RpcConsumerRegistry {
 
         /**
          * Returns a session specific instance (implementation) of requested
@@ -138,15 +138,7 @@ public interface BindingAwareBroker {
          */
         <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);
+
     }
 
     /**
@@ -165,25 +157,12 @@ public interface BindingAwareBroker {
      * 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);
     }
 
index 64aab6e..cb201c5 100644 (file)
@@ -15,23 +15,35 @@ import org.opendaylight.yangtools.yang.binding.Notification;
 
 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);
 }
index 922acb9..10b29f7 100644 (file)
@@ -8,27 +8,63 @@
 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);
 }
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcConsumerRegistry.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcConsumerRegistry.java
new file mode 100644 (file)
index 0000000..e20640d
--- /dev/null
@@ -0,0 +1,20 @@
+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);
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java
new file mode 100644 (file)
index 0000000..972e64f
--- /dev/null
@@ -0,0 +1,39 @@
+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;
+}
index 50ee740..aa846ff 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.controller.md.sal.common.api.data.DataModificationTransa
 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;
@@ -165,4 +166,31 @@ public interface DataBrokerService extends //
     @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);
 }
index 4f69f0b..9ce11c7 100644 (file)
@@ -8,6 +8,7 @@
 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;
@@ -15,17 +16,68 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
 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);
     }
 }
index 32b1d93..523abb5 100644 (file)
@@ -9,11 +9,30 @@ package org.opendaylight.controller.sal.binding.api.data;
 
 
 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);
 }
index f711659..652e14b 100644 (file)
@@ -16,6 +16,12 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 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> {
     
     
index b926e95..844b03a 100644 (file)
@@ -8,11 +8,17 @@
 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 {
 
 }
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/mount/MountProviderInstance.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/mount/MountProviderInstance.java
new file mode 100644 (file)
index 0000000..81a4a24
--- /dev/null
@@ -0,0 +1,22 @@
+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 {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/mount/MountProviderService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/mount/MountProviderService.java
new file mode 100644 (file)
index 0000000..d91a216
--- /dev/null
@@ -0,0 +1,18 @@
+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);
+}
index f94be9c..1d82807 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.sal.binding.spi.DelegateProxy;
 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;
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend
deleted file mode 100644 (file)
index f60816d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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;
-}
index f63f2a3..5b11ec7 100644 (file)
@@ -8,8 +8,9 @@ import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeC
 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> {
 
@@ -17,20 +18,29 @@ 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)
@@ -47,4 +57,9 @@ class RpcRouterCodegenInstance<T extends RpcService> implements RpcRouter<T> {
         val table = getRoutingTable(context);
         return table.getRoute(path);
     }
+
+    override <T extends DataContainer> invoke(Class<T> type, T input) {
+        return invokerDelegate.invoke(type, input);
+    }
+
 }
index 0aee95e..87cc42c 100644 (file)
@@ -33,16 +33,16 @@ import java.util.Arrays
 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 {
 
@@ -70,31 +70,26 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
     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»;
                             }
@@ -108,10 +103,90 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
                         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) {
@@ -119,58 +194,34 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
 
         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) {
@@ -225,18 +276,7 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
         }
     }
 
-    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;
@@ -248,19 +288,18 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
 }
 
 @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;
@@ -272,12 +311,11 @@ class RuntimeGeneratedInvoker implements NotificationInvoker {
     }
 
     override close() {
-        
     }
 }
 
 @Data
-class RuntimeGeneratedInvokerPrototype {
+package class RuntimeGeneratedInvokerPrototype {
 
     @Property
     val Set<Class<? extends Notification>> supportedNotifications;
@@ -285,3 +323,40 @@ class RuntimeGeneratedInvokerPrototype {
     @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;
+}
index bd7f25c..1dc2a88 100644 (file)
@@ -48,6 +48,7 @@ class BindingAwareBrokerImpl implements BindingAwareBroker {
 
     private val clsPool = ClassPool.getDefault()
     private var RuntimeCodeGenerator generator;
+    
 
     /**
      * Map of all Managed Direct Proxies
@@ -63,8 +64,12 @@ class BindingAwareBrokerImpl implements BindingAwareBroker {
      */
     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
@@ -78,12 +83,15 @@ class BindingAwareBrokerImpl implements BindingAwareBroker {
         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)
+        
+        
 
     }
 
index 9a5cbff..fd6e0f0 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.binding.impl;
 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;
@@ -21,13 +22,17 @@ public class BrokerActivator implements BundleActivator {
     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<>();
index 99afbab..9356ecd 100644 (file)
@@ -3,65 +3,242 @@ package org.opendaylight.controller.sal.binding.impl
 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());
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java
new file mode 100644 (file)
index 0000000..9cb9caf
--- /dev/null
@@ -0,0 +1,100 @@
+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);
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DeprecatedDataAPISupport.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DeprecatedDataAPISupport.xtend
new file mode 100644 (file)
index 0000000..8568dd5
--- /dev/null
@@ -0,0 +1,59 @@
+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) {
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend
new file mode 100644 (file)
index 0000000..2356468
--- /dev/null
@@ -0,0 +1,85 @@
+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);
+    }
+}
index 1be19c0..7fd3fd2 100644 (file)
@@ -44,20 +44,6 @@ class OsgiProviderContext extends OsgiConsumerContext implements ProviderContext
         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")
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend
new file mode 100644 (file)
index 0000000..4ebfd9a
--- /dev/null
@@ -0,0 +1,31 @@
+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;
+    }
+}
index 38e309f..7db90b6 100644 (file)
@@ -11,6 +11,7 @@ import java.util.Set;
 
 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;
 
 /**
@@ -25,14 +26,14 @@ 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();
     
     
     /**
@@ -42,7 +43,6 @@ public interface RpcRouter<T extends RpcService> {
      * @return type of RpcService which is served by this instance of router.
      */
     T getInvocationProxy();
-    
 
     /**
      * Returns a routing table for particular route context
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/remote/RemoteRpcRouter.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/remote/RemoteRpcRouter.java
new file mode 100644 (file)
index 0000000..cda20e5
--- /dev/null
@@ -0,0 +1,17 @@
+package org.opendaylight.controller.sal.binding.spi.remote;
+
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+public interface RemoteRpcRouter {
+
+
+    
+    
+    
+    
+    ListenerRegistration<RouteChangeListener> registerRouteChangeListener(RouteChangeListener listener);
+
+    
+    
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/remote/RouteChangeListener.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/remote/RouteChangeListener.java
new file mode 100644 (file)
index 0000000..56cdee9
--- /dev/null
@@ -0,0 +1,13 @@
+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);
+
+}
index 65bc583..1a97bd6 100644 (file)
@@ -28,6 +28,7 @@ import org.opendaylight.controller.sal.binding.test.mock.FlowDelete;
 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;
@@ -64,6 +65,9 @@ public class RuntimeCodeGeneratorTest {
         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);
index 3161e93..9de0bb7 100644 (file)
@@ -11,6 +11,6 @@ public interface FooService extends RpcService {
     
     Future<RpcResult<Void>> simple(SimpleInput obj);
     
-    Future<RpcResult<Void>> inheritedContextInput(InheritedContextInput obj);
+    Future<RpcResult<Void>> inheritedContext(InheritedContextInput obj);
 
 }
index e4afc81..20518bd 100644 (file)
       <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>
index 842b80e..a644619 100644 (file)
@@ -23,6 +23,7 @@ public class TestHelper {
                 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() //
         );
@@ -65,7 +66,7 @@ public class TestHelper {
 
     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"),
 
diff --git a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java
new file mode 100644 (file)
index 0000000..d26f2e7
--- /dev/null
@@ -0,0 +1,103 @@
+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();
+    }
+}
index ff1703f..7240a50 100644 (file)
@@ -10,6 +10,15 @@ package org.opendaylight.controller.md.sal.common.api.data;
 // 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> {
 
     /**
index 8da8f24..0c2344a 100644 (file)
@@ -1,28 +1,47 @@
 <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>
index e786b74..5d76717 100644 (file)
@@ -11,36 +11,34 @@ import org.opendaylight.yangtools.concepts.Path;
 
 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
@@ -49,21 +47,21 @@ public abstract class AbstractDataModification<P extends Path<P>, D> implements
         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();
@@ -72,12 +70,13 @@ public abstract class AbstractDataModification<P extends Path<P>, D> implements
     }
 
     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;
     }
 
@@ -90,7 +89,7 @@ public abstract class AbstractDataModification<P extends Path<P>, D> implements
     public Set<P> getRemovedConfigurationData() {
         return unmodifiable_configurationRemove;
     }
-    
+
     @Override
     public Set<P> getRemovedOperationalData() {
         return unmodifiable_OperationalRemove;
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/ListenerRegistry.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/ListenerRegistry.java
new file mode 100644 (file)
index 0000000..d884dc8
--- /dev/null
@@ -0,0 +1,55 @@
+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);
+        }
+    }
+}
index 6b1b683..91146f3 100644 (file)
@@ -72,8 +72,6 @@ public class ToastConsumerImpl extends AbstractBindingAwareConsumer implements B
         this.session = session;
         NotificationService notificationService = session.getSALService(NotificationService.class);
         notificationService.addNotificationListener(ToastDone.class, this);
-        
-        
     }
 
     @Override
index d8031e5..0bf589b 100644 (file)
@@ -62,7 +62,8 @@ public class ToasterTest {
                 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(), //