Flow Objective implementation

Provides an abstraction which isolates the application from any pipeline
knowledge. By using the provided objectives applications can express
their forwarding desires in a pipeline agnostic way. The objectives
are then consumed by a driver for the specific device who converts them
into the appropriate pipeline coherent flows.

Change-Id: I74a68b4971c367c0cd5b7de9d877abdd117afa98
diff --git a/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java b/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java
index 1e2d277..7308898 100644
--- a/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java
+++ b/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java
@@ -31,11 +31,9 @@
 import org.onosproject.net.flowobjective.FilteringObjective;
 import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.ObjectiveError;
 import org.slf4j.Logger;
 
-import java.util.Collection;
-import java.util.concurrent.Future;
-
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -58,59 +56,62 @@
     }
 
     @Override
-    public Future<Boolean> filter(Collection<FilteringObjective> filters) {
+    public void filter(FilteringObjective filter) {
         throw new UnsupportedOperationException("Single table does not filter.");
     }
 
     @Override
-    public Future<Boolean> forward(Collection<ForwardingObjective> forwardings) {
+    public void forward(ForwardingObjective fwd) {
         FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-        forwardings.forEach(fwd -> {
-            if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
-                throw new UnsupportedOperationException(
-                        "Only VERSATILE is supported.");
-            }
 
-            TrafficSelector selector = fwd.selector();
+        if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
+            throw new UnsupportedOperationException(
+                    "Only VERSATILE is supported.");
+        }
 
-            FlowRule rule = new DefaultFlowRule(deviceId, selector,
-                                                fwd.treatment(),
-                                                fwd.priority(), fwd.appId(),
-                                                new DefaultGroupId(fwd.id()),
-                                                fwd.timeout(), fwd.permanent());
+        TrafficSelector selector = fwd.selector();
 
-            switch (fwd.op()) {
+        FlowRule rule = new DefaultFlowRule(deviceId, selector,
+                                            fwd.treatment(),
+                                            fwd.priority(), fwd.appId(),
+                                            new DefaultGroupId(fwd.id()),
+                                            fwd.timeout(), fwd.permanent());
 
-                case ADD:
-                    flowBuilder.add(rule);
-                    break;
-                case REMOVE:
-                    flowBuilder.remove(rule);
-                    break;
-                default:
-                    log.warn("Unknown operation {}", fwd.op());
-            }
+        switch (fwd.op()) {
 
-        });
+            case ADD:
+                flowBuilder.add(rule);
+                break;
+            case REMOVE:
+                flowBuilder.remove(rule);
+                break;
+            default:
+                log.warn("Unknown operation {}", fwd.op());
+        }
+
 
         SettableFuture<Boolean> future = SettableFuture.create();
 
         flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
             @Override
             public void onSuccess(FlowRuleOperations ops) {
-                future.set(true);
+                if (fwd.context().isPresent()) {
+                    fwd.context().get().onSuccess(fwd);
+                }
             }
 
             @Override
             public void onError(FlowRuleOperations ops) {
-                future.set(false);
+                if (fwd.context().isPresent()) {
+                    fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
+                }
             }
         }));
-        return future;
+
     }
 
     @Override
-    public Future<Boolean> next(Collection<NextObjective> nextObjectives) {
+    public void next(NextObjective nextObjective) {
         throw new UnsupportedOperationException("Single table does not next hop.");
     }