MastershipEvent carries RoleInfo as a subject

Change-Id: I8f850ad1f21bfbdc23fedda1a53f4ccedb1b8d32
diff --git a/cli/src/main/java/org/onlab/onos/cli/RolesCommand.java b/cli/src/main/java/org/onlab/onos/cli/RolesCommand.java
index b81a0c2..55f59d5 100644
--- a/cli/src/main/java/org/onlab/onos/cli/RolesCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/RolesCommand.java
@@ -21,7 +21,7 @@
         description = "Lists mastership roles of nodes for each device.")
 public class RolesCommand extends AbstractShellCommand {
 
-    private static final String FMT_HDR = "%s: master=%s, standbys=%s";
+    private static final String FMT_HDR = "%s: master=%s, standbys=[ %s]";
 
     @Override
     protected void execute() {
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/RoleInfo.java b/core/api/src/main/java/org/onlab/onos/cluster/RoleInfo.java
index 45b96ab..767884d 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/RoleInfo.java
+++ b/core/api/src/main/java/org/onlab/onos/cluster/RoleInfo.java
@@ -3,10 +3,11 @@
 import java.util.List;
 import java.util.Objects;
 
+import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableList;
 
 /**
- * A container for detailed role information for a device,
+ * An immutable container for role information for a device,
  * within the current cluster. Role attributes include current
  * master and a preference-ordered list of backup nodes.
  */
@@ -52,12 +53,9 @@
 
     @Override
     public String toString() {
-        final StringBuilder builder = new StringBuilder();
-        builder.append("master:").append(master).append(",");
-        builder.append("backups:");
-        for (NodeId n : backups) {
-            builder.append(" ").append(n);
-        }
-        return builder.toString();
+        return MoreObjects.toStringHelper(this.getClass())
+            .add("master", master)
+            .add("backups", backups)
+            .toString();
     }
 }
diff --git a/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
index 9f75fc4..dcb2d95 100644
--- a/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
@@ -1,6 +1,7 @@
 package org.onlab.onos.mastership;
 
 import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.cluster.RoleInfo;
 import org.onlab.onos.event.AbstractEvent;
 import org.onlab.onos.net.DeviceId;
 
@@ -9,9 +10,8 @@
  */
 public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceId> {
 
-    //do we worry about explicitly setting slaves/equals? probably not,
-    //to keep it simple
-    NodeId node;
+    //Contains master and standby information.
+    RoleInfo roleInfo;
 
     /**
      * Type of mastership events.
@@ -29,16 +29,16 @@
     }
 
     /**
-     * Creates an event of a given type and for the specified device, master,
-     * and the current time.
+     * Creates an event of a given type and for the specified device,
+     * role information, and the current time.
      *
      * @param type   device event type
      * @param device event device subject
-     * @param node master ID subject
+     * @param info mastership role information subject
      */
-    public MastershipEvent(Type type, DeviceId device, NodeId node) {
+    public MastershipEvent(Type type, DeviceId device, RoleInfo info) {
         super(type, device);
-        this.node = node;
+        this.roleInfo = info;
     }
 
     /**
@@ -50,9 +50,9 @@
      * @param master master ID subject
      * @param time   occurrence time
      */
-    public MastershipEvent(Type type, DeviceId device, NodeId master, long time) {
+    public MastershipEvent(Type type, DeviceId device, RoleInfo info, long time) {
         super(type, device, time);
-        this.node = master;
+        this.roleInfo = info;
     }
 
     /**
@@ -63,7 +63,17 @@
      *
      * @return node ID as a subject
      */
+    //XXX to-be removed - or keep for convenience?
     public NodeId node() {
-        return node;
+        return roleInfo.master();
+    }
+
+    /**
+     * Returns the current role state for the subject.
+     *
+     * @return RoleInfo associated with Device ID subject
+     */
+    public RoleInfo roleInfo() {
+        return roleInfo;
     }
 }
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/flow/impl/ReplicaInfoManagerTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/flow/impl/ReplicaInfoManagerTest.java
index 105e37b..e2a3ddf 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/flow/impl/ReplicaInfoManagerTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/flow/impl/ReplicaInfoManagerTest.java
@@ -5,6 +5,7 @@
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.LinkedList;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -12,6 +13,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.cluster.RoleInfo;
 import org.onlab.onos.event.AbstractListenerRegistry;
 import org.onlab.onos.event.DefaultEventSinkRegistry;
 import org.onlab.onos.event.Event;
@@ -87,7 +89,8 @@
         service.addListener(new MasterNodeCheck(latch, DID1, NID1));
 
         // fake MastershipEvent
-        eventDispatcher.post(new MastershipEvent(Type.MASTER_CHANGED, DID1, NID1));
+        eventDispatcher.post(new MastershipEvent(Type.MASTER_CHANGED, DID1,
+                new RoleInfo(NID1, new LinkedList<NodeId>())));
 
         assertTrue(latch.await(1, TimeUnit.SECONDS));
     }
diff --git a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
index aaf056c..74ca8cd 100644
--- a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
+++ b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
@@ -136,13 +136,13 @@
                     rv.reassign(nodeId, STANDBY, NONE);
                     roleMap.put(deviceId, rv);
                     updateTerm(deviceId);
-                    return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
+                    return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo());
                 case NONE:
                     rv.add(MASTER, nodeId);
                     rv.reassign(nodeId, STANDBY, NONE);
                     roleMap.put(deviceId, rv);
                     updateTerm(deviceId);
-                    return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
+                    return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo());
                 default:
                     log.warn("unknown Mastership Role {}", role);
                     return null;
