All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.palantir.common.base.BatchingVisitableView Maven / Gradle / Ivy

There is a newer version: 0.1152.0
Show newest version
/*
 * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.palantir.common.base;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ForwardingObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.palantir.common.visitor.Visitor;
import com.palantir.logsafe.Preconditions;
import com.palantir.util.paging.TokenBackedBasicResultsPage;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nullable;

/**
 * A wrapper for {@link BatchingVisitable} which adds support for common operations.
 *
 * @param  The contained object type.
 */
public abstract class BatchingVisitableView extends ForwardingObject implements BatchingVisitable {

    private BatchingVisitableView() {
        // don't expose the constructor publicly
    }

    @Override
    protected abstract BatchingVisitable delegate();

    public static  BatchingVisitableView of(final BatchingVisitable underlyingVisitable) {
        Preconditions.checkNotNull(underlyingVisitable, "Cannot wrap a null visitable");
        return new BatchingVisitableView() {
            @Override
            protected BatchingVisitable delegate() {
                return BatchingVisitables.wrap(underlyingVisitable);
            }
        };
    }

    @Override
    public  boolean batchAccept(int batchSize, AbortingVisitor, K> visitor)
            throws K {
        return delegate().batchAccept(batchSize, visitor);
    }

    public BatchingVisitableView concat(BatchingVisitable... inputs) {
        return BatchingVisitables.concat(Lists.asList(delegate(), inputs));
    }

    public long count() {
        return BatchingVisitables.count(delegate());
    }

    public BatchingVisitableView filter(final Predicate predicate) {
        Preconditions.checkNotNull(predicate, "Cannot filter using a null predicate");
        return BatchingVisitables.filter(delegate(), predicate);
    }

    public  BatchingVisitableView filter(final Class type) {
        return filter(Predicates.instanceOf(type));
    }

    public BatchingVisitableView limit(long limit) {
        return BatchingVisitables.limit(delegate(), limit);
    }

    public BatchingVisitableView skip(long toSkip) {
        return BatchingVisitables.skip(delegate(), toSkip);
    }

    public BatchingVisitableView unique() {
        return BatchingVisitables.unique(delegate());
    }

    public BatchingVisitableView uniqueOn(Function function) {
        return BatchingVisitables.uniqueOn(delegate(), function);
    }

    public BatchingVisitableView hintBatchSize(int batchSizeHint) {
        return BatchingVisitables.hintPageSize(delegate(), batchSizeHint);
    }

    public  BatchingVisitableView transform(Function fn) {
        Preconditions.checkNotNull(fn, "Cannot transform using a null function");
        return BatchingVisitables.transform(delegate(), fn);
    }

