16
16
17
17
package com .google .cloud .firestore ;
18
18
19
+ import com .google .common .base .Preconditions ;
20
+ import com .google .firestore .v1beta1 .ArrayValue ;
21
+ import com .google .firestore .v1beta1 .DocumentTransform .FieldTransform ;
22
+ import java .util .Arrays ;
23
+ import java .util .List ;
24
+ import java .util .Objects ;
19
25
import javax .annotation .Nonnull ;
20
26
21
27
/** Sentinel values that can be used when writing document fields with set() or update(). */
22
28
public abstract class FieldValue {
23
29
24
- static final Object SERVER_TIMESTAMP_SENTINEL = new Object ();
25
- static final Object DELETE_SENTINEL = new Object ();
30
+ private static final FieldValue SERVER_TIMESTAMP_SENTINEL =
31
+ new FieldValue () {
32
+ @ Override
33
+ boolean includeInDocumentMask () {
34
+ return false ;
35
+ }
36
+
37
+ @ Override
38
+ boolean includeInDocumentTransform () {
39
+ return true ;
40
+ }
41
+
42
+ @ Override
43
+ String getMethodName () {
44
+ return "FieldValue.serverTimestamp()" ;
45
+ }
46
+
47
+ @ Override
48
+ FieldTransform toProto (FieldPath path ) {
49
+ FieldTransform .Builder fieldTransform = FieldTransform .newBuilder ();
50
+ fieldTransform .setFieldPath (path .getEncodedPath ());
51
+ fieldTransform .setSetToServerValue (FieldTransform .ServerValue .REQUEST_TIME );
52
+ return fieldTransform .build ();
53
+ }
54
+ };
55
+
56
+ static final FieldValue DELETE_SENTINEL =
57
+ new FieldValue () {
58
+ @ Override
59
+ boolean includeInDocumentMask () {
60
+ return true ;
61
+ }
62
+
63
+ @ Override
64
+ boolean includeInDocumentTransform () {
65
+ return false ;
66
+ }
67
+
68
+ @ Override
69
+ String getMethodName () {
70
+ return "FieldValue.delete()" ;
71
+ }
72
+
73
+ @ Override
74
+ FieldTransform toProto (FieldPath path ) {
75
+ throw new IllegalStateException (
76
+ "FieldValue.delete() should not be included in a FieldTransform" );
77
+ }
78
+ };
79
+
80
+ static class ArrayUnionFieldValue extends FieldValue {
81
+ final List <Object > elements ;
82
+
83
+ ArrayUnionFieldValue (List <Object > elements ) {
84
+ this .elements = elements ;
85
+ }
86
+
87
+ @ Override
88
+ boolean includeInDocumentMask () {
89
+ return false ;
90
+ }
91
+
92
+ @ Override
93
+ boolean includeInDocumentTransform () {
94
+ return true ;
95
+ }
96
+
97
+ @ Override
98
+ String getMethodName () {
99
+ return "FieldValue.arrayUnion()" ;
100
+ }
101
+
102
+ @ Override
103
+ FieldTransform toProto (FieldPath path ) {
104
+ ArrayValue .Builder encodedElements = ArrayValue .newBuilder ();
105
+
106
+ for (Object element : elements ) {
107
+ encodedElements .addValues (
108
+ UserDataConverter .encodeValue (path , element , UserDataConverter .ARGUMENT ));
109
+ }
110
+
111
+ FieldTransform .Builder fieldTransform = FieldTransform .newBuilder ();
112
+ fieldTransform .setFieldPath (path .getEncodedPath ());
113
+ fieldTransform .setAppendMissingElements (encodedElements );
114
+ return fieldTransform .build ();
115
+ }
116
+
117
+ @ Override
118
+ public boolean equals (Object o ) {
119
+ if (this == o ) {
120
+ return true ;
121
+ }
122
+ if (o == null || getClass () != o .getClass ()) {
123
+ return false ;
124
+ }
125
+ ArrayUnionFieldValue that = (ArrayUnionFieldValue ) o ;
126
+ return Objects .equals (elements , that .elements );
127
+ }
128
+
129
+ @ Override
130
+ public int hashCode () {
131
+ return Objects .hash (elements );
132
+ }
133
+ }
134
+
135
+ static class ArrayRemoveFieldValue extends FieldValue {
136
+ final List <Object > elements ;
137
+
138
+ ArrayRemoveFieldValue (List <Object > elements ) {
139
+ this .elements = elements ;
140
+ }
141
+
142
+ @ Override
143
+ boolean includeInDocumentMask () {
144
+ return false ;
145
+ }
146
+
147
+ @ Override
148
+ boolean includeInDocumentTransform () {
149
+ return true ;
150
+ }
151
+
152
+ @ Override
153
+ String getMethodName () {
154
+ return "FieldValue.arrayRemove()" ;
155
+ }
156
+
157
+ @ Override
158
+ FieldTransform toProto (FieldPath path ) {
159
+ ArrayValue .Builder encodedElements = ArrayValue .newBuilder ();
160
+
161
+ for (Object element : elements ) {
162
+ encodedElements .addValues (
163
+ UserDataConverter .encodeValue (path , element , UserDataConverter .ARGUMENT ));
164
+ }
165
+
166
+ FieldTransform .Builder fieldTransform = FieldTransform .newBuilder ();
167
+ fieldTransform .setFieldPath (path .getEncodedPath ());
168
+ fieldTransform .setRemoveAllFromArray (encodedElements );
169
+ return fieldTransform .build ();
170
+ }
171
+
172
+ @ Override
173
+ public boolean equals (Object o ) {
174
+ if (this == o ) {
175
+ return true ;
176
+ }
177
+ if (o == null || getClass () != o .getClass ()) {
178
+ return false ;
179
+ }
180
+ ArrayRemoveFieldValue that = (ArrayRemoveFieldValue ) o ;
181
+ return Objects .equals (elements , that .elements );
182
+ }
183
+
184
+ @ Override
185
+ public int hashCode () {
186
+ return Objects .hash (elements );
187
+ }
188
+ }
26
189
27
190
private FieldValue () {}
28
191
@@ -31,16 +194,59 @@ private FieldValue() {}
31
194
* written data.
32
195
*/
33
196
@ Nonnull
34
- public static Object serverTimestamp () {
197
+ public static FieldValue serverTimestamp () {
35
198
return SERVER_TIMESTAMP_SENTINEL ;
36
199
}
37
200
38
201
/** Returns a sentinel used with update() to mark a field for deletion. */
39
202
@ Nonnull
40
- public static Object delete () {
203
+ public static FieldValue delete () {
41
204
return DELETE_SENTINEL ;
42
205
}
43
206
207
+ /**
208
+ * Returns a special value that can be used with set() or update() that tells the server to union
209
+ * the given elements with any array value that already exists on the server. Each specified
210
+ * element that doesn't already exist in the array will be added to the end. If the field being
211
+ * modified is not already an array it will be overwritten with an array containing exactly the
212
+ * specified elements.
213
+ *
214
+ * @param elements The elements to union into the array.
215
+ * @return The FieldValue sentinel for use in a call to set() or update().
216
+ */
217
+ @ Nonnull
218
+ public static FieldValue arrayUnion (@ Nonnull Object ... elements ) {
219
+ Preconditions .checkArgument (elements .length > 0 , "arrayUnion() expects at least 1 element" );
220
+ return new ArrayUnionFieldValue (Arrays .asList (elements ));
221
+ }
222
+
223
+ /**
224
+ * Returns a special value that can be used with set() or update() that tells the server to remove
225
+ * the given elements from any array value that already exists on the server. All instances of
226
+ * each element specified will be removed from the array. If the field being modified is not
227
+ * already an array it will be overwritten with an empty array.
228
+ *
229
+ * @param elements The elements to remove from the array.
230
+ * @return The FieldValue sentinel for use in a call to set() or update().
231
+ */
232
+ @ Nonnull
233
+ public static FieldValue arrayRemove (@ Nonnull Object ... elements ) {
234
+ Preconditions .checkArgument (elements .length > 0 , "arrayRemove() expects at least 1 element" );
235
+ return new ArrayRemoveFieldValue (Arrays .asList (elements ));
236
+ }
237
+
238
+ /** Whether this FieldTransform should be included in the document mask. */
239
+ abstract boolean includeInDocumentMask ();
240
+
241
+ /** Whether this FieldTransform should be included in the list of document transforms. */
242
+ abstract boolean includeInDocumentTransform ();
243
+
244
+ /** The name of the method that returned this FieldValue instance. */
245
+ abstract String getMethodName ();
246
+
247
+ /** Generates the field transform proto. */
248
+ abstract FieldTransform toProto (FieldPath path );
249
+
44
250
/**
45
251
* Returns true if this FieldValue is equal to the provided object.
46
252
*
0 commit comments