in firebase-database/src/testUtil/java/com/google/firebase/database/core/RandomOperationGenerator.java [223:285]
public CacheNode getExpectedClientState(QueryParams params) {
CacheNode cacheNode;
// TODO: this is broken for multiple listens
if (!outstandingListens.isEmpty() && !(writeTree.shadowingWrite(Path.getEmptyPath()) != null)) {
// special case when data has not been sent, maybe have incomplete user writes
Node node = EmptyNode.Empty();
// first: gather any complete children
Set<ChildKey> completeChildren = new HashSet<ChildKey>();
for (WriteOp op : outstandingWrites) {
if (op.operation.getType() == Operation.OperationType.Overwrite) {
Overwrite overwrite = (Overwrite) op.operation;
if (overwrite.getPath().isEmpty()) {
for (NamedNode childEntry : overwrite.getSnapshot()) {
completeChildren.add(childEntry.getName());
}
} else if (op.operation.getPath().size() == 1) {
completeChildren.add(op.operation.getPath().getFront());
}
} else if (op.operation.getType() == Operation.OperationType.Merge) {
Merge merge = (Merge) op.operation;
if (merge.getPath().isEmpty()) {
for (NamedNode completeChild : merge.getChildren().getCompleteChildren()) {
completeChildren.add(completeChild.getName());
}
}
} else {
throw new IllegalStateException("Unknown user write operation: " + op.operation);
}
}
// second: apply all overwrites for complete children
for (WriteOp op : outstandingWrites) {
Path writePath = op.operation.getPath();
if (writePath.isEmpty() || completeChildren.contains(writePath.getFront())) {
node = applyOperation(op.operation, node);
}
}
cacheNode = new CacheNode(IndexedNode.from(node, params.getIndex()), false, false);
} else {
Node node = this.currentServerState;
// TODO: somehow filter out incomplete children
for (WriteOp op : outstandingWrites) {
node = applyOperation(op.operation, node);
}
cacheNode = new CacheNode(IndexedNode.from(node, params.getIndex()), true, false);
}
NodeFilter filter;
if (params.hasLimit()) {
filter = new LimitedFilter(params);
} else if (params.hasStart() || params.hasEnd()) {
filter = new RangedFilter(params);
} else {
filter = new IndexedFilter(params.getIndex());
}
if (params.loadsAllData()) {
return cacheNode;
} else {
// Maybe write custom filter?
IndexedNode newNode =
filter.updateFullNode(
IndexedNode.from(EmptyNode.Empty()), cacheNode.getIndexedNode(), null);
return new CacheNode(newNode, cacheNode.isFullyInitialized(), filter.filtersNodes());
}
}