Skeletons for Intent-runtime, Flow-manager and Match-action modules.

This task is a part of ONOS-1395.
(Sub-tasks: ONOS-1397, ONOS-1398, ONOS-1400)

Change-Id: I30064f658b6c193aee8419079dad380163364475
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/ConflictDetectionPolicy.java b/src/main/java/net/onrc/onos/api/flowmanager/ConflictDetectionPolicy.java
new file mode 100644
index 0000000..6d54450
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/ConflictDetectionPolicy.java
@@ -0,0 +1,21 @@
+package net.onrc.onos.api.flowmanager;
+
+/**
+ * Conflict detection policies for the flow manager.
+ */
+public enum ConflictDetectionPolicy {
+    /**
+     * Do not allow overlap flow-space on any ingress port.
+     */
+    STRICT,
+
+    /**
+     * Keep control of packets flowing through each specified path, tree, etc.
+     */
+    LOOSE,
+
+    /**
+     * No limitation (accepts all, handles by priority).
+     */
+    FREE
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/FlowLink.java b/src/main/java/net/onrc/onos/api/flowmanager/FlowLink.java
new file mode 100644
index 0000000..474ac75
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/FlowLink.java
@@ -0,0 +1,102 @@
+package net.onrc.onos.api.flowmanager;
+
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+
+/**
+ * A link representation used by IFlow objects.
+ * <p>
+ * TODO: Should lambda, bandwidth, tag, etc. be defined in this FlowLink, Path,
+ * Tree or IFlow? We have to define it.
+ */
+public class FlowLink {
+    protected SwitchPort srcSwitchPort;
+    protected SwitchPort dstSwitchPort;
+
+    /**
+     * Creates new FlowLink object using source/destination switch port pair.
+     *
+     * @param src The source switch port.
+     * @param dst The destination switch port.
+     */
+    public FlowLink(SwitchPort src, SwitchPort dst) {
+        this.srcSwitchPort = src;
+        this.dstSwitchPort = dst;
+    }
+
+    /**
+     * Creates new FlowLink object using DPID and port number pairs at
+     * source/destination switches.
+     *
+     * @param srcDpid The source switch DPID.
+     * @param srcPortNumber The source port number at the source switch.
+     * @param dstDpid The destination switch DPID.
+     * @param dstPortNumber The destination port number at the destination
+     *        switch.
+     */
+    public FlowLink(Dpid srcDpid, PortNumber srcPortNumber,
+            Dpid dstDpid, PortNumber dstPortNumber) {
+        this.srcSwitchPort = new SwitchPort(srcDpid, srcPortNumber);
+        this.dstSwitchPort = new SwitchPort(dstDpid, dstPortNumber);
+    }
+
+    /**
+     * Gets the source switch port.
+     *
+     * @return The source switch port.
+     */
+    public SwitchPort getSrcSwitchPort() {
+        return srcSwitchPort;
+    }
+
+    /**
+     * Gets the source switch DPID.
+     *
+     * @return The source switch DPID.
+     */
+    public Dpid getSrcDpid() {
+        return srcSwitchPort.dpid();
+    }
+
+    /**
+     * Gets the source port number at the source switch.
+     *
+     * @return The source port number at the source switch.
+     */
+    public PortNumber getSrcPortNumber() {
+        return srcSwitchPort.port();
+    }
+
+    /**
+     * Gets the destination switch port.
+     *
+     * @return The destination switch port.
+     */
+    public SwitchPort getDstSwitchPort() {
+        return dstSwitchPort;
+    }
+
+    /**
+     * Gets the destination switch DPID.
+     *
+     * @return The destination switch DPID.
+     */
+    public Dpid getDstDpid() {
+        return dstSwitchPort.dpid();
+    }
+
+    /**
+     * Gets the destination port number at the destination switch.
+     *
+     * @return The destination port number at the destination switch.
+     */
+    public PortNumber getDstPortNumber() {
+        return dstSwitchPort.port();
+    }
+
+    @Override
+    public String toString() {
+        return srcSwitchPort + "-->" + dstSwitchPort;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/FlowLinks.java b/src/main/java/net/onrc/onos/api/flowmanager/FlowLinks.java
new file mode 100644
index 0000000..3d2d771
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/FlowLinks.java
@@ -0,0 +1,139 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * A list of FlowLink objects.
+ */
+public class FlowLinks implements List<FlowLink> {
+    protected final List<FlowLink> links = new LinkedList<FlowLink>();
+
+    @Override
+    public int size() {
+        return links.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return links.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return links.contains(o);
+    }
+
+    @Override
+    public Iterator<FlowLink> iterator() {
+        return links.iterator();
+    }
+
+    @Override
+    public Object[] toArray() {
+        return links.toArray();
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+        return links.toArray(a);
+    }
+
+    @Override
+    public boolean add(FlowLink e) {
+        return links.add(e);
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        return links.remove(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        return links.containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends FlowLink> c) {
+        return links.addAll(c);
+    }
+
+    @Override
+    public boolean addAll(int index, Collection<? extends FlowLink> c) {
+        return links.addAll(index, c);
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        return links.removeAll(c);
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        return links.retainAll(c);
+    }
+
+    @Override
+    public void clear() {
+        links.clear();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return links.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return links.hashCode();
+    }
+
+    @Override
+    public FlowLink get(int index) {
+        return links.get(index);
+    }
+
+    @Override
+    public FlowLink set(int index, FlowLink element) {
+        return links.set(index, element);
+    }
+
+    @Override
+    public void add(int index, FlowLink element) {
+        links.add(index, element);
+    }
+
+    @Override
+    public FlowLink remove(int index) {
+        return links.remove(index);
+    }
+
+    @Override
+    public int indexOf(Object o) {
+        return links.indexOf(o);
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+        return links.lastIndexOf(o);
+    }
+
+    @Override
+    public ListIterator<FlowLink> listIterator() {
+        return links.listIterator();
+    }
+
+    @Override
+    public ListIterator<FlowLink> listIterator(int index) {
+        return links.listIterator(index);
+    }
+
+    @Override
+    public List<FlowLink> subList(int fromIndex, int toIndex) {
+        return links.subList(fromIndex, toIndex);
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/IFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/IFlow.java
new file mode 100644
index 0000000..66f116a
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/IFlow.java
@@ -0,0 +1,38 @@
+package net.onrc.onos.api.flowmanager;
+
+import net.onrc.onos.api.batchoperation.IBatchOperationTarget;
+import net.onrc.onos.core.matchaction.MatchActionPlan;
+import net.onrc.onos.core.matchaction.match.IMatch;
+
+/**
+ * An interface class to define flow object which is managed by
+ * FlowManagerModule.
+ * <p>
+ * The flow objects (eg. path, tree, disjoint-paths, etc.) must implement this
+ * interface.
+ */
+public interface IFlow extends IBatchOperationTarget {
+    /**
+     * Gets ID for this flow object.
+     *
+     * @return ID for this object.
+     */
+    @Override
+    public String getId();
+
+    /**
+     * Gets traffic filter for this flow object.
+     *
+     * @return a traffic filter for this flow object.
+     */
+    public IMatch getMatch();
+
+    /**
+     * Compiles this object to MatchAction plan.
+     * <p>
+     * This method is called by FlowManagerModule to create MatchAction plans.
+     *
+     * @return a MatchAction plan of this flow object.
+     */
+    public MatchActionPlan compile();
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/IFlowManagerService.java b/src/main/java/net/onrc/onos/api/flowmanager/IFlowManagerService.java
new file mode 100644
index 0000000..edd3c85
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/IFlowManagerService.java
@@ -0,0 +1,97 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.Collection;
+import java.util.EventListener;
+
+import net.onrc.onos.api.batchoperation.BatchOperation;
+
+/**
+ * An interface class for flow manager. The role of the flow manager is to
+ * manage a set of Match-Action entries based on the specified IFlow objects.
+ * <p>
+ * It compiles accepted IFlow objects to Match-Action entries by calculating the
+ * match-action operation phases and allocating resources based on the
+ * constrains described in the IFlow objects, and executes calculated phases
+ * using Match-Action Service.
+ * <p>
+ * TODO: add more getter with filter for IFlow objects.
+ */
+public interface IFlowManagerService {
+    /**
+     * Adds IFlow object, calculates match-action plan and executes it.
+     *
+     * @param flow IFlow object to be added.
+     * @return true if succeeded, false otherwise.
+     */
+    boolean addFlow(IFlow flow);
+
+    /**
+     * Removes IFlow object, calculates match-action plan and executes it.
+     *
+     * @param id ID for IFlow object to be removed.
+     * @return true if succeeded, false otherwise.
+     */
+    boolean removeFlow(String id);
+
+    /**
+     * Updates IFlow object, calculates match-action plan and executes it.
+     * <p>
+     * The IFlow object having the ID which is the same to the ID of the IFlow
+     * object specified by the parameter will be updated.
+     *
+     * @param flow new IFlow object for the update.
+     * @return true if succeeded, false otherwise.
+     */
+    boolean updateFlow(IFlow flow);
+
+    /**
+     * Gets IFlow object.
+     *
+     * @param id ID of IFlow object.
+     * @return IFlow object if found, null otherwise.
+     */
+    IFlow getFlow(String id);
+
+    /**
+     * Gets All IFlow objects.
+     *
+     * @return the collection of IFlow objects.
+     */
+    Collection<IFlow> getFlows();
+
+    /**
+     * Executes batch operation of IFlow object.
+     *
+     * @param ops FlowOperations to be executed.
+     * @return true if succeeded, false otherwise.
+     */
+    boolean executeBatch(BatchOperation<IFlow> ops);
+
+    /**
+     * Sets a conflict detection policy.
+     *
+     * @param policy ConflictDetectionPolicy object to be set.
+     */
+    void setConflictDetectionPolicy(ConflictDetectionPolicy policy);
+
+    /**
+     * Gets the conflict detection policy.
+     *
+     * @return ConflictDetectionPolicy object being applied currently.
+     */
+    ConflictDetectionPolicy getConflictDetectionPolicy();
+
+    /**
+     * Adds event listener to this service.
+     *
+     * @param listener EventListener to be added.
+     */
+    void addEventListener(EventListener listener);
+
+    /**
+     * Removes event listener from this service.
+     *
+     * @param listener EventListener to be removed.
+     */
+    void removeEventListener(EventListener listener);
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/OpticalPathFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/OpticalPathFlow.java
new file mode 100644
index 0000000..00a4785
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/OpticalPathFlow.java
@@ -0,0 +1,48 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.List;
+
+import net.onrc.onos.core.matchaction.MatchActionPlan;
+import net.onrc.onos.core.matchaction.action.IAction;
+import net.onrc.onos.core.util.PortNumber;
+
+/**
+ * IFlow object representing an optical path.
+ * <p>
+ * TODO: Think this: How do we deal the optical path flow going through the
+ * regenerators? Can we express it with multiple OpticalPathFlow objects?
+ */
+public class OpticalPathFlow extends PathFlow {
+    protected int lambda;
+
+    /**
+     * Constructor.
+     *
+     * @param id ID for this new IFlow object.
+     * @param inPort Ingress port number at the ingress edge node.
+     * @param path Path between ingress and egress edge node.
+     * @param actions The list of IAction objects at the egress edge node.
+     * @param lambda The lambda to be used throughout the path.
+     */
+    public OpticalPathFlow(String id,
+            PortNumber inPort, Path path, List<IAction> actions, int lambda) {
+        super(id, null, inPort, path, actions);
+        this.lambda = lambda;
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * Gets lambda which is used throughout the path.
+     *
+     * @return lambda which is used throughout the path.
+     */
+    public int getLambda() {
+        return lambda;
+    }
+
+    @Override
+    public MatchActionPlan compile() {
+        // TODO Auto-generated method stub
+        return super.compile();
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/PacketPathFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/PacketPathFlow.java
new file mode 100644
index 0000000..087ef47
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/PacketPathFlow.java
@@ -0,0 +1,61 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.List;
+
+import net.onrc.onos.core.matchaction.MatchActionPlan;
+import net.onrc.onos.core.matchaction.action.IAction;
+import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.util.PortNumber;
+
+/**
+ * IFlow object representing a packet path.
+ * <p>
+ * TODO: Think this: Do we need a bandwidth constraint?
+ */
+public class PacketPathFlow extends PathFlow {
+    private int hardTimeout;
+    private int idleTimeout;
+
+    /**
+     * Constructor.
+     *
+     * @param id ID for this new IFlow object.
+     * @param match Match object at the source node of the path.
+     * @param inPort Ingress port number at the ingress edge node.
+     * @param path Path between ingress and egress edge node.
+     * @param edgeActions The list of IAction objects at the egress edge node.
+     * @param hardTimeout hard-timeout value.
+     * @param idleTimeout idle-timeout value.
+     */
+    public PacketPathFlow(String id,
+            PacketMatch match, PortNumber inPort, Path path, List<IAction> edgeActions,
+            int hardTimeout, int idleTimeout) {
+        super(id, match, inPort, path, edgeActions);
+        this.hardTimeout = hardTimeout;
+        this.idleTimeout = idleTimeout;
+    }
+
+    /**
+     * Gets idle-timeout value.
+     *
+     * @return Idle-timeout value (seconds)
+     */
+    public int getIdleTimeout() {
+        return idleTimeout;
+    }
+
+    /**
+     * Gets hard-timeout value.
+     *
+     * @return Hard-timeout value (seconds)
+     */
+    public int getHardTimeout() {
+        return hardTimeout;
+    }
+
+    @Override
+    public MatchActionPlan compile() {
+        // TODO Auto-generated method stub
+        return super.compile();
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/Path.java b/src/main/java/net/onrc/onos/api/flowmanager/Path.java
new file mode 100644
index 0000000..df61e51
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/Path.java
@@ -0,0 +1,79 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.onrc.onos.core.util.Dpid;
+
+/**
+ * Path representation for the flow manager.
+ */
+public class Path extends FlowLinks {
+    /**
+     * Default constructor to create an empty path.
+     */
+    public Path() {
+        super();
+    }
+
+    /**
+     * Gets a list of switch DPIDs of the path.
+     *
+     * @return a list of Dpid objects
+     */
+    public List<Dpid> getDpids() {
+        if (size() < 1) {
+            return null;
+        }
+
+        List<Dpid> dpids = new ArrayList<Dpid>(size() + 1);
+        dpids.add(getSrcDpid());
+        for (FlowLink link: this) {
+            dpids.add(link.getDstDpid());
+        }
+        return dpids;
+    }
+
+    /**
+     * Gets the DPID of the first switch.
+     *
+     * @return a Dpid object of the first switch.
+     */
+    public Dpid getSrcDpid() {
+        if (size() < 1) {
+            return null;
+        }
+        return get(0).getSrcDpid();
+    }
+
+    /**
+     * Gets the DPID of the last switch.
+     *
+     * @return a Dpid object of the last switch.
+     */
+    public Dpid getDstDpid() {
+        if (size() < 1) {
+            return null;
+        }
+        return get(size() - 1).getDstDpid();
+    }
+
+    /**
+     * Returns a string representation of the path.
+     *
+     * @return a string representation of the path.
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        Iterator<FlowLink> i = this.iterator();
+        while (i.hasNext()) {
+            builder.append(i.next().toString());
+            if (i.hasNext()) {
+                builder.append(", ");
+            }
+        }
+        return builder.toString();
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/PathFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/PathFlow.java
new file mode 100644
index 0000000..baf163f
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/PathFlow.java
@@ -0,0 +1,84 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.List;
+
+import net.onrc.onos.core.matchaction.MatchActionPlan;
+import net.onrc.onos.core.matchaction.action.IAction;
+import net.onrc.onos.core.matchaction.match.IMatch;
+import net.onrc.onos.core.util.PortNumber;
+
+/**
+ * A path flow.
+ * <p>
+ * TODO: Think this: Should this class be an abstract class? Is it enough to
+ * have only the PacketPathFlow and OpticalPathFlow classes?
+ */
+public class PathFlow implements IFlow {
+    protected final String id;
+    protected IMatch match;
+    protected PortNumber ingressPort;
+    protected Path path;
+    protected List<IAction> edgeActions;
+
+    /**
+     * Constructor.
+     *
+     * @param id ID for this new PathFlow object.
+     * @param match Match object at the ingress node of the path.
+     * @param ingressPort The ingress port number at the ingress node of the
+     *        path.
+     * @param path Path between ingress and egress edge node.
+     * @param edgeActions The list of IAction objects at the egress edge node.
+     */
+    public PathFlow(String id,
+            IMatch match, PortNumber ingressPort, Path path, List<IAction> edgeActions) {
+        this.id = id;
+        this.match = match;
+        this.ingressPort = ingressPort;
+        this.path = path;
+        this.edgeActions = edgeActions;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public IMatch getMatch() {
+        return match;
+    }
+
+    @Override
+    public MatchActionPlan compile() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /**
+     * Gets the ingress port number at the ingress node of the path.
+     *
+     * @return The ingress port number at the ingress node of the path.
+     */
+    public PortNumber getIngressPortNumber() {
+        return ingressPort;
+    }
+
+    /**
+     * Gets the path from ingress to egress edge node.
+     *
+     * @return The path object from ingress to egress edge node.
+     */
+    public Path getPath() {
+        return path;
+    }
+
+    /**
+     * Gets the list of IAction objects at the egress edge node.
+     *
+     * @return The list of IAction objects at the egress edge node.
+     */
+    public List<IAction> getActions() {
+        return edgeActions;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java
new file mode 100644
index 0000000..82a9b50
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java
@@ -0,0 +1,90 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.onrc.onos.core.matchaction.MatchActionPlan;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.util.SwitchPort;
+
+/**
+ * An IFlow object expressing the multipoints-to-point tree flow for the packet
+ * layer.
+ * <p>
+ * NOTE: This class might generate the MatchActionPlan which includes the MAC
+ * address modifications or other the label-switching-like schemes.
+ */
+public class SingleDstTreeFlow implements IFlow {
+    protected String id;
+    protected PacketMatch match;
+    protected Set<SwitchPort> ingressPorts;
+    protected Tree tree;
+    protected OutputAction outputAction;
+
+    /**
+     * Creates new instance using Tree object.
+     *
+     * @param id ID for this object.
+     * @param match Traffic filter for the tree.
+     * @param ingressPorts A set of ingress ports of the tree.
+     * @param tree Tree object specifying tree topology for this object.
+     * @param outputAction OutputAction object at the egress edge switch.
+     */
+    public SingleDstTreeFlow(String id, PacketMatch match,
+            Collection<SwitchPort> ingressPorts, Tree tree, OutputAction outputAction) {
+        this.id = id;
+        this.match = match;
+        this.ingressPorts = new HashSet<SwitchPort>(ingressPorts);
+        this.tree = tree;
+        this.outputAction = outputAction;
+
+        // TODO: check if the tree is a MP2P tree.
+        // TODO: check consistency among inPorts, tree, and action.
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public PacketMatch getMatch() {
+        return match;
+    }
+
+    @Override
+    public MatchActionPlan compile() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /**
+     * Gets the ingress ports of the tree.
+     *
+     * @return The ingress ports of the tree.
+     */
+    public Collection<SwitchPort> getIngressPorts() {
+        return Collections.unmodifiableCollection(ingressPorts);
+    }
+
+    /**
+     * Gets the tree.
+     *
+     * @return The tree object.
+     */
+    public Tree getTree() {
+        return tree;
+    }
+
+    /**
+     * Gets the output action for the tree.
+     *
+     * @return The OutputAction object.
+     */
+    public OutputAction getOutputAction() {
+        return outputAction;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/SingleSrcTreeFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/SingleSrcTreeFlow.java
new file mode 100644
index 0000000..cecb605
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/SingleSrcTreeFlow.java
@@ -0,0 +1,87 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.Set;
+
+import net.onrc.onos.core.matchaction.MatchActionPlan;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.Pair;
+import net.onrc.onos.core.util.SwitchPort;
+
+/**
+ * An IFlow object expressing the point-to-multipoints tree flow for the packet
+ * layer.
+ */
+public class SingleSrcTreeFlow implements IFlow {
+    protected String id;
+    protected PacketMatch match;
+    protected SwitchPort ingressPort;
+    protected Tree tree;
+    protected Set<Pair<Dpid, OutputAction>> outputActions;
+
+    /**
+     * Creates new instance using Tree object.
+     *
+     * @param id ID for this object.
+     * @param match Traffic filter for the tree.
+     * @param ingressPort A ingress port of the tree.
+     * @param tree Tree object specifying tree topology for this object.
+     * @param outputActions The set of the pairs of the switch DPID and
+     *        OutputAction object at the egress edge switchs.
+     */
+    public SingleSrcTreeFlow(String id, PacketMatch match,
+            SwitchPort ingressPort, Tree tree, Set<Pair<Dpid, OutputAction>> outputActions) {
+        this.id = id;
+        this.match = match;
+        this.ingressPort = ingressPort;
+        this.tree = tree;
+        this.outputActions = outputActions;
+
+        // TODO: check if the tree is a P2MP tree.
+        // TODO: check consistency among rootPort, tree, and actions.
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public PacketMatch getMatch() {
+        return match;
+    }
+
+    @Override
+    public MatchActionPlan compile() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /**
+     * Gets the ingress port (the root) of the tree.
+     *
+     * @return The ingress port of the tree.
+     */
+    public SwitchPort getIngressPort() {
+        return ingressPort;
+    }
+
+    /**
+     * Gets the tree.
+     *
+     * @return The tree object.
+     */
+    public Tree getTree() {
+        return tree;
+    }
+
+    /**
+     * Gets the output actions for the tree.
+     *
+     * @return The set of the pairs of Dpid and OutputAction object.
+     */
+    public Set<Pair<Dpid, OutputAction>> getActions() {
+        return outputActions;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/Tree.java b/src/main/java/net/onrc/onos/api/flowmanager/Tree.java
new file mode 100644
index 0000000..49b05dc
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/flowmanager/Tree.java
@@ -0,0 +1,111 @@
+package net.onrc.onos.api.flowmanager;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+
+/**
+ * A directed connected tree topology representation used by TreeFlow.
+ */
+public class Tree extends FlowLinks {
+    Map<Dpid, Set<PortNumber>> ports = new HashMap<Dpid, Set<PortNumber>>();
+    Map<SwitchPort, FlowLink> inLinks = new HashMap<SwitchPort, FlowLink>();
+    Map<SwitchPort, FlowLink> outLinks = new HashMap<SwitchPort, FlowLink>();
+
+    /**
+     * Creates new instance.
+     */
+    public Tree() {
+        super();
+    }
+
+    /**
+     * Creates new instance using Path object.
+     */
+    public Tree(Path path) {
+        super();
+        // TODO implement
+    }
+
+    private void addPort(SwitchPort port) {
+        if (!ports.containsKey(port.dpid())) {
+            ports.put(port.dpid(), new HashSet<PortNumber>());
+        }
+        ports.get(port.dpid()).add(port.port());
+    }
+
+    /**
+     * Adds FlowLink object to this tree.
+     * <p>
+     * This method checks specified FlowLink object to keep this Tree object a
+     * connected tree.
+     *
+     * @param link FlowLink object to be added.
+     * @return true if succeeded, false otherwise.
+     */
+    public boolean addLink(FlowLink link) {
+        if (links.size() > 0) {
+            if (!hasDpid(link.getSrcDpid()) && !hasDpid(link.getDstDpid())) {
+                // no attaching point
+                return false;
+            }
+            if (hasDpid(link.getSrcDpid()) && hasDpid(link.getDstDpid())) {
+                // loop or duplicated paths
+                return false;
+            }
+        }
+
+        if (hasSwitchPort(link.getSrcSwitchPort())
+                || hasSwitchPort(link.getDstSwitchPort())) {
+            // some port has already been occupied by another link
+            return false;
+        }
+
+        links.add(link);
+        addPort(link.getSrcSwitchPort());
+        addPort(link.getDstSwitchPort());
+
+        inLinks.put(link.getDstSwitchPort(), link);
+        outLinks.put(link.getSrcSwitchPort(), link);
+
+        return true;
+    }
+
+    /**
+     * Checks if specified dpid exists in this tree.
+     *
+     * @param dpid DPID to be checked.
+     * @return true if found, false otherwise.
+     */
+    public boolean hasDpid(Dpid dpid) {
+        return ports.containsKey(dpid);
+    }
+
+    /**
+     * Checks if specified switch-port exists in this tree.
+     *
+     * @param port SwitchPort object to be checked.
+     * @return true if found, false otherwise.
+     */
+    public boolean hasSwitchPort(SwitchPort port) {
+        return inLinks.containsKey(port) || outLinks.containsKey(port);
+    }
+
+    @Override
+    public int hashCode() {
+        // TODO think if this is correct.
+        return super.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        // TODO think if this is correct.
+        // - has to check equality using a set, not a list?
+        return super.equals(o);
+    }
+}