private ViewCache generateEventCacheAfterServerEvent()

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


  private ViewCache generateEventCacheAfterServerEvent(
      ViewCache viewCache,
      Path changePath,
      WriteTreeRef writesCache,
      NodeFilter.CompleteChildSource source,
      ChildChangeAccumulator accumulator) {
    CacheNode oldEventSnap = viewCache.getEventCache();
    if (writesCache.shadowingWrite(changePath) != null) {
      // we have a shadowing write, ignore changes
      return viewCache;
    } else {
      IndexedNode newEventCache;
      if (changePath.isEmpty()) {
        // TODO: figure out how this plays with "sliding ack windows"
        assert viewCache.getServerCache().isFullyInitialized()
        : "If change path is empty, we must have complete server data";
        Node nodeWithLocalWrites;
        if (viewCache.getServerCache().isFiltered()) {
          // We need to special case this, because we need to only apply writes to
          // complete
          // children, or we might end up raising events for incomplete children. If
          // the server data
          // is filtered deep writes cannot be guaranteed to be complete
          Node serverCache = viewCache.getCompleteServerSnap();
          Node completeChildren =
              (serverCache instanceof ChildrenNode) ? serverCache : EmptyNode.Empty();
          nodeWithLocalWrites = writesCache.calcCompleteEventChildren(completeChildren);
        } else {
          nodeWithLocalWrites =
              writesCache.calcCompleteEventCache(viewCache.getCompleteServerSnap());
        }
        IndexedNode indexedNode = IndexedNode.from(nodeWithLocalWrites, this.filter.getIndex());
        newEventCache =
            this.filter.updateFullNode(
                viewCache.getEventCache().getIndexedNode(), indexedNode, accumulator);
      } else {
        ChildKey childKey = changePath.getFront();
        if (childKey.isPriorityChildName()) {
          assert changePath.size() == 1 : "Can't have a priority with additional path components";
          Node oldEventNode = oldEventSnap.getNode();
          Node serverNode = viewCache.getServerCache().getNode();
          // we might have overwrites for this priority
          Node updatedPriority =
              writesCache.calcEventCacheAfterServerOverwrite(changePath, oldEventNode, serverNode);
          if (updatedPriority != null) {
            newEventCache =
                this.filter.updatePriority(oldEventSnap.getIndexedNode(), updatedPriority);
          } else {
            // priority didn't change, keep old node
            newEventCache = oldEventSnap.getIndexedNode();
          }
        } else {
          Path childChangePath = changePath.popFront();
          // update child
          Node newEventChild;
          if (oldEventSnap.isCompleteForChild(childKey)) {
            Node serverNode = viewCache.getServerCache().getNode();
            Node eventChildUpdate =
                writesCache.calcEventCacheAfterServerOverwrite(
                    changePath, oldEventSnap.getNode(), serverNode);
            if (eventChildUpdate != null) {
              newEventChild =
                  oldEventSnap
                  .getNode()
                  .getImmediateChild(childKey)
                  .updateChild(childChangePath, eventChildUpdate);
            } else {
              // Nothing changed, just keep the old child
              newEventChild = oldEventSnap.getNode().getImmediateChild(childKey);
            }
          } else {
            newEventChild = writesCache.calcCompleteChild(childKey, viewCache.getServerCache());
          }
          if (newEventChild != null) {
            newEventCache =
                this.filter.updateChild(
                    oldEventSnap.getIndexedNode(),
                    childKey,
                    newEventChild,
                    childChangePath,
                    source,
                    accumulator);
          } else {
            // no complete child available or no change
            newEventCache = oldEventSnap.getIndexedNode();
          }
        }
      }
      return viewCache.updateEventSnap(
          newEventCache,
          oldEventSnap.isFullyInitialized() || changePath.isEmpty(),
          this.filter.filtersNodes());
    }
  }