GUI -- General GUI backend cleanup and bug fixes. Added custom formatters for existing tables, unit test for Enum Formatter, and more glyphs.

Change-Id: I956f1faf6a59e535094d45b811980f822b084be0
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
index 22c1723..70899bc 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
@@ -39,6 +39,8 @@
 import java.util.List;
 import java.util.Set;
 
+import static org.apache.commons.lang.WordUtils.capitalizeFully;
+
 /**
  * Message handler for device view related messages.
  */
@@ -157,7 +159,7 @@
             ObjectNode data = MAPPER.createObjectNode();
 
             data.put(ID, deviceId.toString());
-            data.put(TYPE, device.type().toString());
+            data.put(TYPE, capitalizeFully(device.type().toString()));
             data.put(TYPE_IID, getTypeIconId(device));
             data.put(MFR, device.manufacturer());
             data.put(HW, device.hwVersion());
@@ -190,8 +192,8 @@
             LinkService ls = get(LinkService.class);
             String name = p.annotations().value(AnnotationKeys.PORT_NAME);
 
-            port.put(ID, p.number().toString());
-            port.put(TYPE, p.type().toString());
+            port.put(ID, capitalizeFully(p.number().toString()));
+            port.put(TYPE, capitalizeFully(p.type().toString()));
             port.put(SPEED, p.portSpeed());
             port.put(ENABLED, p.isEnabled());
             port.put(NAME, name != null ? name : "");
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
index 61417cd..c3e01ff 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
@@ -22,14 +22,14 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.flow.FlowEntry;
 import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.Criterion;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.ui.RequestHandler;
 import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.table.CellFormatter;
 import org.onosproject.ui.table.TableModel;
 import org.onosproject.ui.table.TableRequestHandler;
+import org.onosproject.ui.table.cell.EnumFormatter;
 import org.onosproject.ui.table.cell.IntComparator;
 import org.onosproject.ui.table.cell.LongComparator;
 
@@ -37,9 +37,6 @@
 import java.util.List;
 import java.util.Set;
 
-import static org.apache.commons.lang.WordUtils.capitalizeFully;
-
-
 /**
  * Message handler for flow view related messages.
  */
@@ -95,6 +92,10 @@
             tm.setComparator(TIMEOUT, IntComparator.INSTANCE);
             tm.setComparator(PACKETS, LongComparator.INSTANCE);
             tm.setComparator(BYTES, LongComparator.INSTANCE);
+
+            tm.setFormatter(SELECTOR, new SelectorFormatter());
+            tm.setFormatter(TREATMENT, new TreatmentFormatter());
+            tm.setFormatter(STATE, EnumFormatter.INSTANCE);
             return tm;
         }
 
@@ -116,73 +117,50 @@
                 .cell(GROUP_ID, flow.groupId().id())
                 .cell(TABLE_ID, flow.tableId())
                 .cell(PRIORITY, flow.priority())
-                .cell(SELECTOR, getSelectorString(flow))
-                .cell(TREATMENT, getTreatmentString(flow))
+                .cell(SELECTOR, flow)
+                .cell(TREATMENT, flow)
                 .cell(TIMEOUT, flow.timeout())
                 .cell(PERMANENT, flow.isPermanent())
-                .cell(STATE, capitalizeFully(flow.state().toString()))
+                .cell(STATE, flow.state())
                 .cell(PACKETS, flow.packets())
                 .cell(BYTES, flow.bytes());
         }
 