@@ -306,7 +306,7 @@
             roleMap.put(deviceId, rv);
             Integer term = terms.get(deviceId);
             terms.put(deviceId, ++term);
-            return new MastershipEvent(MASTER_CHANGED, deviceId, backup);
+            return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo());
         }
     }
 
@@ -373,7 +373,7 @@
                 return;
             }
             notifyDelegate(new MastershipEvent(
-                    MASTER_CHANGED, event.getKey(), event.getValue().get(MASTER)));
+                    MASTER_CHANGED, event.getKey(), event.getValue().roleInfo()));
         }
 
         @Override
diff --git a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java
index 1ccee6b..c156143 100644
--- a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java
+++ b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java
@@ -10,6 +10,9 @@
 import org.onlab.onos.cluster.RoleInfo;
 import org.onlab.onos.net.MastershipRole;
 
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+
 /**
  * A structure that holds node mastership roles associated with a
  * {@link DeviceId}. This structure needs to be locked through IMap.
@@ -109,14 +112,10 @@
 
     @Override
     public String toString() {
-        final StringBuilder builder = new StringBuilder();
+        ToStringHelper helper = MoreObjects.toStringHelper(this.getClass());
         for (Map.Entry<MastershipRole, List<NodeId>> el : value.entrySet()) {
-            builder.append(el.getKey().toString()).append(": [");
-            for (NodeId n : el.getValue()) {
-                builder.append(n);
-            }
-            builder.append("]\n");
+            helper.add(el.getKey().toString(), el.getValue());
         }
-        return builder.toString();
+        return helper.toString();
     }
 }
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
index fe34959..709c95a 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
@@ -29,6 +29,8 @@
 import org.onlab.packet.IpPrefix;
 import org.slf4j.Logger;
 
+import com.google.common.collect.Lists;
+
 import static org.onlab.onos.mastership.MastershipEvent.Type.*;
 
 /**
@@ -89,7 +91,8 @@
             }
         }
 
-        return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
+        return new MastershipEvent(MASTER_CHANGED, deviceId,
+                new RoleInfo(nodeId, Lists.newLinkedList(backups)));
     }
 
     @Override
@@ -196,7 +199,8 @@
                     } else {
                         masterMap.put(deviceId, backup);
                         termMap.get(deviceId).incrementAndGet();
-                        return new MastershipEvent(MASTER_CHANGED, deviceId, backup);
+                        return new MastershipEvent(MASTER_CHANGED, deviceId,
+                                new RoleInfo(backup, Lists.newLinkedList(backups)));
                     }
                 case STANDBY:
                 case NONE: