Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 41 additions & 7 deletions lib/src/main/java/io/ably/lib/types/Summary.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public class Summary {

private static final String TAG = Summary.class.getName();

private static final String TOTAL = "total";
private static final String CLIENT_IDS = "clientIds";
private static final String CLIPPED = "clipped";
private static final String TOTAL_UNIDENTIFIED = "totalUnidentified";
private static final String TOTAL_CLIENT_IDS = "totalClientIds";

/**
* (TM2q1) The sdk MUST be able to cope with structures and aggregation types that have it does not yet know about
* or have explicit support for, hence the loose (JsonObject) type.
Expand Down Expand Up @@ -59,27 +65,55 @@ public static Map<String, SummaryClientIdCounts> asSummaryMultipleV1(JsonObject
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
String key = entry.getKey();
JsonObject value = entry.getValue().getAsJsonObject();
int total = value.get("total").getAsInt();
int total = value.get(TOTAL).getAsInt();
Map<String, Integer> clientIds = new HashMap<>();
for (Map.Entry<String, JsonElement> clientEntry: value.get("clientIds").getAsJsonObject().entrySet()) {
for (Map.Entry<String, JsonElement> clientEntry: value.get(CLIENT_IDS).getAsJsonObject().entrySet()) {
clientIds.put(clientEntry.getKey(), clientEntry.getValue().getAsInt());
}
summary.put(key, new SummaryClientIdCounts(total, clientIds));
Integer totalUnidentified = tryReadIntField(value, TOTAL_UNIDENTIFIED);
Integer totalClientIds = tryReadIntField(value, TOTAL_CLIENT_IDS);
summary.put(key, new SummaryClientIdCounts(
total,
clientIds,
totalUnidentified == null ? 0 : totalUnidentified,
tryReadBooleanField(value, CLIPPED),
totalClientIds == null ? total : totalClientIds
));
}
return summary;
}

public static SummaryClientIdList asSummaryFlagV1(JsonObject jsonObject) {
int total = jsonObject.get("total").getAsInt();
List<String> clientIds = Serialisation.gson.fromJson(jsonObject.get("clientIds"), List.class);
return new SummaryClientIdList(total, clientIds);
int total = jsonObject.get(TOTAL).getAsInt();
List<String> clientIds = Serialisation.gson.fromJson(jsonObject.get(CLIENT_IDS), List.class);
return new SummaryClientIdList(
total,
clientIds,
tryReadBooleanField(jsonObject, CLIPPED)
);
}

public static SummaryTotal asSummaryTotalV1(JsonObject jsonObject) {
int total = jsonObject.get("total").getAsInt();
int total = jsonObject.get(TOTAL).getAsInt();
return new SummaryTotal(total);
}

private static boolean tryReadBooleanField(JsonObject jsonObject, String fieldName) {
JsonElement fieldElement = jsonObject.get(fieldName);
if (fieldElement != null && fieldElement.isJsonPrimitive() && fieldElement.getAsJsonPrimitive().isBoolean()) {
return fieldElement.getAsBoolean();
}
return false;
}

private static Integer tryReadIntField(JsonObject jsonObject, String fieldName) {
JsonElement fieldElement = jsonObject.get(fieldName);
if (fieldElement != null && fieldElement.isJsonPrimitive() && fieldElement.getAsJsonPrimitive().isNumber()) {
return fieldElement.getAsInt();
}
return null;
}

static Summary read(MessageUnpacker unpacker) {
try {
return read(Serialisation.msgpackToGson(unpacker.unpackValue()));
Expand Down
35 changes: 34 additions & 1 deletion lib/src/main/java/io/ably/lib/types/SummaryClientIdCounts.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,45 @@

import java.util.Map;

/**
* The per-name value for the multiple.v1 aggregation method.
*/
public class SummaryClientIdCounts {
/**
* The sum of the counts from all clients who have published an annotation with this name
*/
public final int total; // TM7d1a
/**
* A list of the clientIds of all clients who have published an annotation with this
* name, and the count each of them have contributed.
*/
public final Map<String, Integer> clientIds; // TM7d1b
/**
* The sum of the counts from all unidentified clients who have published an annotation with this
* name, and so who are not included in the clientIds list
*/
public final int totalUnidentified; // TM7d1d
/**
* Whether the list of clientIds has been clipped due to exceeding the maximum number of
* clients.
*/
public final boolean clipped; // TM7d1c
/**
* The total number of distinct clientIds in the map (equal to length of map if clipped is false).
*/
public final int totalClientIds; // TM7d1e

public SummaryClientIdCounts(int total, Map<String, Integer> clientIds) {
public SummaryClientIdCounts(
int total,
Map<String, Integer> clientIds,
int totalUnidentified,
boolean clipped,
int totalClientIds
) {
this.total = total;
this.clientIds = clientIds;
this.totalUnidentified = totalUnidentified;
this.clipped = clipped;
this.totalClientIds = totalClientIds;
}
}
21 changes: 19 additions & 2 deletions lib/src/main/java/io/ably/lib/types/SummaryClientIdList.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@

import java.util.List;

/**
* The summary entry for aggregated annotations that use the flag.v1
* aggregation method; also the per-name value for some other aggregation methods.
*/
public class SummaryClientIdList {
/**
* The sum of the counts from all clients who have published an annotation with this name
*/
public final int total; // TM7c1a
public final List<String> clientIds; // TM7c1b
/**
* A list of the clientIds of all clients who have published an annotation with this name (or
* type, depending on context).
*/
public final List<String> clientIds; // TM7
/**
* Whether the list of clientIds has been clipped due to exceeding the maximum number of
* clients.
*/
public final boolean clipped; // TM7c1c

public SummaryClientIdList(int total, List<String> clientIds) {
public SummaryClientIdList(int total, List<String> clientIds, boolean clipped) {
this.total = total;
this.clientIds = clientIds;
this.clipped = clipped;
}
}
47 changes: 47 additions & 0 deletions lib/src/test/java/io/ably/lib/types/SummaryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
Expand Down Expand Up @@ -126,6 +127,25 @@ public void testAsSummaryFlagV1_SingleEntry() {
assertTrue(result.clientIds.contains("client1"));
assertTrue(result.clientIds.contains("client2"));
assertTrue(result.clientIds.contains("client3"));
assertFalse(result.clipped);
}

@Test
public void testAsSummaryFlagV1_clippedTrue() {
JsonObject entryValue = new JsonObject();
entryValue.addProperty("total", 100);
JsonArray clientIds = new JsonArray();
clientIds.add("client1");
entryValue.add("clientIds", clientIds);
entryValue.addProperty("clipped", true);

SummaryClientIdList result = Summary.asSummaryFlagV1(entryValue);

assertNotNull(result);
assertEquals(100, result.total);
assertEquals(1, result.clientIds.size());
assertTrue(result.clientIds.contains("client1"));
assertTrue(result.clipped);
}

@Test
Expand Down Expand Up @@ -196,13 +216,40 @@ public void testAsSummaryMultipleV1_MultipleEntries() {
assertEquals(2, summaryA.clientIds.size());
assertEquals(3, (int) summaryA.clientIds.get("clientA"));
assertEquals(2, (int) summaryA.clientIds.get("clientB"));
assertEquals(0, summaryA.totalUnidentified);
assertEquals(5, summaryA.totalClientIds);
assertFalse(summaryA.clipped);

SummaryClientIdCounts summaryB = result.get("👍️️️️️️");
assertNotNull(summaryB);
assertEquals(2, summaryB.total);
assertEquals(2, summaryB.clientIds.size());
assertEquals(1, (int) summaryB.clientIds.get("clientX"));
assertEquals(1, (int) summaryB.clientIds.get("clientY"));
assertEquals(0, summaryB.totalUnidentified);
assertEquals(2, summaryB.totalClientIds);
assertFalse(summaryA.clipped);
}

@Test
public void testAsSummaryMultipleV1_ClippedTrue() {
JsonObject jsonObject = new JsonObject();

JsonObject entryValue1 = new JsonObject();
entryValue1.addProperty("total", 5);
JsonObject clientIds1 = new JsonObject();
clientIds1.addProperty("clientA", 1);
entryValue1.add("clientIds", clientIds1);
entryValue1.addProperty("clipped", true);
entryValue1.addProperty("totalClientIds", 1);
jsonObject.add("😄️️️", entryValue1);

Map<String, SummaryClientIdCounts> result = Summary.asSummaryMultipleV1(jsonObject);
SummaryClientIdCounts summary = result.get("😄️️️");
assertEquals(5, summary.total);
assertEquals(1, summary.totalClientIds);
assertEquals(0, summary.totalUnidentified);
assertTrue(summary.clipped);
}

@Test
Expand Down
Loading