Register flow-manager and match-action related classes to KryoFactory.

- The following classes are now registered and available on KryoFactory:
 -- FlowId
 -- Path
 -- Tree
 -- FlowLink
 -- OpticalPathFlow
 -- PacketPathFlow
 -- SingleDstTreeFlow
 -- PacketMatch
 -- OutputAction
 -- ModifyDstMacAction
 -- ModifyDstMacAction
- This task is a preperation for ONOS-1736 and ONOS-1842.

Change-Id: If438f5175e68672e0ce02f56681c35c3be87f0bc
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/Flow.java b/src/main/java/net/onrc/onos/api/flowmanager/Flow.java
index 202511d..8608adb 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/Flow.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/Flow.java
@@ -18,6 +18,14 @@
     private final FlowId id;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected Flow() {
+        id = null;
+    }
+
+    /**
      * Creates Flow object using specified ID.
      *
      * @param id the ID to be assigned
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/FlowId.java b/src/main/java/net/onrc/onos/api/flowmanager/FlowId.java
index f6d7f8a..b6bb9f0 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/FlowId.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/FlowId.java
@@ -11,6 +11,14 @@
     private final long value;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected FlowId() {
+        value = 0;
+    }
+
+    /**
      * Creates new instance with string ID.
      * <p>
      * This FlowId instance should be generated with {@link FlowIdGenerator}.
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/FlowLink.java b/src/main/java/net/onrc/onos/api/flowmanager/FlowLink.java
index 2fded10..8b8ad75 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/FlowLink.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/FlowLink.java
@@ -1,6 +1,7 @@
 package net.onrc.onos.api.flowmanager;
 
 import com.google.common.base.Objects;
+
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
@@ -16,6 +17,15 @@
     protected SwitchPort dstSwitchPort;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected FlowLink() {
+        srcSwitchPort = null;
+        dstSwitchPort = null;
+    }
+
+    /**
      * Creates new FlowLink object using source/destination switch port pair.
      *
      * @param src The source switch port.
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/OpticalPathFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/OpticalPathFlow.java
index 46bf4e7..51dce43 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/OpticalPathFlow.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/OpticalPathFlow.java
@@ -23,6 +23,14 @@
     private final int lambda;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected OpticalPathFlow() {
+        lambda = 0;
+    }
+
+    /**
      * Constructor.
      *
      * @param id the ID for this new Flow object
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/PacketPathFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/PacketPathFlow.java
index 42cbd65..37820fb 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/PacketPathFlow.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/PacketPathFlow.java
@@ -31,6 +31,16 @@
     private final int idleTimeout;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected PacketPathFlow() {
+        match = null;
+        hardTimeout = 0;
+        idleTimeout = 0;
+    }
+
+    /**
      * Constructor.
      *
      * @param id ID for this new Flow object
diff --git a/src/main/java/net/onrc/onos/api/flowmanager/PathFlow.java b/src/main/java/net/onrc/onos/api/flowmanager/PathFlow.java
index 0cc35ce..943140d 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/PathFlow.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/PathFlow.java
@@ -2,6 +2,7 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.LinkedList;
 import java.util.List;
 
 import net.onrc.onos.core.matchaction.action.Action;
@@ -16,6 +17,16 @@
     private final List<Action> egressActions;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected PathFlow() {
+        ingressPort = null;
+        path = null;
+        egressActions = null;
+    }
+
+    /**
      * Creates the new flow instance.
      *
      * @param id ID for this new PathFlow object
@@ -28,8 +39,8 @@
             PortNumber ingressPort, Path path, List<Action> egressActions) {
         super(id);
         this.ingressPort = checkNotNull(ingressPort);
-        this.path = checkNotNull(path);
-        this.egressActions = checkNotNull(egressActions);
+        this.path = new Path(checkNotNull(path));
+        this.egressActions = new LinkedList<>(checkNotNull(egressActions));
     }
 
     /**
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 6fbed8a..0caef51 100644
--- a/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java
+++ b/src/main/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlow.java
@@ -7,11 +7,15 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
 import net.onrc.onos.api.flowmanager.FlowBatchOperation.Operator;
 import net.onrc.onos.core.matchaction.MatchAction;
 import net.onrc.onos.core.matchaction.MatchActionIdGenerator;
@@ -25,9 +29,6 @@
 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 {@link Flow} object expressing the multipoints-to-point tree flow for the
  * packet layer.
@@ -43,6 +44,17 @@
     private final List<Action> egressActions;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected SingleDstTreeFlow() {
+        match = null;
+        ingressPorts = null;
+        tree = null;
+        egressActions = null;
+    }
+
+    /**
      * Creates new instance using Tree object.
      *
      * @param id ID for this object
@@ -56,9 +68,9 @@
             Collection<SwitchPort> ingressPorts, Tree tree, List<Action> egressActions) {
         super(id);
         this.match = checkNotNull(match);
-        this.ingressPorts = ImmutableSet.copyOf(checkNotNull(ingressPorts));
+        this.ingressPorts = new HashSet<>(checkNotNull(ingressPorts));
         this.tree = checkNotNull(tree);
-        this.egressActions = ImmutableList.copyOf(checkNotNull(egressActions));
+        this.egressActions = new LinkedList<>(checkNotNull(egressActions));
 
         // TODO: check if the tree is a MP2P tree.
         // TODO: check consistency between ingressPorts and tree topology.
@@ -70,7 +82,7 @@
      * @return the ingress ports of the tree
      */
     public Collection<SwitchPort> getIngressPorts() {
-        return ingressPorts;
+        return ImmutableSet.copyOf(ingressPorts);
     }
 
     /**
@@ -88,7 +100,7 @@
      * @return the list of actions at the egress edge switch
      */
     public List<Action> getEgressActions() {
-        return egressActions;
+        return ImmutableList.copyOf(egressActions);
     }
 
     @Override
