Skip to content

Mutable Documents #2383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Feb 25, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.DocumentSet;
import com.google.firebase.firestore.model.MutableDocument;
import com.google.firebase.firestore.model.ObjectValue;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -42,8 +43,7 @@ public static FirebaseFirestore firestore() {
public static DocumentSnapshot documentSnapshot(
String path, Map<String, Object> data, boolean isFromCache) {
if (data == null) {
return DocumentSnapshot.fromNoDocument(
FIRESTORE, key(path), isFromCache, /*hasPendingWrites=*/ false);
return DocumentSnapshot.fromNoDocument(FIRESTORE, key(path), isFromCache);
} else {
return DocumentSnapshot.fromDocument(
FIRESTORE, doc(path, 1L, data), isFromCache, /*hasPendingWrites=*/ false);
Expand Down Expand Up @@ -72,36 +72,23 @@ public static QuerySnapshot querySnapshot(
Map<String, ObjectValue> docsToAdd,
boolean hasPendingWrites,
boolean isFromCache) {
DocumentSet oldDocuments = docSet(Document.keyComparator());
DocumentSet oldDocuments = docSet(Document.KEY_COMPARATOR);
ImmutableSortedSet<DocumentKey> mutatedKeys = DocumentKey.emptyKeySet();
for (Map.Entry<String, ObjectValue> pair : oldDocs.entrySet()) {
String docKey = path + "/" + pair.getKey();
oldDocuments =
oldDocuments.add(
doc(
docKey,
1L,
pair.getValue(),
hasPendingWrites
? Document.DocumentState.SYNCED
: Document.DocumentState.LOCAL_MUTATIONS));

MutableDocument doc = doc(docKey, 1L, pair.getValue());
if (hasPendingWrites) doc.setHasLocalMutations();
oldDocuments = oldDocuments.add(doc);
if (hasPendingWrites) {
mutatedKeys = mutatedKeys.insert(key(docKey));
}
}
DocumentSet newDocuments = docSet(Document.keyComparator());
DocumentSet newDocuments = docSet(Document.KEY_COMPARATOR);
List<DocumentViewChange> documentChanges = new ArrayList<>();
for (Map.Entry<String, ObjectValue> pair : docsToAdd.entrySet()) {
String docKey = path + "/" + pair.getKey();
Document docToAdd =
doc(
docKey,
1L,
pair.getValue(),
hasPendingWrites
? Document.DocumentState.SYNCED
: Document.DocumentState.LOCAL_MUTATIONS);
MutableDocument docToAdd = doc(docKey, 1L, pair.getValue());
if (hasPendingWrites) docToAdd.setHasLocalMutations();
newDocuments = newDocuments.add(docToAdd);
documentChanges.add(DocumentViewChange.create(Type.ADDED, docToAdd));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.DocumentSet;
import com.google.firebase.firestore.model.MutableDocument;
import com.google.firebase.firestore.model.ObjectValue;
import com.google.firebase.firestore.model.ResourcePath;
import com.google.firebase.firestore.model.SnapshotVersion;
Expand Down Expand Up @@ -62,28 +63,25 @@ public static SnapshotVersion version(long versionMicros) {
return new SnapshotVersion(new Timestamp(seconds, nanos));
}

public static Document doc(String key, long version, Map<String, Object> data) {
return new Document(
key(key), version(version), wrapObject(data), Document.DocumentState.SYNCED);
public static MutableDocument doc(String key, long version, Map<String, Object> data) {
return doc(key(key), version, wrapObject(data));
}

public static Document doc(DocumentKey key, long version, Map<String, Object> data) {
return new Document(key, version(version), wrapObject(data), Document.DocumentState.SYNCED);
public static MutableDocument doc(DocumentKey key, long version, Map<String, Object> data) {
return doc(key, version, wrapObject(data));
}

public static Document doc(
String key, long version, ObjectValue data, Document.DocumentState documentState) {
return new Document(key(key), version(version), data, documentState);
public static MutableDocument doc(String key, long version, ObjectValue data) {
return doc(key(key), version, data);
}

public static Document doc(
String key, long version, Map<String, Object> data, Document.DocumentState documentState) {
return new Document(key(key), version(version), wrapObject(data), documentState);
public static MutableDocument doc(DocumentKey key, long version, ObjectValue data) {
return new MutableDocument(key).convertToFoundDocument(version(version), data);
}

public static DocumentSet docSet(Comparator<Document> comparator, Document... documents) {
public static DocumentSet docSet(Comparator<Document> comparator, MutableDocument... documents) {
DocumentSet set = DocumentSet.emptySet(comparator);
for (Document document : documents) {
for (MutableDocument document : documents) {
set = set.add(document);
}
return set;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public Type getType() {
*
* @return A snapshot of the new data (for {@link DocumentChange.Type#ADDED} or {@link
* DocumentChange.Type#MODIFIED}) or the removed data (for {@link
* DocumentChange.Type.REMOVED}).
* DocumentChange.Type#REMOVED}).
*/
@NonNull
public QueryDocumentSnapshot getDocument() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,7 @@ private ListenerRegistration addSnapshotListenerInternal(
} else {
// We don't raise `hasPendingWrites` for deleted documents.
documentSnapshot =
DocumentSnapshot.fromNoDocument(
firestore, key, snapshot.isFromCache(), /* hasPendingWrites= */ false);
DocumentSnapshot.fromNoDocument(firestore, key, snapshot.isFromCache());
}
userListener.onEvent(documentSnapshot, null);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ static DocumentSnapshot fromDocument(
}

static DocumentSnapshot fromNoDocument(
FirebaseFirestore firestore, DocumentKey key, boolean fromCache, boolean hasPendingWrites) {
return new DocumentSnapshot(firestore, key, null, fromCache, hasPendingWrites);
FirebaseFirestore firestore, DocumentKey key, boolean fromCache) {
return new DocumentSnapshot(firestore, key, null, fromCache, /* hasPendingWrites= */ false);
}

/** @return The id of the document. */
Expand Down Expand Up @@ -534,7 +534,8 @@ public boolean equals(@Nullable Object obj) {
public int hashCode() {
int hash = firestore.hashCode();
hash = hash * 31 + key.hashCode();
hash = hash * 31 + (doc != null ? doc.hashCode() : 0);
hash = hash * 31 + (doc != null ? doc.getKey().hashCode() : 0);
hash = hash * 31 + (doc != null ? doc.getData().hashCode() : 0);
hash = hash * 31 + metadata.hashCode();
return hash;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public class QuerySnapshot implements Iterable<QueryDocumentSnapshot> {
}

private class QuerySnapshotIterator implements Iterator<QueryDocumentSnapshot> {
private final Iterator<com.google.firebase.firestore.model.Document> it;
private final Iterator<Document> it;

QuerySnapshotIterator(Iterator<com.google.firebase.firestore.model.Document> it) {
QuerySnapshotIterator(Iterator<Document> it) {
this.it = it;
}

Expand Down Expand Up @@ -133,7 +133,7 @@ public List<DocumentChange> getDocumentChanges(@NonNull MetadataChanges metadata
@NonNull
public List<DocumentSnapshot> getDocuments() {
List<DocumentSnapshot> res = new ArrayList<>(snapshot.getDocuments().size());
for (com.google.firebase.firestore.model.Document doc : snapshot.getDocuments()) {
for (Document doc : snapshot.getDocuments()) {
res.add(convertDocument(doc));
}
return res;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.firestore.core.UserData.ParsedSetData;
import com.google.firebase.firestore.core.UserData.ParsedUpdateData;
import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.MaybeDocument;
import com.google.firebase.firestore.model.NoDocument;
import com.google.firebase.firestore.model.MutableDocument;
import com.google.firebase.firestore.util.Executors;
import com.google.firebase.firestore.util.Util;
import java.util.Collections;
Expand Down Expand Up @@ -195,17 +193,17 @@ private Task<DocumentSnapshot> getAsync(DocumentReference documentRef) {
if (!task.isSuccessful()) {
throw task.getException();
}
List<MaybeDocument> docs = task.getResult();
List<MutableDocument> docs = task.getResult();
if (docs.size() != 1) {
throw fail("Mismatch in docs returned from document lookup.");
}
MaybeDocument doc = docs.get(0);
if (doc instanceof Document) {
MutableDocument doc = docs.get(0);
if (doc.isFoundDocument()) {
return DocumentSnapshot.fromDocument(
firestore, (Document) doc, /*fromCache=*/ false, /*hasPendingWrites=*/ false);
} else if (doc instanceof NoDocument) {
firestore, doc, /*fromCache=*/ false, /*hasPendingWrites=*/ false);
} else if (doc.isNoDocument()) {
return DocumentSnapshot.fromNoDocument(
firestore, doc.getKey(), /*fromCache=*/ false, /*hasPendingWrites=*/ false);
firestore, doc.getKey(), /*fromCache=*/ false);
} else {
throw fail(
"BatchGetDocumentsRequest returned unexpected document type: "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public ParsedUpdateData parseUpdateData(Map<String, Object> data) {

ParseAccumulator accumulator = new ParseAccumulator(UserData.Source.Update);
ParseContext context = accumulator.rootContext();
ObjectValue.Builder updateData = ObjectValue.newBuilder();
ObjectValue updateData = new ObjectValue();

for (Entry<String, Object> entry : data.entrySet()) {
FieldPath fieldPath =
Expand All @@ -130,7 +130,7 @@ public ParsedUpdateData parseUpdateData(Map<String, Object> data) {
}
}

return accumulator.toUpdateData(updateData.build());
return accumulator.toUpdateData(updateData);
}

/**
Expand All @@ -146,7 +146,7 @@ public ParsedUpdateData parseUpdateData(List<Object> fieldsAndValues) {

ParseAccumulator accumulator = new ParseAccumulator(UserData.Source.Update);
ParseContext context = accumulator.rootContext();
ObjectValue.Builder updateData = ObjectValue.newBuilder();
ObjectValue updateData = new ObjectValue();

Iterator<Object> iterator = fieldsAndValues.iterator();
while (iterator.hasNext()) {
Expand Down Expand Up @@ -180,7 +180,7 @@ public ParsedUpdateData parseUpdateData(List<Object> fieldsAndValues) {
}
}

return accumulator.toUpdateData(updateData.build());
return accumulator.toUpdateData(updateData);
}

/** Parse a "query value" (e.g. value in a where filter or a value in a cursor bound). */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@

import com.google.firebase.database.collection.ImmutableSortedMap;
import com.google.firebase.database.collection.ImmutableSortedSet;
import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.MaybeDocument;
import com.google.firebase.firestore.model.MutableDocument;

/** Interface implemented by components that can apply changes from a bundle to local storage. */
public interface BundleCallback {
Expand All @@ -26,8 +27,8 @@ public interface BundleCallback {
*
* <p>LocalDocuments are re-calculated if there are remaining mutations in the queue.
*/
ImmutableSortedMap<DocumentKey, MaybeDocument> applyBundledDocuments(
ImmutableSortedMap<DocumentKey, MaybeDocument> documents, String bundleId);
ImmutableSortedMap<DocumentKey, Document> applyBundledDocuments(
ImmutableSortedMap<DocumentKey, MutableDocument> documents, String bundleId);

/** Saves the given NamedQuery to local persistence. */
void saveNamedQuery(NamedQuery namedQuery, ImmutableSortedSet<DocumentKey> documentKeys);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@

package com.google.firebase.firestore.bundle;

import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.MutableDocument;

/** A document that was saved to a bundle. */
public class BundleDocument implements BundleElement {
private Document document;
private MutableDocument document;

public BundleDocument(Document document) {
public BundleDocument(MutableDocument document) {
this.document = document;
}

Expand All @@ -31,7 +31,7 @@ public DocumentKey getKey() {
}

/** Returns the document. */
public Document getDocument() {
public MutableDocument getDocument() {
return document;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@

package com.google.firebase.firestore.bundle;

import static com.google.firebase.firestore.model.DocumentCollections.emptyMaybeDocumentMap;
import static com.google.firebase.firestore.model.DocumentCollections.emptyMutableDocumentMap;

import androidx.annotation.Nullable;
import com.google.firebase.database.collection.ImmutableSortedMap;
import com.google.firebase.database.collection.ImmutableSortedSet;
import com.google.firebase.firestore.LoadBundleTaskProgress;
import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.MaybeDocument;
import com.google.firebase.firestore.model.NoDocument;
import com.google.firebase.firestore.model.MutableDocument;
import com.google.firebase.firestore.util.Preconditions;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -39,15 +39,15 @@ public class BundleLoader {
private final List<NamedQuery> queries;
private final Map<DocumentKey, BundledDocumentMetadata> documentsMetadata;

private ImmutableSortedMap<DocumentKey, MaybeDocument> documents;
private ImmutableSortedMap<DocumentKey, MutableDocument> documents;
private long bytesLoaded;
@Nullable private DocumentKey currentDocument;

public BundleLoader(BundleCallback bundleCallback, BundleMetadata bundleMetadata) {
this.bundleCallback = bundleCallback;
this.bundleMetadata = bundleMetadata;
this.queries = new ArrayList<>();
this.documents = emptyMaybeDocumentMap();
this.documents = emptyMutableDocumentMap();
this.documentsMetadata = new HashMap<>();
}

Expand All @@ -73,10 +73,8 @@ public BundleLoader(BundleCallback bundleCallback, BundleMetadata bundleMetadata
documents =
documents.insert(
bundledDocumentMetadata.getKey(),
new NoDocument(
bundledDocumentMetadata.getKey(),
bundledDocumentMetadata.getReadTime(),
/* hasCommittedMutations= */ false));
new MutableDocument(bundledDocumentMetadata.getKey())
.convertToNoDocument(bundledDocumentMetadata.getReadTime()));
currentDocument = null;
}
} else if (bundleElement instanceof BundleDocument) {
Expand All @@ -103,7 +101,7 @@ public BundleLoader(BundleCallback bundleCallback, BundleMetadata bundleMetadata
}

/** Applies the loaded documents and queries to local store. Returns the document view changes. */
public ImmutableSortedMap<DocumentKey, MaybeDocument> applyChanges() {
public ImmutableSortedMap<DocumentKey, Document> applyChanges() {
Preconditions.checkArgument(
currentDocument == null,
"Bundled documents end with a document metadata element instead of a document.");
Expand All @@ -114,7 +112,7 @@ public ImmutableSortedMap<DocumentKey, MaybeDocument> applyChanges() {
bundleMetadata.getTotalDocuments(),
documents.size());

ImmutableSortedMap<DocumentKey, MaybeDocument> changes =
ImmutableSortedMap<DocumentKey, Document> changes =
bundleCallback.applyBundledDocuments(documents, bundleMetadata.getBundleId());

Map<String, ImmutableSortedSet<DocumentKey>> queryDocumentMap = getQueryDocumentMapping();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
import com.google.firebase.firestore.core.OrderBy;
import com.google.firebase.firestore.core.Query;
import com.google.firebase.firestore.core.Target;
import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.FieldPath;
import com.google.firebase.firestore.model.MutableDocument;
import com.google.firebase.firestore.model.ObjectValue;
import com.google.firebase.firestore.model.ResourcePath;
import com.google.firebase.firestore.model.SnapshotVersion;
Expand Down Expand Up @@ -111,11 +111,9 @@ BundleDocument decodeDocument(JSONObject document) throws JSONException {
decodeMapValue(value, document.getJSONObject("fields"));

return new BundleDocument(
new Document(
key,
updateTime,
ObjectValue.fromMap(value.getMapValue().getFieldsMap()),
Document.DocumentState.SYNCED));
new MutableDocument(key)
.convertToFoundDocument(
updateTime, ObjectValue.fromMap(value.getMapValue().getFieldsMap())));
}

private ResourcePath decodeName(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public boolean equals(Object o) {
public int hashCode() {
int res = 61;
res = res * 31 + type.hashCode();
res = res * 31 + document.hashCode();
res = res * 31 + document.getKey().hashCode();
res = res * 31 + document.getData().hashCode();
return res;
}

Expand Down
Loading