ONOS-6257: fixing Region-peer-location function...
- corrected UiRegion.isRoot() implementation
- added to/from-compact-strings for LayoutLocation, so we can encode
a list of them in an annotation
- Fixed bug in DistributedRegionStore which was emiting events that
had a null region as subject.
Change-Id: I547e0c7f62385b85b191b8d63e6b569196623b84
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
index ada4d15..0a2fa2f 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
@@ -123,7 +123,7 @@
* @return true if root region
*/
public boolean isRoot() {
- return id().equals(parent);
+ return parent == null;
}
/**
@@ -181,7 +181,7 @@
* @return the backing region instance
*/
public Region backingRegion() {
- return topology.services.region().getRegion(regionId);
+ return isRoot() ? null : topology.services.region().getRegion(regionId);
}
/**
diff --git a/core/api/src/main/java/org/onosproject/ui/topo/LayoutLocation.java b/core/api/src/main/java/org/onosproject/ui/topo/LayoutLocation.java
index 9e006b5..69be6aa 100644
--- a/core/api/src/main/java/org/onosproject/ui/topo/LayoutLocation.java
+++ b/core/api/src/main/java/org/onosproject/ui/topo/LayoutLocation.java
@@ -17,6 +17,12 @@
package org.onosproject.ui.topo;
+import com.google.common.base.Strings;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -25,6 +31,14 @@
*/
public final class LayoutLocation {
private static final double ZERO_THRESHOLD = Double.MIN_VALUE * 2.0;
+ private static final String COMMA = ",";
+ private static final String TILDE = "~";
+ private static final String EMPTY = "";
+
+ private static final String E_BAD_COMPACT = "Badly formatted compact form: ";
+ private static final String E_EMPTY_ID = "id must be non-empty";
+ private static final String E_BAD_DOUBLE = "unparsable double";
+
/**
* Designates the type of location; either geographic or logical grid.
@@ -45,7 +59,6 @@
this.locType = locType;
}
-
private boolean doubleIsZero(double value) {
return value >= -ZERO_THRESHOLD && value <= ZERO_THRESHOLD;
}
@@ -70,6 +83,16 @@
}
/**
+ * Returns the location type (geo or grid), which indicates how the data
+ * is to be interpreted.
+ *
+ * @return location type
+ */
+ public Type locType() {
+ return locType;
+ }
+
+ /**
* Returns the latitude (geo) or y-coord (grid) data value.
*
* @return geo latitude or grid y-coord
@@ -87,27 +110,111 @@
return longOrX;
}
- /**
- * Returns the location type (geo or grid), which indicates how the data
- * is to be interpreted.
- *
- * @return location type
- */
- public Type locType() {
- return locType;
- }
-
@Override
public String toString() {
return toStringHelper(this)
.add("id", id)
+ .add("loc-type", locType)
.add("lat/Y", latOrY)
.add("long/X", longOrX)
- .add("loc-type", locType)
.toString();
}
/**
+ * Produces a compact string representation of this instance.
+ *
+ * @return compact string rep
+ */
+ public String toCompactListString() {
+ return id + COMMA + locType + COMMA + latOrY + COMMA + longOrX;
+ }
+
+ /**
+ * Produces a layout location instance from a compact string representation.
+ *
+ * @param s the compact string
+ * @return a corresponding instance
+ */
+ public static LayoutLocation fromCompactString(String s) {
+ String[] tokens = s.split(COMMA);
+ if (tokens.length != 4) {
+ throw new IllegalArgumentException(E_BAD_COMPACT + s);
+ }
+ String id = tokens[0];
+ String type = tokens[1];
+ String latY = tokens[2];
+ String longX = tokens[3];
+
+ if (Strings.isNullOrEmpty(id)) {
+ throw new IllegalArgumentException(E_BAD_COMPACT + E_EMPTY_ID);
+ }
+
+ double latOrY;
+ double longOrX;
+ try {
+ latOrY = Double.parseDouble(latY);
+ longOrX = Double.parseDouble(longX);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException(E_BAD_COMPACT + E_BAD_DOUBLE);
+ }
+
+ return LayoutLocation.layoutLocation(id, type, latOrY, longOrX);
+ }
+
+ /**
+ * Produces a compact encoding of a list of layout locations.
+ *
+ * @param locs array of layout location instances
+ * @return string encoding
+ */
+ public static String toCompactListString(LayoutLocation... locs) {
+ if (locs == null || locs.length == 0) {
+ return EMPTY;
+ }
+ List<LayoutLocation> lls = Arrays.asList(locs);
+ return toCompactListString(lls);
+ }
+
+ /**
+ * Produces a compact encoding of a list of layout locations.
+ *
+ * @param locs list of layout location instances
+ * @return string encoding
+ */
+ public static String toCompactListString(List<LayoutLocation> locs) {
+ // note: locs may be empty
+ if (locs == null || locs.isEmpty()) {
+ return EMPTY;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (LayoutLocation ll : locs) {
+ sb.append(ll.toCompactListString()).append(TILDE);
+ }
+ final int len = sb.length();
+ sb.replace(len - 1, len, "");
+ return sb.toString();
+ }
+
+ /**
+ * Returns a list of layout locations from a compact string representation.
+ *
+ * @param compactList string representation
+ * @return corresponding list of layout locations
+ */
+ public static List<LayoutLocation> fromCompactListString(String compactList) {
+ List<LayoutLocation> locs = new ArrayList<>();
+ if (!Strings.isNullOrEmpty(compactList)) {
+ String[] items = compactList.split(TILDE);
+ for (String s : items) {
+ locs.add(fromCompactString(s));
+ }
+ }
+ return locs;
+ }
+
+
+ /**
* Creates an instance of a layout location.
*
* @param id an identifier for the item at this location
diff --git a/core/api/src/test/java/org/onosproject/ui/topo/LayoutLocationTest.java b/core/api/src/test/java/org/onosproject/ui/topo/LayoutLocationTest.java
index 64908fd..cca430c 100644
--- a/core/api/src/test/java/org/onosproject/ui/topo/LayoutLocationTest.java
+++ b/core/api/src/test/java/org/onosproject/ui/topo/LayoutLocationTest.java
@@ -20,9 +20,12 @@
import org.junit.Test;
import org.onosproject.ui.AbstractUiTest;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.collect.ImmutableList.of;
import static org.junit.Assert.*;
-import static org.onosproject.ui.topo.LayoutLocation.Type;
-import static org.onosproject.ui.topo.LayoutLocation.layoutLocation;
+import static org.onosproject.ui.topo.LayoutLocation.*;
/**
* Unit tests for {@link LayoutLocation}.
@@ -30,11 +33,18 @@
public class LayoutLocationTest extends AbstractUiTest {
private static final String SOME_ID = "foo";
+ private static final String OTHER_ID = "bar";
private static final double SQRT2 = 1.414;
private static final double PI = 3.142;
private static final double ZERO = 0.0;
+ private static final String COMPACT_LL_1 = "foo,GEO,3.142,1.414";
+ private static final String COMPACT_LL_2 = "bar,GRID,1.414,3.142";
+
+ private static final String COMPACT_LIST = COMPACT_LL_1 + "~" + COMPACT_LL_2;
+
private LayoutLocation ll;
+ private LayoutLocation ll2;
@Test
public void basic() {
@@ -86,4 +96,121 @@
public void nullId() {
layoutLocation(null, Type.GRID, PI, PI);
}
+
+ @Test
+ public void compactString() {
+ ll = layoutLocation(SOME_ID, Type.GEO, PI, SQRT2);
+ String s = ll.toCompactListString();
+ assertEquals("wrong compactness", COMPACT_LL_1, s);
+ }
+
+ @Test
+ public void fromCompactStringTest() {
+ ll = fromCompactString(COMPACT_LL_1);
+ verifyLL1(ll);
+ }
+
+ private void verifyLL1(LayoutLocation ll) {
+ assertEquals("LL1 bad id", SOME_ID, ll.id());
+ assertEquals("LL1 bad type", Type.GEO, ll.locType());
+ assertEquals("LL1 bad Y", PI, ll.latOrY(), TOLERANCE);
+ assertEquals("LL1 bad X", SQRT2, ll.longOrX(), TOLERANCE);
+ }
+
+ private void verifyLL2(LayoutLocation ll) {
+ assertEquals("LL1 bad id", OTHER_ID, ll.id());
+ assertEquals("LL1 bad type", Type.GRID, ll.locType());
+ assertEquals("LL1 bad Y", SQRT2, ll.latOrY(), TOLERANCE);
+ assertEquals("LL1 bad X", PI, ll.longOrX(), TOLERANCE);
+ }
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void badCompactTooShort() {
+ fromCompactString("one,two,three");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void badCompactTooLong() {
+ fromCompactString("one,two,three,4,5");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void badCompactNoId() {
+ fromCompactString(",GEO,1,2");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void badCompactUnparsableY() {
+ fromCompactString("foo,GEO,yyy,2.3");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void badCompactUnparsableX() {
+ fromCompactString("foo,GEO,0.2,xxx");
+ }
+
+ @Test
+ public void toCompactList() {
+ ll = layoutLocation(SOME_ID, Type.GEO, PI, SQRT2);
+ ll2 = layoutLocation(OTHER_ID, Type.GRID, SQRT2, PI);
+ String compact = toCompactListString(ll, ll2);
+ print(compact);
+ assertEquals("wrong list encoding", COMPACT_LIST, compact);
+ }
+
+ @Test
+ public void toCompactList2() {
+ ll = layoutLocation(SOME_ID, Type.GEO, PI, SQRT2);
+ ll2 = layoutLocation(OTHER_ID, Type.GRID, SQRT2, PI);
+ List<LayoutLocation> locs = of(ll, ll2);
+ String compact = toCompactListString(locs);
+ print(compact);
+ assertEquals("wrong list encoding", COMPACT_LIST, compact);
+ }
+
+ @Test
+ public void fromCompactList() {
+ List<LayoutLocation> locs = fromCompactListString(COMPACT_LIST);
+ ll = locs.get(0);
+ ll2 = locs.get(1);
+ verifyLL1(ll);
+ verifyLL2(ll2);
+ }
+
+ @Test
+ public void fromCompactListNull() {
+ List<LayoutLocation> locs = fromCompactListString(null);
+ assertEquals("non-empty list", 0, locs.size());
+ }
+
+ @Test
+ public void fromCompactListEmpty() {
+ List<LayoutLocation> locs = fromCompactListString("");
+ assertEquals("non-empty list", 0, locs.size());
+ }
+
+ @Test
+ public void toCompactListStringNullList() {
+ String s = toCompactListString((List<LayoutLocation>) null);
+ assertEquals("not empty string", "", s);
+ }
+
+ @Test
+ public void toCompactListStringNullArray() {
+ String s = toCompactListString((LayoutLocation[]) null);
+ assertEquals("not empty string", "", s);
+ }
+
+ @Test
+ public void toCompactListStringEmptyArray() {
+ String s = toCompactListString();
+ assertEquals("not empty string", "", s);
+ }
+
+ @Test
+ public void toCompactListStringEmptyList() {
+ String s = toCompactListString(new ArrayList<>());
+ assertEquals("not empty string", "", s);
+ }
}