diff --git a/src/main/java/net/onrc/onos/core/matchaction/action/ModifyDstMacAction.java b/src/main/java/net/onrc/onos/core/matchaction/action/ModifyDstMacAction.java
index 491d986..c39cebe 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/action/ModifyDstMacAction.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/action/ModifyDstMacAction.java
@@ -15,6 +15,14 @@
     private final MACAddress dstMac;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected ModifyDstMacAction() {
+        dstMac = null;
+    }
+
+    /**
      * Constructor.
      *
      * @param dstMac destination MAC address after the modification
diff --git a/src/main/java/net/onrc/onos/core/matchaction/action/ModifySrcMacAction.java b/src/main/java/net/onrc/onos/core/matchaction/action/ModifySrcMacAction.java
index 21ecf32..e679e29 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/action/ModifySrcMacAction.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/action/ModifySrcMacAction.java
@@ -15,6 +15,14 @@
     private final MACAddress srcMac;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected ModifySrcMacAction() {
+        srcMac = null;
+    }
+
+    /**
      * Constructor.
      *
      * @param srcMac source MAC address after the modification
diff --git a/src/main/java/net/onrc/onos/core/matchaction/action/OutputAction.java b/src/main/java/net/onrc/onos/core/matchaction/action/OutputAction.java
index 2453640..10b5aaf 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/action/OutputAction.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/action/OutputAction.java
@@ -15,6 +15,14 @@
     private final PortNumber portNumber;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected OutputAction() {
+        portNumber = null;
+    }
+
+    /**
      * Constructor.
      *
      * @param dstPort The port number of the target output port.
diff --git a/src/main/java/net/onrc/onos/core/matchaction/match/PacketMatch.java b/src/main/java/net/onrc/onos/core/matchaction/match/PacketMatch.java
index c9b1f9d..c49c3d8 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/match/PacketMatch.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/match/PacketMatch.java
@@ -26,6 +26,21 @@
     private final Short dstTcpPort;
 
     /**
+     * Default constructor for Kryo deserialization.
+     */
+    @Deprecated
+    protected PacketMatch() {
+        srcMac = null;
+        dstMac = null;
+        etherType = null;
+        srcIp = null;
+        dstIp = null;
+        ipProto = null;
+        srcTcpPort = null;
+        dstTcpPort = null;
+    }
+
+    /**
      * Package private constructor.
      * <p>
      * This class should be instantiated by the builder.
diff --git a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
index 4341e4a..5fec5b2 100644
--- a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
+++ b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
@@ -16,6 +16,12 @@
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.api.batchoperation.BatchOperationEntry;
+import net.onrc.onos.api.flowmanager.FlowId;
+import net.onrc.onos.api.flowmanager.FlowLink;
+import net.onrc.onos.api.flowmanager.OpticalPathFlow;
+import net.onrc.onos.api.flowmanager.PacketPathFlow;
+import net.onrc.onos.api.flowmanager.SingleDstTreeFlow;
+import net.onrc.onos.api.flowmanager.Tree;
 import net.onrc.onos.api.newintent.AbstractIntent;
 import net.onrc.onos.api.newintent.ConnectivityIntent;
 import net.onrc.onos.api.newintent.IntentEvent;
@@ -38,6 +44,10 @@
 import net.onrc.onos.core.intent.PathIntent;
 import net.onrc.onos.core.intent.ShortestPathIntent;
 import net.onrc.onos.core.intent.runtime.IntentStateList;
+import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
+import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.match.PacketMatch;
 import net.onrc.onos.core.newintent.IntentCompilationResult;
 import net.onrc.onos.core.newintent.PathFlowIntent;
 import net.onrc.onos.core.newintent.SingleDstTreeFlowIntent;
@@ -240,6 +250,21 @@
         kryo.register(TestIntent.class);
         kryo.register(TestSubclassIntent.class);
 
+        // New flow manager related classes
+        kryo.register(FlowId.class);
+        kryo.register(net.onrc.onos.api.flowmanager.Path.class);
+        kryo.register(Tree.class);
+        kryo.register(FlowLink.class);
+        kryo.register(OpticalPathFlow.class);
+        kryo.register(PacketPathFlow.class);
+        kryo.register(SingleDstTreeFlow.class);
+
+        // New match action related classes
+        kryo.register(PacketMatch.class);
+        kryo.register(OutputAction.class);
+        kryo.register(ModifyDstMacAction.class);
+        kryo.register(ModifySrcMacAction.class);
+
         // Host-related classes
         kryo.register(HashSet.class);
         kryo.register(Host.class);
diff --git a/src/test/java/net/onrc/onos/api/flowmanager/OpticalPathFlowTest.java b/src/test/java/net/onrc/onos/api/flowmanager/OpticalPathFlowTest.java
new file mode 100644
index 0000000..4d3c9ba
--- /dev/null
+++ b/src/test/java/net/onrc/onos/api/flowmanager/OpticalPathFlowTest.java
@@ -0,0 +1,59 @@
+package net.onrc.onos.api.flowmanager;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+import net.onrc.onos.core.util.serializers.KryoFactory;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class OpticalPathFlowTest {
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Tests if the object can be serialized and deserialized properly with
+     * Kryo.
+     */
+    @Test
+    public void testKryo() {
+        final FlowId id = new FlowId(1);
+        final PortNumber ingressPort = PortNumber.uint32(12345);
+        final Path path = new Path(Arrays.asList(
+                new FlowLink(new SwitchPort(1, (short) 1), new SwitchPort(2, (short) 2)),
+                new FlowLink(new SwitchPort(2, (short) 1), new SwitchPort(3, (short) 2))
+                ));
+        final List<Action> egressActions =
+                Arrays.asList((Action) new OutputAction(PortNumber.uint32(54321)));
+        final int lambda = 100;
+
+        final OpticalPathFlow originalFlow =
+                new OpticalPathFlow(id, ingressPort, path, egressActions, lambda);
+
+        assertNotNull(originalFlow);
+        byte[] buf = KryoFactory.serialize(originalFlow);
+
+        final OpticalPathFlow obtainedFlow = KryoFactory.deserialize(buf);
+
+        assertEquals(id, obtainedFlow.getId());
+        assertEquals(ingressPort, obtainedFlow.getIngressPortNumber());
+        assertEquals(path, obtainedFlow.getPath());
+        assertEquals(egressActions, obtainedFlow.getEgressActions());
+        assertEquals(lambda, obtainedFlow.getLambda());
+    }
+}
diff --git a/src/test/java/net/onrc/onos/api/flowmanager/PacketPathFlowTest.java b/src/test/java/net/onrc/onos/api/flowmanager/PacketPathFlowTest.java
index 04e2649..45405f6 100644
--- a/src/test/java/net/onrc/onos/api/flowmanager/PacketPathFlowTest.java
+++ b/src/test/java/net/onrc/onos/api/flowmanager/PacketPathFlowTest.java
@@ -25,6 +25,7 @@
 import net.onrc.onos.core.util.IdBlockAllocator;
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
+import net.onrc.onos.core.util.serializers.KryoFactory;
 
 import org.junit.After;
 import org.junit.Before;
