Skip to content

Commit

Permalink
fix: adds maximum and minimum FieldValue transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
mfranberg committed Dec 21, 2022
1 parent 0e4f2be commit 0f81a7a
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 0 deletions.
Expand Up @@ -126,6 +126,104 @@ public int hashCode() {
}
}

static class NumericMaximumFieldValue extends FieldValue {
final Number operand;

NumericMaximumFieldValue(Number operand) {
this.operand = operand;
}

@Override
boolean includeInDocumentMask() {
return false;
}

@Override
boolean includeInDocumentTransform() {
return true;
}

@Override
String getMethodName() {
return "FieldValue.maximum()";
}

@Override
FieldTransform toProto(FieldPath path) {
FieldTransform.Builder fieldTransform = FieldTransform.newBuilder();
fieldTransform.setFieldPath(path.getEncodedPath());
fieldTransform.setMaximum(
UserDataConverter.encodeValue(path, operand, UserDataConverter.ARGUMENT));
return fieldTransform.build();
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NumericMaximumFieldValue that = (NumericMaximumFieldValue) o;
return Objects.equals(operand, that.operand);
}

@Override
public int hashCode() {
return Objects.hash(operand);
}
}

static class NumericMinimumFieldValue extends FieldValue {
final Number operand;

NumericMinimumFieldValue(Number operand) {
this.operand = operand;
}

@Override
boolean includeInDocumentMask() {
return false;
}

@Override
boolean includeInDocumentTransform() {
return true;
}

@Override
String getMethodName() {
return "FieldValue.minimum()";
}

@Override
FieldTransform toProto(FieldPath path) {
FieldTransform.Builder fieldTransform = FieldTransform.newBuilder();
fieldTransform.setFieldPath(path.getEncodedPath());
fieldTransform.setMinimum(
UserDataConverter.encodeValue(path, operand, UserDataConverter.ARGUMENT));
return fieldTransform.build();
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NumericMinimumFieldValue that = (NumericMinimumFieldValue) o;
return Objects.equals(operand, that.operand);
}

@Override
public int hashCode() {
return Objects.hash(operand);
}
}