    /**
     * This can also be used to filter or multiply the input. It is common to
     * return a list of a smaller size than you pass in if you are filtering.
     * 

* In the filtering case, the caller may only want one value, but you may * have to visit batches of size 100 to find that value. In this case you * should call .transformBatch and then call .hintBatchSize(100) so your * function will get 100 at a time even though the final consumer is only * requesting a batch of size 1. * A good example of this is in BatchingVisitablesTest#testHintPageSize() */ public BatchingVisitableView transformBatch(Function, ? extends List> fn) { Preconditions.checkNotNull(fn, "Cannot transform using a null function"); return BatchingVisitables.transformBatch(delegate(), fn); } public void forEach(int batchSize, final Visitor visitor) { delegate().batchAccept(batchSize, batch -> { for (T item : batch) { visitor.visit(item); } return true; }); } public void forEach(final Visitor visitor) { forEach(BatchingVisitables.DEFAULT_BATCH_SIZE, visitor); } public BatchingVisitableView visitWhile(Predicate condition) { return BatchingVisitables.visitWhile(delegate(), condition); } /** * Gets the first element in the visitable. * * @return the first element or null if the visitable is empty */ @Nullable public T getFirst() { return BatchingVisitables.getFirst(delegate()); } /** * Gets the first element in the visitable. * * If a default value of null is wanted, then consider * calling {@link BatchingVisitableView#getFirst()} instead. * * @return the first element or defaultElement if the visitable is empty */ @Nullable public T getFirst(@Nullable T defaultElement) { return BatchingVisitables.getFirst(delegate(), defaultElement); } public TokenBackedBasicResultsPage getFirstPage(int numToVisitArg) { return BatchingVisitables.getFirstPage(delegate(), numToVisitArg); } /** * Gets the last element in the visitable. * * @return the last element or null if the visitable is empty */ @Nullable public T getLast() { return BatchingVisitables.getLast(delegate()); } /** * Gets the last element in the visitable. * * If a default value of null is wanted, then consider * calling {@link BatchingVisitableView#getLast()} instead. * * @return the last element or defaultElement if the visitable is empty */ @Nullable public T getLast(@Nullable T defaultElement) { return BatchingVisitables.getLast(delegate(), defaultElement); } /** * This will return the first maximal element in the visitable. This method * takes a default element and will return that if the visitable is empty. * If the visitable is non-empty it will return the largest value in the * visitable. *

* A common way to use this would be to pass null as the * defaultElement and have the ordering throw on null elements so you know * the visitable doesn't have any nulls. */ public T getMax(Ordering ordering, @Nullable T defaultElement) { return BatchingVisitables.getMax(delegate(), ordering, defaultElement); } /** * This will return the first maximal element in the visitable. This method * takes a default element and will return that if the visitable is empty. * If the visitable is non-empty it will return the largest value in the * visitable. *

* A common way to use this would be to pass null as the * defaultElement and have the ordering throw on null elements so you know * the visitable doesn't have any nulls. */ public T getMin(Ordering ordering, @Nullable T defaultElement) { return BatchingVisitables.getMin(delegate(), ordering, defaultElement); } /** * Returns an immutable copy of the elements in this visitable. * * @throws NullPointerException if any elements in the visitable are null */ public ImmutableList immutableCopy() { final ImmutableList.Builder builder = ImmutableList.builder(); delegate().batchAccept(BatchingVisitables.DEFAULT_BATCH_SIZE, items -> { builder.addAll(items); return true; }); return builder.build(); } /** * Returns an immutable copy of the elements in this visitable. * * @throws NullPointerException if any elements in the visitable are null */ public ImmutableSet immutableSetCopy() { final ImmutableSet.Builder builder = ImmutableSet.builder(); delegate().batchAccept(BatchingVisitables.DEFAULT_BATCH_SIZE, items -> { builder.addAll(items); return true; }); return builder.build(); } /** * Copies the elements in this visitable into an existing collection. This method has * equivalent behaviour to {@code Iterables.addAll(collection, this)}. * * @return a reference to {@code collection}, for convenience */ public > S copyInto(final S collection) { Preconditions.checkNotNull(collection, "Cannot copy the visitable into a null collection"); delegate().batchAccept(BatchingVisitables.DEFAULT_BATCH_SIZE, items -> { collection.addAll(items); return true; }); return collection; } /** * Returns {@code true} iff one or more elements satisfy the predicate. */ public boolean any(final Predicate predicate) { Preconditions.checkNotNull(predicate, "Cannot check against a null predicate"); return !delegate().batchAccept(BatchingVisitables.DEFAULT_BATCH_SIZE, items -> { for (T t : items) { if (predicate.apply(t)) { return false; } } return true; }); } /** * Returns {@code true} iff every element satisfies the * predicate. If empty, {@code true} is returned. */ public boolean all(final Predicate predicate) { Preconditions.checkNotNull(predicate, "Cannot check against a null predicate"); return delegate().batchAccept(BatchingVisitables.DEFAULT_BATCH_SIZE, items -> { for (T t : items) { if (!predicate.apply(t)) { return false; } } return true; }); } public boolean isEmpty() { return BatchingVisitables.isEmpty(delegate()); } public boolean isEqual(Iterable it) { return BatchingVisitables.isEqual(delegate(), it); } public boolean isEqual(Iterator it) { return BatchingVisitables.isEqual(delegate(), it); } public long size() { return BatchingVisitables.count(delegate()); } public T find(Predicate predicate, @Nullable T defaultValue) { return filter(predicate).getFirst(defaultValue); } }