@@ -231,4 +232,31 @@
         assertEquals(new OutputAction(PortNumber.uint32(101)),
                 ma4.getActions().get(1));
     }
+
+    /**
+     * Tests if the object can be serialized and deserialized properly with
+     * Kryo.
+     */
+    @Test
+    public void testKryo() {
+        final FlowId id = new FlowId(1);
+        final PortNumber ingressPort = PortNumber.uint32(12345);
+
+        final PacketPathFlow originalFlow =
+                new PacketPathFlow(id, match, ingressPort, pathWith4Switches,
+                        actions, 1000, 100);
+
+        assertNotNull(originalFlow);
+        byte[] buf = KryoFactory.serialize(originalFlow);
+
+        final PacketPathFlow obtainedFlow = KryoFactory.deserialize(buf);
+
+        assertEquals(id, obtainedFlow.getId());
+        assertEquals(match, obtainedFlow.getMatch());
+        assertEquals(ingressPort, obtainedFlow.getIngressPortNumber());
+        assertEquals(pathWith4Switches, obtainedFlow.getPath());
+        assertEquals(actions, obtainedFlow.getEgressActions());
+        assertEquals(1000, obtainedFlow.getHardTimeout());
+        assertEquals(100, obtainedFlow.getIdleTimeout());
+    }
 }