static class ArrayUnionFieldValue extends FieldValue {
final List<Object> elements;

Expand Down Expand Up @@ -288,6 +386,58 @@ public static FieldValue increment(double d) {
return new NumericIncrementFieldValue(d);
}

/**
* Returns a special value that can be used with set(), create() or update() that tells the server
* to take the maximum of the field's current value and the given value.
*
* <p>If the current field is not an integer or double, or if the field does not yet exist, the
* transformation will set the field to the given value.
*
* @return The FieldValue sentinel for use in a call to set(), create() or update().
*/
@Nonnull
public static FieldValue maximum(long l) { return new NumericMaximumFieldValue(l); }

/**
* Returns a special value that can be used with set(), create() or update() that tells the server
* to take the maximum of the field's current value and the given value.
*
* <p>If the current field is not an integer or double, or if the field does not yet exist, the
* transformation will set the field to the given value.
*
* @return The FieldValue sentinel for use in a call to set(), create() or update().
*/
@Nonnull
public static FieldValue maximum(double d) {
return new NumericMaximumFieldValue(d);
}

/**
* Returns a special value that can be used with set(), create() or update() that tells the server
* to take the minimum of the field's current value and the given value.
*
* <p>If the current field is not an integer or double, or if the field does not yet exist, the
* transformation will set the field to the given value.
*
* @return The FieldValue sentinel for use in a call to set(), create() or update().
*/
@Nonnull
public static FieldValue minimum(long l) { return new NumericMinimumFieldValue(l); }

/**
* Returns a special value that can be used with set(), create() or update() that tells the server
* to take the minimum of the field's current value and the given value.
*
* <p>If the current field is not an integer or double, or if the field does not yet exist, the
* transformation will set the field to the given value.
*
* @return The FieldValue sentinel for use in a call to set(), create() or update().
*/
@Nonnull
public static FieldValue minimum(double d) {
return new NumericMinimumFieldValue(d);
}

/**
* Returns a special value that can be used with set(), create() or update() that tells the server
* to union the given elements with any array value that already exists on the server. Each
Expand Down
Expand Up @@ -48,6 +48,8 @@
import static com.google.cloud.firestore.LocalFirestoreHelper.getAllResponse;
import static com.google.cloud.firestore.LocalFirestoreHelper.increment;
import static com.google.cloud.firestore.LocalFirestoreHelper.map;
import static com.google.cloud.firestore.LocalFirestoreHelper.maximum;
import static com.google.cloud.firestore.LocalFirestoreHelper.minimum;
import static com.google.cloud.firestore.LocalFirestoreHelper.object;
import static com.google.cloud.firestore.LocalFirestoreHelper.serverTimestamp;
import static com.google.cloud.firestore.LocalFirestoreHelper.set;
Expand Down Expand Up @@ -517,6 +519,54 @@ public void setWithIncrement() throws Exception {
assertCommitEquals(set, commitRequest);
}

@Test
public void setWithMaximum() throws Exception {
doReturn(FIELD_TRANSFORM_COMMIT_RESPONSE)
.when(firestoreMock)
.sendRequest(
commitCapture.capture(), Matchers.<UnaryCallable<CommitRequest, CommitResponse>>any());

documentReference
.set(map("integer", FieldValue.maximum(1), "double", FieldValue.maximum(1.1)))
.get();

CommitRequest set =
commit(
set(Collections.emptyMap()),
transform(
"integer",
maximum(Value.newBuilder().setIntegerValue(1).build()),
"double",
maximum(Value.newBuilder().setDoubleValue(1.1).build())));

CommitRequest commitRequest = commitCapture.getValue();
assertCommitEquals(set, commitRequest);
}

@Test
public void setWithMinimum() throws Exception {
doReturn(FIELD_TRANSFORM_COMMIT_RESPONSE)
.when(firestoreMock)
.sendRequest(
commitCapture.capture(), Matchers.<UnaryCallable<CommitRequest, CommitResponse>>any());

documentReference
.set(map("integer", FieldValue.minimum(1), "double", FieldValue.minimum(1.1)))
.get();

CommitRequest set =
commit(
set(Collections.emptyMap()),
transform(
"integer",
minimum(Value.newBuilder().setIntegerValue(1).build()),
"double",
minimum(Value.newBuilder().setDoubleValue(1.1).build())));

CommitRequest commitRequest = commitCapture.getValue();
assertCommitEquals(set, commitRequest);
}

@Test
public void setWithArrayUnion() throws Exception {
doReturn(FIELD_TRANSFORM_COMMIT_RESPONSE)
Expand Down
Expand Up @@ -185,6 +185,30 @@ public void incrementEquals() {
assertNotEquals(increment2, increment4);
}

@Test
public void maximumEquals() {
FieldValue maximum1 = FieldValue.maximum(42);
FieldValue maximum2 = FieldValue.maximum(42);
FieldValue maximum3 = FieldValue.maximum(42.0);
FieldValue maximum4 = FieldValue.maximum(42.0);
assertEquals(maximum1, maximum2);
assertEquals(maximum3, maximum4);
assertNotEquals(maximum1, maximum3);
assertNotEquals(maximum2, maximum4);
}

@Test
public void minimumEquals() {
FieldValue minimum1 = FieldValue.minimum(42);
FieldValue minimum2 = FieldValue.minimum(42);
FieldValue minimum3 = FieldValue.minimum(42.0);
FieldValue minimum4 = FieldValue.minimum(42.0);
assertEquals(minimum1, minimum2);
assertEquals(minimum3, minimum4);
assertNotEquals(minimum1, minimum3);
assertNotEquals(minimum2, minimum4);
}

@Test
public void arrayUnionWithPojo() throws ExecutionException, InterruptedException {
doReturn(commitResponse(1, 0))
Expand Down
Expand Up @@ -486,6 +486,14 @@ public static FieldTransform increment(Value value) {
return FieldTransform.newBuilder().setIncrement(value).build();
}

public static FieldTransform minimum(Value value) {
return FieldTransform.newBuilder().setMinimum(value).build();
}

public static FieldTransform maximum(Value value) {
return FieldTransform.newBuilder().setMaximum(value).build();
}

public static FieldTransform arrayUnion(Value... values) {
return FieldTransform.newBuilder()
.setAppendMissingElements(ArrayValue.newBuilder().addAllValues(Arrays.asList(values)))
Expand Down
Expand Up @@ -279,6 +279,24 @@ public void setWithIncrementAndMerge() throws ExecutionException, InterruptedExc
assertEquals(3L, docSnap.get("sum"));
}

@Test
public void setWithMaximumAndMerge() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("max", 1L)).get();
docRef.set(Collections.singletonMap("max", FieldValue.maximum(2)), SetOptions.merge()).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(2L, docSnap.get("max"));
}

@Test
public void setWithMinimumAndMerge() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("min", 1L)).get();
docRef.set(Collections.singletonMap("min", FieldValue.minimum(2)), SetOptions.merge()).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(1L, docSnap.get("min"));
}

@Test
public void mergeDocumentWithServerTimestamp() throws Exception {
Map<String, Object> originalMap = LocalFirestoreHelper.map("a", "b");
Expand Down Expand Up @@ -1392,6 +1410,42 @@ public void floatIncrement() throws ExecutionException, InterruptedException {
assertEquals(3.3, (Double) docSnap.get("sum"), DOUBLE_EPSILON);
}

@Test
public void integerMaximum() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("max", 1L)).get();
docRef.update("max", FieldValue.maximum(2)).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(2L, docSnap.get("max"));
}

@Test
public void floatMaximum() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("max", 1.1)).get();
docRef.update("max", FieldValue.maximum(2.2)).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(2.2, (Double) docSnap.get("max"), DOUBLE_EPSILON);
}

@Test
public void integerMinimum() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("min", 1L)).get();
docRef.update("min", FieldValue.minimum(2)).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(1L, docSnap.get("min"));
}

@Test
public void floatMinimum() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("min", 1.1)).get();
docRef.update("min", FieldValue.minimum(2.2)).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(1.1, (Double) docSnap.get("min"), DOUBLE_EPSILON);
}

@Test
public void getAllWithObserver() throws Exception {
DocumentReference ref1 = randomColl.document("doc1");
Expand Down

0 comments on commit 0f81a7a

Please sign in to comment.