private ViewCache applyServerMerge()

in src/main/java/com/google/firebase/database/core/view/ViewProcessor.java [469:539]


  private ViewCache applyServerMerge(
      final ViewCache viewCache,
      final Path path,
      CompoundWrite changedChildren,
      final WriteTreeRef writesCache,
      final Node serverCache,
      final boolean filterServerNode,
      final ChildChangeAccumulator accumulator) {
    // If we don't have a cache yet, this merge was intended for a previously listen in the same
    // location. Ignore it and wait for the complete data update coming soon.
    if (viewCache.getServerCache().getNode().isEmpty()
        && !viewCache.getServerCache().isFullyInitialized()) {
      return viewCache;
    }

    // HACK: In the case of a limit query, there may be some changes that bump things out of the
    // window leaving room for new items.  It's important we process these changes first, so we
    // iterate the changes twice, first processing any that affect items currently in view.
    // TODO: I consider an item "in view" if cacheHasChild is true, which checks both the server
    // and event snap.  I'm not sure if this will result in edge cases when a child is in one
    // but
    // not the other.
    ViewCache curViewCache = viewCache;
    assert changedChildren.rootWrite() == null : "Can't have a merge that is an overwrite";
    CompoundWrite actualMerge;
    if (path.isEmpty()) {
      actualMerge = changedChildren;
    } else {
      actualMerge = CompoundWrite.emptyWrite().addWrites(path, changedChildren);
    }
    Node serverNode = viewCache.getServerCache().getNode();
    Map<ChildKey, CompoundWrite> childCompoundWrites = actualMerge.childCompoundWrites();
    for (Map.Entry<ChildKey, CompoundWrite> childMerge : childCompoundWrites.entrySet()) {
      ChildKey childKey = childMerge.getKey();
      if (serverNode.hasChild(childKey)) {
        Node serverChild = serverNode.getImmediateChild(childKey);
        Node newChild = childMerge.getValue().apply(serverChild);
        curViewCache =
            applyServerOverwrite(
                curViewCache,
                new Path(childKey),
                newChild,
                writesCache,
                serverCache,
                filterServerNode,
                accumulator);
      }
    }
    for (Map.Entry<ChildKey, CompoundWrite> childMerge : childCompoundWrites.entrySet()) {
      ChildKey childKey = childMerge.getKey();
      CompoundWrite childCompoundWrite = childMerge.getValue();
      boolean isUnknownDeepMerge =
          !viewCache.getServerCache().isCompleteForChild(childKey)
          && childCompoundWrite.rootWrite() == null;
      if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) {
        Node serverChild = serverNode.getImmediateChild(childKey);
        Node newChild = childMerge.getValue().apply(serverChild);
        curViewCache =
            applyServerOverwrite(
                curViewCache,
                new Path(childKey),
                newChild,
                writesCache,
                serverCache,
                filterServerNode,
                accumulator);
      }
    }

    return curViewCache;
  }