diff --git a/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java b/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
index ae7b4e3..ee65455 100644
--- a/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
+++ b/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
@@ -28,6 +28,7 @@
 import net.onrc.onos.core.util.IdBlockAllocator;
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
+import net.onrc.onos.core.util.serializers.KryoFactory;
 
 import org.junit.After;
 import org.junit.Before;
@@ -206,4 +207,25 @@
         assertEquals(match, ma25.getMatch());
         assertEquals(egressActions, ma25.getActions());
     }
+
+    /**
+     * Tests if the object can be serialized and deserialized properly with
+     * Kryo.
+     */
+    @Test
+    public void testKryo() {
+        SingleDstTreeFlow originalFlow = new SingleDstTreeFlow(
+                new FlowId(1L), match, ingressPorts, tree, egressActions);
+
+        assertNotNull(originalFlow);
+        byte[] buf = KryoFactory.serialize(originalFlow);
+
+        final SingleDstTreeFlow obtainedFlow = KryoFactory.deserialize(buf);
+
+        assertEquals(new FlowId(1L), obtainedFlow.getId());
+        assertEquals(match, obtainedFlow.getMatch());
+        assertEquals(ingressPorts, obtainedFlow.getIngressPorts());
+        assertEquals(tree, obtainedFlow.getTree());
+        assertEquals(egressActions, obtainedFlow.getEgressActions());
+    }
 }