|
24 | 24 | import com.google.firebase.firestore.model.DocumentKey;
|
25 | 25 | import com.google.firebase.firestore.model.value.ArrayValue;
|
26 | 26 | import com.google.firebase.firestore.model.value.FieldValue;
|
27 |
| -import com.google.firebase.firestore.model.value.FieldValueOptions; |
28 | 27 | import com.google.firebase.firestore.model.value.ObjectValue;
|
29 | 28 | import com.google.firebase.firestore.model.value.ReferenceValue;
|
| 29 | +import com.google.firebase.firestore.model.value.ServerTimestampValue; |
| 30 | +import com.google.firebase.firestore.model.value.TimestampValue; |
30 | 31 | import com.google.firebase.firestore.util.CustomClassMapper;
|
31 | 32 | import com.google.firebase.firestore.util.Logger;
|
32 | 33 | import java.util.ArrayList;
|
@@ -80,6 +81,18 @@ public enum ServerTimestampBehavior {
|
80 | 81 | static final ServerTimestampBehavior DEFAULT = ServerTimestampBehavior.NONE;
|
81 | 82 | }
|
82 | 83 |
|
| 84 | + /** Holds settings that define field value deserialization options. */ |
| 85 | + static class FieldValueOptions { |
| 86 | + final ServerTimestampBehavior serverTimestampBehavior; |
| 87 | + final boolean timestampsInSnapshotsEnabled; |
| 88 | + |
| 89 | + private FieldValueOptions( |
| 90 | + ServerTimestampBehavior serverTimestampBehavior, boolean timestampsInSnapshotsEnabled) { |
| 91 | + this.serverTimestampBehavior = serverTimestampBehavior; |
| 92 | + this.timestampsInSnapshotsEnabled = timestampsInSnapshotsEnabled; |
| 93 | + } |
| 94 | + } |
| 95 | + |
83 | 96 | private final FirebaseFirestore firestore;
|
84 | 97 |
|
85 | 98 | private final DocumentKey key;
|
@@ -165,7 +178,7 @@ public Map<String, Object> getData(@NonNull ServerTimestampBehavior serverTimest
|
165 | 178 | ? null
|
166 | 179 | : convertObject(
|
167 | 180 | doc.getData(),
|
168 |
| - FieldValueOptions.create( |
| 181 | + new FieldValueOptions( |
169 | 182 | serverTimestampBehavior,
|
170 | 183 | firestore.getFirestoreSettings().areTimestampsInSnapshotsEnabled()));
|
171 | 184 | }
|
@@ -286,7 +299,7 @@ public Object get(
|
286 | 299 | serverTimestampBehavior, "Provided serverTimestampBehavior value must not be null.");
|
287 | 300 | return getInternal(
|
288 | 301 | fieldPath.getInternalPath(),
|
289 |
| - FieldValueOptions.create( |
| 302 | + new FieldValueOptions( |
290 | 303 | serverTimestampBehavior,
|
291 | 304 | firestore.getFirestoreSettings().areTimestampsInSnapshotsEnabled()));
|
292 | 305 | }
|
@@ -449,7 +462,7 @@ public Date getDate(
|
449 | 462 | Object maybeDate =
|
450 | 463 | getInternal(
|
451 | 464 | FieldPath.fromDotSeparatedPath(field).getInternalPath(),
|
452 |
| - FieldValueOptions.create( |
| 465 | + new FieldValueOptions( |
453 | 466 | serverTimestampBehavior, /*timestampsInSnapshotsEnabled=*/ false));
|
454 | 467 | return castTypedValue(maybeDate, field, Date.class);
|
455 | 468 | }
|
@@ -492,8 +505,7 @@ public Timestamp getTimestamp(
|
492 | 505 | Object maybeTimestamp =
|
493 | 506 | getInternal(
|
494 | 507 | FieldPath.fromDotSeparatedPath(field).getInternalPath(),
|
495 |
| - FieldValueOptions.create( |
496 |
| - serverTimestampBehavior, /*timestampsInSnapshotsEnabled=*/ true)); |
| 508 | + new FieldValueOptions(serverTimestampBehavior, /*timestampsInSnapshotsEnabled=*/ true)); |
497 | 509 | return castTypedValue(maybeTimestamp, field, Timestamp.class);
|
498 | 510 | }
|
499 | 511 |
|
@@ -571,29 +583,56 @@ private Object convertValue(FieldValue value, FieldValueOptions options) {
|
571 | 583 | } else if (value instanceof ArrayValue) {
|
572 | 584 | return convertArray((ArrayValue) value, options);
|
573 | 585 | } else if (value instanceof ReferenceValue) {
|
574 |
| - ReferenceValue referenceValue = (ReferenceValue) value; |
575 |
| - DocumentKey key = (DocumentKey) referenceValue.value(options); |
576 |
| - DatabaseId refDatabase = ((ReferenceValue) value).getDatabaseId(); |
577 |
| - DatabaseId database = this.firestore.getDatabaseId(); |
578 |
| - if (!refDatabase.equals(database)) { |
579 |
| - // TODO: Somehow support foreign references. |
580 |
| - Logger.warn( |
581 |
| - "DocumentSnapshot", |
582 |
| - "Document %s contains a document reference within a different database " |
583 |
| - + "(%s/%s) which is not supported. It will be treated as a reference in " |
584 |
| - + "the current database (%s/%s) instead.", |
585 |
| - key.getPath(), |
586 |
| - refDatabase.getProjectId(), |
587 |
| - refDatabase.getDatabaseId(), |
588 |
| - database.getProjectId(), |
589 |
| - database.getDatabaseId()); |
590 |
| - } |
591 |
| - return new DocumentReference(key, firestore); |
| 586 | + return convertReference((ReferenceValue) value); |
| 587 | + } else if (value instanceof TimestampValue) { |
| 588 | + return convertTimestamp((TimestampValue) value, options); |
| 589 | + } else if (value instanceof ServerTimestampValue) { |
| 590 | + return convertServerTimestamp((ServerTimestampValue) value, options); |
| 591 | + } else { |
| 592 | + return value.value(); |
| 593 | + } |
| 594 | + } |
| 595 | + |
| 596 | + private Object convertServerTimestamp(ServerTimestampValue value, FieldValueOptions options) { |
| 597 | + switch (options.serverTimestampBehavior) { |
| 598 | + case PREVIOUS: |
| 599 | + return value.getPreviousValue(); |
| 600 | + case ESTIMATE: |
| 601 | + return value.getLocalWriteTime(); |
| 602 | + default: |
| 603 | + return value.value(); |
| 604 | + } |
| 605 | + } |
| 606 | + |
| 607 | + private Object convertTimestamp(TimestampValue value, FieldValueOptions options) { |
| 608 | + Timestamp timestamp = value.value(); |
| 609 | + if (options.timestampsInSnapshotsEnabled) { |
| 610 | + return timestamp; |
592 | 611 | } else {
|
593 |
| - return value.value(options); |
| 612 | + return timestamp.toDate(); |
594 | 613 | }
|
595 | 614 | }
|
596 | 615 |
|
| 616 | + private Object convertReference(ReferenceValue value) { |
| 617 | + DocumentKey key = value.value(); |
| 618 | + DatabaseId refDatabase = value.getDatabaseId(); |
| 619 | + DatabaseId database = this.firestore.getDatabaseId(); |
| 620 | + if (!refDatabase.equals(database)) { |
| 621 | + // TODO: Somehow support foreign references. |
| 622 | + Logger.warn( |
| 623 | + "DocumentSnapshot", |
| 624 | + "Document %s contains a document reference within a different database " |
| 625 | + + "(%s/%s) which is not supported. It will be treated as a reference in " |
| 626 | + + "the current database (%s/%s) instead.", |
| 627 | + key.getPath(), |
| 628 | + refDatabase.getProjectId(), |
| 629 | + refDatabase.getDatabaseId(), |
| 630 | + database.getProjectId(), |
| 631 | + database.getDatabaseId()); |
| 632 | + } |
| 633 | + return new DocumentReference(key, firestore); |
| 634 | + } |
| 635 | + |
597 | 636 | private Map<String, Object> convertObject(ObjectValue objectValue, FieldValueOptions options) {
|
598 | 637 | Map<String, Object> result = new HashMap<>();
|
599 | 638 | for (Map.Entry<String, FieldValue> entry : objectValue.getInternalValue()) {
|
|
0 commit comments