Added more network config validation checks

Change-Id: I9e810206fc3e744c86f854865dfdd9614a84fdf7
diff --git a/core/api/src/main/java/org/onosproject/net/config/Config.java b/core/api/src/main/java/org/onosproject/net/config/Config.java
index bfdacb7..b36b0e2 100644
--- a/core/api/src/main/java/org/onosproject/net/config/Config.java
+++ b/core/api/src/main/java/org/onosproject/net/config/Config.java
@@ -26,6 +26,7 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
+import org.onlab.packet.TpPort;
 import org.onosproject.net.ConnectPoint;
 
 import java.util.Collection;
@@ -397,7 +398,7 @@
      * Indicates whether only the specified fields are present in the backing JSON.
      *
      * @param allowedFields allowed field names
-     * @return true if all allowedFields are present; false otherwise
+     * @return true if only allowedFields are present; false otherwise
      */
     protected boolean hasOnlyFields(String... allowedFields) {
         return hasOnlyFields(object, allowedFields);
@@ -409,7 +410,7 @@
      *
      * @param node node whose fields to check
      * @param allowedFields allowed field names
-     * @return true if all allowedFields are present; false otherwise
+     * @return true if only allowedFields are present; false otherwise
      */
     protected boolean hasOnlyFields(ObjectNode node, String... allowedFields) {
         Set<String> fields = ImmutableSet.copyOf(allowedFields);
@@ -417,6 +418,29 @@
     }
 
     /**
+     * Indicates whether all specified fields are present in the backing JSON.
+     *
+     * @param mandatoryFields mandatory field names
+     * @return true if all mandatory fields are present; false otherwise
+     */
+    protected boolean hasFields(String... mandatoryFields) {
+        return hasFields(object, mandatoryFields);
+    }
+
+    /**
+     * Indicates whether all specified fields are present in a particular
+     * JSON object.
+     *
+     * @param node node whose fields to check
+     * @param mandatoryFields mandatory field names
+     * @return true if all mandatory fields are present; false otherwise
+     */
+    protected boolean hasFields(ObjectNode node, String... mandatoryFields) {
+        Set<String> fields = ImmutableSet.copyOf(mandatoryFields);
+        return Iterators.all(fields.iterator(), f -> !node.path(f).isMissingNode());
+    }
+
+    /**
      * Indicates whether the specified field holds a valid MAC address.
      *
      * @param field    JSON field name
@@ -505,6 +529,34 @@
     }
 
     /**
+     * Indicates whether the specified field holds a valid transport layer port.
+     *
+     * @param field JSON field name
+     * @param presence specifies if field is optional or mandatory
+     * @return true if valid; false otherwise
+     * @throws IllegalArgumentException if field is present, but not valid value
+     */
+    protected boolean isTpPort(String field, FieldPresence presence) {
+        return isTpPort(object, field, presence);
+    }
+
+    /**
+     * Indicates whether the specified field of a particular node holds a valid
+     * transport layer port.
+     *
+     * @param objectNode node from whom to access the field
+     * @param field JSON field name
+     * @param presence specifies if field is optional or mandatory
+     * @return true if valid; false otherwise
+     * @throws IllegalArgumentException if field is present, but not valid value
+     */
+    protected boolean isTpPort(ObjectNode objectNode, String field, FieldPresence presence) {
+        JsonNode node = objectNode.path(field);
+        return isValid(node, presence, node.isNumber() &&
+                TpPort.tpPort(node.asInt()) != null);
+    }
+
+    /**
      * Indicates whether the specified field holds a valid connect point string.
      *
      * @param field    JSON field name
diff --git a/core/api/src/test/java/org/onosproject/net/config/ConfigTest.java b/core/api/src/test/java/org/onosproject/net/config/ConfigTest.java
index 57cc997..84dbca7 100644
--- a/core/api/src/test/java/org/onosproject/net/config/ConfigTest.java
+++ b/core/api/src/test/java/org/onosproject/net/config/ConfigTest.java
@@ -39,6 +39,8 @@
     private static final String DOUBLE = "double";
     private static final String MAC = "mac";
     private static final String IP = "ip";
+    private static final String TP_PORT = "tpPort";
+    private static final String BAD_TP_PORT = "badTpPort";
 
     private final ObjectMapper mapper = new ObjectMapper();
     private final ConfigApplyDelegate delegate = new TestDelegate();
@@ -50,19 +52,27 @@
     public void setUp() {
         json = new ObjectMapper().createObjectNode()
                 .put(TEXT, "foo").put(LONG, 5).put(DOUBLE, 0.5)
-                .put(MAC, "ab:cd:ef:ca:fe:ed").put(IP, "12.34.56.78");
+                .put(MAC, "ab:cd:ef:ca:fe:ed").put(IP, "12.34.56.78")
+                .put(TP_PORT, 65535).put(BAD_TP_PORT, 65536);
         cfg = new TestConfig();
         cfg.init(SUBJECT, KEY, json, mapper, delegate);
     }
 
     @Test
     public void hasOnlyFields() {
-        assertTrue("has unexpected fields", cfg.hasOnlyFields(TEXT, LONG, DOUBLE, MAC, IP));
+        assertTrue("has unexpected fields", cfg.hasOnlyFields(TEXT, LONG, DOUBLE, MAC, IP,
+                                                              TP_PORT, BAD_TP_PORT));
         assertFalse("did not detect unexpected fields", cfg.hasOnlyFields(TEXT, LONG, DOUBLE, MAC));
         assertTrue("is not proper text", cfg.isString(TEXT, MANDATORY));
     }
 
     @Test
+    public void hasFields() {
+        assertTrue("does not have mandatory field", cfg.hasFields(TEXT, LONG, DOUBLE, MAC));
+        assertFalse("did not detect missing field", cfg.hasFields("none"));
+    }
+
+    @Test
     public void isString() {
         assertTrue("is not proper text", cfg.isString(TEXT, MANDATORY));
         assertTrue("is not proper text", cfg.isString(TEXT, MANDATORY, "^f.*"));
@@ -127,6 +137,18 @@
         assertTrue("is not proper ip", cfg.isIpAddress(TEXT, MANDATORY));
     }
 
+    @Test
+    public void isTpPort() {
+        assertTrue("is not proper transport port", cfg.isTpPort(TP_PORT, MANDATORY));
+        assertTrue("is not proper transport port", cfg.isTpPort(TP_PORT, OPTIONAL));
+        assertTrue("is not proper transport port", cfg.isTpPort("none", OPTIONAL));
+        assertFalse("did not detect missing field", cfg.isTpPort("none", MANDATORY));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void badTpPort() {
+        assertTrue("is not proper transport port", cfg.isTpPort(BAD_TP_PORT, MANDATORY));
+    }
 
     // TODO: Add tests for other helper methods