--- /dev/null
+<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>flow-management-compatibility</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>Forwarding Rules Manager Adapter for MD-SAL</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ </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.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.lib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwardingrulesmanager</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-compability</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+
+ </dependencies>
+</project>
--- /dev/null
+package org.opendaylight.controller.md.frm.compatibility
+
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder
+import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager
+import static com.google.common.base.Preconditions.*;
+import static extension org.opendaylight.controller.md.frm.compatibility.FlowConfigMapping.*;
+import static extension org.opendaylight.controller.sal.compability.NodeMapping.*;
+import org.opendaylight.controller.sal.common.util.Arguments
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.common.RpcResult
+import org.opendaylight.controller.forwardingrulesmanager.FlowConfig
+import java.util.HashSet
+import org.opendaylight.controller.sal.common.util.Rpcs
+import java.util.Collections
+import org.opendaylight.yangtools.yang.common.RpcError
+
+class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ static val FLOWS_PATH = InstanceIdentifier.builder().node(Flows).toInstance;
+
+ @Property
+ var DataProviderService dataService;
+
+ @Property
+ var DataChangeListener changeListener;
+
+ @Property
+ var IForwardingRulesManager manager;
+
+ FlowManagementReader configuration = new ConfigurationReader();
+
+ def init() {
+ //dataService.registerDataChangeListener(FLOWS_PATH, changeListener);
+ dataService.registerCommitHandler(FLOWS_PATH, this);
+ }
+
+ override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+ return readFrom(configuration, path);
+ }
+
+ override DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+ return readFrom(configuration, path);
+ }
+
+ def DataObject readFrom(FlowManagementReader store, InstanceIdentifier<? extends DataObject> path) {
+ if (FLOWS_PATH == path) {
+ return store.readAllFlows();
+ }
+ if (FLOWS_PATH.contains(path)) {
+ return store.readFlow(path.toFlowKey());
+ }
+ return null;
+ }
+
+ override FlowCommitTransaction requestCommit(
+ DataModification modification) {
+ return new FlowCommitTransaction(this,modification);
+ }
+
+ def toFlowKey(InstanceIdentifier<? extends DataObject> identifier) {
+ checkNotNull(identifier)
+ val item = Arguments.checkInstanceOf(identifier.path.get(1),IdentifiableItem);
+ val key = Arguments.checkInstanceOf(item.key,FlowKey)
+ return key;
+ }
+
+ def RpcResult<Void> finish(FlowCommitTransaction transaction) {
+ for(flw: transaction.toRemove) {
+ manager.removeStaticFlow(flw.name,flw.node)
+ }
+
+ for(flw: transaction.toUpdate) {
+ manager.removeStaticFlow(flw.name,flw.node);
+ manager.addStaticFlow(flw);
+ }
+
+ return Rpcs.<Void>getRpcResult(true,null,Collections.<RpcError>emptySet())
+ }
+
+ def RpcResult<Void> rollback(FlowCommitTransaction transaction) {
+ // NOOP: We did not changed any state.
+ }
+
+}
+
+class ConfigurationReader implements FlowManagementReader {
+
+ @Property
+ var IForwardingRulesManager manager;
+
+ override Flows readAllFlows() {
+ val it = new FlowsBuilder();
+ flow = manager.staticFlows.map[
+ toConfigurationFlow();
+ ]
+ return it.build();
+ }
+
+ override readFlow(FlowKey key) {
+ val flowCfg = manager.getStaticFlow(key.id,key.node.toADNode());
+ return flowCfg.toConfigurationFlow;
+ }
+}
+
+public static class FlowCommitTransaction implements DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ @Property
+ val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+
+ @Property
+ val FRMRuntimeDataProvider flowManager;
+
+ @Property
+ val toAdd = new HashSet<FlowConfig>();
+
+ @Property
+ var Iterable<FlowConfig> toUpdate
+
+ @Property
+ var Iterable<FlowConfig> toRemove
+
+
+ new(FRMRuntimeDataProvider flowManager,DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ super();
+ _flowManager = flowManager;
+ _modification = modification;
+ processModification();
+ }
+
+ override finish() throws IllegalStateException {
+ return flowManager.finish(this);
+ }
+
+ override rollback() throws IllegalStateException
+{
+ return flowManager.rollback(this);
+ }
+
+ def processModification() {
+ val updated = modification.updatedConfigurationData.entrySet;
+
+ val _toUpdate = updated.filter[key.isFlowPath].map[
+ return (value as Flow).toFlowConfig
+ ]
+ toUpdate = _toUpdate as Iterable<FlowConfig>
+
+
+ val _toRemove = modification.removedConfigurationData.filter[isFlowPath].map[
+ toFlowConfig
+ ]
+ toRemove = _toRemove as Iterable<FlowConfig>
+
+ }
+}
--- /dev/null
+package org.opendaylight.controller.md.frm.compatibility
+
+import org.opendaylight.controller.forwardingrulesmanager.FlowConfig
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder
+
+import static extension org.opendaylight.controller.sal.compability.NodeMapping.*
+import static org.opendaylight.controller.sal.compability.MDFlowMapping.*
+import static org.opendaylight.controller.sal.compability.ToSalConversionsUtils.*
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.binding.Identifiable
+
+class FlowConfigMapping {
+
+ static def toConfigurationFlow(FlowConfig sourceCfg) {
+ val it = new FlowBuilder();
+ val source = flowAdded(sourceCfg.flow);
+
+ action = source.action;
+ cookie = source.cookie;
+ hardTimeout = source.hardTimeout
+ idleTimeout = source.idleTimeout
+ match = source.match
+ node = source.node
+ key = new FlowKey(sourceCfg.name, node)
+ return it.build();
+ }
+
+ static def toFlowConfig(Flow sourceCfg) {
+ val flow = toFlow(sourceCfg);
+ val it = new FlowConfig;
+ name = sourceCfg.key.id
+ node = sourceCfg.node.toADNode();
+
+ return it
+ }
+
+ static def toFlowConfig(InstanceIdentifier<?> identifier) {
+ val it = new FlowConfig()
+ val FlowKey key = ((identifier.path.get(2) as IdentifiableItem<Flow,FlowKey>).key)
+ name = key.id;
+ node = key.node.toADNode();
+
+ return it;
+ }
+
+ static def boolean isFlowPath(InstanceIdentifier<?> path) {
+ if(path.path.size < 2) return false;
+ if (path.path.get(2) instanceof IdentifiableItem<?,?>) {
+ val IdentifiableItem<?,? extends Identifiable<?>> item = path.path.get(2) as IdentifiableItem<?,? extends Identifiable<?>>;
+ val Identifiable<?> key = item.key;
+ if (key instanceof FlowKey) {
+ return true;
+ }
+ }
+ return false;
+ }
+}