ONOS-5411: BasicRegionConfig and BasicUiTopoLayoutConfig.
- added setters to BasicRegionConfig.
- implemented BasicUiTopoLayoutConfig.
- also furnished unit tests.
Change-Id: I965ce5817c7f36b56e634a318989447071130c2a
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 1b57cdb..a3824c8 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
@@ -29,6 +29,7 @@
import org.onosproject.net.ConnectPoint;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
@@ -86,7 +87,7 @@
* @param delegate delegate context, or null for detached configs.
*/
public final void init(S subject, String key, JsonNode node, ObjectMapper mapper,
- ConfigApplyDelegate delegate) {
+ ConfigApplyDelegate delegate) {
this.subject = checkNotNull(subject, "Subject cannot be null");
this.key = key;
this.node = checkNotNull(node, "Node cannot be null");
@@ -206,7 +207,7 @@
/**
* Clears the specified property.
*
- * @param name property name
+ * @param name property name
* @return self
*/
protected Config<S> clear(String name) {
@@ -364,10 +365,10 @@
/**
* Gets the specified array property as a list of items.
*
- * @param name property name
- * @param function mapper from string to item
+ * @param name property name
+ * @param function mapper from string to item
* @param defaultValue default value if property not set
- * @param <T> type of item
+ * @param <T> type of item
* @return list of items
*/
protected <T> List<T> getList(String name, Function<String, T> function, List<T> defaultValue) {
@@ -402,6 +403,33 @@
}
/**
+ * Returns true if this config contains a field with the given name.
+ *
+ * @param name the field name
+ * @return true if field is present, false otherwise
+ */
+ protected boolean hasField(String name) {
+ return hasField(object, name);
+ }
+
+ /**
+ * Returns true if the given node contains a field with the given name.
+ *
+ * @param node the node to examine
+ * @param name the name to look for
+ * @return true if the node has a field with the given name, false otherwise
+ */
+ protected boolean hasField(ObjectNode node, String name) {
+ Iterator<String> fnames = node.fieldNames();
+ while (fnames.hasNext()) {
+ if (fnames.next().equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Indicates whether only the specified fields are present in the backing JSON.
*
* @param allowedFields allowed field names
@@ -415,7 +443,7 @@
* Indicates whether only the specified fields are present in a particular
* JSON object.
*
- * @param node node whose fields to check
+ * @param node node whose fields to check
* @param allowedFields allowed field names
* @return true if only allowedFields are present; false otherwise
*/
@@ -443,7 +471,7 @@
* Indicates whether all specified fields are present in a particular
* JSON object.
*
- * @param node node whose fields to check
+ * @param node node whose fields to check
* @param mandatoryFields mandatory field names
* @return true if all mandatory fields are present; false otherwise
*/
@@ -474,8 +502,8 @@
* MAC address.
*
* @param objectNode JSON node
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -502,9 +530,9 @@
* Indicates whether the specified field of a particular node holds a valid
* IP address.
*
- * @param objectNode node from whom to access the field
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
+ * @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 InvalidFieldException if the field is present but not valid
*/
@@ -531,9 +559,9 @@
* Indicates whether the specified field of a particular node holds a valid
* IP prefix.
*
- * @param objectNode node from whom to access the field
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
+ * @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 InvalidFieldException if the field is present but not valid
*/
@@ -547,7 +575,7 @@
/**
* Indicates whether the specified field holds a valid transport layer port.
*
- * @param field JSON field name
+ * @param field JSON field name
* @param presence specifies if field is optional or mandatory
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
@@ -561,8 +589,8 @@
* 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
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -590,8 +618,8 @@
* connect point string.
*
* @param objectNode JSON node
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -620,9 +648,9 @@
* string value.
*
* @param objectNode JSON node
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
- * @param pattern optional regex pattern
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @param pattern optional regex pattern
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -655,9 +683,9 @@
* valid number.
*
* @param objectNode JSON object
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
- * @param minMax optional min/max values
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @param minMax optional min/max values
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -692,9 +720,9 @@
* integer.
*
* @param objectNode JSON node
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
- * @param minMax optional min/max values
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @param minMax optional min/max values
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -729,9 +757,9 @@
* decimal number.
*
* @param objectNode JSON node
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
- * @param minMax optional min/max values
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @param minMax optional min/max values
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -765,8 +793,8 @@
* boolean value.
*
* @param objectNode JSON object node
- * @param field JSON field name
- * @param presence specifies if field is optional or mandatory
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
* @return true if valid; false otherwise
* @throws InvalidFieldException if the field is present but not valid
*/
@@ -794,9 +822,9 @@
* Indicates whether a field in the node is present and of correct value or
* not mandatory and absent.
*
- * @param objectNode JSON object node containing field to validate
- * @param field name of field to validate
- * @param presence specified if field is optional or mandatory
+ * @param objectNode JSON object node containing field to validate
+ * @param field name of field to validate
+ * @param presence specified if field is optional or mandatory
* @param validationFunction function which can be used to verify if the
* node has the correct value
* @return true if the field is as expected
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java
index 200b375..2d15fa5 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java
@@ -16,24 +16,55 @@
package org.onosproject.net.config.basics;
+import com.google.common.base.MoreObjects;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.Config;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;
import java.util.List;
+import java.util.Set;
/**
* Basic configuration for network regions.
*/
public final class BasicRegionConfig extends Config<RegionId> {
+ private static final String NAME = "name";
private static final String TYPE = "type";
private static final String DEVICES = "devices";
@Override
public boolean isValid() {
- return hasOnlyFields(TYPE, DEVICES);
+ return hasOnlyFields(NAME, TYPE, DEVICES);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("name", name())
+ .add("type", type())
+ .add("devices", devices())
+ .toString();
+ }
+
+ /**
+ * Returns the region name.
+ *
+ * @return the region name
+ */
+ public String name() {
+ return get(NAME, null);
+ }
+
+ /**
+ * Sets the name of this region.
+ *
+ * @param name name of region, or null to unset
+ * @return the config of the region
+ */
+ public BasicRegionConfig name(String name) {
+ return (BasicRegionConfig) setOrClear(NAME, name);
}
/**
@@ -41,7 +72,7 @@
*
* @return the region type
*/
- public Region.Type getType() {
+ public Region.Type type() {
String t = get(TYPE, null);
return t == null ? null : regionTypeFor(t);
}
@@ -55,13 +86,32 @@
}
/**
+ * Sets the region type.
+ *
+ * @param type the region type, or null to unset
+ * @return the config of the region
+ */
+ public BasicRegionConfig type(Region.Type type) {
+ String t = type == null ? null : type.name().toLowerCase();
+ return (BasicRegionConfig) setOrClear(TYPE, t);
+ }
+
+ /**
* Returns the identities of the devices in this region.
*
* @return list of device identifiers
*/
- public List<DeviceId> getDevices() {
- return getList(DEVICES, DeviceId::deviceId);
+ public List<DeviceId> devices() {
+ return object.has(DEVICES) ? getList(DEVICES, DeviceId::deviceId) : null;
}
- // TODO: implement setters
+ /**
+ * Sets the devices of this region.
+ *
+ * @param devices the device identifiers, or null to unset
+ * @return the config of the region
+ */
+ public BasicRegionConfig devices(Set<DeviceId> devices) {
+ return (BasicRegionConfig) setOrClear(DEVICES, devices);
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java
index 5ba8093..e75df69 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java
@@ -16,7 +16,9 @@
package org.onosproject.net.config.basics;
+import com.google.common.base.MoreObjects;
import org.onosproject.net.config.Config;
+import org.onosproject.net.config.InvalidFieldException;
import org.onosproject.net.region.RegionId;
import org.onosproject.ui.model.topo.UiTopoLayoutId;
@@ -24,37 +26,206 @@
/**
* Basic configuration for UI topology layouts.
+ * <p>
+ * Note that a layout configuration will include information about
+ * which background map (or sprites definition) to use, and at what
+ * relative scale and offset.
+ * <p>
+ * Note also that the {@code geomap} and {@code sprites} fields are
+ * mutually exclusive.
*/
public class BasicUiTopoLayoutConfig extends Config<UiTopoLayoutId> {
- private static final String REGION = "region";
- private static final String PARENT = "parent";
+ static final String REGION = "region";
+ static final String PARENT = "parent";
+ static final String GEOMAP = "geomap";
+ static final String SPRITES = "sprites";
+ static final String SCALE = "scale";
+ static final String OFFSET_X = "offsetX";
+ static final String OFFSET_Y = "offsetY";
+
+ static final double DEFAULT_SCALE = 1.0;
+ static final double DEFAULT_OFFSET = 0.0;
+
+ private static final String E_GEOMAP_SPRITE =
+ "Layout cannot have both geomap and sprites defined";
+ private static final String E_SPRITES_ALREADY_SET =
+ "Can't set geomap when sprites is already set";
+ private static final String E_GEOMAP_ALREADY_SET =
+ "Can't set sprites when geomap is already set";
@Override
public boolean isValid() {
- return hasOnlyFields(REGION, PARENT);
+ if (object.has(GEOMAP) && object.has(SPRITES)) {
+ throw new InvalidFieldException(GEOMAP, E_GEOMAP_SPRITE);
+ }
+
+ return hasOnlyFields(REGION, PARENT, GEOMAP, SPRITES, SCALE,
+ OFFSET_X, OFFSET_Y);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("region", region())
+ .add("parent", parent())
+ .add("geomap", geomap())
+ .add("sprites", sprites())
+ .add("scale", scale())
+ .add("offX", offsetX())
+ .add("offY", offsetY())
+ .toString();
}
/**
* Returns the identifier of the backing region. This will be
* null if there is no backing region.
*
- * @return backing region identity
+ * @return backing region identifier
*/
- public RegionId getRegion() {
+ public RegionId region() {
String r = get(REGION, null);
return r == null ? null : regionId(r);
}
/**
+ * Sets the identifier of the backing region.
+ *
+ * @param id backing region identifier, or null to unset
+ * @return config for UI topology layout
+ */
+ public BasicUiTopoLayoutConfig region(RegionId id) {
+ setOrClear(REGION, id == null ? null : id.id());
+ return this;
+ }
+
+ /**
* Returns the identifier of the parent layout.
*
* @return layout identifier of parent
*/
- public UiTopoLayoutId getParent() {
+ public UiTopoLayoutId parent() {
String p = get(PARENT, null);
return p == null ? UiTopoLayoutId.DEFAULT_ID : UiTopoLayoutId.layoutId(p);
}
- // TODO: implement setters
+ /**
+ * Sets the identifier of the parent layout.
+ *
+ * @param id parent ui-topo-layout identifier, or null to unset
+ * @return config for UI topology layout
+ */
+ public BasicUiTopoLayoutConfig parent(UiTopoLayoutId id) {
+ setOrClear(PARENT, id == null ? null : id.id());
+ return this;
+ }
+
+ /**
+ * Returns the identifier for the background geo-map.
+ *
+ * @return geo-map identifier
+ */
+ public String geomap() {
+ return get(GEOMAP, null);
+ }
+
+ /**
+ * Sets the name of the geomap (topojson file) to use for this layout.
+ *
+ * @param geomap geomap name
+ * @return config for UI topology layout
+ * @throws InvalidFieldException if the sprites field is already set
+ */
+ public BasicUiTopoLayoutConfig geomap(String geomap) {
+ if (hasField(SPRITES)) {
+ throw new InvalidFieldException(GEOMAP, E_SPRITES_ALREADY_SET);
+ }
+ setOrClear(GEOMAP, geomap);
+ return this;
+ }
+
+ /**
+ * Returns the identifier for the background sprites.
+ *
+ * @return sprites identifier
+ */
+ public String sprites() {
+ return get(SPRITES, null);
+ }
+
+ /**
+ * Sets the name of the sprites definition to use for this layout.
+ *
+ * @param sprites sprites definition name
+ * @return config for UI topology layout
+ * @throws InvalidFieldException if the geomap field is already set
+ */
+ public BasicUiTopoLayoutConfig sprites(String sprites) {
+ if (hasField(GEOMAP)) {
+ throw new InvalidFieldException(GEOMAP, E_GEOMAP_ALREADY_SET);
+ }
+ setOrClear(SPRITES, sprites);
+ return this;
+ }
+
+ /**
+ * Returns the scale for the geomap / sprites background.
+ *
+ * @return scale of background map / diagram
+ */
+ public double scale() {
+ return get(SCALE, DEFAULT_SCALE);
+ }
+
+ /**
+ * Sets the scale for the geomap / sprites background.
+ *
+ * @param scale the scale to set
+ * @return config for UI topology layout
+ */
+ public BasicUiTopoLayoutConfig scale(Double scale) {
+ setOrClear(SCALE, scale);
+ return this;
+ }
+
+ /**
+ * Returns the x-offset for the geomap / sprites background.
+ *
+ * @return x-offset of background map / diagram
+ */
+ public double offsetX() {
+ return get(OFFSET_X, DEFAULT_OFFSET);
+ }
+
+ /**
+ * Sets the x-offset for the geomap / sprites background.
+ *
+ * @param offsetX the x-offset to set
+ * @return config for UI topology layout
+ */
+ public BasicUiTopoLayoutConfig offsetX(Double offsetX) {
+ setOrClear(OFFSET_X, offsetX);
+ return this;
+ }
+
+ /**
+ * Returns the y-offset for the geomap / sprites background.
+ *
+ * @return y-offset of background map / diagram
+ */
+ public double offsetY() {
+ return get(OFFSET_Y, DEFAULT_OFFSET);
+ }
+
+ /**
+ * Sets the scale for the geomap / sprites background.
+ *
+ * @param offsetY the y-offset to set
+ * @return config for UI topology layout
+ */
+ public BasicUiTopoLayoutConfig offsetY(Double offsetY) {
+ setOrClear(OFFSET_Y, offsetY);
+ return this;
+ }
+
}
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 956befe..2597588 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
@@ -21,6 +21,7 @@
import org.junit.Before;
import org.junit.Test;
+import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.config.Config.FieldPresence.MANDATORY;
import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
@@ -70,6 +71,12 @@
}
@Test
+ public void hasField() {
+ assertTrue("missing field", cfg.hasField(MAC));
+ assertFalse("unexpected field", cfg.hasField("non-existent"));
+ }
+
+ @Test
public void hasOnlyFields() {
assertTrue("has unexpected fields",
cfg.hasOnlyFields(TEXT, LONG, DOUBLE, BOOLEAN, MAC, BAD_MAC,
diff --git a/core/api/src/test/java/org/onosproject/net/config/basics/AbstractConfigTest.java b/core/api/src/test/java/org/onosproject/net/config/basics/AbstractConfigTest.java
index 4eb00c2..3778904 100644
--- a/core/api/src/test/java/org/onosproject/net/config/basics/AbstractConfigTest.java
+++ b/core/api/src/test/java/org/onosproject/net/config/basics/AbstractConfigTest.java
@@ -18,6 +18,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.ConfigApplyDelegate;
@@ -33,14 +34,14 @@
private static final String D_PREFIX = "of:00000000000000";
- /**
- * Shared object mapper.
- */
+ static final String BASIC = "basic";
+ static final String JSON_LOADED = "%nJSON loaded: %s";
+ static final String CHECKING_S = " checking: %s";
+
+ // Shared object mapper.
final ObjectMapper mapper = new ObjectMapper();
- /**
- * Shared null-delegate.
- */
+ // Shared null-delegate.
final ConfigApplyDelegate delegate = config -> {
};
@@ -93,4 +94,37 @@
static DeviceId dstr(String suffix) {
return DeviceId.deviceId(D_PREFIX + suffix);
}
+
+ /**
+ * Utility class to build quick JSON structures.
+ */
+ final class TmpJson {
+
+ final ObjectNode root = mapper.createObjectNode();
+
+ TmpJson props(String... keys) {
+ for (String k : keys) {
+ root.put(k, k);
+ }
+ return this;
+ }
+
+ TmpJson arrays(String... keys) {
+ for (String k : keys) {
+ root.set(k, mapper.createArrayNode());
+ }
+ return this;
+ }
+
+ TmpJson objects(String... keys) {
+ for (String k : keys) {
+ root.set(k, mapper.createObjectNode());
+ }
+ return this;
+ }
+
+ ObjectNode node() {
+ return root;
+ }
+ }
}
diff --git a/core/api/src/test/java/org/onosproject/net/config/basics/BasicRegionConfigTest.java b/core/api/src/test/java/org/onosproject/net/config/basics/BasicRegionConfigTest.java
index 9a01b3d..51c5676 100644
--- a/core/api/src/test/java/org/onosproject/net/config/basics/BasicRegionConfigTest.java
+++ b/core/api/src/test/java/org/onosproject/net/config/basics/BasicRegionConfigTest.java
@@ -17,16 +17,20 @@
package org.onosproject.net.config.basics;
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.InvalidFieldException;
import org.onosproject.net.region.Region;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.region.RegionId.regionId;
@@ -36,19 +40,30 @@
public class BasicRegionConfigTest extends AbstractConfigTest {
private static final String REGION_JSON = "configs.regions.1.json";
+
+ private static final String NAME = "name";
+ private static final String TYPE = "type";
+ private static final String DEVICES = "devices";
+
private static final String R1 = "r1";
private static final String R2 = "r2";
private static final String R3 = "r3";
+ private static final String EUROPE = "Europe";
+ private static final String PARIS = "Paris";
+ private static final String AUSTRALIA = "Australia";
+
private static final Set<DeviceId> R1_DEVS =
ImmutableSet.of(dstr("01"), dstr("02"), dstr("03"));
private static final Set<DeviceId> R2_DEVS =
ImmutableSet.of(dstr("04"), dstr("05"), dstr("06"));
private static final Set<DeviceId> R3_DEVS =
ImmutableSet.of(dstr("07"), dstr("08"), dstr("09"));
-
+ private static final Set<DeviceId> ALT_DEVICES =
+ ImmutableSet.of(dstr("0a"), dstr("0b"), dstr("0c"));
private JsonNode data;
+ private BasicRegionConfig cfg;
@Before
public void setUp() {
@@ -59,36 +74,114 @@
return data.get("regions").get(key).get("basic");
}
- private void checkRegion(String rid, Region.Type expT, Set<DeviceId> expD) {
- JsonNode r1json = getR(rid);
- print(r1json);
+ // loads a region config from the test resource file
+ private void loadRegion(String rid) {
+ JsonNode node = getR(rid);
+ print(JSON_LOADED, node);
- BasicRegionConfig brc = new BasicRegionConfig();
- brc.init(regionId(rid), rid, r1json, mapper, delegate);
+ cfg = new BasicRegionConfig();
+ cfg.init(regionId(rid), rid, node, mapper, delegate);
+ }
- Region.Type type = brc.getType();
- assertEquals("wrong type", expT, type);
+ private void checkRegion(String expN, Region.Type expT, Set<DeviceId> expD) {
+ print(CHECKING_S, cfg);
+ assertEquals("wrong name", expN, cfg.name());
+ assertEquals("wrong type", expT, cfg.type());
- List<DeviceId> devs = brc.getDevices();
- assertEquals("wr.size", expD.size(), devs.size());
- for (DeviceId d : expD) {
- assertTrue("missing dev: " + d, devs.contains(d));
+ List<DeviceId> devs = cfg.devices();
+ if (expD == null) {
+ assertNull("unexp device list", devs);
+ } else {
+ assertNotNull(devs);
+ assertEquals("wr.size", expD.size(), devs.size());
+ for (DeviceId d : expD) {
+ assertTrue("missing dev: " + d, devs.contains(d));
+ }
}
}
@Test
public void region1Config() {
- checkRegion(R1, Region.Type.CONTINENT, R1_DEVS);
+ loadRegion(R1);
+ checkRegion(EUROPE, Region.Type.CONTINENT, R1_DEVS);
}
@Test
public void region2Config() {
- checkRegion(R2, Region.Type.METRO, R2_DEVS);
+ loadRegion(R2);
+ checkRegion(PARIS, Region.Type.METRO, R2_DEVS);
}
@Test
public void region3Config() {
- checkRegion(R3, null, R3_DEVS);
+ loadRegion(R3);
+ checkRegion(null, null, R3_DEVS);
}
+ @Test
+ public void modifyName() {
+ loadRegion(R1);
+ cfg.name(AUSTRALIA);
+ checkRegion(AUSTRALIA, Region.Type.CONTINENT, R1_DEVS);
+ }
+
+ @Test
+ public void clearName() {
+ loadRegion(R1);
+ cfg.name(null);
+ checkRegion(null, Region.Type.CONTINENT, R1_DEVS);
+ }
+
+ @Test
+ public void modifyType() {
+ loadRegion(R2);
+ cfg.type(Region.Type.CAMPUS);
+ checkRegion(PARIS, Region.Type.CAMPUS, R2_DEVS);
+ }
+
+ @Test
+ public void clearType() {
+ loadRegion(R2);
+ cfg.type(null);
+ checkRegion(PARIS, null, R2_DEVS);
+ }
+
+ @Test
+ public void modifyDevices() {
+ loadRegion(R3);
+ cfg.devices(ALT_DEVICES);
+ checkRegion(null, null, ALT_DEVICES);
+ }
+
+ @Test
+ public void clearDevices() {
+ loadRegion(R3);
+ cfg.devices(null);
+ checkRegion(null, null, null);
+ }
+
+
+ @Test
+ public void sampleValidConfig() {
+ ObjectNode node = new TmpJson()
+ .props(NAME, TYPE)
+ .arrays(DEVICES)
+ .node();
+ cfg = new BasicRegionConfig();
+ cfg.init(regionId(R1), BASIC, node, mapper, delegate);
+
+ assertTrue("not valid: " + cfg, cfg.isValid());
+ }
+
+ @Test(expected = InvalidFieldException.class)
+ public void sampleInvalidConfig() {
+ ObjectNode node = new TmpJson()
+ .props(NAME, TYPE, "foo")
+ .arrays(DEVICES)
+ .node();
+ cfg = new BasicRegionConfig();
+ cfg.init(regionId(R1), BASIC, node, mapper, delegate);
+
+ cfg.isValid();
+ }
}
diff --git a/core/api/src/test/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfigTest.java b/core/api/src/test/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfigTest.java
new file mode 100644
index 0000000..f04dd9e
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfigTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.config.basics;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.net.config.InvalidFieldException;
+import org.onosproject.net.region.RegionId;
+import org.onosproject.ui.model.topo.UiTopoLayoutId;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.onosproject.net.config.basics.BasicElementConfig.ZERO_THRESHOLD;
+import static org.onosproject.net.config.basics.BasicUiTopoLayoutConfig.GEOMAP;
+import static org.onosproject.net.config.basics.BasicUiTopoLayoutConfig.OFFSET_X;
+import static org.onosproject.net.config.basics.BasicUiTopoLayoutConfig.OFFSET_Y;
+import static org.onosproject.net.config.basics.BasicUiTopoLayoutConfig.SCALE;
+import static org.onosproject.net.config.basics.BasicUiTopoLayoutConfig.SPRITES;
+import static org.onosproject.net.region.RegionId.regionId;
+import static org.onosproject.ui.model.topo.UiTopoLayoutId.layoutId;
+
+/**
+ * Test class for {@link BasicUiTopoLayoutConfig}.
+ */
+public class BasicUiTopoLayoutConfigTest extends AbstractConfigTest {
+
+ private static final String LAYOUT_JSON = "configs.layouts.1.json";
+
+ private static final String L_DEFAULT = "_default_";
+ private static final String L1 = "l1";
+ private static final String L2 = "l2";
+ private static final String L3 = "l3";
+
+ private static final RegionId R1 = regionId("r1");
+ private static final RegionId R2 = regionId("r2");
+ private static final RegionId R3 = regionId("r3");
+
+ private static final String UK = "uk";
+ private static final String UK_BRIGHTON = "uk-brighton";
+ private static final String UK_LONDON = "uk-london";
+ private static final String UK_LONDON_WEST = "uk-london-westminster";
+
+ private static final RegionId NEW_REGION = regionId("new-region");
+ private static final UiTopoLayoutId NEW_PARENT = layoutId("new-parent");
+ private static final String NEW_MAP = "new-geomap";
+ private static final String NEW_SPR = "new-sprites";
+
+
+ private JsonNode data;
+ private BasicUiTopoLayoutConfig cfg;
+
+ @Before
+ public void setUp() {
+ data = getTestJson(LAYOUT_JSON);
+ }
+
+ private JsonNode getL(String key) {
+ return data.get("layouts").get(key).get("basic");
+ }
+
+ private void loadLayout(String lid) {
+ JsonNode node = getL(lid);
+ print(JSON_LOADED, node);
+
+ cfg = new BasicUiTopoLayoutConfig();
+ cfg.init(layoutId(lid), lid, node, mapper, delegate);
+ }
+
+ private void checkLayout(RegionId expRegion, UiTopoLayoutId expParent,
+ String expGeo, String expSpr) {
+ print(CHECKING_S, cfg);
+ assertEquals("wrong region", expRegion, cfg.region());
+ assertEquals("wrong parent", expParent, cfg.parent());
+ assertEquals("wrong geomap", expGeo, cfg.geomap());
+ assertEquals("wrong sprites", expSpr, cfg.sprites());
+ }
+
+ private void checkScale(double expScale, double expOffx, double expOffy) {
+ assertEquals(SCALE, expScale, cfg.scale(), ZERO_THRESHOLD);
+ assertEquals(OFFSET_X, expOffx, cfg.offsetX(), ZERO_THRESHOLD);
+ assertEquals(OFFSET_Y, expOffy, cfg.offsetY(), ZERO_THRESHOLD);
+ }
+
+ @Test
+ public void layoutConfigDefault() {
+ loadLayout(L_DEFAULT);
+ checkLayout(null, UiTopoLayoutId.DEFAULT_ID, UK, null);
+ checkScale(1.2, -50, 0);
+ }
+
+ @Test
+ public void layoutConfigOne() {
+ loadLayout(L1);
+ checkLayout(R1, UiTopoLayoutId.DEFAULT_ID, UK_BRIGHTON, null);
+ checkScale(0.9, 200, -45);
+ }
+
+ @Test
+ public void layoutConfigTwo() {
+ loadLayout(L2);
+ checkLayout(R2, UiTopoLayoutId.DEFAULT_ID, UK_LONDON, null);
+ checkScale(1, 0, 0);
+ }
+
+ @Test
+ public void layoutConfigThree() {
+ loadLayout(L3);
+ checkLayout(R3, layoutId(L2), null, UK_LONDON_WEST);
+ checkScale(1, 0, 0);
+ }
+
+ private ObjectNode tmpNode(String... props) {
+ return new TmpJson().props(props).node();
+ }
+
+ private BasicUiTopoLayoutConfig cfgFromJson(ObjectNode json) {
+ BasicUiTopoLayoutConfig cfg = new BasicUiTopoLayoutConfig();
+ cfg.init(layoutId("foo"), BASIC, json, mapper, delegate);
+ return cfg;
+ }
+
+ @Test(expected = InvalidFieldException.class)
+ public void cantHaveGeoAndSprite() {
+ cfg = cfgFromJson(tmpNode(GEOMAP, SPRITES));
+ cfg.isValid();
+ }
+
+ @Test(expected = InvalidFieldException.class)
+ public void cantSetGeoIfSpritesAreSet() {
+ cfg = cfgFromJson(tmpNode(SPRITES));
+ cfg.geomap("map-name");
+ }
+
+ @Test(expected = InvalidFieldException.class)
+ public void cantSetSpritesIfGeoIsSet() {
+ cfg = cfgFromJson(tmpNode(GEOMAP));
+ cfg.sprites("sprites-name");
+ }
+
+ @Test
+ public void setRegion() {
+ loadLayout(L1);
+ assertEquals("not region-1", R1, cfg.region());
+ cfg.region(NEW_REGION);
+ assertEquals("not new region", NEW_REGION, cfg.region());
+ cfg.region(null);
+ assertNull("region not cleared", cfg.region());
+ }
+
+ @Test
+ public void setParent() {
+ loadLayout(L1);
+ assertEquals("parent not default layout", UiTopoLayoutId.DEFAULT_ID, cfg.parent());
+ cfg.parent(NEW_PARENT);
+ assertEquals("not new parent", NEW_PARENT, cfg.parent());
+ cfg.parent(null);
+ assertEquals("parent not reset to default", UiTopoLayoutId.DEFAULT_ID, cfg.parent());
+ }
+
+ @Test
+ public void setGeomap() {
+ loadLayout(L1);
+ assertEquals("map not brighton", UK_BRIGHTON, cfg.geomap());
+ cfg.geomap(NEW_MAP);
+ assertEquals("not new map", NEW_MAP, cfg.geomap());
+ cfg.geomap(null);
+ assertNull("geomap not cleared", cfg.geomap());
+ }
+
+ @Test
+ public void setSprites() {
+ loadLayout(L3);
+ assertEquals("sprites not westminster", UK_LONDON_WEST, cfg.sprites());
+ cfg.sprites(NEW_SPR);
+ assertEquals("not new sprites", NEW_SPR, cfg.sprites());
+ cfg.sprites(null);
+ assertNull("sprites not cleared", cfg.sprites());
+ }
+
+ @Test
+ public void setScaleAndOffset() {
+ loadLayout(L1);
+ assertEquals("wrong init scale", 0.9, cfg.scale(), ZERO_THRESHOLD);
+ assertEquals("wrong init x-offset", 200, cfg.offsetX(), ZERO_THRESHOLD);
+ assertEquals("wrong init y-offset", -45, cfg.offsetY(), ZERO_THRESHOLD);
+ cfg.scale(3.14).offsetX(12.0).offsetY(13.0);
+ assertEquals("wrong new scale", 3.14, cfg.scale(), ZERO_THRESHOLD);
+ assertEquals("wrong new x-offset", 12, cfg.offsetX(), ZERO_THRESHOLD);
+ assertEquals("wrong new y-offset", 13, cfg.offsetY(), ZERO_THRESHOLD);
+ cfg.scale(null).offsetX(null).offsetY(null);
+ assertEquals("wrong default scale", 1, cfg.scale(), ZERO_THRESHOLD);
+ assertEquals("wrong default x-offset", 0, cfg.offsetX(), ZERO_THRESHOLD);
+ assertEquals("wrong default y-offset", 0, cfg.offsetY(), ZERO_THRESHOLD);
+ }
+}
diff --git a/core/api/src/test/resources/org/onosproject/net/config/basics/configs.layouts.1.json b/core/api/src/test/resources/org/onosproject/net/config/basics/configs.layouts.1.json
index b92c999..790693b 100644
--- a/core/api/src/test/resources/org/onosproject/net/config/basics/configs.layouts.1.json
+++ b/core/api/src/test/resources/org/onosproject/net/config/basics/configs.layouts.1.json
@@ -2,7 +2,6 @@
"layouts": {
"_default_": {
"basic": {
- "region": "",
"geomap": "uk",
"scale": 1.2,
"offsetX": -50,
diff --git a/core/api/src/test/resources/org/onosproject/net/config/basics/configs.regions.1.json b/core/api/src/test/resources/org/onosproject/net/config/basics/configs.regions.1.json
index 9ce4073..2d6ca5e 100644
--- a/core/api/src/test/resources/org/onosproject/net/config/basics/configs.regions.1.json
+++ b/core/api/src/test/resources/org/onosproject/net/config/basics/configs.regions.1.json
@@ -2,6 +2,7 @@
"regions": {
"r1": {
"basic": {
+ "name": "Europe",
"type": "continent",
"devices": [
"of:0000000000000001",
@@ -12,6 +13,7 @@
},
"r2": {
"basic": {
+ "name": "Paris",
"type": "metro",
"devices": [
"of:0000000000000004",