diff --git a/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java
index 60be78f..6fbed8a 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java
@@ -1,59 +1,67 @@
 package net.onrc.onos.api.flowmanager;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import net.onrc.onos.api.flowmanager.FlowBatchOperation.Operator;
+import net.onrc.onos.core.matchaction.MatchAction;
 import net.onrc.onos.core.matchaction.MatchActionIdGenerator;
+import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
 import net.onrc.onos.core.matchaction.MatchActionOperations;
 import net.onrc.onos.core.matchaction.MatchActionOperationsIdGenerator;
 import net.onrc.onos.core.matchaction.action.Action;
+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.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
 /**
- * A Flow object expressing the multipoints-to-point tree flow for the packet
- * layer.
+ * A {@link Flow} 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.
+ * NOTE: This class might generate the {@link MatchAction} operations which
+ * includes the MAC address modifications or other the label-switching-like
+ * schemes.
  */
 public class SingleDstTreeFlow extends Flow {
     private final PacketMatch match;
     private final Set<SwitchPort> ingressPorts;
     private final Tree tree;
-    private final List<Action> actions;
+    private final List<Action> egressActions;
 
     /**
      * Creates new instance using Tree object.
-     * <p>
-     * For now, the actions parameter must be the list of a single
-     * ModifyDstMacAction object and a single OutputAction object. But in the
-     * future, the parameter should accept any type of the list of IAction
-     * objects.
      *
      * @param id ID for this object
      * @param match the traffic filter for the tree
      * @param ingressPorts the set of ingress ports of the tree
      * @param tree the Tree object specifying tree topology for this object
-     * @param actions the list of Action objects at the egress edge switch
+     * @param egressActions the list of {@link Action} objects to be executed at
+     *        the egress edge switch
      */
     public SingleDstTreeFlow(FlowId id, PacketMatch match,
-            Collection<SwitchPort> ingressPorts, Tree tree, List<Action> actions) {
+            Collection<SwitchPort> ingressPorts, Tree tree, List<Action> egressActions) {
         super(id);
         this.match = checkNotNull(match);
         this.ingressPorts = ImmutableSet.copyOf(checkNotNull(ingressPorts));
         this.tree = checkNotNull(tree);
-        this.actions = ImmutableList.copyOf(checkNotNull(actions));
+        this.egressActions = ImmutableList.copyOf(checkNotNull(egressActions));
 
         // TODO: check if the tree is a MP2P tree.
-        // TODO: check consistency among ingressPorts, tree, and actions.
+        // TODO: check consistency between ingressPorts and tree topology.
     }
 
     /**
@@ -80,7 +88,7 @@
      * @return the list of actions at the egress edge switch
      */
     public List<Action> getEgressActions() {
-        return actions;
+        return egressActions;
     }
 
     @Override
@@ -92,7 +100,158 @@
     public List<MatchActionOperations> compile(Operator op,
             MatchActionIdGenerator maIdGenerator,
             MatchActionOperationsIdGenerator maoIdGenerator) {
+        switch (op) {
+        case ADD:
+            return compileAddOperation(maIdGenerator, maoIdGenerator);
+        case REMOVE:
+            return compileRemoveOperation();
+        default:
+            throw new UnsupportedOperationException("Unknown operation.");
+        }
+    }
+
+    private MatchAction createMatchAction(SwitchPort port, List<Action> actions,
+            MatchActionIdGenerator maIdGenerator) {
+        checkNotNull(port);
+        checkNotNull(actions);
+
+        return new MatchAction(maIdGenerator.getNewId(), port, getMatch(), actions);
+    }
+
+    /**
+     * Generates MatchAactionOperations at inner ports and at the egress switch.
+     *
+     * @param egressSwitch the egress switch of the tree
+     * @param inPorts a map of a set of incoming ports on each switch in the
+     *        tree
+     * @param outPorts a map of outgoing port on each switch in the tree
+     * @param maIdGenerator ID generator for MatchAction objects
+     * @param maoIdGenerator ID generator for MatchActionOperations objects
+     * @return the operations at inner ports and egress switch
+     */
+    private MatchActionOperations generateFirstAddOperations(
+            Dpid egressSwitch,
+            Map<Dpid, Set<PortNumber>> inPorts,
+            Map<Dpid, PortNumber> outPorts,
+            MatchActionIdGenerator maIdGenerator,
+            MatchActionOperationsIdGenerator maoIdGenerator) {
+        MatchActionOperations firstOps =
+                new MatchActionOperations(maoIdGenerator.getNewId());
+        for (Entry<Dpid, Set<PortNumber>> innerSw : inPorts.entrySet()) {
+            for (PortNumber innerPortNumber : innerSw.getValue()) {
+                SwitchPort innerPort = new SwitchPort(innerSw.getKey(), innerPortNumber);
+                MatchAction ma;
+                if (innerPort.getDpid().equals(egressSwitch)) {
+                    ma = createMatchAction(innerPort, getEgressActions(), maIdGenerator);
+                } else {
+                    PortNumber outputPortNumber = checkNotNull(
+                            outPorts.get(innerPort.getDpid()),
+                            String.format("The tree has no output port at %s",
+                                    innerPort.getDpid()));
+                    ma = createMatchAction(innerPort,
+                            Arrays.asList((Action) new OutputAction(outputPortNumber)),
+                            maIdGenerator);
+                }
+                firstOps.addOperation(new MatchActionOperationEntry(
+                        MatchActionOperations.Operator.ADD, ma));
+            }
+        }
+        return firstOps;
+    }
+
+    /**
+     * Generates MatchActionOperations for ingress switches in the tree.
+     *
+     * @param egressSwitch the egress switch of the tree
+     * @param outPorts a map of outgoing port on each switch in the tree
+     * @param maIdGenerator ID generator for MatchAction objects
+     * @param maoIdGenerator ID generator for MatchActionOperations objects
+     * @return operations at ingress switches in the tree
+     */
+    private MatchActionOperations generateSecondAddOperations(
+            Dpid egressSwitch,
+            Map<Dpid, PortNumber> outPorts,
+            MatchActionIdGenerator maIdGenerator,
+            MatchActionOperationsIdGenerator maoIdGenerator) {
+        MatchActionOperations secondOps =
+                new MatchActionOperations(maoIdGenerator.getNewId());
+        for (SwitchPort port : getIngressPorts()) {
+            PortNumber outputPort = outPorts.get(port.getDpid());
+            if (outputPort == null) {
+                if (port.getDpid().equals(egressSwitch)) {
+                    MatchAction ma = createMatchAction(
+                            port, getEgressActions(), maIdGenerator);
+                    secondOps.addOperation(new MatchActionOperationEntry(
+                            MatchActionOperations.Operator.ADD, ma));
+                } else {
+                    throw new IllegalStateException(String.format(
+                            "The switch %s specified as one of ingress ports "
+                                    + "does not have path to the egress switch.",
+                            port.getDpid()));
+                }
+            } else {
+                MatchAction ma = createMatchAction(port,
+                        Arrays.asList((Action) new OutputAction(outputPort)),
+                        maIdGenerator);
+                secondOps.addOperation(new MatchActionOperationEntry(
+                        MatchActionOperations.Operator.ADD, ma));
+            }
+        }
+        return secondOps;
+    }
+
+    private List<MatchActionOperations> compileAddOperation(
+            MatchActionIdGenerator maIdGenerator,
+            MatchActionOperationsIdGenerator maoIdGenerator) {
+        checkNotNull(tree);
+        checkState(tree.size() > 0, "Tree object has no link.");
+
+        // TODO: check consistency of the tree topology
+
+        // collect input ports and output ports checking consistency
+        Map<Dpid, PortNumber> outPorts = new HashMap<>();
+        Map<Dpid, Set<PortNumber>> inPorts = new HashMap<>();
+        for (FlowLink link : tree) {
+            SwitchPort srcPort = link.getSrcSwitchPort();
+            if (outPorts.containsKey(srcPort.getDpid())) {
+                throw new IllegalStateException(
+                        String.format("Dpid:%s has multiple output ports.",
+                                srcPort.getDpid()));
+            }
+            outPorts.put(srcPort.getDpid(), srcPort.getPortNumber());
+
+            SwitchPort dstPort = link.getDstSwitchPort();
+            Set<PortNumber> inPortNumbers = inPorts.get(dstPort.getDpid());
+            if (inPortNumbers == null) {
+                inPortNumbers = new HashSet<>();
+            }
+            inPortNumbers.add(dstPort.getPortNumber());
+            inPorts.put(dstPort.getDpid(), inPortNumbers);
+        }
+
+        // find the egress switch
+        Set<Dpid> egressSwitches = new HashSet<>(inPorts.keySet());
+        egressSwitches.removeAll(outPorts.keySet());
+        checkState(egressSwitches.size() == 1,
+                "The specified tree is not a single destination tree.");
+        Dpid egressSwitch = egressSwitches.iterator().next();
+
+        MatchActionOperations firstOps = generateFirstAddOperations(
+                egressSwitch, inPorts, outPorts, maIdGenerator, maoIdGenerator);
+        checkState(firstOps.size() > 0,
+                "No operations found for the first set of operations.");
+
+        MatchActionOperations secondOps = generateSecondAddOperations(
+                egressSwitch, outPorts, maIdGenerator, maoIdGenerator);
+        checkState(secondOps.size() > 0,
+                "No operations found for the second set of operations.");
+
+        return Arrays.asList(firstOps, secondOps);
+    }
+
+    private List<MatchActionOperations> compileRemoveOperation() {
         // TODO Auto-generated method stub
-        return null;
+        throw new UnsupportedOperationException(
+                "REMOVE operation is not implemented yet.");
     }
 }
