Search in sources :

Example 6 with ImmutableSortedMap

use of com.google.firebase.database.collection.ImmutableSortedMap in project firebase-android-sdk by firebase.

the class View method computeDocChanges.

/**
 * Iterates over a set of doc changes, applies the query limit, and computes what the new results
 * should be, what the changes were, and whether we may need to go back to the local cache for
 * more results. Does not make any changes to the view.
 *
 * @param docChanges The doc changes to apply to this view.
 * @param previousChanges If this is being called with a refill, then start with this set of docs
 *     and changes instead of the current view.
 * @return a new set of docs, changes, and refill flag.
 */
public DocumentChanges computeDocChanges(ImmutableSortedMap<DocumentKey, Document> docChanges, @Nullable DocumentChanges previousChanges) {
    DocumentViewChangeSet changeSet = previousChanges != null ? previousChanges.changeSet : new DocumentViewChangeSet();
    DocumentSet oldDocumentSet = previousChanges != null ? previousChanges.documentSet : documentSet;
    ImmutableSortedSet<DocumentKey> newMutatedKeys = previousChanges != null ? previousChanges.mutatedKeys : mutatedKeys;
    DocumentSet newDocumentSet = oldDocumentSet;
    boolean needsRefill = false;
    // Track the last doc in a (full) limit. This is necessary, because some update (a delete, or an
    // update moving a doc past the old limit) might mean there is some other document in the local
    // cache that either should come (1) between the old last limit doc and the new last document,
    // in the case of updates, or (2) after the new last document, in the case of deletes. So we
    // keep this doc at the old limit to compare the updates to.
    // 
    // Note that this should never get used in a refill (when previousChanges is set), because there
    // will only be adds -- no deletes or updates.
    Document lastDocInLimit = (query.hasLimitToFirst() && oldDocumentSet.size() == query.getLimitToFirst()) ? oldDocumentSet.getLastDocument() : null;
    Document firstDocInLimit = (query.hasLimitToLast() && oldDocumentSet.size() == query.getLimitToLast()) ? oldDocumentSet.getFirstDocument() : null;
    for (Map.Entry<DocumentKey, Document> entry : docChanges) {
        DocumentKey key = entry.getKey();
        Document oldDoc = oldDocumentSet.getDocument(key);
        Document newDoc = query.matches(entry.getValue()) ? entry.getValue() : null;
        boolean oldDocHadPendingMutations = oldDoc != null && this.mutatedKeys.contains(oldDoc.getKey());
        // We only consider committed mutations for documents that were mutated during the lifetime of
        // the view.
        boolean newDocHasPendingMutations = newDoc != null && (newDoc.hasLocalMutations() || (this.mutatedKeys.contains(newDoc.getKey()) && newDoc.hasCommittedMutations()));
        boolean changeApplied = false;
        // Calculate change
        if (oldDoc != null && newDoc != null) {
            boolean docsEqual = oldDoc.getData().equals(newDoc.getData());
            if (!docsEqual) {
                if (!shouldWaitForSyncedDocument(oldDoc, newDoc)) {
                    changeSet.addChange(DocumentViewChange.create(Type.MODIFIED, newDoc));
                    changeApplied = true;
                    if ((lastDocInLimit != null && query.comparator().compare(newDoc, lastDocInLimit) > 0) || (firstDocInLimit != null && query.comparator().compare(newDoc, firstDocInLimit) < 0)) {
                        // This doc moved from inside the limit to outside the limit. That means there may be
                        // some doc in the local cache that should be included instead.
                        needsRefill = true;
                    }
                }
            } else if (oldDocHadPendingMutations != newDocHasPendingMutations) {
                changeSet.addChange(DocumentViewChange.create(Type.METADATA, newDoc));
                changeApplied = true;
            }
        } else if (oldDoc == null && newDoc != null) {
            changeSet.addChange(DocumentViewChange.create(Type.ADDED, newDoc));
            changeApplied = true;
        } else if (oldDoc != null && newDoc == null) {
            changeSet.addChange(DocumentViewChange.create(Type.REMOVED, oldDoc));
            changeApplied = true;
            if (lastDocInLimit != null || firstDocInLimit != null) {
                // A doc was removed from a full limit query. We'll need to requery from the local cache
                // to see if we know about some other doc that should be in the results.
                needsRefill = true;
            }
        }
        if (changeApplied) {
            if (newDoc != null) {
                newDocumentSet = newDocumentSet.add(newDoc);
                if (newDoc.hasLocalMutations()) {
                    newMutatedKeys = newMutatedKeys.insert(newDoc.getKey());
                } else {
                    newMutatedKeys = newMutatedKeys.remove(newDoc.getKey());
                }
            } else {
                newDocumentSet = newDocumentSet.remove(key);
                newMutatedKeys = newMutatedKeys.remove(key);
            }
        }
    }
    // Drop documents out to meet limitToFirst/limitToLast requirement.
    if (query.hasLimitToFirst() || query.hasLimitToLast()) {
        long limit = query.hasLimitToFirst() ? query.getLimitToFirst() : query.getLimitToLast();
        for (long i = newDocumentSet.size() - limit; i > 0; --i) {
            Document oldDoc = query.hasLimitToFirst() ? newDocumentSet.getLastDocument() : newDocumentSet.getFirstDocument();
            newDocumentSet = newDocumentSet.remove(oldDoc.getKey());
            newMutatedKeys = newMutatedKeys.remove(oldDoc.getKey());
            changeSet.addChange(DocumentViewChange.create(Type.REMOVED, oldDoc));
        }
    }
    hardAssert(!needsRefill || previousChanges == null, "View was refilled using docs that themselves needed refilling.");
    return new DocumentChanges(newDocumentSet, changeSet, newMutatedKeys, needsRefill);
}
Also used : DocumentKey(com.google.firebase.firestore.model.DocumentKey) DocumentSet(com.google.firebase.firestore.model.DocumentSet) Document(com.google.firebase.firestore.model.Document) Map(java.util.Map) ImmutableSortedMap(com.google.firebase.database.collection.ImmutableSortedMap)

