Implement IntentInstallers

IntentInstallers for:
- PathFlowIntent
- SingleDstTreeFlowIntent
- SingleSrcTreeFlowIntent

This resolves ONOS-1884, ONOS-1885, and ONOS-1886.

Change-Id: Ie0eac4bab9a2898b582edf2e4291498f0a583d71
diff --git a/src/test/java/net/onrc/onos/api/flowmanager/FakeFlowManagerService.java b/src/test/java/net/onrc/onos/api/flowmanager/FakeFlowManagerService.java
new file mode 100644
index 0000000..c231bca
--- /dev/null
+++ b/src/test/java/net/onrc/onos/api/flowmanager/FakeFlowManagerService.java
@@ -0,0 +1,119 @@
+package net.onrc.onos.api.flowmanager;
+
+import com.google.common.collect.ImmutableList;
+import net.onrc.onos.core.flowmanager.FlowBatchHandleImpl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Fake implementation of {@link FlowManagerService} for testing.
+ */
+public class FakeFlowManagerService implements FlowManagerService {
+    private final List<FlowManagerListener> listeners = new ArrayList<>();
+    private final ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    private final FlowId target;
+    private final List<FlowState> transition;
+    private final boolean returnNull;
+
+    public FakeFlowManagerService(FlowId target, boolean returnNull, FlowState... transition) {
+        this.target = target;
+        this.transition = ImmutableList.copyOf(transition);
+        this.returnNull = returnNull;
+    }
+
+    public FlowBatchHandle addFlow(Flow flow) {
+        return processFlow();
+    }
+
+    @Override
+    public FlowBatchHandle removeFlow(FlowId id) {
+        return processFlow();
+    }
+
+    private FlowBatchHandle processFlow() {
+        if (returnNull) {
+            return null;
+        }
+
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                changeStates();
+            }
+        });
+
+        // This is a test-only workaround. Passing null to the constructor is harmful,
+        // but we could not create a FlowOperationMap instance due to visibility of
+        // the constructor.
+        // TODO: consider correct visibility of the constructor and package structure
+        return new FlowBatchHandleImpl(null, new FlowBatchId(1));
+    }
+
+    private void changeStates() {
+        for (int i = 0; i < transition.size(); i++) {
+            FlowStateChange change;
+            if (i == 0) {
+                change = new FlowStateChange(target,
+                        transition.get(i), null);
+            } else {
+                change = new FlowStateChange(target,
+                        transition.get(i), transition.get(i - 1));
+            }
+            HashSet<FlowStateChange> changes = new HashSet<>(Arrays.asList(change));
+            invokeListeners(new FlowStatesChangedEvent(System.currentTimeMillis(), changes));
+        }
+    }
+
+    @Override
+    public Flow getFlow(FlowId id) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Collection<Flow> getFlows() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public FlowBatchHandle executeBatch(FlowBatchOperation ops) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public FlowIdGenerator getFlowIdGenerator() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setConflictDetectionPolicy(ConflictDetectionPolicy policy) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ConflictDetectionPolicy getConflictDetectionPolicy() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addListener(FlowManagerListener listener) {
+        listeners.add(listener);
+    }
+
+    @Override
+    public void removeListener(FlowManagerListener listener) {
+        listeners.remove(listener);
+    }
+
+    private void invokeListeners(FlowStatesChangedEvent event) {
+        for (FlowManagerListener listener: listeners) {
+            listener.flowStatesChanged(event);
+        }
+    }
+}