diff --git a/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java b/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
new file mode 100644
index 0000000..1a40013
--- /dev/null
+++ b/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
@@ -0,0 +1,209 @@
+package net.onrc.onos.api.flowmanager;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.api.flowmanager.FlowBatchOperation.Operator;
+import net.onrc.onos.core.matchaction.MatchAction;
+import net.onrc.onos.core.matchaction.MatchActionIdGeneratorWithIdBlockAllocator;
+import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
+import net.onrc.onos.core.matchaction.MatchActionOperations;
+import net.onrc.onos.core.matchaction.MatchActionOperationsIdGeneratorWithIdBlockAllocator;
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
+import net.onrc.onos.core.util.IdBlock;
+import net.onrc.onos.core.util.IdBlockAllocator;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Unit tests for {@link SingleDstTreeFlow} class.
+ */
+public class SingleDstTreeFlowTest {
+    private PacketMatch match;
+    private Set<SwitchPort> ingressPorts;
+    private Tree tree;
+    private List<Action> egressActions;
+    private IdBlockAllocator allocator;
+
+    @Before
+    public void setUp() throws Exception {
+        allocator = createMock(IdBlockAllocator.class);
+        expect(allocator.allocateUniqueIdBlock())
+                .andReturn(new IdBlock(0, 100))
+                .andReturn(new IdBlock(100, 100));
+        replay(allocator);
+
+        PacketMatchBuilder builder = new PacketMatchBuilder();
+        builder.setDstMac(MACAddress.valueOf(54321));
+        match = builder.build();
+
+        ingressPorts = Sets.newHashSet(
+                new SwitchPort(1L, (short) 101),
+                new SwitchPort(1L, (short) 102),
+                new SwitchPort(2L, (short) 103),
+                new SwitchPort(3L, (short) 104),
+                new SwitchPort(5L, (short) 105));
+
+        tree = new Tree();
+        tree.addLink(new FlowLink(
+                new SwitchPort(1L, (short) 10),
+                new SwitchPort(3L, (short) 12)));
+        tree.addLink(new FlowLink(
+                new SwitchPort(2L, (short) 11),
+                new SwitchPort(3L, (short) 13)));
+        tree.addLink(new FlowLink(
+                new SwitchPort(3L, (short) 14),
+                new SwitchPort(5L, (short) 15)));
+        tree.addLink(new FlowLink(
+                new SwitchPort(4L, (short) 16),
+                new SwitchPort(5L, (short) 17)));
+
+        egressActions = Arrays.asList(
+                new ModifyDstMacAction(MACAddress.valueOf(12345)),
+                new OutputAction(PortNumber.uint32(100)));
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Tests if constructor initialized fields properly.
+     */
+    @Test
+    public void testConstructor() {
+        SingleDstTreeFlow treeFlow = new SingleDstTreeFlow(
+                new FlowId(1L), match, ingressPorts, tree, egressActions);
+
+        assertNotNull(treeFlow);
+        assertEquals(new FlowId(1L), treeFlow.getId());
+        assertEquals(match, treeFlow.getMatch());
+        assertEquals(ingressPorts, treeFlow.getIngressPorts());
+        assertEquals(tree, treeFlow.getTree());
+        assertEquals(egressActions, treeFlow.getEgressActions());
+    }
+
+    /**
+     * Generates a list of {@link Action} contains {@link OutputAction} with
+     * specified output port.
+     *
+     * @param outputPort the output port number
+     * @return a list of {@link Action} contains one {@link OutputAction}
+     */
+    private List<Action> outputAction(int outputPort) {
+        return Arrays.asList(
+                (Action) new OutputAction(new PortNumber((short) outputPort)));
+    }
+
+    /**
+     * Tests if compile method with {@link Operator}.ADD generates two
+     * {@link MatchActionOperations} objects and they have
+     * {@link MatchActionOperationEntry} properly based on specified match,
+     * ingress ports, tree, and egress actinos.
+     */
+    @Test
+    public void testCompileWithAddOperation() {
+        SingleDstTreeFlow treeFlow = new SingleDstTreeFlow(
+                new FlowId(1L), match, ingressPorts, tree, egressActions);
+
+        List<MatchActionOperations> maOpsList =
+                treeFlow.compile(Operator.ADD,
+                        new MatchActionIdGeneratorWithIdBlockAllocator(allocator),
+                        new MatchActionOperationsIdGeneratorWithIdBlockAllocator(
+                                allocator));
+
+        assertEquals(2, maOpsList.size());
+
+        MatchActionOperations firstOp = maOpsList.get(0);
+        MatchActionOperations secondOp = maOpsList.get(1);
+
+        assertEquals(4, firstOp.size());
+        Map<SwitchPort, MatchAction> maMap1 = new HashMap<>();
+        for (MatchActionOperationEntry entry : firstOp.getOperations()) {
+            assertEquals(MatchActionOperations.Operator.ADD, entry.getOperator());
+            MatchAction ma = entry.getTarget();
+            maMap1.put(ma.getSwitchPort(), ma);
+        }
+        assertEquals(4, maMap1.size());
+
+        assertEquals(5, secondOp.size());
+        Map<SwitchPort, MatchAction> maMap2 = new HashMap<>();
+        for (MatchActionOperationEntry entry : secondOp.getOperations()) {
+            assertEquals(MatchActionOperations.Operator.ADD, entry.getOperator());
+            MatchAction ma = entry.getTarget();
+            maMap2.put(ma.getSwitchPort(), ma);
+        }
+        assertEquals(5, maMap2.size());
+
+        assertEquals(Sets.newHashSet(
+                new SwitchPort(3L, (short) 12),
+                new SwitchPort(3L, (short) 13),
+                new SwitchPort(5L, (short) 15),
+                new SwitchPort(5L, (short) 17)
+                ), maMap1.keySet());
+
+        MatchAction ma11 = maMap1.get(new SwitchPort(3L, (short) 12));
+        assertEquals(match, ma11.getMatch());
+        assertEquals(outputAction(14), ma11.getActions());
+
+        MatchAction ma12 = maMap1.get(new SwitchPort(3L, (short) 13));
+        assertEquals(match, ma12.getMatch());
+        assertEquals(outputAction(14), ma12.getActions());
+
+        MatchAction ma13 = maMap1.get(new SwitchPort(5L, (short) 15));
+        assertEquals(match, ma13.getMatch());
+        assertEquals(egressActions, ma13.getActions());
+
+        MatchAction ma14 = maMap1.get(new SwitchPort(5L, (short) 17));
+        assertEquals(match, ma14.getMatch());
+        assertEquals(egressActions, ma14.getActions());
+
+        assertEquals(Sets.newHashSet(
+                new SwitchPort(1L, (short) 101),
+                new SwitchPort(1L, (short) 102),
+                new SwitchPort(2L, (short) 103),
+                new SwitchPort(3L, (short) 104),
+                new SwitchPort(5L, (short) 105)
+                ), maMap2.keySet());
+
+        MatchAction ma21 = maMap2.get(new SwitchPort(1L, (short) 101));
+        assertEquals(match, ma21.getMatch());
+        assertEquals(outputAction(10), ma21.getActions());
+
+        MatchAction ma22 = maMap2.get(new SwitchPort(1L, (short) 102));
+        assertEquals(match, ma22.getMatch());
+        assertEquals(outputAction(10), ma22.getActions());
+
+        MatchAction ma23 = maMap2.get(new SwitchPort(2L, (short) 103));
+        assertEquals(match, ma23.getMatch());
+        assertEquals(outputAction(11), ma23.getActions());
+
+        MatchAction ma24 = maMap2.get(new SwitchPort(3L, (short) 104));
+        assertEquals(match, ma24.getMatch());
+        assertEquals(outputAction(14), ma24.getActions());
+
+        MatchAction ma25 = maMap2.get(new SwitchPort(5L, (short) 105));
+        assertEquals(match, ma25.getMatch());
+        assertEquals(egressActions, ma25.getActions());
+    }
+}