Example 7 with ImmutableSortedMap

use of com.google.firebase.database.collection.ImmutableSortedMap in project firebase-android-sdk by firebase.

the class SQLiteIndexManager method updateIndexEntries.

@Override
public void updateIndexEntries(ImmutableSortedMap<DocumentKey, Document> documents) {
    hardAssert(started, "IndexManager not started");
    for (Map.Entry<DocumentKey, Document> entry : documents) {
        Collection<FieldIndex> fieldIndexes = getFieldIndexes(entry.getKey().getCollectionGroup());
        for (FieldIndex fieldIndex : fieldIndexes) {
            SortedSet<IndexEntry> existingEntries = getExistingIndexEntries(entry.getKey(), fieldIndex);
            SortedSet<IndexEntry> newEntries = computeIndexEntries(entry.getValue(), fieldIndex);
            if (!existingEntries.equals(newEntries)) {
                updateEntries(entry.getValue(), existingEntries, newEntries);
            }
        }
    }
}
Also used : FieldIndex(com.google.firebase.firestore.model.FieldIndex) DocumentKey(com.google.firebase.firestore.model.DocumentKey) IndexEntry(com.google.firebase.firestore.index.IndexEntry) Document(com.google.firebase.firestore.model.Document) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableSortedMap(com.google.firebase.database.collection.ImmutableSortedMap)

Example 8 with ImmutableSortedMap

use of com.google.firebase.database.collection.ImmutableSortedMap in project firebase-android-sdk by firebase.

the class LocalDocumentsView method computeViews.

