Moved MD SAL from sal/yang-prototype to md-sal
authorTony Tkacik <ttkacik@cisco.com>
Mon, 23 Sep 2013 11:54:29 +0000 (13:54 +0200)
committerGiovanni Meo <gmeo@cisco.com>
Tue, 24 Sep 2013 09:57:56 +0000 (11:57 +0200)
Moved MD SAL sources, artefacts from
 opendaylight/sal/yang-prototype to opendaylight/md-sal

Change-Id: Ic3a6dca94faff8cef0dffe830a767d3ad5f0f21a
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
84 files changed:
opendaylight/md-sal/sal-binding-api/.gitignore [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/AbstractBindingAwareConsumer.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/AbstractBindingAwareProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareConsumer.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataBrokerService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataCommitHandler.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataProviderService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataRefresher.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataValidator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/RuntimeDataProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/package-info.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/.gitignore [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BrokerActivator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationServiceImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcServiceRegistrationImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/package-info.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Futures.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/RpcErrors.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/.gitignore [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Broker.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/BrokerService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Consumer.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Provider.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataBrokerService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataCommitHandler.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataValidator.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/package-info.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationProviderService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/package-info.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/package-info.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/NotificationModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/package-info.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/BrokerModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/package-info.java [new file with mode: 0644]

diff --git a/opendaylight/md-sal/sal-binding-api/.gitignore b/opendaylight/md-sal/sal-binding-api/.gitignore
new file mode 100644 (file)
index 0000000..ea8c4bf
--- /dev/null
@@ -0,0 +1 @@
+/target
diff --git a/opendaylight/md-sal/sal-binding-api/pom.xml b/opendaylight/md-sal/sal-binding-api/pom.xml
new file mode 100644 (file)
index 0000000..1dae28f
--- /dev/null
@@ -0,0 +1,37 @@
+<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-binding-api</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.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>${osgi.core.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/AbstractBindingAwareConsumer.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/AbstractBindingAwareConsumer.java
new file mode 100644 (file)
index 0000000..a176664
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.sal.binding.api;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public abstract class AbstractBindingAwareConsumer implements BindingAwareConsumer,BundleActivator {
+
+    @Override
+    public final void start(BundleContext context) throws Exception {
+        ServiceReference<BindingAwareBroker> brokerRef = context.getServiceReference(BindingAwareBroker.class);
+        BindingAwareBroker broker = context.getService(brokerRef);
+        broker.registerConsumer(this, context);
+        startImpl(context);
+        //context.ungetService(brokerRef);
+    }
+
+    @Deprecated
+    abstract protected void startImpl(BundleContext context);
+    
+    @Override
+    public final  void stop(BundleContext context) throws Exception {
+        // TODO Auto-generated method stub
+        
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/AbstractBindingAwareProvider.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/AbstractBindingAwareProvider.java
new file mode 100644 (file)
index 0000000..20a7c0d
--- /dev/null
@@ -0,0 +1,25 @@
+package org.opendaylight.controller.sal.binding.api;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public abstract class AbstractBindingAwareProvider implements BindingAwareProvider, BundleActivator {
+
+    @Override
+    public final void start(BundleContext context) throws Exception {
+            ServiceReference<BindingAwareBroker> brokerRef = context.getServiceReference(BindingAwareBroker.class);
+            BindingAwareBroker broker = context.getService(brokerRef);
+            broker.registerProvider(this, context);
+            startImpl(context);
+    }
+    
+    @Deprecated
+    abstract protected void startImpl(BundleContext context);
+    
+    @Override
+    public final void stop(BundleContext context) throws Exception {
+            
+            
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java
new file mode 100644 (file)
index 0000000..87008cd
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * 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.api;
+
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Binding-aware core of the SAL layer responsible for wiring the SAL consumers.
+ * 
+ * The responsibility of the broker is to maintain registration of SAL
+ * functionality {@link Consumer}s and {@link Provider}s, store provider and
+ * consumer specific context and functionality registration via
+ * {@link ConsumerContext} and provide access to infrastructure services, which
+ * removes direct dependencies between providers and consumers.
+ * 
+ * The Binding-aware broker is also responsible for translation from Java
+ * classes modeling the functionality and data to binding-indpenedent form which
+ * is used in SAL Core.
+ * 
+ * 
+ * <h3>Infrastructure services</h3> Some examples of infrastructure services:
+ * 
+ * <ul>
+ * <li>YANG Module service - see {@link ConsumerContext#getRpcService(Class)},
+ * {@link ProviderContext}
+ * <li>Notification Service - see {@link NotificationService} and
+ * {@link NotificationProviderService}
+ * <li>Functionality and Data model
+ * <li>Data Store access and modification - see {@link DataBrokerService} and
+ * {@link DataProviderService}
+ * </ul>
+ * 
+ * The services are exposed via session.
+ * 
+ * <h3>Session-based access</h3>
+ * 
+ * The providers and consumers needs to register in order to use the
+ * binding-independent SAL layer and to expose functionality via SAL layer.
+ * 
+ * For more information about session-based access see {@link ConsumerContext}
+ * and {@link ProviderContext}
+ * 
+ * 
+ * 
+ */
+public interface BindingAwareBroker {
+    /**
+     * Registers the {@link BindingAwareConsumer}, which will use the SAL layer.
+     * 
+     * <p>
+     * Note that consumer could register additional functionality at later point
+     * by using service and functionality specific APIs.
+     * 
+     * <p>
+     * The consumer is required to use returned session for all communication
+     * with broker or one of the broker services. The session is announced to
+     * the consumer by invoking
+     * {@link Consumer#onSessionInitiated(ConsumerContext)}.
+     * 
+     * @param cons
+     *            Consumer to be registered.
+     * @return a session specific to consumer registration
+     * @throws IllegalArgumentException
+     *             If the consumer is <code>null</code>.
+     * @throws IllegalStateException
+     *             If the consumer is already registered.
+     */
+    ConsumerContext registerConsumer(BindingAwareConsumer consumer, BundleContext ctx);
+
+    /**
+     * Registers the {@link BindingAwareProvider}, which will use the SAL layer.
+     * 
+     * <p>
+     * During the registration, the broker obtains the initial functionality
+     * from consumer, using the
+     * {@link BindingAwareProvider#getImplementations()}, and register that
+     * functionality into system and concrete infrastructure services.
+     * 
+     * <p>
+     * Note that provider could register additional functionality at later point
+     * by using service and functionality specific APIs.
+     * 
+     * <p>
+     * The consumer is <b>required to use</b> returned session for all
+     * communication with broker or one of the broker services. The session is
+     * announced to the consumer by invoking
+     * {@link BindingAwareProvider#onSessionInitiated(ProviderContext)}.
+     * 
+     * 
+     * @param prov
+     *            Provider to be registered.
+     * @return a session unique to the provider registration.
+     * @throws IllegalArgumentException
+     *             If the provider is <code>null</code>.
+     * @throws IllegalStateException
+     *             If the consumer is already registered.
+     */
+    ProviderContext registerProvider(BindingAwareProvider provider, BundleContext ctx);
+
+    /**
+     * {@link BindingAwareConsumer} specific access to the SAL functionality.
+     * 
+     * <p>
+     * ConsumerSession is {@link BindingAwareConsumer}-specific access to the
+     * SAL functionality and infrastructure services.
+     * 
+     * <p>
+     * The session serves to store SAL context (e.g. registration of
+     * functionality) for the consumer and provides access to the SAL
+     * infrastructure services and other functionality provided by
+     * {@link Provider}s.
+     * 
+     * 
+     * 
+     */
+    public interface ConsumerContext {
+
+        /**
+         * Returns a session specific instance (implementation) of requested
+         * binding-aware infrastructural service
+         * 
+         * @param service
+         *            Broker service
+         * @return Session specific implementation of service
+         */
+        <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);
+    }
+
+    /**
+     * {@link BindingAwareProvider} specific access to the SAL functionality.
+     * 
+     * <p>
+     * ProviderSession is {@link BindingAwareProvider}-specific access to the
+     * SAL functionality and infrastructure services, which also allows for
+     * exposing the provider's functionality to the other
+     * {@link BindingAwareConsumer}s.
+     * 
+     * <p>
+     * The session serves to store SAL context (e.g. registration of
+     * functionality) for the providers and exposes access to the SAL
+     * infrastructure services, dynamic functionality registration and any other
+     * functionality provided by other {@link BindingAwareConsumer}s.
+     * 
+     */
+    public interface ProviderContext extends ConsumerContext {
+
+        <T extends RpcService> RpcServiceRegistration<T> addRpcImplementation(Class<T> type, T implementation);
+    }
+
+    public interface RpcServiceRegistration<T extends RpcService> {
+
+        T getService();
+
+        void unregister();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareConsumer.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareConsumer.java
new file mode 100644 (file)
index 0000000..fc29726
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.api;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+
+/**
+ * 
+ * Defines the component of controller and supplies additional metadata. A
+ * component of the controller or application supplies a concrete implementation
+ * of this interface.
+ * 
+ * A user-implemented component (application) which faciliates the SAL and SAL
+ * services to access infrastructure services or providers' functionality.
+ * 
+ * 
+ * 
+ */
+public interface BindingAwareConsumer {
+
+    /**
+     * Callback signaling initialization of the consumer session to the SAL.
+     * 
+     * The consumer MUST use the session for all communication with SAL or
+     * retrieving SAL infrastructure services.
+     * 
+     * This method is invoked by
+     * {@link BindingAwareBroker#registerConsumer(BindingAwareConsumer)}
+     * 
+     * @param session
+     *            Unique session between consumer and SAL.
+     */
+    void onSessionInitialized(ConsumerContext session);
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareProvider.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareProvider.java
new file mode 100644 (file)
index 0000000..3641d76
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.api;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+/**
+ * 
+ * Defines the component of controller and supplies additional metadata. A
+ * component of the controller or application supplies a concrete implementation
+ * of this interface.
+ * 
+ * <p>
+ * A user-implemented component (application) which facilitates the SAL and SAL
+ * services to access infrastructure services and to provide functionality to
+ * {@link Consumer}s and other providers.
+ * 
+ * 
+ */
+public interface BindingAwareProvider {
+
+    void onSessionInitialized(ConsumerContext session);
+
+    /**
+     * Returns a set of provided implementations of YANG modules and their rpcs.
+     * 
+     * 
+     * @return Set of provided implementation of YANG modules and their Rpcs
+     */
+    Collection<? extends RpcService> getImplementations();
+
+    /**
+     * Gets a set of implementations of provider functionality to be registered
+     * into system during the provider registration to the SAL.
+     * 
+     * <p>
+     * This method is invoked by {@link Broker#registerProvider(Provider)} to
+     * learn the initial provided functionality
+     * 
+     * @return Set of provider's functionality.
+     */
+    Collection<? extends ProviderFunctionality> getFunctionality();
+
+    /**
+     * Functionality provided by the {@link BindingAwareProvider}
+     * 
+     * <p>
+     * Marker interface used to mark the interfaces describing specific
+     * functionality which could be exposed by providers to other components.
+     * 
+     * 
+     * 
+     */
+    public interface ProviderFunctionality {
+
+    }
+
+    void onSessionInitiated(ProviderContext session);
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareService.java
new file mode 100644 (file)
index 0000000..b368056
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.api;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+
+/**
+ * 
+ * Session-specific instance of the broker functionality.
+ * 
+ * <p>
+ * BindingAwareService is marker interface for infrastructure services provided
+ * by the SAL. These services are session-specific, each
+ * {@link BindingAwareConsumer} and {@link BindingAwareProvider} usually has own
+ * instance of the service with it's own context.
+ * 
+ * <p>
+ * The consumer's (or provider's) instance of specific service could be obtained
+ * by invoking {@link ConsumerContext#getSALService(Class)} method on session
+ * assigned to the consumer.
+ * 
+ * <p>
+ * {@link BindingAwareService} and {@link BindingAwareProvider} may seem
+ * similar, but provider provides YANG model-based functionality and
+ * {@link BindingAwareProvider} exposes the necessary supporting functionality
+ * to implement specific functionality of YANG and to reuse it in the
+ * development of {@link BindingAwareConsumer}s and {@link BindingAwareProvider}
+ * s.
+ * 
+ * 
+ * 
+ */
+public interface BindingAwareService {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationListener.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationListener.java
new file mode 100644 (file)
index 0000000..ccc7391
--- /dev/null
@@ -0,0 +1,6 @@
+package org.opendaylight.controller.sal.binding.api;
+
+public interface NotificationListener<T> {
+
+    void onNotification(T notification);
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java
new file mode 100644 (file)
index 0000000..86c9eeb
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * 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.api;
+
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+public interface NotificationProviderService extends NotificationService {
+
+    void notify(Notification notification);
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java
new file mode 100644 (file)
index 0000000..3723c70
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.api;
+
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+public interface NotificationService extends BindingAwareService {
+
+    <T extends Notification> void addNotificationListener(Class<T> notificationType, NotificationListener<T> listener);
+
+    <T extends Notification> void removeNotificationListener(Class<T> notificationType, NotificationListener<T> listener);
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataBrokerService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataBrokerService.java
new file mode 100644 (file)
index 0000000..dd055aa
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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.api.data;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareService;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * DataBrokerService provides unified access to the data stores available in the
+ * system.
+ * 
+ * 
+ * @see DataProviderService
+ */
+public interface DataBrokerService extends BindingAwareService {
+
+    /**
+     * Returns a data from specified Data Store.
+     * 
+     * Returns all the data visible to the consumer from specified Data Store.
+     * 
+     * @param <T>
+     *            Interface generated from YANG module representing root of data
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @return data visible to the consumer
+     */
+    <T extends DataRoot> T getData(DataStoreIdentifier store, Class<T> rootType);
+
+    /**
+     * Returns a filtered subset of data from specified Data Store.
+     * 
+     * <p>
+     * The filter is modeled as an hierarchy of Java TOs starting with
+     * implementation of {@link DataRoot} representing data root. The semantics
+     * of the filter tree is the same as filter semantics defined in the NETCONF
+     * protocol for rpc operations <code>get</code> and <code>get-config</code>
+     * in Section 6 of RFC6241.
+     * 
+     * 
+     * @see http://tools.ietf.org/html/rfc6241#section-6
+     * @param <T>
+     *            Interface generated from YANG module representing root of data
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @param filter
+     *            Data tree filter similar to the NETCONF filter
+     * @return
+     */
+    <T extends DataRoot> T getData(DataStoreIdentifier store, T filter);
+
+    /**
+     * Returns a candidate data which are not yet commited.
+     * 
+     * 
+     * @param <T>
+     *            Interface generated from YANG module representing root of data
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @return
+     */
+    <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, Class<T> rootType);
+
+    /**
+     * Returns a filtered subset of candidate data from specified Data Store.
+     * 
+     * <p>
+     * The filter is modeled as an hierarchy of {@link Node} starting with
+     * {@link CompositeNode} representing data root. The semantics of the filter
+     * tree is the same as filter semantics defined in the NETCONF protocol for
+     * rpc operations <code>get</code> and <code>get-config</code> in Section 6
+     * of RFC6241.
+     * 
+     * 
+     * @see http://tools.ietf.org/html/rfc6241#section-6
+     * @param <T>
+     *            Interface generated from YANG module representing root of data
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @param filter
+     *            A filter data root
+     * @return
+     */
+    <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, T filter);
+
+    /**
+     * 
+     * @param <T>
+     *            Interface generated from YANG module representing root of data
+     * @param store
+     *            Identifier of the store, in which will be the candidate data
+     *            modified
+     * @param changeSet
+     *            Modification of data tree.
+     * @return Result object containing the modified data tree if the operation
+     *         was successful, otherwise list of the encountered errors.
+     */
+    RpcResult<DataRoot> editCandidateData(DataStoreIdentifier store, DataRoot changeSet);
+
+    /**
+     * 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.
+     */
+    Future<RpcResult<Void>> commit(DataStoreIdentifier store);
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataCommitHandler.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataCommitHandler.java
new file mode 100644 (file)
index 0000000..ea5a16e
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * 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.api.data;
+
+import java.util.Set;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Two phase commit handler (cohort) of the two-phase commit protocol of data.
+ * 
+ * <p>
+ * The provider should expose the implementation of DataCommitHandler if it's
+ * functionality depends on any subset of data stored in data repositories, in
+ * order to participate in {@link DataBrokerService#commit(DataStoreIdentifier)
+ * operation.
+ * 
+ * <p>
+ * Operations of two-phase commit handlers should not change data in data store,
+ * this is responsibility of the coordinator (broker or some component of the
+ * broker).
+ * 
+ * The commit handlers are responsible for changing the internal state of the
+ * provider to reflect the commited changes in data.
+ * 
+ * <h3>Two-phase commit</h3>
+ * 
+ * <h4>Commit Request Phase</h4>
+ * 
+ * <ol>
+ * <li> <code>Consumer</code> edits data by invocation of
+ * <code>DataBrokerService.editCandidateData(DataStoreIdentifier, DataRoot)</code>
+ * <li> <code>Consumer</code> starts a commit by invoking
+ * <code>DataBrokerService.commit(DataStoreIdentifier)</code>
+ * <li> <code>Broker</code> retrieves a list of all registered
+ * <code>DataCommitHandlers</code>
+ * <li>For each <code>DataCommitHandler</code>
+ * <ol>
+ * <li><code>Broker</code> invokes a
+ * <code>DataCommitHandler.requestCommit(DataStoreIdentifier)</code> operation.
+ * <li><code>DataCommitHandler</code> returns a <code>RpcResult</code> with
+ * <code>CommitTransaction</code>
+ * <li>If the result was successful, broker adds <code>CommitTransaction</code>
+ * to the list of opened transactions. If not, brokers stops a commit request
+ * phase and starts a rollback phase.
+ * </ol>
+ * <li><code>Broker</code> starts a commit finish phase
+ * </ol>
+ * 
+ * <h4>Commit Finish Phase</h4>
+ * 
+ * <ol>
+ * <li>For each <code>CommitTransaction</code> from Commit Request phase
+ * <ol>
+ * <li><code>Broker</code> broker invokes a
+ * <code>CommitTransaction.finish()</code>
+ * <li>The provider finishes a commit (applies the change) and returns an
+ * <code>RpcResult</code>.
+ * </ol>
+ * <li>
+ * <ul>
+ * <li>If all returned results means successful, the brokers end two-phase
+ * commit by returning a success commit result to the Consumer.
+ * <li>If error occured, the broker starts a commit rollback phase.
+ * </ul>
+ * </ol>
+ * 
+ * <h4>Commit Rollback Phase</h4>
+ * <li>For each <code>CommitTransaction</code> from Commit Request phase
+ * <ol>
+ * <li><code>Broker</code>
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * 
+ * broker invokes a {@link CommitTransaction#finish()}
+ * <li>The provider rollbacks a commit and returns an {@link RpcResult} of
+ * rollback. </ol>
+ * <li>Broker returns a error result to the consumer.
+ * 
+ * 
+ * <h3>Registration of functionality</h3>
+ * The registration could be done by :
+ * <ul>
+ * <li>returning an instance of implementation in the return value of
+ * {@link Provider#getProviderFunctionality()}
+ * <li>passing an instance of implementation and {@link DataStoreIdentifier} of
+ * rpc as arguments to the
+ * {@link DataProviderService#addCommitHandler(DataStoreIdentifier, DataCommitHandler)}
+ * </ul>
+ * 
+ * 
+ * 
+ */
+public interface DataCommitHandler extends ProviderFunctionality {
+    /**
+     * A set of Data Stores supported by implementation.
+     * 
+     * The set of {@link DataStoreIdentifier}s which identifies target data
+     * stores which are supported by this commit handler. This set is used, when
+     * {@link Provider} is registered to the SAL, to register and expose the
+     * commit handler functionality to affected data stores.
+     * 
+     * @return Set of Data Store identifiers
+     */
+    Set<DataStoreIdentifier> getSupportedDataStores();
+
+    /**
+     * The provider (commit handler) starts a commit transaction.
+     * 
+     * <p>
+     * The commit handler (provider) prepares an commit scenario, rollback
+     * scenario and validates data.
+     * 
+     * <p>
+     * If the provider is aware that at this point the commit would not be
+     * successful, the transaction is not created, but list of errors which
+     * prevented the start of transaction are returned.
+     * 
+     * @param store
+     * @return Transaction object representing this commit, errors otherwise.
+     */
+    RpcResult<CommitTransaction> requestCommit(DataStoreIdentifier store);
+
+    public interface CommitTransaction {
+        /**
+         * 
+         * @return Data store affected by the transaction
+         */
+        DataStoreIdentifier getDataStore();
+
+        /**
+         * Returns the handler associated with this transaction.
+         * 
+         * @return Handler
+         */
+        DataCommitHandler getHandler();
+
+        /**
+         * 
+         * Finishes a commit.
+         * 
+         * The provider (commit handler) should apply all changes to its state
+         * which are a result of data change-
+         * 
+         * @return
+         */
+        RpcResult<Void> finish() throws IllegalStateException;
+
+        /**
+         * Rollbacks a commit.
+         * 
+         * @return
+         * @throws IllegalStateException
+         *             If the method is invoked after {@link #finish()}
+         */
+        RpcResult<Void> rollback() throws IllegalStateException;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataProviderService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataProviderService.java
new file mode 100644 (file)
index 0000000..857b07b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.api.data;
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+
+public interface DataProviderService extends DataBrokerService {
+
+    /**
+     * Adds {@link DataValidator} for specified Data Store
+     * 
+     * @param store
+     *            Data Store
+     * @param validator
+     *            Validator
+     */
+    public void addValidator(DataStoreIdentifier store, DataValidator validator);
+
+    /**
+     * Removes {@link DataValidator} from specified Data Store
+     * 
+     * @param store
+     * @param validator
+     *            Validator
+     */
+    public void removeValidator(DataStoreIdentifier store, DataValidator validator);
+
+    /**
+     * Adds {@link DataCommitHandler} for specified data store
+     * 
+     * @param store
+     * @param provider
+     */
+    void addCommitHandler(DataStoreIdentifier store, DataCommitHandler provider);
+
+    /**
+     * Removes {@link DataCommitHandler} from specified data store
+     * 
+     * @param store
+     * @param provider
+     */
+    void removeCommitHandler(DataStoreIdentifier store, DataCommitHandler provider);
+
+    /**
+     * Adds {@link DataRefresher} for specified data store
+     * 
+     * @param store
+     * @param refresher
+     */
+    void addRefresher(DataStoreIdentifier store, DataRefresher refresher);
+
+    /**
+     * Removes {@link DataRefresher} from specified data store
+     * 
+     * @param store
+     * @param refresher
+     */
+    void removeRefresher(DataStoreIdentifier store, DataRefresher refresher);
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataRefresher.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataRefresher.java
new file mode 100644 (file)
index 0000000..f54e131
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.api.data;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality;
+
+/**
+ * Trigger for refreshing of the data exposed by the {@link Provider}
+ * 
+ * 
+ * 
+ */
+public interface DataRefresher extends BindingAwareProvider.ProviderFunctionality {
+
+    /**
+     * Fired when some component explicitly requested the data refresh.
+     * 
+     * The provider which exposed the {@link DataRefresher} should republish its
+     * provided data by editing the data in all affected data stores.
+     */
+    void refreshData();
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataValidator.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataValidator.java
new file mode 100644 (file)
index 0000000..8099600
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.api.data;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public interface DataValidator extends ProviderFunctionality {
+
+    RpcResult<Void> validate(DataRoot data);
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/RuntimeDataProvider.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/RuntimeDataProvider.java
new file mode 100644 (file)
index 0000000..4b01aed
--- /dev/null
@@ -0,0 +1,51 @@
+package org.opendaylight.controller.sal.binding.api.data;
+
+import java.util.Set;
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+
+public interface RuntimeDataProvider {
+
+    Set<DataStoreIdentifier> getSupportedStores();
+    
+    
+    Set<Class<? extends DataRoot>> getProvidedDataRoots();
+    
+    
+    /**
+     * Returns a data from specified Data Store.
+     * 
+     * Returns all the data visible to the consumer from specified Data Store.
+     * 
+     * @param <T>
+     *            Interface generated from YANG module representing root of data
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @return data visible to the consumer
+     */
+    <T extends DataRoot> T getData(DataStoreIdentifier store, Class<T> rootType);
+
+    /**
+     * Returns a filtered subset of data from specified Data Store.
+     * 
+     * <p>
+     * The filter is modeled as an hierarchy of Java TOs starting with
+     * implementation of {@link DataRoot} representing data root. The semantics
+     * of the filter tree is the same as filter semantics defined in the NETCONF
+     * protocol for rpc operations <code>get</code> and <code>get-config</code>
+     * in Section 6 of RFC6241.
+     * 
+     * 
+     * @see http://tools.ietf.org/html/rfc6241#section-6
+     * @param <T>
+     *            Interface generated from YANG module representing root of data
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @param filter
+     *            Data tree filter similar to the NETCONF filter
+     * @return
+     */
+    <T extends DataRoot> T getData(DataStoreIdentifier store, T filter);
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/package-info.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/package-info.java
new file mode 100644 (file)
index 0000000..31eec6b
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * 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.api;
+
diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml
new file mode 100644 (file)
index 0000000..8e06c9d
--- /dev/null
@@ -0,0 +1,117 @@
+<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-binding-broker-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>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Bundle-Activator>org.opendaylight.controller.sal.binding.impl.BrokerActivator</Bundle-Activator>
+                        <Private-Package>
+                            org.opendaylight.controller.sal.binding.impl,
+                            org.opendaylight.controller.sal.binding.impl.*,
+                            org.opendaylight.controller.sal.binding.codegen.*,
+                            org.eclipse.xtend2.lib,
+                            org.eclipse.xtend.lib,
+                            org.eclipse.xtext.xbase.*
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+                <version>2.4.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${basedir}/src/main/xtend-gen</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <version>2.4.1</version>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>${basedir}/src/main/xtend-gen</directory>
+                            <includes>
+                                <include>**</include>
+                            </includes>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <!-- >dependency> <groupId>org.opendaylight.controller</groupId> 
+            <artifactId>sal-core-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency -->
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>${osgi.core.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.9-RC1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.javassist</groupId>
+            <artifactId>javassist</artifactId>
+            <version>3.17.1-GA</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+            <version>2.4.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/.gitignore b/opendaylight/md-sal/sal-binding-broker/src/main/.gitignore
new file mode 100644 (file)
index 0000000..04b73cb
--- /dev/null
@@ -0,0 +1 @@
+/xtend-gen
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend
new file mode 100644 (file)
index 0000000..6bdb3c8
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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
+
+import java.util.Map
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity
+import org.opendaylight.yangtools.yang.binding.RpcService
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
+import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
+
+class RuntimeCodeHelper {
+    /**
+     * Helper method to return delegate from ManagedDirectedProxy with use of reflection.
+     * 
+     * Note: This method uses reflection, but access to delegate field should be 
+     * avoided and called only if neccessary.
+     * 
+     */
+    public static def <T extends RpcService> getDelegate(RpcService proxy) {
+        val field = proxy.class.getField(DELEGATE_FIELD)
+        if (field == null) throw new UnsupportedOperationException("Unable to get delegate from proxy");
+        return field.get(proxy) as T
+    }
+
+    /**
+     * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
+     * 
+     * Note: This method uses reflection, but setting delegate field should not occur too much
+     * to introduce any significant performance hits.
+     * 
+     */
+    public static def void setDelegate(RpcService proxy, RpcService delegate) {
+        val field = proxy.class.getField(DELEGATE_FIELD)
+        if (field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy");
+        if (field.type.isAssignableFrom(delegate.class)) {
+            field.set(proxy, delegate)
+        } else
+            throw new IllegalArgumentException("delegate class is not assignable to proxy");
+    }
+
+    public static def Map<InstanceIdentifier, ? extends RpcService> getRoutingTable(RpcService target,
+        Class<? extends BaseIdentity> tableClass) {
+        val field = target.class.getField(tableClass.routingTableField)
+        if (field == null) throw new UnsupportedOperationException(
+            "Unable to get routing table. Table field does not exists");
+        return field.get(target) as Map<InstanceIdentifier, ? extends RpcService>;
+    }
+
+    public static def void setRoutingTable(RpcService target, Class<? extends BaseIdentity> tableClass,
+        Map<InstanceIdentifier, ? extends RpcService> routingTable) {
+         val field = target.class.getField(tableClass.routingTableField)
+        if (field == null) throw new UnsupportedOperationException(
+            "Unable to set routing table. Table field does not exists");
+        field.set(target,routingTable);
+        
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend
new file mode 100644 (file)
index 0000000..c6e76c2
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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
+
+import org.opendaylight.yangtools.yang.binding.RpcService
+import org.opendaylight.yangtools.yang.binding.BaseIdentity
+import org.opendaylight.yangtools.yang.binding.NotificationListener
+
+/**
+ * 
+ * 
+ */
+class RuntimeCodeSpecification {
+
+    public static val PACKAGE_PREFIX = "_gen.";
+
+    public static val DIRECT_PROXY_SUFFIX = "DirectProxy";
+    public static val ROUTER_SUFFIX = "Router";
+    public static val INVOKER_SUFFIX = "Invoker";
+
+    public static val DELEGATE_FIELD = "_delegate"
+    public static val ROUTING_TABLE_FIELD_PREFIX = "_routes_"
+
+    public static def getInvokerName(Class<? extends NotificationListener> listener) {
+        getGeneratedName(listener, INVOKER_SUFFIX);
+    }
+
+    /**
+     * Returns a name for DirectProxy implementation
+     * 
+     * 
+     */
+    public static def getDirectProxyName(Class<? extends RpcService> base) {
+        getGeneratedName(base, DIRECT_PROXY_SUFFIX);
+    }
+
+    /**
+     * Returns a name for Router implementation
+     * 
+     */
+    public static def getRouterName(Class<? extends RpcService> base) {
+        getGeneratedName(base, ROUTER_SUFFIX);
+    }
+
+    /**
+     * Returns a name for generated interface
+     * 
+     */
+    public static def getGeneratedName(Class<?> cls, String suffix) {
+        '''«PACKAGE_PREFIX»«cls.package.name».«cls.simpleName»$«suffix»'''.toString()
+    }
+
+    /**
+     * Returns a field name for specified routing context
+     * 
+     */
+    public static def getRoutingTableField(Class<? extends BaseIdentity> routingContext) {
+        return '''_routes_«routingContext.simpleName»'''.toString;
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend
new file mode 100644 (file)
index 0000000..18d3e26
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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
+
+import java.lang.reflect.Method
+import org.opendaylight.yangtools.yang.binding.Notification
+
+public static class YangtoolsMappingHelper {
+
+    public static def boolean isNotificationCallback(Method it) {
+        return name.startsWith("on") && parameterTypes.size === 1 &&
+            Notification.isAssignableFrom(parameterTypes.get(0))
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java
new file mode 100644 (file)
index 0000000..c6be284
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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 javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+
+public class JavassistUtils {
+
+    public static interface ClassGenerator {
+        void process(CtClass cls);
+    }
+
+    public static interface MethodGenerator {
+        void process(CtMethod method);
+    }
+
+    public static interface FieldGenerator {
+        void process(CtField field);
+    }
+}
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
new file mode 100644 (file)
index 0000000..4324b4e
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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;
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
new file mode 100644 (file)
index 0000000..3b3f419
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * 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 javassist.ClassPool
+import org.opendaylight.yangtools.yang.binding.RpcService
+
+import javassist.CtClass
+import static com.google.common.base.Preconditions.*
+
+import javassist.CtField
+import javassist.Modifier
+import javassist.CtMethod
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
+import org.opendaylight.yangtools.yang.binding.BaseIdentity
+
+import java.util.Map
+import java.util.HashMap
+import javassist.NotFoundException
+import javassist.LoaderClassPath
+import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.MethodGenerator
+import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.ClassGenerator
+import org.opendaylight.yangtools.yang.binding.NotificationListener
+import org.opendaylight.yangtools.yang.binding.Notification
+import java.util.Arrays
+
+import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
+import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
+
+class RuntimeCodeGenerator {
+
+    val ClassPool classPool;
+
+    public new(ClassPool pool) {
+        classPool = pool;
+    }
+
+    def <T extends RpcService> Class<? extends T> generateDirectProxy(Class<T> iface) {
+        val supertype = iface.asCtClass
+        val targetCls = createClass(iface.directProxyName, supertype) [
+            field(DELEGATE_FIELD, iface);
+            implementMethodsFrom(supertype) [
+                body = '''return ($r) Â«DELEGATE_FIELD».«it.name»($$);'''
+            ]
+        ]
+        return targetCls.toClass(iface.classLoader)
+    }
+
+    def <T extends RpcService> Class<? extends T> generateRouter(Class<T> iface) {
+        val supertype = iface.asCtClass
+        val targetCls = createClass(iface.routerName, supertype) [
+            //field(ROUTING_TABLE_FIELD,Map)
+            field(DELEGATE_FIELD, iface)
+            val contexts = 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)
+                    contexts.put(routingPair.context.routingTableField, routingPair.context);
+            ]
+            for (ctx : contexts.entrySet) {
+                field(ctx.key, Map)
+            }
+            implementMethodsFrom(supertype) [
+                if (parameterTypes.size === 1) {
+                    val routingPair = routingContextInput;
+                    val bodyTmp = '''
+                    {
+                        final Â«InstanceIdentifier.name» identifier = $1.«routingPair.getter.name»();
+                        Â«supertype.name» instance = («supertype.name») Â«routingPair.context.routingTableField».get(identifier);
+                        if(instance == null) {
+                           instance = Â«DELEGATE_FIELD»;
+                        }
+                        return ($r) instance.«it.name»($$);
+                    }'''
+                    body = bodyTmp
+                } else if (parameterTypes.size === 0) {
+                    body = '''return ($r) Â«DELEGATE_FIELD».«it.name»($$);'''
+                }
+            ]
+        ]
+        return targetCls.toClass(iface.classLoader)
+    }
+
+    def Class<?> generateListenerInvoker(Class<? extends NotificationListener> iface) {
+        val targetCls = createClass(iface.invokerName) [
+            field(DELEGATE_FIELD, iface)
+            it.method(Void, "invoke", Notification) [
+                val callbacks = iface.methods.filter[notificationCallback]
+                body = '''
+                    {
+                        Â«FOR callback : callbacks SEPARATOR " else "»
+                            if($1 instanceof Â«val cls = callback.parameterTypes.get(0).name») {
+                                Â«DELEGATE_FIELD».«callback.name»((«cls») $1);
+                                return;
+                            }
+                        Â«ENDFOR»
+                    }
+                '''
+            ]
+        ]
+        return targetCls.toClass(iface.classLoader);
+    }
+
+    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.parameterTypes.size === 0 && method.name.startsWith("get")) {
+                for (annotation : method.availableAnnotations) {
+                    if (annotation instanceof RoutingContext) {
+                        return new RoutingPair((annotation as RoutingContext).value, method)
+                    }
+                }
+            }
+        }
+        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) {
+                val redeclaredMethod = new CtMethod(method, target, null);
+                function1.process(redeclaredMethod);
+                target.addMethod(redeclaredMethod);
+            }
+        }
+    }
+
+    private def CtClass createClass(String fqn, ClassGenerator cls) {
+        val target = classPool.makeClass(fqn);
+        cls.process(target);
+        return target;
+    }
+
+    private def CtClass createClass(String fqn, CtClass superInterface, ClassGenerator cls) {
+        val target = classPool.makeClass(fqn);
+        target.implementsType(superInterface);
+        cls.process(target);
+        return target;
+    }
+
+    private def void implementsType(CtClass it, CtClass supertype) {
+        checkArgument(supertype.interface, "Supertype must be interface");
+        addInterface(supertype);
+    }
+
+    private def asCtClass(Class<?> class1) {
+        classPool.get(class1);
+    }
+
+    private def CtField field(CtClass it, String name, Class<?> returnValue) {
+        val field = new CtField(returnValue.asCtClass, name, it);
+        field.modifiers = Modifier.PUBLIC
+        addField(field);
+        return field;
+    }
+
+    def get(ClassPool pool, Class<?> cls) {
+        try {
+            return pool.get(cls.name)
+        } catch (NotFoundException e) {
+            pool.appendClassPath(new LoaderClassPath(cls.classLoader));
+            return pool.get(cls.name)
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend
new file mode 100644 (file)
index 0000000..298a74e
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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.impl
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider
+import org.opendaylight.yangtools.yang.binding.RpcService
+import javassist.ClassPool
+import org.osgi.framework.BundleContext
+import java.util.Map
+import java.util.HashMap
+import javassist.LoaderClassPath
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker
+import java.util.Hashtable
+import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*
+
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService
+import org.osgi.framework.ServiceRegistration
+import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.*
+import static extension org.opendaylight.controller.sal.binding.impl.osgi.PropertiesUtils.*
+import org.opendaylight.controller.sal.binding.api.NotificationService
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
+
+import org.slf4j.LoggerFactory
+import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator
+
+class BindingAwareBrokerImpl implements BindingAwareBroker {
+    private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl)
+    
+    private val clsPool = ClassPool.getDefault()
+    private var RuntimeCodeGenerator generator;
+    private Map<Class<? extends RpcService>, RpcProxyContext> managedProxies = new HashMap();
+    private var NotificationBrokerImpl notifyBroker
+    private var ServiceRegistration<NotificationProviderService> notifyBrokerRegistration
+    
+    @Property
+    var BundleContext brokerBundleContext
+
+    def start() {
+        initGenerator();
+
+        // Initialization of notificationBroker
+        notifyBroker = new NotificationBrokerImpl(null);
+        val brokerProperties = newProperties();
+        notifyBrokerRegistration = brokerBundleContext.registerService(NotificationProviderService, notifyBroker,
+            brokerProperties)
+        brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties)
+    }
+
+    def initGenerator() {
+
+        // YANG Binding Class Loader
+        clsPool.appendClassPath(new LoaderClassPath(RpcService.classLoader));
+        generator = new RuntimeCodeGenerator(clsPool);
+    }
+
+    override registerConsumer(BindingAwareConsumer consumer, BundleContext bundleCtx) {
+        val ctx = consumer.createContext(bundleCtx)
+        consumer.onSessionInitialized(ctx)
+        return ctx
+    }
+
+    override registerProvider(BindingAwareProvider provider, BundleContext bundleCtx) {
+        val ctx = provider.createContext(bundleCtx)
+        provider.onSessionInitialized(ctx)
+        provider.onSessionInitiated(ctx as ProviderContext)
+        return ctx
+    }
+
+    private def createContext(BindingAwareConsumer consumer, BundleContext consumerCtx) {
+        new OsgiConsumerContext(consumerCtx, this)
+    }
+
+    private def createContext(BindingAwareProvider provider, BundleContext providerCtx) {
+        new OsgiProviderContext(providerCtx, this)
+    }
+
+    /**
+     * Returns a Managed Direct Proxy for supplied class
+     * 
+     * Managed direct proxy is a generated proxy class conforming to the supplied interface
+     * which delegates all calls to the backing delegate.
+     * 
+     * Proxy does not do any validation, null pointer checks or modifies data in any way, it
+     * is only use to avoid exposing direct references to backing implementation of service.
+     * 
+     * If proxy class does not exist for supplied service class it will be generated automatically.
+     */
+    def <T extends RpcService> getManagedDirectProxy(Class<T> service) {
+        
+        var RpcProxyContext existing = null
+        if ((existing = managedProxies.get(service)) != null) {
+            return existing.proxy
+        }
+        val proxyClass = generator.generateDirectProxy(service)
+        val rpcProxyCtx = new RpcProxyContext(proxyClass)
+        val properties = new Hashtable<String, String>()
+        rpcProxyCtx.proxy = proxyClass.newInstance as RpcService
+
+        properties.salServiceType = SAL_SERVICE_TYPE_CONSUMER_PROXY
+        rpcProxyCtx.registration = brokerBundleContext.registerService(service, rpcProxyCtx.proxy as T, properties)
+        managedProxies.put(service, rpcProxyCtx)
+        return rpcProxyCtx.proxy
+    }
+    /**
+     * Registers RPC Implementation
+     * 
+     */
+    def <T extends RpcService> registerRpcImplementation(Class<T> type, T service, OsgiProviderContext context,
+        Hashtable<String, String> properties) {
+        val proxy = getManagedDirectProxy(type)
+        if(proxy.delegate != null) {
+            throw new IllegalStateException("Service " + type + "is already registered");
+        }
+        val osgiReg = context.bundleContext.registerService(type, service, properties);
+        proxy.delegate = service;
+        return new RpcServiceRegistrationImpl<T>(type, service, osgiReg);
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BrokerActivator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BrokerActivator.java
new file mode 100644 (file)
index 0000000..c5d54ec
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.impl;
+
+import java.util.Hashtable;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BrokerActivator implements BundleActivator {
+
+       private static final Logger log = LoggerFactory.getLogger(BrokerActivator.class);
+       private BindingAwareBrokerImpl baSal;
+       private ServiceRegistration<BindingAwareBroker> baSalRegistration;
+       
+       
+       @Override
+       public void start(BundleContext context) throws Exception {
+               log.info("Binding Aware Broker initialized");
+               baSal = new BindingAwareBrokerImpl();
+               baSal.setBrokerBundleContext(context);
+               baSal.start();
+               
+               BindingAwareBroker baSalService = baSal;
+               Hashtable<String, String> properties = new Hashtable<>();
+               this.baSalRegistration = context.registerService(BindingAwareBroker.class,baSalService, properties);
+               
+       }
+
+       @Override
+       public void stop(BundleContext context) throws Exception {
+               log.info("Binding Aware Broker stopped");
+               baSalRegistration.unregister();
+       }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend
new file mode 100644 (file)
index 0000000..398a219
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.impl
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
+
+class DataProviderContext {
+
+    @Property
+    var DataStoreIdentifier identifier;
+    @Property
+    var RuntimeDataProvider provider;
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend
new file mode 100644 (file)
index 0000000..22db735
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.impl
+
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService
+import org.opendaylight.yangtools.yang.binding.Notification
+import com.google.common.collect.Multimap
+import org.opendaylight.controller.sal.binding.api.NotificationListener
+import com.google.common.collect.HashMultimap
+import java.util.concurrent.ExecutorService
+import java.util.Collection
+
+class NotificationBrokerImpl implements NotificationProviderService {
+
+    val Multimap<Class<? extends Notification>, NotificationListener<?>> listeners;
+    val ExecutorService executor;
+
+    new(ExecutorService executor) {
+        listeners = HashMultimap.create()
+        this.executor = executor;
+    }
+
+    override <T extends Notification> addNotificationListener(Class<T> notificationType,
+        NotificationListener<T> listener) {
+        listeners.put(notificationType, listener)
+    }
+
+    override <T extends Notification> removeNotificationListener(Class<T> notificationType,
+        NotificationListener<T> listener) {
+        listeners.remove(notificationType, listener)
+    }
+
+    override notify(Notification notification) {
+        notification.notificationTypes.forEach [
+            listeners.get(it as Class<? extends Notification>)?.notifyAll(notification)
+        ]
+    }
+
+    def getNotificationTypes(Notification notification) {
+        notification.class.interfaces.filter[it != Notification && Notification.isAssignableFrom(it)]
+    }
+
+    @SuppressWarnings("unchecked")
+    def notifyAll(Collection<NotificationListener<?>> listeners, Notification notification) {
+        listeners.forEach[(it as NotificationListener).onNotification(notification)]
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationServiceImpl.xtend
new file mode 100644 (file)
index 0000000..fb35ee3
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.impl
+
+import org.opendaylight.controller.sal.binding.api.NotificationService
+import org.opendaylight.controller.sal.binding.api.NotificationListener
+import org.opendaylight.yangtools.yang.binding.Notification
+import com.google.common.collect.Multimap
+import com.google.common.collect.HashMultimap
+
+class NotificationServiceImpl implements NotificationService {
+    val Multimap<Class<? extends Notification>, NotificationListener<?>> listeners;
+
+    new() {
+        listeners = HashMultimap.create()
+    }
+
+    override <T extends Notification> addNotificationListener(Class<T> notificationType,
+        NotificationListener<T> listener) {
+        listeners.put(notificationType, listener)
+    }
+
+    override <T extends Notification> removeNotificationListener(Class<T> notificationType,
+        NotificationListener<T> listener) {
+        listeners.remove(notificationType, listener)
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend
new file mode 100644 (file)
index 0000000..a903124
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.impl;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareService;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.LoggerFactory
+import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.*
+
+class OsgiConsumerContext implements ConsumerContext {
+
+    static val log = LoggerFactory.getLogger(OsgiConsumerContext)
+    protected val BundleContext bundleContext;
+    protected val BindingAwareBrokerImpl broker;
+
+    new(BundleContext ctx, BindingAwareBrokerImpl broker) {
+        this.bundleContext = ctx;
+        this.broker = broker;
+    }
+
+    override def <T extends BindingAwareService> getSALService(Class<T> service) {
+
+        // SAL Services are global
+        var ref = bundleContext.getServiceReference(service);
+        return bundleContext.getService(ref) as T;
+    }
+
+    override def <T extends RpcService> T getRpcService(Class<T> module) {
+        try {
+
+            val services = bundleContext.getServiceReferences(module, getProxyFilter());
+
+            // Proxy service found / using first implementation
+            // FIXME: Add advanced logic to retrieve service with right set of models
+            if (false == services.empty) {
+                val ref = services.iterator().next() as ServiceReference<T>;
+                return bundleContext.getService(ref) as T;
+            }
+        } catch (InvalidSyntaxException e) {
+            log.error("Created filter was invalid:", e.message, e)
+        }
+        return null;
+
+    }
+
+    private def getProxyFilter() {
+        return '''(«SAL_SERVICE_TYPE»=«SAL_SERVICE_TYPE_CONSUMER_PROXY»)'''
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend
new file mode 100644 (file)
index 0000000..c769ca1
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.impl;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcServiceRegistration;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.framework.BundleContext;
+
+import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.*;
+import static extension org.opendaylight.controller.sal.binding.impl.osgi.PropertiesUtils.*;
+
+class OsgiProviderContext extends OsgiConsumerContext implements ProviderContext {
+
+    @Property
+    val Map<Class<? extends RpcService>, RpcServiceRegistrationImpl<? extends RpcService>> registeredServices
+
+    new(BundleContext ctx, BindingAwareBrokerImpl broker) {
+        super(ctx, broker);
+        _registeredServices = new HashMap();
+    }
+
+    override def <T extends RpcService> RpcServiceRegistration<T> addRpcImplementation(Class<T> type, T implementation) {
+
+        // TODO Auto-generated method stub
+        val properties = new Hashtable<String, String>();
+        properties.salServiceType = SAL_SERVICE_TYPE_PROVIDER
+
+        // Fill requirements
+        val salReg = broker.registerRpcImplementation(type, implementation, this, properties)
+        registeredServices.put(type, salReg)
+        return salReg;
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.xtend
new file mode 100644 (file)
index 0000000..0749459
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.impl
+
+import org.opendaylight.yangtools.yang.binding.RpcService
+import org.osgi.framework.ServiceRegistration
+
+class RpcProxyContext {
+       
+       new(Class<? extends RpcService> proxyClass) {
+               this.proxyClass = proxyClass
+       }
+       
+       protected val Class<? extends RpcService> proxyClass;
+       
+       @Property
+       protected var RpcService proxy;
+       
+       @Property
+       protected var ServiceRegistration<? extends RpcService> registration;
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcServiceRegistrationImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcServiceRegistrationImpl.xtend
new file mode 100644 (file)
index 0000000..afb27b4
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.impl
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcServiceRegistration
+import org.osgi.framework.ServiceRegistration
+import org.opendaylight.yangtools.yang.binding.RpcService
+
+class RpcServiceRegistrationImpl<T extends RpcService> implements RpcServiceRegistration<T> {
+
+    val ServiceRegistration<T> osgiRegistration;
+    private val T service;
+    val Class<T> cls;
+
+    public new(Class<T> type, T service, ServiceRegistration<T> osgiReg) {
+        this.cls = type;
+        this.osgiRegistration = osgiReg;
+        this.service = service;
+    }
+
+    override getService() {
+        this.service
+    }
+
+    override unregister() {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend
new file mode 100644 (file)
index 0000000..b278df5
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.impl
+
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
+import org.opendaylight.controller.sal.common.DataStoreIdentifier
+import org.opendaylight.yangtools.yang.binding.DataRoot
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.controller.sal.binding.api.data.DataCommitHandler
+import org.opendaylight.controller.sal.binding.api.data.DataRefresher
+import org.opendaylight.controller.sal.binding.api.data.DataValidator
+import org.opendaylight.yangtools.yang.common.RpcResult
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
+import java.util.Map
+
+class _DataBrokerImpl implements DataProviderService {
+
+    Map<DataStoreIdentifier, DataProviderContext> dataProviders;
+    var DataProviderContext defaultDataProvider;
+
+    override <T extends DataRoot> getData(DataStoreIdentifier store, Class<T> rootType) {
+        val dataStore = resolveProvider(store, rootType);
+        return dataStore.provider.getData(store, rootType);
+    }
+
+    override <T extends DataRoot> getData(DataStoreIdentifier store, T filter) {
+    }
+
+    override <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, Class<T> rootType) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub");
+    }
+
+    override <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, T filter) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub");
+    }
+
+    override commit(DataStoreIdentifier store) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override editCandidateData(DataStoreIdentifier store, DataRoot changeSet) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override addCommitHandler(DataStoreIdentifier store, DataCommitHandler provider) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override addValidator(DataStoreIdentifier store, DataValidator validator) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override removeCommitHandler(DataStoreIdentifier store, DataCommitHandler provider) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    override removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    def DataProviderContext resolveProvider(DataStoreIdentifier store, Class<? extends DataRoot> root) {
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend
new file mode 100644 (file)
index 0000000..9fb2140
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.impl.osgi
+
+class Constants {
+
+    private new() {
+    }
+
+    public static val SAL_SERVICE_TYPE = "salServiceType"
+    public static val SAL_SERVICE_TYPE_CONSUMER_PROXY = "consumerProxy"
+    public static val SAL_SERVICE_TYPE_PROVIDER = "provider"
+    public static val SAL_SERVICE_TYPE_CONNECTOR = "connector"
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend
new file mode 100644 (file)
index 0000000..d04ca7f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.impl.osgi
+
+import java.util.Hashtable
+import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.*
+
+class PropertiesUtils {
+
+    private new() {
+    }
+
+    static def setSalServiceType(Hashtable<String, String> properties, String value) {
+        properties.put(SAL_SERVICE_TYPE, value)
+        return properties
+    }
+
+    static def getSalServiceType(Hashtable<String, String> properties) {
+        return properties.get(SAL_SERVICE_TYPE)
+    }
+
+    static def newProperties() {
+        new Hashtable<String, String>()
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java
new file mode 100644 (file)
index 0000000..d788ccf
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.impl.osgi;
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/package-info.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/package-info.java
new file mode 100644 (file)
index 0000000..e5f26b9
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+  * 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.impl;
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java b/opendaylight/md-sal/sal-binding-broker/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java
new file mode 100644 (file)
index 0000000..9bbb501
--- /dev/null
@@ -0,0 +1,31 @@
+package org.opendaylight.controller.sal.binding.test;
+import static org.junit.Assert.*;
+
+import java.util.concurrent.Future;
+
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.impl.ProxyFactoryGenerator;
+import org.opendaylight.controller.sal.binding.impl.RpcServiceProxy;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+
+public class GenerationTest {
+
+       public interface MockService extends RpcService {
+               
+           Future<RpcResult<java.lang.Void>> cancelToast();
+           
+           Future<RpcResult<java.lang.Void>> makeToast(String input);
+       }
+       
+       @Test
+       public void test() {
+               ProxyFactoryGenerator generator = new ProxyFactoryGenerator();
+               Class<? extends RpcServiceProxy<MockService>> ret = generator.generate(MockService.class);
+               
+               assertTrue(RpcServiceProxy.class.isAssignableFrom(ret));
+               assertTrue(MockService.class.isAssignableFrom(ret));
+       }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java
new file mode 100644 (file)
index 0000000..5dddd1a
--- /dev/null
@@ -0,0 +1,142 @@
+package org.opendaylight.controller.sal.binding.test;
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import javassist.ClassPool;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*;
+import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator;
+import org.opendaylight.controller.sal.binding.test.mock.FooService;
+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;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+import static org.mockito.Mockito.*;
+
+
+public class RuntimeCodeGeneratorTest {
+
+    private RuntimeCodeGenerator codeGenerator;
+
+    
+    @Before
+    public void initialize() {
+        this.codeGenerator = new RuntimeCodeGenerator(ClassPool.getDefault());
+    }
+    
+    @Test
+    public void testGenerateDirectProxy() {
+        Class<? extends FooService> product = codeGenerator.generateDirectProxy(FooService.class);
+        assertNotNull(product);
+    }
+
+    @Test
+    public void testGenerateRouter() throws Exception {
+        Class<? extends FooService> product = codeGenerator.generateRouter(FooService.class);
+        assertNotNull(product);
+        assertNotNull(product.getSimpleName());
+        assertEquals("2 fields should be generated.",2,product.getFields().length);
+        
+        verifyRouting(product.newInstance());
+    }
+
+    private void verifyRouting(FooService product) {
+        Map<InstanceIdentifier,FooService> routingTable = new HashMap<>();
+        setRoutingTable(product, BaseIdentity.class, routingTable);
+        
+        assertSame("Returned routing table should be same instance",routingTable,getRoutingTable(product, BaseIdentity.class));
+        
+        int servicesCount = 2;
+        int instancesPerService = 3;
+        
+        InstanceIdentifier[][] identifiers = identifiers(servicesCount,instancesPerService);
+        FooService service[] = new FooService[] {
+                mock(FooService.class, "Instance 0"),
+                mock(FooService.class,"Instance 1")
+        };
+        
+        for(int i = 0;i<service.length;i++) {
+            for (InstanceIdentifier instance : identifiers[i]) {
+                routingTable.put(instance, service[i]);
+            }
+        }
+        
+        assertEquals("All instances should be registered.", servicesCount*instancesPerService, routingTable.size());
+        
+        SimpleInput[] instance_0_input = new SimpleInputImpl[] {
+            new SimpleInputImpl(identifiers[0][0]),
+            new SimpleInputImpl(identifiers[0][1]),
+            new SimpleInputImpl(identifiers[0][2])
+        };
+        
+        SimpleInput[] instance_1_input = new SimpleInputImpl[] {
+                new SimpleInputImpl(identifiers[1][0]),
+                new SimpleInputImpl(identifiers[1][1]),
+                new SimpleInputImpl(identifiers[1][2])
+        };
+        
+        // We test sending mock messages
+        
+        product.simple(instance_0_input[0]);
+        verify(service[0]).simple(instance_0_input[0]);
+        
+        product.simple(instance_0_input[1]);
+        product.simple(instance_0_input[2]);
+        
+        verify(service[0]).simple(instance_0_input[1]);
+        verify(service[0]).simple(instance_0_input[2]);
+        
+        product.simple(instance_1_input[0]);
+        verify(service[1]).simple(instance_1_input[0]);
+    }
+
+    private InstanceIdentifier[][] identifiers(int serviceSize, int instancesPerService) {
+        InstanceIdentifier[][] ret = new InstanceIdentifier[serviceSize][];
+        int service = 0;
+        for (int i = 0;i<serviceSize;i++) {
+            
+            InstanceIdentifier[] instanceIdentifiers = new InstanceIdentifier[instancesPerService];
+            ret[i] = instanceIdentifiers;
+            for(int id = 0;id<instancesPerService;id++) {
+                instanceIdentifiers[id] = referencableIdentifier(service*instancesPerService+id);
+            }
+            service++;
+        }
+        
+        return ret;
+    }
+
+    private InstanceIdentifier referencableIdentifier(int i) {
+        ReferencableObjectKey key = new ReferencableObjectKey(i);
+        IdentifiableItem<ReferencableObject,ReferencableObjectKey> pathArg = new IdentifiableItem<>(ReferencableObject.class,key);
+        return new InstanceIdentifier(Arrays.<PathArgument>asList(pathArg), ReferencableObject.class);
+    }
+
+    private static class SimpleInputImpl implements SimpleInput {
+        private final InstanceIdentifier identifier;
+
+        public SimpleInputImpl(InstanceIdentifier _identifier) {
+            this.identifier = _identifier;
+        }
+
+        @Override
+        public <E extends Augmentation<SimpleInput>> E getAugmentation(Class<E> augmentationType) {
+            return null;
+        }
+
+        @Override
+        public InstanceIdentifier getIdentifier() {
+            return this.identifier;
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java
new file mode 100644 (file)
index 0000000..b64ebdf
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+public interface BarUpdate extends Grouping,Notification {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java
new file mode 100644 (file)
index 0000000..3629689
--- /dev/null
@@ -0,0 +1,10 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+
+public interface FooListener extends NotificationListener {
+
+    void onFooUpdate(FooUpdate notification);
+    void onBarUpdate(BarUpdate notification);
+    
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java
new file mode 100644 (file)
index 0000000..3161e93
--- /dev/null
@@ -0,0 +1,16 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public interface FooService extends RpcService {
+    
+    Future<RpcResult<Void>> foo();
+    
+    Future<RpcResult<Void>> simple(SimpleInput obj);
+    
+    Future<RpcResult<Void>> inheritedContextInput(InheritedContextInput obj);
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java
new file mode 100644 (file)
index 0000000..a5a5eb8
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+public interface FooUpdate extends Notification {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java
new file mode 100644 (file)
index 0000000..86624e0
--- /dev/null
@@ -0,0 +1,11 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
+
+public interface Grouping {
+
+    @RoutingContext(BaseIdentity.class)
+    InstanceIdentifier getInheritedIdentifier();
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java
new file mode 100644 (file)
index 0000000..39b20cc
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+public interface InheritedContextInput extends Grouping {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java
new file mode 100644 (file)
index 0000000..8e0d457
--- /dev/null
@@ -0,0 +1,8 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+
+public interface ReferencableObject extends DataObject,Identifiable<ReferencableObjectKey> {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java
new file mode 100644 (file)
index 0000000..d2e1817
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+public class ReferencableObjectKey implements Identifier<ReferencableObject> {
+
+    final Integer value;
+    
+    public ReferencableObjectKey(Integer _value) {
+        this.value = _value;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((value == null) ? 0 : value.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;
+        ReferencableObjectKey other = (ReferencableObjectKey) obj;
+        if (value == null) {
+            if (other.value != null)
+                return false;
+        } else if (!value.equals(other.value))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "ReferencableObjectKey [value=" + value + "]";
+    }
+    
+    
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java
new file mode 100644 (file)
index 0000000..dedbd98
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
+
+public interface SimpleInput extends DataObject,Augmentable<SimpleInput> {
+
+    @RoutingContext(BaseIdentity.class)
+    InstanceIdentifier getIdentifier();
+}
diff --git a/opendaylight/md-sal/sal-common-util/pom.xml b/opendaylight/md-sal/sal-common-util/pom.xml
new file mode 100644 (file)
index 0000000..a1f396e
--- /dev/null
@@ -0,0 +1,29 @@
+<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-util</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>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <packaging>bundle</packaging>
+</project>
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Futures.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Futures.java
new file mode 100644 (file)
index 0000000..c942159
--- /dev/null
@@ -0,0 +1,51 @@
+package org.opendaylight.controller.sal.common.util;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class Futures {
+
+       private Futures(){}
+       
+       public static <T> Future<T> immediateFuture(T result) {
+               return new ImmediateFuture<T>(result);
+       }
+       
+       private static class ImmediateFuture<T> implements Future<T> {
+
+               private final T result;
+               
+               public ImmediateFuture(T result) {
+                       this.result = result;
+               }
+               
+               @Override
+               public boolean cancel(boolean mayInterruptIfRunning) {
+                       return false;
+               }
+
+               @Override
+               public boolean isCancelled() {
+                       return false;
+               }
+
+               @Override
+               public boolean isDone() {
+                       return true;
+               }
+
+               @Override
+               public T get() throws InterruptedException, ExecutionException {
+                       return result;
+               }
+
+               @Override
+               public T get(long timeout, TimeUnit unit) throws InterruptedException,
+                               ExecutionException, TimeoutException {
+                       return result;
+               }
+               
+       }
+}
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/RpcErrors.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/RpcErrors.java
new file mode 100644 (file)
index 0000000..86dcba9
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.common.util;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+
+/**
+ * @author mirehak
+ *
+ */
+public class RpcErrors {
+    
+    /**
+     * @param applicationTag
+     * @param tag
+     * @param info
+     * @param severity
+     * @param message
+     * @param errorType 
+     * @param cause 
+     * @return {@link RpcError} implementation
+     */
+    public static RpcError getRpcError(String applicationTag, String tag, String info,
+            ErrorSeverity severity, String message, ErrorType errorType, Throwable cause) {
+        RpcErrorTO ret = new RpcErrorTO(applicationTag, tag, info, severity, message, 
+                errorType, cause);
+        return ret;
+    }
+
+    private static class RpcErrorTO implements RpcError {
+
+        private final String applicationTag;
+        private final String tag;
+        private final String info;
+        private final ErrorSeverity severity;
+        private final String message;
+        private final ErrorType errorType;
+        private final Throwable cause;
+
+        /**
+         * @param applicationTag
+         * @param tag
+         * @param info
+         * @param severity
+         * @param message
+         * @param errorType
+         * @param cause
+         */
+        protected RpcErrorTO(String applicationTag, String tag, String info,
+                ErrorSeverity severity, String message, ErrorType errorType, Throwable cause) {
+            super();
+            this.applicationTag = applicationTag;
+            this.tag = tag;
+            this.info = info;
+            this.severity = severity;
+            this.message = message;
+            this.errorType = errorType;
+            this.cause = cause;
+        }
+
+        @Override
+        public String getApplicationTag() {
+            return applicationTag;
+        }
+
+        @Override
+        public String getInfo() {
+            return info;
+        }
+
+        @Override
+        public String getMessage() {
+            return message;
+        }
+
+        @Override
+        public ErrorSeverity getSeverity() {
+            return severity;
+        }
+
+        @Override
+        public String getTag() {
+            return tag;
+        }
+
+        @Override
+        public Throwable getCause() {
+            return cause;
+        }
+        
+        @Override
+        public ErrorType getErrorType() {
+            return errorType;
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java
new file mode 100644 (file)
index 0000000..e46b566
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.common.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class Rpcs {
+    public static <T> RpcResult<T> getRpcResult(boolean successful, T result,
+            Collection<RpcError> errors) {
+        RpcResult<T> ret = new RpcResultTO<T>(successful, result, errors);
+        return ret;
+    }
+
+    private static class RpcResultTO<T> implements RpcResult<T> {
+
+        private final Collection<RpcError> errors;
+        private final T result;
+        private final boolean successful;
+
+        public RpcResultTO(boolean successful, T result,
+                Collection<RpcError> errors) {
+            this.successful = successful;
+            this.result = result;
+            this.errors = Collections.unmodifiableList(new ArrayList<RpcError>(
+                    errors));
+        }
+
+        @Override
+        public boolean isSuccessful() {
+            return successful;
+        }
+
+        @Override
+        public T getResult() {
+            return result;
+        }
+
+        @Override
+        public Collection<RpcError> getErrors() {
+            return errors;
+        }
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-api/.gitignore b/opendaylight/md-sal/sal-dom-api/.gitignore
new file mode 100644 (file)
index 0000000..ea8c4bf
--- /dev/null
@@ -0,0 +1 @@
+/target
diff --git a/opendaylight/md-sal/sal-dom-api/pom.xml b/opendaylight/md-sal/sal-dom-api/pom.xml
new file mode 100644 (file)
index 0000000..b9aedbe
--- /dev/null
@@ -0,0 +1,37 @@
+<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-core-api</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>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>5.0.0</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java
new file mode 100644 (file)
index 0000000..5e13aad
--- /dev/null
@@ -0,0 +1,40 @@
+package org.opendaylight.controller.sal.core.api;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public abstract class AbstractConsumer implements Consumer, BundleActivator {
+
+    Broker broker;
+    ServiceReference<Broker> brokerRef;
+    @Override
+    public final void start(BundleContext context) throws Exception {
+        brokerRef = context.getServiceReference(Broker.class);
+        broker = context.getService(brokerRef);
+
+        this.startImpl(context);
+
+        broker.registerConsumer(this,context);
+    }
+
+    public abstract void startImpl(BundleContext context);
+
+    @Override
+    public final void stop(BundleContext context) throws Exception {
+        broker = null;
+        if(brokerRef != null) {
+            context.ungetService(brokerRef);
+        }
+    }
+
+    
+    @Override
+    public Collection<ConsumerFunctionality> getConsumerFunctionality() {
+        return Collections.emptySet();
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java
new file mode 100644 (file)
index 0000000..c25b2f9
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.sal.core.api;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public abstract class AbstractProvider implements BundleActivator, Provider {
+
+    private ServiceReference<Broker> brokerRef;
+    private Broker broker;
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public final void start(BundleContext context) throws Exception {
+        brokerRef = context.getServiceReference(Broker.class);
+        broker = context.getService(brokerRef);
+
+        this.startImpl(context);
+
+        broker.registerProvider(this,context);
+    }
+
+    public abstract void startImpl(BundleContext context);
+
+    @Override
+    public final void stop(BundleContext context) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Broker.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Broker.java
new file mode 100644 (file)
index 0000000..b2c3550
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * 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.core.api;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationProviderService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.BundleContext;
+
+
+/**
+ * Core component of the SAL layer responsible for wiring the SAL consumers.
+ * 
+ * The responsibility of the broker is to maintain registration of SAL
+ * functionality {@link Consumer}s and {@link Provider}s, store provider and
+ * consumer specific context and functionality registration via
+ * {@link ConsumerSession} and provide access to infrastructure services, which
+ * removes direct dependencies between providers and consumers.
+ * 
+ * 
+ * <h3>Infrastructure services</h3> Some examples of infrastructure services:
+ * 
+ * <ul>
+ * <li>RPC Invocation - see {@link ConsumerSession#rpc(QName, CompositeNode)},
+ * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)} and
+ * {@link RpcImplementation}
+ * <li>Notification Service - see {@link NotificationService} and
+ * {@link NotificationProviderService}
+ * <li>Functionality and Data model
+ * <li>Data Store access and modification - see {@link DataBrokerService} and
+ * {@link DataProviderService}
+ * </ul>
+ * 
+ * The services are exposed via session.
+ * 
+ * <h3>Session-based access</h3>
+ * 
+ * The providers and consumers needs to register in order to use the
+ * binding-independent SAL layer and to expose functionality via SAL layer.
+ * 
+ * For more information about session-based access see {@link ConsumerSession}
+ * and {@link ProviderSession}
+ * 
+ * 
+ * 
+ */
+public interface Broker {
+
+    /**
+     * Registers the {@link Consumer}, which will use the SAL layer.
+     * 
+     * <p>
+     * During the registration, the broker obtains the initial functionality
+     * from consumer, using the {@link Consumer#getConsumerFunctionality()}, and
+     * register that functionality into system and concrete infrastructure
+     * services.
+     * 
+     * <p>
+     * Note that consumer could register additional functionality at later point
+     * by using service and functionality specific APIs.
+     * 
+     * <p>
+     * The consumer is required to use returned session for all communication
+     * with broker or one of the broker services. The session is announced to
+     * the consumer by invoking
+     * {@link Consumer#onSessionInitiated(ConsumerSession)}.
+     * 
+     * @param cons
+     *            Consumer to be registered.
+     * @param context 
+     * @return a session specific to consumer registration
+     * @throws IllegalArgumentException
+     *             If the consumer is <code>null</code>.
+     * @throws IllegalStateException
+     *             If the consumer is already registered.
+     */
+    ConsumerSession registerConsumer(Consumer cons, BundleContext context);
+
+    /**
+     * Registers the {@link Provider}, which will use the SAL layer.
+     * 
+     * <p>
+     * During the registration, the broker obtains the initial functionality
+     * from consumer, using the {@link Provider#getProviderFunctionality()}, and
+     * register that functionality into system and concrete infrastructure
+     * services.
+     * 
+     * <p>
+     * Note that consumer could register additional functionality at later point
+     * by using service and functionality specific APIs (e.g.
+     * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)}
+     * 
+     * <p>
+     * The consumer is <b>required to use</b> returned session for all
+     * communication with broker or one of the broker services. The session is
+     * announced to the consumer by invoking
+     * {@link Provider#onSessionInitiated(ProviderSession)}.
+     * 
+     * 
+     * @param prov
+     *            Provider to be registered.
+     * @param context 
+     * @return a session unique to the provider registration.
+     * @throws IllegalArgumentException
+     *             If the provider is <code>null</code>.
+     * @throws IllegalStateException
+     *             If the consumer is already registered.
+     */
+    ProviderSession registerProvider(Provider prov, BundleContext context);
+
+    /**
+     * {@link Consumer} specific access to the SAL functionality.
+     * 
+     * <p>
+     * ConsumerSession is {@link Consumer}-specific access to the SAL
+     * functionality and infrastructure services.
+     * 
+     * <p>
+     * The session serves to store SAL context (e.g. registration of
+     * functionality) for the consumer and provides access to the SAL
+     * infrastructure services and other functionality provided by
+     * {@link Provider}s.
+     * 
+
+     * 
+     */
+    public interface ConsumerSession {
+
+        /**
+         * Sends an RPC to other components registered to the broker.
+         * 
+         * @see RpcImplementation
+         * @param rpc
+         *            Name of RPC
+         * @param input
+         *            Input data to the RPC
+         * @return Result of the RPC call
+         */
+        Future<RpcResult<CompositeNode>> rpc(QName rpc, CompositeNode input);
+
+        boolean isClosed();
+
+        /**
+         * Returns a session specific instance (implementation) of requested
+         * service
+         * 
+         * @param service
+         *            Broker service
+         * @return Session specific implementation of service
+         */
+        <T extends BrokerService> T getService(Class<T> service);
+
+        /**
+         * Closes a session between consumer and broker.
+         * 
+         * <p>
+         * The close operation unregisters a consumer and remove all registered
+         * functionality of the consumer from the system.
+         * 
+         */
+        void close();
+    }
+
+    /**
+     * {@link Provider} specific access to the SAL functionality.
+     * 
+     * <p>
+     * ProviderSession is {@link Provider}-specific access to the SAL
+     * functionality and infrastructure services, which also allows for exposing
+     * the provider's functionality to the other {@link Consumer}s.
+     * 
+     * <p>
+     * The session serves to store SAL context (e.g. registration of
+     * functionality) for the providers and exposes access to the SAL
+     * infrastructure services, dynamic functionality registration and any other
+     * functionality provided by other {@link Provider}s.
+     * 
+     */
+    public interface ProviderSession extends ConsumerSession {
+        /**
+         * Registers an implementation of the rpc.
+         * 
+         * <p>
+         * The registered rpc functionality will be available to all other
+         * consumers and providers registered to the broker, which are aware of
+         * the {@link QName} assigned to the rpc.
+         * 
+         * <p>
+         * There is no assumption that rpc type is in the set returned by
+         * invoking {@link RpcImplementation#getSupportedRpcs()}. This allows
+         * for dynamic rpc implementations.
+         * 
+         * @param rpcType
+         *            Name of Rpc
+         * @param implementation
+         *            Provider's Implementation of the RPC functionality
+         * @throws IllegalArgumentException
+         *             If the name of RPC is invalid
+         */
+        void addRpcImplementation(QName rpcType,
+                RpcImplementation implementation)
+                throws IllegalArgumentException;
+
+        /**
+         * Unregisters an Rpc implementation
+         * 
+         * @param rpcType
+         *            Name of Rpc
+         * @param implementation
+         *            Registered Implementation of the Rpc functionality
+         * @throws IllegalArgumentException
+         */
+        void removeRpcImplementation(QName rpcType,
+                RpcImplementation implementation)
+                throws IllegalArgumentException;
+
+        /**
+         * Closes a session between provider and SAL.
+         * 
+         * <p>
+         * The close operation unregisters a provider and remove all registered
+         * functionality of the provider from the system.
+         */
+        @Override
+        public void close();
+
+        @Override
+        boolean isClosed();
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/BrokerService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/BrokerService.java
new file mode 100644 (file)
index 0000000..b425368
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.core.api;
+
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+
+/**
+ * 
+ * Session-specific instance of the broker functionality.
+ * 
+ * <p>
+ * BrokerService is marker interface for infrastructure services provided by the
+ * SAL. These services are session-specific, each {@link Provider} and
+ * {@link Consumer} usually has own instance of the service with it's own
+ * context.
+ * 
+ * <p>
+ * The consumer's (or provider's) instance of specific service could be obtained
+ * by invoking {@link ConsumerSession#getService(Class)} method on session
+ * assigned to the consumer.
+ * 
+ * <p>
+ * {@link BrokerService} and {@link Provider} may seem similar, but provider
+ * provides YANG model-based functionality and {@link BrokerService} exposes the
+ * necessary supporting functionality to implement specific functionality of
+ * YANG and to reuse it in the development of {@link Consumer}s and
+ * {@link Provider}s.
+ * 
+ * 
+ */
+public interface BrokerService {
+
+    void closeSession();
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Consumer.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Consumer.java
new file mode 100644 (file)
index 0000000..0006953
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.core.api;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+
+/**
+ * 
+ * Defines the component of controller and supplies additional metadata. A
+ * component of the controller or application supplies a concrete implementation
+ * of this interface.
+ * 
+ * A user-implemented component (application) which faciliates the SAL and SAL
+ * services to access infrastructure services or providers' functionality.
+ * 
+ * 
+ */
+public interface Consumer {
+
+    /**
+     * Callback signaling initialization of the consumer session to the SAL.
+     * 
+     * The consumer MUST use the session for all communication with SAL or
+     * retrieving SAL infrastructure services.
+     * 
+     * This method is invoked by {@link Broker#registerConsumer(Consumer)}
+     * 
+     * @param session
+     *            Unique session between consumer and SAL.
+     */
+    public void onSessionInitiated(ConsumerSession session);
+
+    /**
+     * Get a set of implementations of consumer functionality to be registered
+     * into system during the consumer registration to the SAL.
+     * 
+     * This method is invoked by {@link Broker#registerConsumer(Consumer)}.
+     * 
+     * @return Set of consumer functionality.
+     */
+    public Collection<ConsumerFunctionality> getConsumerFunctionality();
+
+    /**
+     * The marker interface for the interfaces describing the consumer
+     * functionality contracts.
+     * 
+     * 
+     */
+    public interface ConsumerFunctionality {
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Provider.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Provider.java
new file mode 100644 (file)
index 0000000..e2df70b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.core.api;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+
+/**
+ * 
+ * Defines the component of controller and supplies additional metadata. A
+ * component of the controller or application supplies a concrete implementation
+ * of this interface.
+ * 
+ * <p>
+ * A user-implemented component (application) which faciliates the SAL and SAL
+ * services to access infrastructure services and to provide functionality to
+ * {@link Consumer}s and other providers.
+ * 
+ * 
+ */
+public interface Provider {
+
+    /**
+     * Callback signaling initialization of the provider session to the SAL.
+     * 
+     * <p>
+     * The provider <b>MUST use the session</b> for all communication with SAL
+     * or retrieving SAL infrastructure services.
+     * 
+     * <p>
+     * This method is invoked by {@link Broker#registerConsumer(Consumer)}
+     * 
+     * @param session
+     *            Unique session between provider and SAL.
+     */
+    public void onSessionInitiated(ProviderSession session);
+
+    /**
+     * Gets a set of implementations of provider functionality to be registered
+     * into system during the provider registration to the SAL.
+     * 
+     * <p>
+     * This method is invoked by {@link Broker#registerProvider(Provider)} to
+     * learn the initial provided functionality
+     * 
+     * @return Set of provider's functionality.
+     */
+    public Collection<ProviderFunctionality> getProviderFunctionality();
+
+    /**
+     * Functionality provided by the {@link Provider}
+     * 
+     * <p>
+     * Marker interface used to mark the interfaces describing specific
+     * functionality which could be exposed by providers to other components.
+     * 
+
+     * 
+     */
+    public interface ProviderFunctionality {
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java
new file mode 100644 (file)
index 0000000..0299505
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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.core.api;
+
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+/**
+ * {@link Provider}'s implementation of rpc.
+ * 
+ * In order to expose the rpc to other components, the provider MUST register
+ * concrete implementation of this interface
+ * 
+ * The registration could be done by :
+ * <ul>
+ * <li>returning an instance of implementation in the return value of
+ * {@link Provider#getProviderFunctionality()}
+ * <li>passing an instance of implementation and {@link QName} of rpc as
+ * arguments to the
+ * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)}
+ * </ul>
+ * 
+ * The simplified process of the invocation of rpc is following:
+ * 
+ * <ol>
+ * <li> {@link Consumer} invokes
+ * {@link ConsumerSession#rpc(QName, CompositeNode)}
+ * <li> {@link Broker} finds registered {@link RpcImplementation}s
+ * <li> {@link Broker} invokes
+ * {@link RpcImplementation#invokeRpc(QName, CompositeNode)}
+ * <li> {@link RpcImplementation} processes the data and returns a
+ * {@link RpcResult}
+ * <li> {@link Broker} returns the {@link RpcResult} to {@link Consumer}
+ * </ol>
+ * 
+ * 
+ */
+public interface RpcImplementation extends Provider.ProviderFunctionality {
+
+    /**
+     * A set of rpc types supported by implementation.
+     * 
+     * The set of rpc {@link QName}s which are supported by this implementation.
+     * This set is used, when {@link Provider} is registered to the SAL, to
+     * register and expose the implementation of the returned rpcs.
+     * 
+     * @return Set of QNames identifying supported RPCs
+     */
+    Set<QName> getSupportedRpcs();
+
+    /**
+     * Invokes a implementation of specified rpc.
+     * 
+     * 
+     * @param rpc
+     *            Rpc to be invoked
+     * @param input
+     *            Input data for rpc.
+     * 
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>If rpc is null.
+     *             <li>If input is not <code>null</code> and
+     *             <code>false == rpc.equals(input.getNodeType)</code>
+     *             </ul>
+     * @return RpcResult containing the output of rpc if was executed
+     *         successfully, the list of errors otherwise.
+     */
+    RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input);
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataBrokerService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataBrokerService.java
new file mode 100644 (file)
index 0000000..fef894b
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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.core.api.data;
+
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Consumer;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+
+/**
+ * DataBrokerService provides unified access to the data stores available in the
+ * system.
+ * 
+ * 
+ * @see DataProviderService
+ * 
+ */
+public interface DataBrokerService extends BrokerService {
+
+    
+    Set<DataStoreIdentifier> getDataStores();
+    
+    /**
+     * Returns a data from specified Data Store.
+     * 
+     * Returns all the data visible to the consumer from specified Data Store.
+     * 
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @return data visible to the consumer
+     */
+    CompositeNode getData(DataStoreIdentifier store);
+
+    /**
+     * Returns a filtered subset of data from specified Data Store.
+     * 
+     * <p>
+     * The filter is modeled as an hierarchy of {@link Node} starting with
+     * {@link CompositeNode} representing data root. The semantics of the filter
+     * tree is the same as filter semantics defined in the NETCONF protocol for
+     * rpc operations <code>get</code> and <code>get-config</code> in Section 6
+     * of RFC6241.
+     * 
+     * 
+     * @see http://tools.ietf.org/html/rfc6241#section-6
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @param filter
+     *            Data tree filter similar to the NETCONF filter
+     * @return
+     */
+    CompositeNode getData(DataStoreIdentifier store, CompositeNode filter);
+
+    /**
+     * Returns a candidate data which are not yet commited.
+     * 
+     * 
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @return
+     */
+    CompositeNode getCandidateData(DataStoreIdentifier store);
+
+    /**
+     * Returns a filtered subset of candidate data from specified Data Store.
+     * 
+     * <p>
+     * The filter is modeled as an hierarchy of {@link Node} starting with
+     * {@link CompositeNode} representing data root. The semantics of the filter
+     * tree is the same as filter semantics defined in the NETCONF protocol for
+     * rpc operations <code>get</code> and <code>get-config</code> in Section 6
+     * of RFC6241.
+     * 
+     * 
+     * @see http://tools.ietf.org/html/rfc6241#section-6
+     * @param store
+     *            Identifier of the store, from which will be data retrieved
+     * @param filter
+     *            A CompositeNode filter
+     * @return
+     */
+    CompositeNode getCandidateData(DataStoreIdentifier store,
+            CompositeNode filter);
+
+    /**
+     * 
+     * @param store
+     *            Identifier of the store, in which will be the candidate data
+     *            modified
+     * @param changeSet
+     *            Modification of data tree.
+     * @return Result object containing the modified data tree if the operation
+     *         was successful, otherwise list of the encountered errors.
+     */
+    RpcResult<CompositeNode> editCandidateData(DataStoreIdentifier store,
+            MutableCompositeNode changeSet);
+
+    /**
+     * 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.
+     */
+    Future<RpcResult<Void>> commit(DataStoreIdentifier store);
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataCommitHandler.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataCommitHandler.java
new file mode 100644 (file)
index 0000000..fc1894a
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * 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.core.api.data;
+
+import java.util.Set;
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+
+/**
+ * Two phase commit handler (cohort) of the two-phase commit protocol of data.
+ * 
+ * <p>
+ * The provider should expose the implementation of DataCommitHandler if it's
+ * functionality depends on any subset of data stored in data repositories, in
+ * order to participate in {@link DataBrokerService#commit(DataStoreIdentifier)
+ * operation.
+ * 
+ * <p>
+ * Operations of two-phase commit handlers should not change data in data store,
+ * this is responsibility of the coordinator (broker or some component of the
+ * broker).
+ * 
+ * The commit handlers are responsible for changing the internal state of the
+ * provider to reflect the commited changes in data.
+ * 
+ * <h3>Two-phase commit</h3>
+ * 
+ * <h4>Commit Request Phase</h4>
+ * 
+ * <ol>
+ * <li> <code>Consumer</code> edits data by invocation of
+ * <code>DataBrokerService.editCandidateData(DataStoreIdentifier, CompositeNodeModification)</code>
+ * <li> <code>Consumer</code> starts a commit by invoking
+ * <code>DataBrokerService.commit(DataStoreIdentifier)</code>
+ * <li> <code>Broker</code> retrieves a list of all registered
+ * <code>DataCommitHandlers</code>
+ * <li>For each <code>DataCommitHandler</code>
+ * <ol>
+ * <li><code>Broker</code> invokes a
+ * <code>DataCommitHandler.requestCommit(DataStoreIdentifier)</code> operation.
+ * <li><code>DataCommitHandler</code> returns a <code>RpcResult</code> with
+ * <code>CommitTransaction</code>
+ * <li>If the result was successful, broker adds <code>CommitTransaction</code>
+ * to the list of opened transactions. If not, brokers stops a commit request
+ * phase and starts a rollback phase.
+ * </ol>
+ * <li><code>Broker</code> starts a commit finish phase
+ * </ol>
+ * 
+ * <h4>Commit Finish Phase</h4>
+ * 
+ * <ol>
+ * <li>For each <code>CommitTransaction</code> from Commit Request phase
+ * <ol>
+ * <li><code>Broker</code> broker invokes a
+ * <code>CommitTransaction.finish()</code>
+ * <li>The provider finishes a commit (applies the change) and returns an
+ * <code>RpcResult</code>.
+ * </ol>
+ * <li>
+ * <ul>
+ * <li>If all returned results means successful, the brokers end two-phase
+ * commit by returning a success commit result to the Consumer.
+ * <li>If error occured, the broker starts a commit rollback phase.
+ * </ul>
+ * </ol>
+ * 
+ * <h4>Commit Rollback Phase</h4>
+ * <li>For each <code>CommitTransaction</code> from Commit Request phase
+ * <ol>
+ * <li><code>Broker</code>
+ * 
+ * broker invokes a {@link CommitTransaction#finish()}
+ * <li>The provider rollbacks a commit and returns an {@link RpcResult} of
+ * rollback. </ol>
+ * <li>Broker returns a error result to the consumer.
+ * 
+ * 
+ * <h3>Registration of functionality</h3>
+ * The registration could be done by :
+ * <ul>
+ * <li>returning an instance of implementation in the return value of
+ * {@link Provider#getProviderFunctionality()}
+ * <li>passing an instance of implementation and {@link DataStoreIdentifier} of
+ * rpc as arguments to the
+ * {@link DataProviderService#addCommitHandler(DataStoreIdentifier, DataCommitHandler)}
+ * </ul>
+ * 
+ * 
+ */
+public interface DataCommitHandler extends Provider.ProviderFunctionality {
+
+    /**
+     * A set of Data Stores supported by implementation.
+     * 
+     * The set of {@link DataStoreIdentifier}s which identifies target data
+     * stores which are supported by this commit handler. This set is used, when
+     * {@link Provider} is registered to the SAL, to register and expose the
+     * commit handler functionality to affected data stores.
+     * 
+     * @return Set of Data Store identifiers
+     */
+    Set<DataStoreIdentifier> getSupportedDataStores();
+
+    /**
+     * The provider (commit handler) starts a commit transaction.
+     * 
+     * <p>
+     * The commit handler (provider) prepares an commit scenario, rollback
+     * scenario and validates data.
+     * 
+     * <p>
+     * If the provider is aware that at this point the commit would not be
+     * successful, the transaction is not created, but list of errors which
+     * prevented the start of transaction are returned.
+     * 
+     * @param store
+     * @return Transaction object representing this commit, errors otherwise.
+     */
+    RpcResult<CommitTransaction> requestCommit(DataStoreIdentifier store);
+
+    public interface CommitTransaction {
+        /**
+         * 
+         * @return Data store affected by the transaction
+         */
+        DataStoreIdentifier getDataStore();
+
+        /**
+         * Returns the handler associated with this transaction.
+         * 
+         * @return Handler
+         */
+        DataCommitHandler getHandler();
+
+        /**
+         * 
+         * Finishes a commit.
+         * 
+         * The provider (commit handler) should apply all changes to its state
+         * which are a result of data change-
+         * 
+         * @return
+         */
+        RpcResult<Void> finish() throws IllegalStateException;
+
+        /**
+         * Rollbacks a commit.
+         * 
+         * @return
+         * @throws IllegalStateException
+         *             If the method is invoked after {@link #finish()}
+         */
+        RpcResult<Void> rollback() throws IllegalStateException;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java
new file mode 100644 (file)
index 0000000..32035ea
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.core.api.data;
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.Provider;
+
+public interface DataProviderService extends DataBrokerService {
+
+    /**
+     * Adds {@link DataValidator} for specified Data Store
+     * 
+     * @param store
+     *            Data Store
+     * @param validator
+     *            Validator
+     */
+    public void addValidator(DataStoreIdentifier store, DataValidator validator);
+
+    /**
+     * Removes {@link DataValidator} from specified Data Store
+     * 
+     * @param store
+     * @param validator
+     *            Validator
+     */
+    public void removeValidator(DataStoreIdentifier store,
+            DataValidator validator);
+
+    /**
+     * Adds {@link DataCommitHandler} for specified data store
+     * 
+     * @param store
+     * @param provider
+     */
+    void addCommitHandler(DataStoreIdentifier store, DataCommitHandler provider);
+
+    /**
+     * Removes {@link DataCommitHandler} from specified data store
+     * 
+     * @param store
+     * @param provider
+     */
+    void removeCommitHandler(DataStoreIdentifier store,
+            DataCommitHandler provider);
+
+    /**
+     * Adds {@link DataRefresher} for specified data store
+     * 
+     * @param store
+     * @param refresher
+     */
+    void addRefresher(DataStoreIdentifier store, DataRefresher refresher);
+
+    /**
+     * Removes {@link DataRefresher} from specified data store
+     * 
+     * @param store
+     * @param refresher
+     */
+    void removeRefresher(DataStoreIdentifier store, DataRefresher refresher);
+
+    public interface DataRefresher extends Provider.ProviderFunctionality {
+
+        /**
+         * Fired when some component explicitly requested the data refresh.
+         * 
+         * The provider which exposed the {@link DataRefresher} should republish
+         * its provided data by editing the data in all affected data stores.
+         */
+        void refreshData();
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataValidator.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataValidator.java
new file mode 100644 (file)
index 0000000..2bcb84b
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.core.api.data;
+
+import java.util.Set;
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+
+/**
+ * {@link Provider}-supplied Validator of the data.
+ * 
+ * <p>
+ * The registration could be done by :
+ * <ul>
+ * <li>returning an instance of implementation in the return value of
+ * {@link Provider#getProviderFunctionality()}
+ * <li>passing an instance of implementation and {@link DataStoreIdentifier} rpc
+ * as arguments to the
+ * {@link DataProviderService#addValidator(DataStoreIdentifier, DataValidator)}
+ * </ul>
+ * 
+ **/
+public interface DataValidator extends Provider.ProviderFunctionality {
+
+    /**
+     * A set of Data Stores supported by implementation.
+     * 
+     * The set of {@link DataStoreIdentifier}s which identifies target data
+     * stores which are supported by this implementation. This set is used, when
+     * {@link Provider} is registered to the SAL, to register and expose the
+     * validation functionality to affected data stores.
+     * 
+     * @return Set of Data Store identifiers
+     */
+    Set<DataStoreIdentifier> getSupportedDataStores();
+
+    /**
+     * Performs validation on supplied data.
+     * 
+     * @param toValidate
+     *            Data to validate
+     * @return Validation result. The
+     *         <code>{@link RpcResult#isSuccessful()} == true</code> if the data
+     *         passed validation, otherwise contains list of errors.
+     */
+    RpcResult<Void> validate(CompositeNode toValidate);
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/package-info.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/package-info.java
new file mode 100644 (file)
index 0000000..1791196
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.core.api.data;
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
new file mode 100644 (file)
index 0000000..52f60b3
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.core.api.model;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface SchemaService extends BrokerService {
+
+    /**
+     * Registers a YANG module to session and global context 
+     * 
+     * @param module
+     */
+    void addModule(Module module);
+    
+    /**
+     * Unregisters a YANG module from session context
+     * 
+     * @param module
+     */
+    void removeModule(Module module);
+    
+    /**
+     * Returns session specific YANG schema context
+     * @return
+     */
+    SchemaContext getSessionContext();
+    
+    /**
+     * Returns global schema context
+     * 
+     * @return
+     */
+    SchemaContext getGlobalContext();
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationListener.java
new file mode 100644 (file)
index 0000000..5b0c992
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.core.api.notify;
+
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.Consumer;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+
+/**
+ * Notification listener for SAL notifications.
+ */
+public interface NotificationListener extends Consumer.ConsumerFunctionality {
+    /**
+     * A set of notification types supported by listeners.
+     * 
+     * The set of notification {@link QName}s which are supported by this
+     * listener. This set is used, when {@link Consumer} is registered to the
+     * SAL, to automatically register the listener.
+     * 
+     * @return Set of QNames identifying supported notifications.
+     */
+    Set<QName> getSupportedNotifications();
+
+    /**
+     * Fired when the notification occurs.
+     * 
+     * The type of the notification could be learned by
+     * <code>QName type = notification.getNodeType();</code>
+     * 
+     * @param notification
+     *            Notification content
+     */
+    void onNotification(CompositeNode notification);
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationProviderService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationProviderService.java
new file mode 100644 (file)
index 0000000..51871a7
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.core.api.notify;
+
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+
+/**
+ * Notification Publishing Service
+ * 
+ * The simplified process of the notification publishing is following:
+ * 
+ * <ol>
+ * <li> {@link Provider} invokes {@link #sendNotification(CompositeNode)}
+ * <li> {@link Broker} finds {@link NotificationListener}s which subscribed for
+ * the notification type.
+ * 
+ * <li>For each subscriber {@link Broker} invokes
+ * {@link NotificationListener#onNotification(CompositeNode)}
+ * </ol>
+ * 
+ * 
+ * 
+ */
+public interface NotificationProviderService extends NotificationService {
+
+    /**
+     * Publishes a notification.
+     * 
+     * Notification type is determined by the
+     * {@link CompositeNode#getNodeType()} of the
+     * <code>notification<code> parameter.
+     * 
+     * @param notification
+     *            Notification to publish
+     */
+    void sendNotification(CompositeNode notification);
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationService.java
new file mode 100644 (file)
index 0000000..3bf1054
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.core.api.notify;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.yang.common.QName;
+
+
+/**
+ * NotificationService provides access to the notification functionality of the
+ * SAL.
+ * 
+ * NotificationService allows for consumption of notifications by registering
+ * implementations of NotificationListener.
+ * 
+ * The registration of notification listeners could be done by:
+ * <ul>
+ * <li>returning an instance of implementation in the return value of
+ * {@link Provider#getProviderFunctionality()}
+ * <li>passing an instance of implementation and {@link QName} of rpc as an
+ * arguments to the
+ * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)}
+ * </ul>
+ * 
+ * 
+ */
+public interface NotificationService extends BrokerService {
+
+    /**
+     * Registers a notification listener for supplied notification type.
+     * 
+     * @param notification
+     * @param listener
+     */
+    void addNotificationListener(QName notification,
+            NotificationListener listener);
+
+    /**
+     * Removes a notification listener for supplied notification type.
+     * 
+     * @param notification
+     * @param listener
+     */
+    void removeNotificationListener(QName notification,
+            NotificationListener listener);
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/package-info.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/package-info.java
new file mode 100644 (file)
index 0000000..61426a3
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * 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
+ */
+/**
+ * SAL Notification functionality
+ */
+package org.opendaylight.controller.sal.core.api.notify;
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/package-info.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/package-info.java
new file mode 100644 (file)
index 0000000..395c09a
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * 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
+ */
+/**
+ * Core binding-independent SAL contracts and components
+ */
+package org.opendaylight.controller.sal.core.api;
diff --git a/opendaylight/md-sal/sal-dom-broker/pom.xml b/opendaylight/md-sal/sal-dom-broker/pom.xml
new file mode 100644 (file)
index 0000000..b3f3f3e
--- /dev/null
@@ -0,0 +1,57 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+    <modelVersion>4.0.0</modelVersion>\r
+    <parent>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>sal-parent</artifactId>\r
+        <version>1.0-SNAPSHOT</version>\r
+    </parent>\r
+    <artifactId>sal-broker-impl</artifactId>\r
+    <scm>\r
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
+    </scm>\r
+\r
+    <dependencies>\r
+        <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>sal-core-api</artifactId>\r
+            <version>1.0-SNAPSHOT</version>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>sal-common-util</artifactId>\r
+            <version>1.0-SNAPSHOT</version>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>sal-core-spi</artifactId>\r
+            <version>1.0-SNAPSHOT</version>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.slf4j</groupId>\r
+            <artifactId>slf4j-api</artifactId>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>com.google.guava</groupId>\r
+            <artifactId>guava</artifactId>\r
+        </dependency>\r
+    </dependencies>\r
+\r
+    <build>\r
+        <plugins>\r
+            <plugin>\r
+                <groupId>org.apache.felix</groupId>\r
+                <artifactId>maven-bundle-plugin</artifactId>\r
+                <extensions>true</extensions>\r
+                <configuration>\r
+                    <instructions>\r
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>\r
+                        <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>\r
+                    </instructions>\r
+                </configuration>\r
+            </plugin>\r
+        </plugins>\r
+    </build>\r
+</project>\r
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java
new file mode 100644 (file)
index 0000000..e3f5e4b
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.util.Hashtable;
+
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class BrokerActivator implements BundleActivator {
+
+    BrokerImpl broker;
+    private ServiceRegistration<Broker> brokerReg;
+    
+    @Override
+    public void start(BundleContext context) throws Exception {
+        broker = new BrokerImpl();
+        broker.setBundleContext(context);
+        brokerReg = context.registerService(Broker.class, broker, new Hashtable<String,String>());
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        if(brokerReg != null) {
+            brokerReg.unregister();
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java
new file mode 100644 (file)
index 0000000..24b2b4b
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * 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.dom.broker;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Consumer;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.spi.BrokerModule;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BrokerImpl implements Broker {
+    private static Logger log = LoggerFactory.getLogger(BrokerImpl.class);
+
+    // Broker Generic Context
+    private Set<ConsumerSessionImpl> sessions = Collections
+            .synchronizedSet(new HashSet<ConsumerSessionImpl>());
+    private Set<ProviderSessionImpl> providerSessions = Collections
+            .synchronizedSet(new HashSet<ProviderSessionImpl>());
+    private Set<BrokerModule> modules = Collections
+            .synchronizedSet(new HashSet<BrokerModule>());
+    private Map<Class<? extends BrokerService>, BrokerModule> serviceProviders = Collections
+            .synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerModule>());
+
+    // RPC Context
+    private Map<QName, RpcImplementation> rpcImpls = Collections
+            .synchronizedMap(new HashMap<QName, RpcImplementation>());
+
+    // Implementation specific
+    private ExecutorService executor;
+
+    private BundleContext bundleContext;
+
+    @Override
+    public ConsumerSession registerConsumer(Consumer consumer,BundleContext ctx) {
+        checkPredicates(consumer);
+        log.info("Registering consumer " + consumer);
+        ConsumerSessionImpl session = newSessionFor(consumer,ctx);
+        consumer.onSessionInitiated(session);
+        sessions.add(session);
+        return session;
+    }
+
+    @Override
+    public ProviderSession registerProvider(Provider provider,BundleContext ctx) {
+        checkPredicates(provider);
+
+        ProviderSessionImpl session = newSessionFor(provider,ctx);
+        provider.onSessionInitiated(session);
+        providerSessions.add(session);
+        return session;
+    }
+
+    public void addModule(BrokerModule module) {
+        log.info("Registering broker module " + module);
+        if (modules.contains(module)) {
+            log.error("Module already registered");
+            throw new IllegalArgumentException("Module already exists.");
+        }
+    
+        Set<Class<? extends BrokerService>> provServices = module
+                .getProvidedServices();
+        for (Class<? extends BrokerService> serviceType : provServices) {
+            log.info("  Registering session service implementation: "
+                    + serviceType.getCanonicalName());
+            serviceProviders.put(serviceType, module);
+        }
+    }
+
+    public <T extends BrokerService> T serviceFor(Class<T> service,
+            ConsumerSessionImpl session) {
+        BrokerModule prov = serviceProviders.get(service);
+        if (prov == null) {
+            log.warn("Service " + service.toString() + " is not supported");
+            return null;
+        }
+        return prov.getServiceForSession(service, session);
+    }
+
+    // RPC Functionality
+    
+    private void addRpcImplementation(QName rpcType,
+            RpcImplementation implementation) {
+        synchronized (rpcImpls) {
+            if (rpcImpls.get(rpcType) != null) {
+                throw new IllegalStateException("Implementation for rpc "
+                        + rpcType + " is already registered.");
+            }
+            rpcImpls.put(rpcType, implementation);
+        }
+        // TODO Add notification for availability of Rpc Implementation
+    }
+
+    private void removeRpcImplementation(QName rpcType,
+            RpcImplementation implToRemove) {
+        synchronized (rpcImpls) {
+            if (implToRemove == rpcImpls.get(rpcType)) {
+                rpcImpls.remove(rpcType);
+            }
+        }
+        // TODO Add notification for removal of Rpc Implementation
+    }
+
+    private Future<RpcResult<CompositeNode>> invokeRpc(QName rpc,
+            CompositeNode input) {
+        RpcImplementation impl = rpcImpls.get(rpc);
+        // if()
+
+        Callable<RpcResult<CompositeNode>> call = callableFor(impl,
+                rpc, input);
+        Future<RpcResult<CompositeNode>> result = executor.submit(call);
+
+        return result;
+    }
+    
+    // Validation
+
+    private void checkPredicates(Provider prov) {
+        if (prov == null)
+            throw new IllegalArgumentException("Provider should not be null.");
+        for (ProviderSessionImpl session : providerSessions) {
+            if (prov.equals(session.getProvider()))
+                throw new IllegalStateException("Provider already registered");
+        }
+
+    }
+
+    private void checkPredicates(Consumer cons) {
+        if (cons == null)
+            throw new IllegalArgumentException("Consumer should not be null.");
+        for (ConsumerSessionImpl session : sessions) {
+            if (cons.equals(session.getConsumer()))
+                throw new IllegalStateException("Consumer already registered");
+        }
+    }
+
+    // Private Factory methods
+    
+    private ConsumerSessionImpl newSessionFor(Consumer provider, BundleContext ctx) {
+        return new ConsumerSessionImpl(provider,ctx);
+    }
+
+    private ProviderSessionImpl newSessionFor(Provider provider, BundleContext ctx) {
+        return new ProviderSessionImpl(provider,ctx);
+    }
+
+    private void consumerSessionClosed(ConsumerSessionImpl consumerSessionImpl) {
+        sessions.remove(consumerSessionImpl);
+        providerSessions.remove(consumerSessionImpl);
+    }
+
+    private static Callable<RpcResult<CompositeNode>> callableFor(
+            final RpcImplementation implemenation, final QName rpc,
+            final CompositeNode input) {
+
+        return new Callable<RpcResult<CompositeNode>>() {
+
+            @Override
+            public RpcResult<CompositeNode> call() throws Exception {
+                return implemenation.invokeRpc(rpc, input);
+            }
+        };
+    }
+    
+    private class ConsumerSessionImpl implements ConsumerSession {
+
+        private final Consumer consumer;
+
+        private Map<Class<? extends BrokerService>, BrokerService> instantiatedServices = Collections
+                .synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerService>());
+        private boolean closed = false;
+
+        private BundleContext context;
+
+        public Consumer getConsumer() {
+            return consumer;
+        }
+
+        public ConsumerSessionImpl(Consumer consumer, BundleContext ctx) {
+            this.consumer = consumer;
+            this.context = ctx;
+        }
+
+        @Override
+        public Future<RpcResult<CompositeNode>> rpc(QName rpc,
+                CompositeNode input) {
+            return BrokerImpl.this.invokeRpc(rpc, input);
+        }
+
+        @Override
+        public <T extends BrokerService> T getService(Class<T> service) {
+            BrokerService potential = instantiatedServices.get(service);
+            if (potential != null) {
+                @SuppressWarnings("unchecked")
+                T ret = (T) potential;
+                return ret;
+            }
+            T ret = BrokerImpl.this.serviceFor(service, this);
+            if (ret != null) {
+                instantiatedServices.put(service, ret);
+            }
+            return ret;
+        }
+
+        @Override
+        public void close() {
+            Collection<BrokerService> toStop = instantiatedServices.values();
+            this.closed = true;
+            for (BrokerService brokerService : toStop) {
+                brokerService.closeSession();
+            }
+            BrokerImpl.this.consumerSessionClosed(this);
+        }
+
+        @Override
+        public boolean isClosed() {
+            return closed;
+        }
+
+    }
+
+    private class ProviderSessionImpl extends ConsumerSessionImpl implements
+            ProviderSession {
+
+        private Provider provider;
+        private Map<QName, RpcImplementation> sessionRpcImpls = Collections.synchronizedMap(new HashMap<QName, RpcImplementation>());
+
+        public ProviderSessionImpl(Provider provider, BundleContext ctx) {
+            super(null,ctx);
+            this.provider = provider;
+        }
+
+        @Override
+        public void addRpcImplementation(QName rpcType,
+                RpcImplementation implementation)
+                throws IllegalArgumentException {
+            if (rpcType == null) {
+                throw new IllegalArgumentException("rpcType must not be null");
+            }
+            if (implementation == null) {
+                throw new IllegalArgumentException(
+                        "Implementation must not be null");
+            }
+            BrokerImpl.this.addRpcImplementation(rpcType, implementation);
+            sessionRpcImpls.put(rpcType, implementation);
+        }
+
+        @Override
+        public void removeRpcImplementation(QName rpcType,
+                RpcImplementation implToRemove) throws IllegalArgumentException {
+            RpcImplementation localImpl = rpcImpls.get(rpcType);
+            if (localImpl != implToRemove) {
+                throw new IllegalStateException(
+                        "Implementation was not registered in this session");
+            }
+
+            BrokerImpl.this.removeRpcImplementation(rpcType, implToRemove);
+            sessionRpcImpls.remove(rpcType);
+        }
+
+        public Provider getProvider() {
+            return this.provider;
+        }
+
+    }
+
+    public void setBundleContext(BundleContext context) {
+        this.bundleContext = context;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerModule.java
new file mode 100644 (file)
index 0000000..7fa20d7
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * 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.dom.broker;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality;
+import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataCommitHandler;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.controller.sal.core.api.data.DataCommitHandler.CommitTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService.DataRefresher;
+import org.opendaylight.controller.sal.core.spi.BrokerModule;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableSet;
+
+public class DataBrokerModule implements BrokerModule {
+
+    private static final Logger log = LoggerFactory
+            .getLogger(DataBrokerModule.class);
+
+    private static final Set<Class<? extends ProviderFunctionality>> SUPPORTED_PROVIDER_FUNCTIONALITY = ImmutableSet
+            .of((Class<? extends ProviderFunctionality>) DataValidator.class,
+                    DataRefresher.class, DataCommitHandler.class);
+
+    private static final Set<Class<? extends BrokerService>> PROVIDED_SESSION_SERVICES = ImmutableSet
+            .of((Class<? extends BrokerService>) DataBrokerService.class,
+                    DataProviderService.class);
+
+    private Map<DataStoreIdentifier, StoreContext> storeContext;
+
+    private ExecutorService executor;
+    
+    private SequentialCommitHandlerCoordinator coordinator = new SequentialCommitHandlerCoordinator();
+
+    @Override
+    public Set<Class<? extends BrokerService>> getProvidedServices() {
+        return PROVIDED_SESSION_SERVICES;
+    }
+
+    @Override
+    public Set<Class<? extends ProviderFunctionality>> getSupportedProviderFunctionality() {
+        return SUPPORTED_PROVIDER_FUNCTIONALITY;
+    }
+
+    @Override
+    public Set<Class<? extends ConsumerFunctionality>> getSupportedConsumerFunctionality() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public <T extends BrokerService> T getServiceForSession(Class<T> service,
+            ConsumerSession session) {
+        if (DataProviderService.class.equals(service)
+                && session instanceof ProviderSession) {
+            @SuppressWarnings("unchecked")
+            T ret = (T) newDataProviderService(session);
+            return ret;
+        } else if (DataBrokerService.class.equals(service)) {
+
+            @SuppressWarnings("unchecked")
+            T ret = (T) newDataConsumerService(session);
+            return ret;
+        }
+
+        throw new IllegalArgumentException(
+                "The requested session-specific service is not provided by this module.");
+    }
+
+    private DataProviderService newDataProviderService(ConsumerSession session) {
+        return new DataProviderSession();
+    }
+
+    private DataBrokerService newDataConsumerService(ConsumerSession session) {
+        return new DataConsumerSession();
+    }
+
+    private StoreContext context(DataStoreIdentifier store) {
+        return storeContext.get(store);
+    }
+
+    private static class StoreContext {
+        private Set<DataCommitHandler> commitHandlers = Collections
+                .synchronizedSet(new HashSet<DataCommitHandler>());
+        private Set<DataValidator> validators = Collections
+                .synchronizedSet(new HashSet<DataValidator>());
+        private Set<DataRefresher> refreshers = Collections
+                .synchronizedSet(new HashSet<DataRefresher>());
+    }
+
+    private class DataConsumerSession implements DataBrokerService {
+
+        @Override
+        public CompositeNode getData(DataStoreIdentifier store) {
+            // TODO Implement this method
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        @Override
+        public CompositeNode getData(DataStoreIdentifier store,
+                CompositeNode filter) {
+            // TODO Implement this method
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        @Override
+        public CompositeNode getCandidateData(DataStoreIdentifier store) {
+            // TODO Implement this method
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        @Override
+        public CompositeNode getCandidateData(DataStoreIdentifier store,
+                CompositeNode filter) {
+            // TODO Implement this method
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        @Override
+        public RpcResult<CompositeNode> editCandidateData(
+                DataStoreIdentifier store, MutableCompositeNode changeSet) {
+            // TODO Implement this method
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        @Override
+        public Future<RpcResult<Void>> commit(DataStoreIdentifier store) {
+            // TODO Implement this method
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        @Override
+        public void closeSession() {
+            // TODO Implement this method
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        @Override
+        public Set<DataStoreIdentifier> getDataStores() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+    }
+
+    private class DataProviderSession extends DataConsumerSession implements
+            DataProviderService {
+
+        private Set<DataCommitHandler> providerCommitHandlers = new HashSet<DataCommitHandler>();
+        private Set<DataValidator> providerValidators = new HashSet<DataValidator>();
+        private Set<DataRefresher> providerRefreshers = new HashSet<DataRefresher>();
+
+        @Override
+        public void addValidator(DataStoreIdentifier store,
+                DataValidator validator) {
+            if (validator == null)
+                throw new IllegalArgumentException(
+                        "Validator should not be null");
+
+            providerValidators.add(validator);
+            context(store).validators.add(validator);
+        }
+
+        @Override
+        public void removeValidator(DataStoreIdentifier store,
+                DataValidator validator) {
+            if (validator == null)
+                throw new IllegalArgumentException(
+                        "Validator should not be null");
+
+            providerValidators.remove(validator);
+            context(store).validators.remove(validator);
+        }
+
+        @Override
+        public void addCommitHandler(DataStoreIdentifier store,
+                DataCommitHandler provider) {
+            if (provider == null)
+                throw new IllegalArgumentException(
+                        "CommitHandler should not be null");
+
+            providerCommitHandlers.add(provider);
+            context(store).commitHandlers.add(provider);
+        }
+
+        @Override
+        public void removeCommitHandler(DataStoreIdentifier store,
+                DataCommitHandler provider) {
+            if (provider == null)
+                throw new IllegalArgumentException(
+                        "CommitHandler should not be null");
+
+            providerCommitHandlers.remove(provider);
+            context(store).commitHandlers.remove(provider);
+        }
+
+        @Override
+        public void addRefresher(DataStoreIdentifier store,
+                DataRefresher provider) {
+            if (provider == null)
+                throw new IllegalArgumentException(
+                        "Refresher should not be null");
+
+            providerRefreshers.add(provider);
+            context(store).refreshers.add(provider);
+        }
+
+        @Override
+        public void removeRefresher(DataStoreIdentifier store,
+                DataRefresher provider) {
+            if (provider == null)
+                throw new IllegalArgumentException(
+                        "Refresher should not be null");
+
+            providerRefreshers.remove(provider);
+            context(store).refreshers.remove(provider);
+        }
+
+    }
+
+    private class SequentialCommitHandlerCoordinator implements
+            DataCommitHandler {
+
+        @Override
+        public RpcResult<CommitTransaction> requestCommit(
+                DataStoreIdentifier store) {
+            List<RpcError> errors = new ArrayList<RpcError>();
+            Set<CommitTransaction> transactions = new HashSet<DataCommitHandler.CommitTransaction>();
+            boolean successful = true;
+
+            for (DataCommitHandler commitHandler : context(store).commitHandlers) {
+                try {
+                    RpcResult<CommitTransaction> partialResult = commitHandler
+                            .requestCommit(store);
+                    successful = partialResult.isSuccessful() & successful;
+                    if (partialResult.isSuccessful()) {
+                        transactions.add(partialResult.getResult());
+                    }
+
+                    errors.addAll(partialResult.getErrors());
+                } catch (Exception e) {
+                    log.error("Uncaught exception prevented commit request."
+                            + e.getMessage(), e);
+                    successful = false;
+                    // FIXME: Add RPC Error with exception.
+                }
+                if (successful == false)
+                    break;
+            }
+            CommitTransaction transaction = new SequentialCommitTransaction(
+                    store, transactions);
+            return Rpcs.getRpcResult(successful, transaction, errors);
+        }
+
+        @Override
+        public Set<DataStoreIdentifier> getSupportedDataStores() {
+            return Collections.emptySet();
+        }
+    }
+
+    private class SequentialCommitTransaction implements CommitTransaction {
+
+        final Set<CommitTransaction> transactions;
+        final DataStoreIdentifier store;
+
+        public SequentialCommitTransaction(DataStoreIdentifier s,
+                Set<CommitTransaction> t) {
+            transactions = t;
+            store = s;
+        }
+
+        @Override
+        public RpcResult<Void> finish() {
+            List<RpcError> errors = new ArrayList<RpcError>();
+            boolean successful = true;
+
+            for (CommitTransaction commitHandler : transactions) {
+                try {
+                    RpcResult<Void> partialResult = commitHandler.finish();
+                    successful = partialResult.isSuccessful() & successful;
+                    errors.addAll(partialResult.getErrors());
+                } catch (Exception e) {
+                    log.error(
+                            "Uncaught exception prevented finishing of commit."
+                                    + e.getMessage(), e);
+                    successful = false;
+                    // FIXME: Add RPC Error with exception.
+                }
+                if (successful == false)
+                    break;
+            }
+
+            return Rpcs.getRpcResult(successful, null, errors);
+        }
+
+        @Override
+        public RpcResult<Void> rollback() {
+            List<RpcError> errors = new ArrayList<RpcError>();
+            boolean successful = true;
+
+            for (CommitTransaction commitHandler : transactions) {
+                try {
+                    RpcResult<Void> partialResult = commitHandler.rollback();
+                    successful = partialResult.isSuccessful() & successful;
+                    errors.addAll(partialResult.getErrors());
+                } catch (Exception e) {
+                    log.error(
+                            "Uncaught exception prevented rollback of commit."
+                                    + e.getMessage(), e);
+                    successful = false;
+                    // FIXME: Add RPC Error with exception.
+                }
+                if (successful == false)
+                    break;
+            }
+
+            return Rpcs.getRpcResult(successful, null, errors);
+        }
+
+        @Override
+        public DataStoreIdentifier getDataStore() {
+            return this.store;
+        }
+
+        @Override
+        public DataCommitHandler getHandler() {
+            return coordinator;
+        }
+    }
+
+    private class ValidationCoordinator implements DataValidator {
+
+        private final DataStoreIdentifier store;
+
+        ValidationCoordinator(DataStoreIdentifier store) {
+            this.store = store;
+        }
+
+        @Override
+        public RpcResult<Void> validate(CompositeNode toValidate) {
+            List<RpcError> errors = new ArrayList<RpcError>();
+            boolean successful = true;
+
+            for (DataValidator validator : context(store).validators) {
+                try {
+                    RpcResult<Void> partialResult = validator
+                            .validate(toValidate);
+                    successful = partialResult.isSuccessful() & successful;
+                    errors.addAll(partialResult.getErrors());
+                } catch (Exception e) {
+                    log.error(
+                            "Uncaught exception prevented validation."
+                                    + e.getMessage(), e);
+                    successful = false;
+                    // FIXME: Add RPC Error with exception.
+                }
+                if (successful == false)
+                    break;
+            }
+
+            return Rpcs.getRpcResult(successful, null, errors);
+        }
+
+        @Override
+        public Set<DataStoreIdentifier> getSupportedDataStores() {
+            return Collections.emptySet();
+        }
+
+    }
+
+    private class DataRefreshCoordinator implements DataRefresher {
+
+        private final DataStoreIdentifier store;
+
+        DataRefreshCoordinator(DataStoreIdentifier store) {
+            this.store = store;
+        }
+
+        @Override
+        public void refreshData() {
+
+            for (DataRefresher refresher : context(store).refreshers) {
+                try {
+                    refresher.refreshData();
+                } catch (Exception e) {
+                    log.error(
+                            "Uncaught exception during refresh of data: "
+                                    + e.getMessage(), e);
+                }
+
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/NotificationModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/NotificationModule.java
new file mode 100644 (file)
index 0000000..9a002ec
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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.dom.broker;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality;
+import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality;
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationProviderService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.controller.sal.core.spi.BrokerModule;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+
+public class NotificationModule implements BrokerModule {
+    private static Logger log = LoggerFactory
+            .getLogger(NotificationModule.class);
+
+    private Multimap<QName, NotificationListener> listeners = HashMultimap
+            .create();
+
+    private static final Set<Class<? extends BrokerService>> PROVIDED_SERVICE_TYPE = ImmutableSet
+            .of((Class<? extends BrokerService>) NotificationService.class,
+                    NotificationProviderService.class);
+
+    private static final Set<Class<? extends ConsumerFunctionality>> SUPPORTED_CONSUMER_FUNCTIONALITY = ImmutableSet
+            .of((Class<? extends ConsumerFunctionality>) NotificationListener.class,
+                    NotificationListener.class); // Workaround: if we use the
+                                                 // version of method with only
+                                                 // one argument, the generics
+                                                 // inference will not work
+
+    @Override
+    public Set<Class<? extends BrokerService>> getProvidedServices() {
+        return PROVIDED_SERVICE_TYPE;
+    }
+
+    @Override
+    public Set<Class<? extends ConsumerFunctionality>> getSupportedConsumerFunctionality() {
+        return SUPPORTED_CONSUMER_FUNCTIONALITY;
+    }
+
+    @Override
+    public <T extends BrokerService> T getServiceForSession(Class<T> service,
+            ConsumerSession session) {
+        if (NotificationProviderService.class.equals(service)
+                && session instanceof ProviderSession) {
+            @SuppressWarnings("unchecked")
+            T ret = (T) newNotificationProviderService(session);
+            return ret;
+        } else if (NotificationService.class.equals(service)) {
+
+            @SuppressWarnings("unchecked")
+            T ret = (T) newNotificationConsumerService(session);
+            return ret;
+        }
+
+        throw new IllegalArgumentException(
+                "The requested session-specific service is not provided by this module.");
+    }
+
+    private void sendNotification(CompositeNode notification) {
+        QName type = notification.getNodeType();
+        Collection<NotificationListener> toNotify = listeners.get(type);
+        log.info("Publishing notification " + type);
+
+        if (toNotify == null) {
+            // No listeners were registered - returns.
+            return;
+        }
+
+        for (NotificationListener listener : toNotify) {
+            try {
+                // FIXME: ensure that notification is immutable
+                listener.onNotification(notification);
+            } catch (Exception e) {
+                log.error("Uncaught exception in NotificationListener", e);
+            }
+        }
+
+    }
+
+    private NotificationService newNotificationConsumerService(
+            ConsumerSession session) {
+        return new NotificationConsumerSessionImpl();
+    }
+
+    private NotificationProviderService newNotificationProviderService(
+            ConsumerSession session) {
+        return new NotificationProviderSessionImpl();
+    }
+
+    private class NotificationConsumerSessionImpl implements
+            NotificationService {
+
+        private Multimap<QName, NotificationListener> consumerListeners = HashMultimap
+                .create();
+        private boolean closed = false;
+
+        @Override
+        public void addNotificationListener(QName notification,
+                NotificationListener listener) {
+            checkSessionState();
+            if (notification == null) {
+                throw new IllegalArgumentException(
+                        "Notification type must not be null.");
+            }
+            if (listener == null) {
+                throw new IllegalArgumentException("Listener must not be null.");
+            }
+
+            consumerListeners.put(notification, listener);
+            listeners.put(notification, listener);
+            log.info("Registered listener for notification: " + notification);
+        }
+
+        @Override
+        public void removeNotificationListener(QName notification,
+                NotificationListener listener) {
+            checkSessionState();
+            if (notification == null) {
+                throw new IllegalArgumentException(
+                        "Notification type must not be null.");
+            }
+            if (listener == null) {
+                throw new IllegalArgumentException("Listener must not be null.");
+            }
+            consumerListeners.remove(notification, listener);
+            listeners.remove(notification, listener);
+        }
+
+        @Override
+        public void closeSession() {
+            closed = true;
+            Map<QName, Collection<NotificationListener>> toRemove = consumerListeners
+                    .asMap();
+            for (Entry<QName, Collection<NotificationListener>> entry : toRemove
+                    .entrySet()) {
+                listeners.remove(entry.getKey(), entry.getValue());
+            }
+        }
+
+        protected void checkSessionState() {
+            if (closed)
+                throw new IllegalStateException("Session is closed");
+        }
+    }
+
+    private class NotificationProviderSessionImpl extends
+            NotificationConsumerSessionImpl implements
+            NotificationProviderService {
+
+        @Override
+        public void sendNotification(CompositeNode notification) {
+            checkSessionState();
+            if (notification == null)
+                throw new IllegalArgumentException(
+                        "Notification must not be null.");
+            NotificationModule.this.sendNotification(notification);
+        }
+    }
+
+    @Override
+    public Set<Class<? extends ProviderFunctionality>> getSupportedProviderFunctionality() {
+        return Collections.emptySet();
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/package-info.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/package-info.java
new file mode 100644 (file)
index 0000000..9793108
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.dom.broker;
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-spi/pom.xml b/opendaylight/md-sal/sal-dom-spi/pom.xml
new file mode 100644 (file)
index 0000000..5593545
--- /dev/null
@@ -0,0 +1,22 @@
+<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">\r
+  <modelVersion>4.0.0</modelVersion>\r
+  <parent>\r
+    <groupId>org.opendaylight.controller</groupId>\r
+    <artifactId>sal-parent</artifactId>\r
+    <version>1.0-SNAPSHOT</version>\r
+  </parent>\r
+   <artifactId>sal-core-spi</artifactId>\r
+    <scm>\r
+      <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
+      <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
+    </scm>\r
+   \r
+   <dependencies>\r
+       <dependency>\r
+               <groupId>org.opendaylight.controller</groupId>\r
+               <artifactId>sal-core-api</artifactId>\r
+               <version>1.0-SNAPSHOT</version>\r
+       </dependency>\r
+       </dependencies>\r
+</project>\r
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/BrokerModule.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/BrokerModule.java
new file mode 100644 (file)
index 0000000..99438c8
--- /dev/null
@@ -0,0 +1,27 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.sal.core.spi;\r
+\r
+import java.util.Set;\r
+\r
+import org.opendaylight.controller.sal.core.api.BrokerService;\r
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;\r
+import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality;\r
+import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality;\r
+\r
+public interface BrokerModule {\r
+\r
+    Set<Class<? extends BrokerService>> getProvidedServices();\r
+\r
+    Set<Class<? extends ConsumerFunctionality>> getSupportedConsumerFunctionality();\r
+\r
+    <T extends BrokerService> T getServiceForSession(Class<T> service,\r
+            ConsumerSession session);\r
+\r
+    Set<Class<? extends ProviderFunctionality>> getSupportedProviderFunctionality();\r
+}\r
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/package-info.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/package-info.java
new file mode 100644 (file)
index 0000000..76493af
--- /dev/null
@@ -0,0 +1,8 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.sal.core.spi;
\ No newline at end of file