-        private String getSelectorString(FlowEntry f) {
-            String result;
-            TrafficSelector selector = f.selector();
-            Set<Criterion> criteria = selector.criteria();
+        private final class SelectorFormatter implements CellFormatter {
+            @Override
+            public String format(Object value) {
+                FlowEntry flow = (FlowEntry) value;
+                Set<Criterion> criteria = flow.selector().criteria();
 
-            if (criteria.isEmpty()) {
-                result = "(No traffic selectors for this flow)";
-            } else {
-                StringBuilder sb = new StringBuilder("Criteria = ");
+                if (criteria.isEmpty()) {
+                    return "(No traffic selector criteria for this flow)";
+                }
+                StringBuilder sb = new StringBuilder("Criteria: ");
                 for (Criterion c : criteria) {
-                    sb.append(capitalizeFully(c.type().toString())).append(COMMA);
-                }
-                result = removeTrailingComma(sb).toString();
-            }
-            return result;
-        }
-
-        private String getTreatmentString(FlowEntry f) {
-            TrafficTreatment treatment = f.treatment();
-            List<Instruction> deferred = treatment.deferred();
-            List<Instruction> immediate = treatment.immediate();
-            boolean haveDef = !deferred.isEmpty();
-            boolean haveImm = !immediate.isEmpty();
-            boolean both = haveDef && haveImm;
-            boolean neither = !haveDef && !haveImm;
-            String result;
-
-            if (neither) {
-                result = "(No traffic treatment instructions for this flow)";
-            } else {
-                StringBuilder sb = new StringBuilder();
-                addDeferred(sb, deferred);
-                if (both) {
-                    sb.append(COMMA);
-                }
-                addImmediate(sb, immediate);
-                result = sb.toString();
-            }
-            return result;
-        }
-
-        private void addDeferred(StringBuilder sb, List<Instruction> deferred) {
-            if (!deferred.isEmpty()) {
-                sb.append("Deferred instructions = ");
-                for (Instruction i : deferred) {
-                    sb.append(capitalizeFully(i.type().toString())).append(COMMA);
+                    sb.append(c).append(COMMA);
                 }
                 removeTrailingComma(sb);
+
+                return sb.toString();
             }
         }
 
-        private void addImmediate(StringBuilder sb, List<Instruction> immediate) {
-            if (!immediate.isEmpty()) {
-                sb.append("Immediate instructions = ");
-                for (Instruction i : immediate) {
-                    sb.append(capitalizeFully(i.type().toString())).append(COMMA);
+        private final class TreatmentFormatter implements CellFormatter {
+            @Override
+            public String format(Object value) {
+                FlowEntry flow = (FlowEntry) value;
+                List<Instruction> instructions = flow.treatment().allInstructions();
+
+                if (instructions.isEmpty()) {
+                    return "(No traffic treatment instructions for this flow)";
+                }
+                StringBuilder sb = new StringBuilder("Treatment Instructions: ");
+                for (Instruction i : instructions) {
+                    sb.append(i).append(COMMA);
                 }
                 removeTrailingComma(sb);
+
+                return sb.toString();
             }
         }
 
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java
index b61c1b7..17ef891 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java
@@ -123,9 +123,9 @@
 
                 for (GroupBucket b : buckets) {
                     sb.append("Bytes: ")
-                            .append(Long.toString(b.bytes()))
+                            .append(b.bytes())
                             .append(" Packets: ")
-                            .append(Long.toString(b.packets()))
+                            .append(b.packets())
                             .append(" Actions: ")
                             .append(b.treatment().allInstructions())
                             .append(COMMA);
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java
index 643fe40..a42ed90 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java
@@ -17,16 +17,19 @@
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.IpAddress;
 import org.onosproject.net.AnnotationKeys;
 import org.onosproject.net.Host;
 import org.onosproject.net.host.HostService;
 import org.onosproject.ui.RequestHandler;
 import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.table.CellFormatter;
 import org.onosproject.ui.table.TableModel;
 import org.onosproject.ui.table.TableRequestHandler;
 import org.onosproject.ui.table.cell.HostLocationFormatter;
 
 import java.util.Collection;
+import java.util.Set;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 
@@ -72,6 +75,7 @@
         protected TableModel createTableModel() {
             TableModel tm = super.createTableModel();
             tm.setFormatter(LOCATION, HostLocationFormatter.INSTANCE);
+            tm.setFormatter(IPS, new IpSetFormatter());
             return tm;
         }
 
@@ -97,5 +101,30 @@
             return HOST_ICON_PREFIX +
                     (isNullOrEmpty(hostType) ? "endstation" : hostType);
         }
+
+        private final class IpSetFormatter implements CellFormatter {
+            private static final String COMMA = ", ";
+
+            @Override
+            public String format(Object value) {
+                Set<IpAddress> ips = (Set<IpAddress>) value;
+                if (ips.isEmpty()) {
+                    return "(No IP Addresses for this host)";
+                }
+                StringBuilder sb = new StringBuilder();
+                for (IpAddress ip : ips) {
+                    sb.append(ip.toString())
+                            .append(COMMA);
+                }
+                removeTrailingComma(sb);
+                return sb.toString();
+            }
+
+            private StringBuilder removeTrailingComma(StringBuilder sb) {
+                int pos = sb.lastIndexOf(COMMA);
+                sb.delete(pos, sb.length());
+                return sb;
+            }
+        }
     }
 }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java
index 2ab2f08..2af458b 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java
@@ -18,6 +18,7 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.ImmutableSet;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.NetworkResource;
 import org.onosproject.net.flow.criteria.Criterion;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.intent.ConnectivityIntent;
@@ -32,6 +33,7 @@
 import org.onosproject.net.intent.SinglePointToMultiPointIntent;
 import org.onosproject.ui.RequestHandler;
 import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.table.CellFormatter;
 import org.onosproject.ui.table.TableModel;
 import org.onosproject.ui.table.TableRequestHandler;
 import org.onosproject.ui.table.cell.AppIdFormatter;
@@ -86,7 +88,10 @@
         protected TableModel createTableModel() {
             TableModel tm = super.createTableModel();
             tm.setComparator(PRIORITY, IntComparator.INSTANCE);
+
             tm.setFormatter(APP_ID, AppIdFormatter.INSTANCE);
+            tm.setFormatter(RESOURCES, new ResourcesFormatter());
+            tm.setFormatter(DETAILS, new DetailsFormatter());
             return tm;
         }
 
@@ -103,137 +108,168 @@
                 .cell(KEY, intent.key())
                 .cell(TYPE, intent.getClass().getSimpleName())
                 .cell(PRIORITY, intent.priority())
-                .cell(RESOURCES, formatResources(intent))
-                .cell(DETAILS, formatDetails(intent));
+                .cell(RESOURCES, intent)
+                .cell(DETAILS, intent);
         }
 
+        private final class ResourcesFormatter implements CellFormatter {
+            private static final String COMMA = ", ";
 
-        // == TODO: Review -- Move the following code to a helper class?
-        private StringBuilder details = new StringBuilder();
+            @Override
+            public String format(Object value) {
+                Intent intent = (Intent) value;
+                Collection<NetworkResource> resources = intent.resources();
+                if (resources.isEmpty()) {
+                    return "(No resources for this intent)";
+                }
+                StringBuilder sb = new StringBuilder("Resources: ");
+                for (NetworkResource nr : resources) {
+                    sb.append(nr).append(COMMA);
+                }
+                removeTrailingComma(sb);
 
-        private void appendMultiPointsDetails(Set<ConnectPoint> points) {
-            for (ConnectPoint point : points) {
-                details.append(point.elementId())
+                return sb.toString();
+            }
+
+            private StringBuilder removeTrailingComma(StringBuilder sb) {
+                int pos = sb.lastIndexOf(COMMA);
+                sb.delete(pos, sb.length());
+                return sb;
+            }
+        }
+
+        private final class DetailsFormatter implements CellFormatter {
+            @Override
+            public String format(Object value) {
+                return formatDetails((Intent) value, new StringBuilder()).toString();
+            }
+
+            private StringBuilder formatDetails(Intent intent, StringBuilder sb) {
+                if (intent instanceof ConnectivityIntent) {
+                    buildConnectivityDetails((ConnectivityIntent) intent, sb);
+                }
+
+                if (intent instanceof HostToHostIntent) {
+                    buildHostToHostDetails((HostToHostIntent) intent, sb);
+
+                } else if (intent instanceof PointToPointIntent) {
+                    buildPointToPointDetails((PointToPointIntent) intent, sb);
+
+                } else if (intent instanceof MultiPointToSinglePointIntent) {
+                    buildMPToSPDetails((MultiPointToSinglePointIntent) intent, sb);
+
+                } else if (intent instanceof SinglePointToMultiPointIntent) {
+                    buildSPToMPDetails((SinglePointToMultiPointIntent) intent, sb);
+
+                } else if (intent instanceof PathIntent) {
+                    buildPathDetails((PathIntent) intent, sb);
+
+                } else if (intent instanceof LinkCollectionIntent) {
+                    buildLinkConnectionDetails((LinkCollectionIntent) intent, sb);
+                }
+
+                if (sb.length() == 0) {
+                    sb.append("(No details for this intent)");
+                } else {
+                    sb.insert(0, "Details: ");
+                }
+                return sb;
+            }
+
+            private void appendMultiPointsDetails(Set<ConnectPoint> points,
+                                                  StringBuilder sb) {
+                for (ConnectPoint point : points) {
+                    sb.append(point.elementId())
+                            .append('/')
+                            .append(point.port())
+                            .append(' ');
+                }
+            }
+
+            private void buildConnectivityDetails(ConnectivityIntent intent,
+                                                  StringBuilder sb) {
+                Set<Criterion> criteria = intent.selector().criteria();
+                List<Instruction> instructions = intent.treatment().allInstructions();
+                List<Constraint> constraints = intent.constraints();
+
+                if (!criteria.isEmpty()) {
+                    sb.append("Selector: ").append(criteria);
+                }
+                if (!instructions.isEmpty()) {
+                    sb.append("Treatment: ").append(instructions);
+                }
+                if (constraints != null && !constraints.isEmpty()) {
+                    sb.append("Constraints: ").append(constraints);
+                }
+            }
+
+            private void buildHostToHostDetails(HostToHostIntent intent,
+                                                StringBuilder sb) {
+                sb.append(" Host 1: ")
+                        .append(intent.one())
+                        .append(", Host 2: ")
+                        .append(intent.two());
+            }
+
+            private void buildPointToPointDetails(PointToPointIntent intent,
+                                                  StringBuilder sb) {
+                ConnectPoint ingress = intent.ingressPoint();
+                ConnectPoint egress = intent.egressPoint();
+                sb.append(" Ingress: ")
+                        .append(ingress.elementId())
                         .append('/')
-                        .append(point.port())
+                        .append(ingress.port())
+
+                        .append(", Egress: ")
+                        .append(egress.elementId())
+                        .append('/')
+                        .append(egress.port())
                         .append(' ');
             }
-        }
 
-        private void buildConnectivityDetails(ConnectivityIntent intent) {
-            Set<Criterion> criteria = intent.selector().criteria();
-            List<Instruction> instructions = intent.treatment().allInstructions();
-            List<Constraint> constraints = intent.constraints();
+            private void buildMPToSPDetails(MultiPointToSinglePointIntent intent,
+                                            StringBuilder sb) {
+                ConnectPoint egress = intent.egressPoint();
 
-            if (!criteria.isEmpty()) {
-                details.append("selector=").append(criteria);
-            }
-            if (!instructions.isEmpty()) {
-                details.append("treatment=").append(instructions);
-            }
-            if (constraints != null && !constraints.isEmpty()) {
-                details.append("constraints=").append(constraints);
-            }
-        }
+                sb.append(" Ingress=");
+                appendMultiPointsDetails(intent.ingressPoints(), sb);
 
-        private void buildHostToHostDetails(HostToHostIntent intent) {
-            details.append(" host1=")
-                    .append(intent.one())
-                    .append(", host2=")
-                    .append(intent.two());
-        }
-
-        private void buildPointToPointDetails(PointToPointIntent intent) {
-            ConnectPoint ingress = intent.ingressPoint();
-            ConnectPoint egress = intent.egressPoint();
-            details.append(" ingress=")
-                    .append(ingress.elementId())
-                    .append('/')
-                    .append(ingress.port())
-
-                    .append(", egress=")
-                    .append(egress.elementId())
-                    .append('/')
-                    .append(egress.port())
-                    .append(' ');
-        }
-
-        private void buildMPToSPDetails(MultiPointToSinglePointIntent intent) {
-            ConnectPoint egress = intent.egressPoint();
-
-            details.append(" ingress=");
-            appendMultiPointsDetails(intent.ingressPoints());
-
-            details.append(", egress=")
-                    .append(egress.elementId())
-                    .append('/')
-                    .append(egress.port())
-                    .append(' ');
-        }
-
-        private void buildSPToMPDetails(SinglePointToMultiPointIntent intent) {
-            ConnectPoint ingress = intent.ingressPoint();
-
-            details.append(" ingress=")
-                    .append(ingress.elementId())
-                    .append('/')
-                    .append(ingress.port())
-                    .append(", egress=");
-
-            appendMultiPointsDetails(intent.egressPoints());
-        }
-
-        private void buildPathDetails(PathIntent intent) {
-            details.append(" path=")
-                    .append(intent.path().links())
-                    .append(", cost=")
-                    .append(intent.path().cost());
-        }
-
-        private void buildLinkConnectionDetails(LinkCollectionIntent intent) {
-            details.append(" links=")
-                    .append(intent.links())
-                    .append(", egress=");
-
-            appendMultiPointsDetails(intent.egressPoints());
-        }
-
-        private String formatDetails(Intent intent) {
-            if (intent instanceof ConnectivityIntent) {
-                buildConnectivityDetails((ConnectivityIntent) intent);
+                sb.append(", Egress=")
+                        .append(egress.elementId())
+                        .append('/')
+                        .append(egress.port())
+                        .append(' ');
             }
 
-            if (intent instanceof HostToHostIntent) {
-                buildHostToHostDetails((HostToHostIntent) intent);
+            private void buildSPToMPDetails(SinglePointToMultiPointIntent intent,
+                                            StringBuilder sb) {
+                ConnectPoint ingress = intent.ingressPoint();
 
-            } else if (intent instanceof PointToPointIntent) {
-                buildPointToPointDetails((PointToPointIntent) intent);
+                sb.append(" Ingress=")
+                        .append(ingress.elementId())
+                        .append('/')
+                        .append(ingress.port())
+                        .append(", Egress=");
 
-            } else if (intent instanceof MultiPointToSinglePointIntent) {
-                buildMPToSPDetails((MultiPointToSinglePointIntent) intent);
-
-            } else if (intent instanceof SinglePointToMultiPointIntent) {
-                buildSPToMPDetails((SinglePointToMultiPointIntent) intent);
-
-            } else if (intent instanceof PathIntent) {
-                buildPathDetails((PathIntent) intent);
-
-            } else if (intent instanceof LinkCollectionIntent) {
-                buildLinkConnectionDetails((LinkCollectionIntent) intent);
+                appendMultiPointsDetails(intent.egressPoints(), sb);
             }
 
-            if (details.length() == 0) {
-                details.append("(No details for this intent)");
-            } else {
-                details.insert(0, "Details: ");
+            private void buildPathDetails(PathIntent intent, StringBuilder sb) {
+                sb.append(" path=")
+                        .append(intent.path().links())
+                        .append(", cost=")
+                        .append(intent.path().cost());
             }
-            return details.toString();
-        }
 
-        private String formatResources(Intent intent) {
-            return (intent.resources().isEmpty() ?
-                    "(No resources for this intent)" :
-                    "Resources: " + intent.resources());
+            private void buildLinkConnectionDetails(LinkCollectionIntent intent,
+                                                    StringBuilder sb) {
+                sb.append(" links=")
+                        .append(intent.links())
+                        .append(", egress=");
+
+                appendMultiPointsDetails(intent.egressPoints(), sb);
+            }
+
         }
     }
 }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java
index e361563..f594a92 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java
@@ -28,6 +28,7 @@
 import org.onosproject.ui.table.TableModel;
 import org.onosproject.ui.table.TableRequestHandler;
 import org.onosproject.ui.table.cell.ConnectPointFormatter;
+import org.onosproject.ui.table.cell.EnumFormatter;
 
 import java.util.Collection;
 import java.util.Map;
@@ -83,6 +84,7 @@
             TableModel tm = super.createTableModel();
             tm.setFormatter(ONE, ConnectPointFormatter.INSTANCE);
             tm.setFormatter(TWO, ConnectPointFormatter.INSTANCE);
+            tm.setFormatter(TYPE, EnumFormatter.INSTANCE);
             return tm;
         }
 
@@ -113,7 +115,7 @@
             if (link.two != null && link.two.type() != link.one.type()) {
                 sb.append(" / ").append(link.two.type());
             }
-            return sb.toString().toLowerCase();
+            return sb.toString();
         }
 
         private String linkState(BiLink link) {