/*Computes the local view for doc */
private ImmutableSortedMap<DocumentKey, Document> computeViews(Map<DocumentKey, MutableDocument> docs, Map<DocumentKey, Overlay> overlays, Set<DocumentKey> existenceStateChanged) {
    ImmutableSortedMap<DocumentKey, Document> results = emptyDocumentMap();
    Map<DocumentKey, MutableDocument> recalculateDocuments = new HashMap<>();
    for (MutableDocument doc : docs.values()) {
        Overlay overlay = overlays.get(doc.getKey());
        // but would now match.
        if (existenceStateChanged.contains(doc.getKey()) && (overlay == null || overlay.getMutation() instanceof PatchMutation)) {
            recalculateDocuments.put(doc.getKey(), doc);
        } else if (overlay != null) {
            overlay.getMutation().applyToLocalView(doc, null, Timestamp.now());
        }
    }
    recalculateAndSaveOverlays(recalculateDocuments);
    for (Map.Entry<DocumentKey, MutableDocument> entry : docs.entrySet()) {
        results = results.insert(entry.getKey(), entry.getValue());
    }
    return results;
}
Also used : HashMap(java.util.HashMap) DocumentKey(com.google.firebase.firestore.model.DocumentKey) MutableDocument(com.google.firebase.firestore.model.MutableDocument) PatchMutation(com.google.firebase.firestore.model.mutation.PatchMutation) Document(com.google.firebase.firestore.model.Document) MutableDocument(com.google.firebase.firestore.model.MutableDocument) Overlay(com.google.firebase.firestore.model.mutation.Overlay) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) ImmutableSortedMap(com.google.firebase.database.collection.ImmutableSortedMap) DocumentCollections.emptyDocumentMap(com.google.firebase.firestore.model.DocumentCollections.emptyDocumentMap)

Example 9 with ImmutableSortedMap

use of com.google.firebase.database.collection.ImmutableSortedMap in project firebase-android-sdk by firebase.

the class LocalDocumentsView method getDocumentsMatchingCollectionQuery.

private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollectionQuery(Query query, IndexOffset offset) {
    Map<DocumentKey, MutableDocument> remoteDocuments = remoteDocumentCache.getAll(query.getPath(), offset);
    Map<DocumentKey, Overlay> overlays = documentOverlayCache.getOverlays(query.getPath(), offset.getLargestBatchId());
    // for all overlays in the initial document set.
    for (Map.Entry<DocumentKey, Overlay> entry : overlays.entrySet()) {
        if (!remoteDocuments.containsKey(entry.getKey())) {
            remoteDocuments.put(entry.getKey(), MutableDocument.newInvalidDocument(entry.getKey()));
        }
    }
    // Apply the overlays and match against the query.
    ImmutableSortedMap<DocumentKey, Document> results = emptyDocumentMap();
    for (Map.Entry<DocumentKey, MutableDocument> docEntry : remoteDocuments.entrySet()) {
        Overlay overlay = overlays.get(docEntry.getKey());
        if (overlay != null) {
            overlay.getMutation().applyToLocalView(docEntry.getValue(), null, Timestamp.now());
        }
        // Finally, insert the documents that still match the query
        if (query.matches(docEntry.getValue())) {
            results = results.insert(docEntry.getKey(), docEntry.getValue());
        }
    }
    return results;
}
Also used : DocumentKey(com.google.firebase.firestore.model.DocumentKey) MutableDocument(com.google.firebase.firestore.model.MutableDocument) Overlay(com.google.firebase.firestore.model.mutation.Overlay) Document(com.google.firebase.firestore.model.Document) MutableDocument(com.google.firebase.firestore.model.MutableDocument) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) ImmutableSortedMap(com.google.firebase.database.collection.ImmutableSortedMap) DocumentCollections.emptyDocumentMap(com.google.firebase.firestore.model.DocumentCollections.emptyDocumentMap)

Example 10 with ImmutableSortedMap

use of com.google.firebase.database.collection.ImmutableSortedMap in project GreenHouse by utsanjan.

the class NodeUtilities method NodeFromJSON.

