Adding ability to assign roles to elements as part of network config.

Change-Id: I1ecda58e35f0dd30054536024060c67e389d3d73
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
index 7387bcb..d8f0d8e 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
@@ -15,6 +15,11 @@
  */
 package org.onosproject.net.config.basics;
 
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Set;
+
 /**
  * Basic configuration for network elements, e.g. devices, hosts. Such elements
  * can have a friendly name, geo-coordinates (or grid-coordinates),
@@ -68,6 +73,11 @@
     protected static final String OWNER = "owner";
 
     /**
+     * Key for roles.
+     */
+    protected static final String ROLES = "roles";
+
+    /**
      * Threshold for detecting double value is zero.
      */
     protected static final double ZERO_THRESHOLD = Double.MIN_VALUE * 2.0;
@@ -290,6 +300,30 @@
         return (BasicElementConfig) setOrClear(OWNER, owner);
     }
 
+    /**
+     * Returns set of roles assigned to the element.
+     *
+     * @return set of roles
+     */
+    public Set<String> roles() {
+        ImmutableSet.Builder<String> roles = ImmutableSet.builder();
+        if (object.has(ROLES)) {
+            ArrayNode roleNodes = (ArrayNode) object.path(ROLES);
+            roleNodes.forEach(r -> roles.add(r.asText()));
+        }
+        return roles.build();
+    }
+
+    /**
+     * Sets the roles of the element.
+     *
+     * @param roles new roles; null to clear
+     * @return self
+     */
+    public BasicElementConfig roles(Set<String> roles) {
+        return (BasicElementConfig) setOrClear(ROLES, roles);
+    }
+
     @Override
     public boolean isValid() {
         return isValidLength(NAME, NAME_MAX_LENGTH)
diff --git a/core/api/src/test/java/org/onosproject/net/config/basics/BasicElementConfigTest.java b/core/api/src/test/java/org/onosproject/net/config/basics/BasicElementConfigTest.java
index c87d6b1..b116180 100644
--- a/core/api/src/test/java/org/onosproject/net/config/basics/BasicElementConfigTest.java
+++ b/core/api/src/test/java/org/onosproject/net/config/basics/BasicElementConfigTest.java
@@ -17,12 +17,11 @@
 package org.onosproject.net.config.basics;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableSet;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 import static org.onosproject.net.config.basics.BasicElementConfig.ZERO_THRESHOLD;
 
 /**
@@ -35,10 +34,12 @@
     private static final String E1 = "e1";
     private static final String GEO = "geo";
     private static final String GRID = "grid";
+    public static final ImmutableSet<String> ROLES = ImmutableSet.of("spine", "primary");
 
     // concrete subclass of abstract class we are testing
     private static class ElmCfg extends BasicElementConfig<String> {
         ElmCfg() {
+            mapper = MAPPER;
             object = MAPPER.createObjectNode();
         }
 
@@ -150,4 +151,11 @@
         print(cfg);
         assertEquals("not geo", GEO, cfg.locType());
     }
+
+    @Test
+    public void roles() {
+        cfg.roles(ROLES);
+        print(cfg);
+        assertEquals("not roles", ROLES, cfg.roles());
+    }
 }