public static <T> BatchingVisitableView<T> skip( final BatchingVisitable<T> visitable, final long toSkip) { Preconditions.checkNotNull(visitable); Preconditions.checkArgument(toSkip >= 0); if (toSkip == 0) { return BatchingVisitableView.of(visitable); } return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( int batchSizeHint, final ConsistentVisitor<T, K> v) throws K { visitable.batchAccept( batchSizeHint, new AbortingVisitor<List<T>, K>() { long visited = 0; @Override public boolean visit(List<T> batch) throws K { for (T item : batch) { if (visited < toSkip) { visited++; continue; } if (!v.visitOne(item)) { return false; } } return true; } }); } }); }
/** * @return Visitable containing elements from the start of the visitable for which the predicate * holds true. Once boundingPredicate returns false for an element of visitable, no more * elements will be included in the returned visitable. */ public static <T> BatchingVisitableView<T> visitWhile( final BatchingVisitable<T> visitable, final Predicate<T> condition) { return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( int batchSizeHint, final ConsistentVisitor<T, K> v) throws K { visitable.batchAccept( batchSizeHint, new AbortingVisitor<List<T>, K>() { @Override public boolean visit(List<T> batch) throws K { for (T t : batch) { if (!condition.apply(t)) { return false; } boolean keepGoing = v.visitOne(t); if (!keepGoing) { return false; } } return true; } }); } }); }
public static <T> BatchingVisitableView<T> flatten( final int outerBatchHint, final BatchingVisitable<? extends BatchingVisitable<? extends T>> inputs) { Preconditions.checkNotNull(inputs); return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( final int batchSizeHint, final ConsistentVisitor<T, K> v) throws K { inputs.batchAccept( outerBatchHint, new AbortingVisitor<List<? extends BatchingVisitable<? extends T>>, K>() { @Override public boolean visit(List<? extends BatchingVisitable<? extends T>> bvs) throws K { for (BatchingVisitable<? extends T> bv : bvs) { // This is safe because cast is never passed to anything and it's function // batchAccept is covariant @SuppressWarnings("unchecked") BatchingVisitable<T> cast = (BatchingVisitable<T>) bv; if (!cast.batchAccept(batchSizeHint, v)) { return false; } } return true; } }); } }); }
/** * This is similar to the unix uniq command. * * <p>If there is a sequence of identical values, it will be replaced by one value. * * <p>For example "AAABABBB" will become "ABAB" * * <p>If the list passed in is sorted, then it will actually result in a list of unique elements * * <p>This uses {@link Objects#equal(Object, Object)} to do comparisons. * * <p>null is supported bug discouraged */ public static <T> BatchingVisitableView<T> unique(final BatchingVisitable<T> visitable) { Preconditions.checkNotNull(visitable); return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( int batchSizeHint, final ConsistentVisitor<T, K> v) throws K { visitable.batchAccept( batchSizeHint, new AbortingVisitor<List<T>, K>() { boolean hasVisitedFirst = false; T lastVisited = null; @Override public boolean visit(List<T> batch) throws K { for (T item : batch) { if (!hasVisitedFirst || !Objects.equal(item, lastVisited)) { if (!v.visitOne(item)) { return false; } hasVisitedFirst = true; lastVisited = item; } } return true; } }); } }); }
public static <T> List<T> take( BatchingVisitable<T> v, final int howMany, final boolean includeFirst) { BatchingVisitableView<T> visitable = BatchingVisitableView.of(v); if (!includeFirst) { visitable = visitable.skip(1); } return visitable.limit(howMany).immutableCopy(); }
public static <T> BatchingVisitableView<T> singleton(final T t) { return BatchingVisitableView.of( new BatchingVisitable<T>() { @Override public <K extends Exception> boolean batchAccept( int batchSize, AbortingVisitor<? super List<T>, K> v) throws K { return v.visit(ImmutableList.of(t)); } }); }
public static <T> BatchingVisitableView<T> emptyBatchingVisitable() { return BatchingVisitableView.of( new BatchingVisitable<T>() { @Override public <K extends Exception> boolean batchAccept( int batchSize, AbortingVisitor<? super List<T>, K> v) throws K { return true; } }); }
/** * This method will wrap the passed visitable so it is called with the passed pageSize when it is * called. * * <p>This can be used to make the performance of batching visitables better. One example of where * this is useful is if I just visit the results one at a time, but I know that I will visit 100 * results, then I can save a lot of potential round trips my hinting a page size of 100. */ public static <T> BatchingVisitableView<T> hintPageSize( final BatchingVisitable<T> bv, final int pageSize) { Preconditions.checkArgument(pageSize > 0); return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( int batchSizeHint, ConsistentVisitor<T, K> v) throws K { bv.batchAccept(pageSize, v); } }); }
public static <F, T> BatchingVisitableView<T> transformBatch( final BatchingVisitable<F> visitable, final Function<? super List<F>, ? extends List<T>> f) { Preconditions.checkNotNull(visitable); Preconditions.checkNotNull(f); return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( int batchSizeHint, final ConsistentVisitor<T, K> v) throws K { visitable.batchAccept( batchSizeHint, new AbortingVisitor<List<F>, K>() { @Override public boolean visit(List<F> batch) throws K { return v.visit(f.apply(batch)); } }); } }); }
public static <T> BatchingVisitableView<T> concat( final Iterable<? extends BatchingVisitable<? extends T>> inputs) { Preconditions.checkNotNull(inputs); return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( int batchSizeHint, ConsistentVisitor<T, K> v) throws K { for (BatchingVisitable<? extends T> bv : inputs) { // This is safe because cast is never passed to anything and it's function // batchAccept is covariant @SuppressWarnings("unchecked") BatchingVisitable<T> cast = (BatchingVisitable<T>) bv; if (!cast.batchAccept(batchSizeHint, v)) { return; } } } }); }
public static <T> BatchingVisitableView<T> limit( final BatchingVisitable<T> visitable, final long limit) { Preconditions.checkNotNull(visitable); Preconditions.checkArgument(limit >= 0); if (limit == 0) { return emptyBatchingVisitable(); } return BatchingVisitableView.of( new AbstractBatchingVisitable<T>() { @Override protected <K extends Exception> void batchAcceptSizeHint( int batchSizeHint, final ConsistentVisitor<T, K> v) throws K { if (batchSizeHint > limit) { batchSizeHint = (int) limit; } visitable.batchAccept( batchSizeHint, new AbortingVisitor<List<T>, K>() { long visited = 0; @Override public boolean visit(List<T> batch) throws K { for (T item : batch) { if (!v.visitOne(item)) { return false; } visited++; if (visited >= limit) { // Stop visiting early by returning false. // The underlying ConsistentVisitor will still cause #batchAccept // to return true. return false; } } return true; } }); } }); }
public static <T, TOKEN> TokenBackedBasicResultsPage<T, TOKEN> getFirstPage( BatchingVisitable<T> v, int numToVisitArg, Function<T, TOKEN> tokenExtractor) { Preconditions.checkArgument( numToVisitArg >= 0, "numToVisit cannot be negative. Value was: " + numToVisitArg); if (numToVisitArg == Integer.MAX_VALUE) { // prevent issue with overflow numToVisitArg--; } final int numToVisit = numToVisitArg + 1; ImmutableList<T> list = BatchingVisitableView.of(v).limit(numToVisit).immutableCopy(); Preconditions.checkState(list.size() <= numToVisit); if (list.size() >= numToVisit) { TOKEN token = tokenExtractor.apply(list.get(list.size() - 1)); list = list.subList(0, numToVisit - 1); return new SimpleTokenBackedResultsPage<T, TOKEN>(token, list, true); } return new SimpleTokenBackedResultsPage<T, TOKEN>(null, list, false); }
public static <T> List<T> copyToList(BatchingVisitable<T> v) { return BatchingVisitableView.of(v).immutableCopy(); }