public static Node NodeFromJSON(Object value, Node priority) throws DatabaseException {
    Map<ChildKey, Node> childData;
    try {
        if (value instanceof Map) {
            Map mapValue = (Map) value;
            if (mapValue.containsKey(".priority")) {
                priority = PriorityUtilities.parsePriority(mapValue.get(".priority"));
            }
            if (mapValue.containsKey(".value")) {
                value = mapValue.get(".value");
            }
        }
        if (value == null) {
            return EmptyNode.Empty();
        }
        if (value instanceof String) {
            return new StringNode((String) value, priority);
        }
        if (value instanceof Long) {
            return new LongNode((Long) value, priority);
        }
        if (value instanceof Integer) {
            return new LongNode(Long.valueOf(((Integer) value).intValue()), priority);
        }
        if (value instanceof Double) {
            return new DoubleNode((Double) value, priority);
        }
        if (value instanceof Boolean) {
            return new BooleanNode((Boolean) value, priority);
        }
        if (!(value instanceof Map) && !(value instanceof List)) {
            throw new DatabaseException("Failed to parse node with class " + value.getClass().toString());
        }
        if (value instanceof Map) {
            Map mapValue2 = (Map) value;
            if (mapValue2.containsKey(ServerValues.NAME_SUBKEY_SERVERVALUE)) {
                Node node = new DeferredValueNode(mapValue2, priority);
                return node;
            }
            childData = new HashMap<>(mapValue2.size());
            for (String key : mapValue2.keySet()) {
                if (!key.startsWith(".")) {
                    Node childNode = NodeFromJSON(mapValue2.get(key));
                    if (!childNode.isEmpty()) {
                        ChildKey childKey = ChildKey.fromString(key);
                        childData.put(childKey, childNode);
                    }
                }
            }
        } else {
            List listValue = (List) value;
            childData = new HashMap<>(listValue.size());
            for (int i = 0; i < listValue.size(); i++) {
                String key2 = "" + i;
                Node childNode2 = NodeFromJSON(listValue.get(i));
                if (!childNode2.isEmpty()) {
                    ChildKey childKey2 = ChildKey.fromString(key2);
                    childData.put(childKey2, childNode2);
                }
            }
        }
        if (childData.isEmpty()) {
            return EmptyNode.Empty();
        }
        ImmutableSortedMap<ChildKey, Node> childSet = ImmutableSortedMap.Builder.fromMap(childData, ChildrenNode.NAME_ONLY_COMPARATOR);
        return new ChildrenNode(childSet, priority);
    } catch (ClassCastException e) {
        throw new DatabaseException("Failed to parse node", e);
    }
}
Also used : List(java.util.List) Map(java.util.Map) ImmutableSortedMap(com.google.firebase.database.collection.ImmutableSortedMap) HashMap(java.util.HashMap) DatabaseException(com.google.firebase.database.DatabaseException)

Aggregations

ImmutableSortedMap (com.google.firebase.database.collection.ImmutableSortedMap)10 Map (java.util.Map)10 HashMap (java.util.HashMap)9 DocumentKey (com.google.firebase.firestore.model.DocumentKey)7 Document (com.google.firebase.firestore.model.Document)6 MutableDocument (com.google.firebase.firestore.model.MutableDocument)5 DocumentCollections.emptyDocumentMap (com.google.firebase.firestore.model.DocumentCollections.emptyDocumentMap)3 TargetChange (com.google.firebase.firestore.remote.TargetChange)3 TreeMap (java.util.TreeMap)3 DatabaseException (com.google.firebase.database.DatabaseException)2 Overlay (com.google.firebase.firestore.model.mutation.Overlay)2 List (java.util.List)2 Query (com.google.firebase.firestore.core.Query)1 IndexEntry (com.google.firebase.firestore.index.IndexEntry)1 LocalViewChanges (com.google.firebase.firestore.local.LocalViewChanges)1 QueryResult (com.google.firebase.firestore.local.QueryResult)1 DocumentSet (com.google.firebase.firestore.model.DocumentSet)1 FieldIndex (com.google.firebase.firestore.model.FieldIndex)1 ResourcePath (com.google.firebase.firestore.model.ResourcePath)1 SnapshotVersion (com.google.firebase.firestore.model.SnapshotVersion)1