OTUplinkImpl implements OTUplink<K, D, PC> { @Override public Promise<FetchData<K, D>> checkout() { RefInt epoch = new RefInt(0); Ref<List<D>> cachedSnapshotRef = new Ref<>(); return repository.getHeads() .then(heads -> findParent( repository, otSystem, heads, DiffsReducer.toList(), commit -> repository.loadSnapshot(commit.getId()) .map(maybeSnapshot -> (cachedSnapshotRef.value = maybeSnapshot.orElse(null)) != null))) .whenResult(findResult -> epoch.set(findResult.getEpoch())) .then(findResult -> Promise.of( new FetchData<>( findResult.getChild(), findResult.getChildLevel(), concat(cachedSnapshotRef.value, findResult.getAccumulatedDiffs())))) .then(checkoutData -> fetch(checkoutData.getCommitId()) .map(fetchData -> new FetchData<>( fetchData.getCommitId(), fetchData.getLevel(), otSystem.squash(concat(checkoutData.getDiffs(), fetchData.getDiffs())) )) ) .whenComplete(toLogger(logger, thisMethod())); } private  OTUplinkImpl(OTRepository<K, D> repository, OTSystem<D> otSystem, Function<OTCommit<K, D>, PC> protoCommitEncoder,
			Function<PC, OTCommit<K, D>> protoCommitDecoder); static OTUplinkImpl<K, D, C> create(OTRepository<K, D> repository, OTSystem<D> otSystem,
			Function<OTCommit<K, D>, C> commitToObject, Function<C, OTCommit<K, D>> objectToCommit); static OTUplinkImpl<K, D, OTCommit<K, D>> create(OTRepository<K, D> repository, OTSystem<D> otSystem); OTRepository<K, D> getRepository(); @Override Promise<PC> createProtoCommit(K parent, List<D> diffs, long parentLevel); @Override Promise<FetchData<K, D>> push(PC protoCommit); @Override Promise<FetchData<K, D>> checkout(); @Override Promise<FetchData<K, D>> fetch(K currentCommitId); @Override Promise<FetchData<K, D>> poll(K currentCommitId);  }
@Test public void testCheckoutEmptyGraph() { FetchData<Integer, TestOp> fetchData = await(node.checkout()); assertFetchData(0, 1, 0, fetchData); }
@Test public void testCheckoutLinearGraph() { REPOSITORY.setGraph(g -> { g.add(0, 1, add(1)); g.add(1, 2, add(2)); g.add(2, 3, add(3)); g.add(3, 4, add(4)); g.add(4, 5, add(5)); g.add(5, 6, add(6)); }); FetchData<Integer, TestOp> fetchData = await(node.checkout()); assertFetchData(6, 7, 21, fetchData); }