/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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.vaadin.data.provider;
import java.io.Serializable;
import java.util.Objects;
import java.util.stream.Stream;
import com.vaadin.data.ValueProvider;
/**
* Data provider that uses one callback for fetching items from a back end and
* another callback for counting the number of available items.
*
* @author Vaadin Ltd
* @since 8.0
*
* @param <T>
* data provider data type
* @param <F>
* data provider filter type
*/
public class CallbackDataProvider<T, F>
extends AbstractBackEndDataProvider<T, F> {
/**
* Callback interface for fetching a stream of items from a backend based on
* a query.
*
* @param <T>
* the type of the items to fetch
* @param <F>
* the type of the optional filter in the query,
* <code>Void</code> if filtering is not supported
*/
@FunctionalInterface
public interface FetchCallback<T, F> extends Serializable {
/**
* Fetches a stream of items based on a query. The query defines the
* paging of the items to fetch through {@link Query#getOffset()} and
* {@link Query#getLimit()}, the sorting through
* {@link Query#getSortOrders()} and optionally also any filtering to
* use through {@link Query#getFilter()}.
*
* @param query
* the query that defines which items to fetch
* @return a stream of items
*/
public Stream<T> fetch(Query<T, F> query);
}
/**
* Callback interface for counting the number of items in a backend based on
* a query.
*
* @param <T>
* the type of the items to count
* @param <F>
* the type of the optional filter in the query,
* <code>Void</code> if filtering is not supported
*/
@FunctionalInterface
public interface CountCallback<T, F> extends Serializable {
/**
* Counts the number of available items based on a query. The query
* optionally defines any filtering to use through
* {@link Query#getFilter()}. The query also contains information about
* paging and sorting although that information is generally not
* applicable for determining the number of items.
*
* @param query
* the query that defines which items to count
* @return the number of available items
*/
public int count(Query<T, F> query);
}
private final FetchCallback<T, F> fetchCallback;
private final CountCallback<T, F> countCallback;
private final ValueProvider<T, Object> idGetter;
/**
* Constructs a new DataProvider to request data using callbacks for
* fetching and counting items in the back end.
*
* @param fetchCallback
* function that returns a stream of items from the back end for
* a query
* @param countCallback
* function that return the number of items in the back end for a
* query
*
* @see #CallbackDataProvider(FetchCallback, CountCallback, ValueProvider)
*/
public CallbackDataProvider(FetchCallback<T, F> fetchCallback,
CountCallback<T, F> countCallback) {
this(fetchCallback, countCallback, t -> t);
}
/**
* Constructs a new DataProvider to request data using callbacks for
* fetching and counting items in the back end.
*
* @param fetchCallBack
* function that requests data from back end based on query
* @param countCallback
* function that returns the amount of data in back end for query
* @param identifierGetter
* function that returns the identifier for a given item
*/
public CallbackDataProvider(FetchCallback<T, F> fetchCallBack,
CountCallback<T, F> countCallback,
ValueProvider<T, Object> identifierGetter) {
Objects.requireNonNull(fetchCallBack, "Request function can't be null");
Objects.requireNonNull(countCallback, "Count callback can't be null");
Objects.requireNonNull(identifierGetter,
"Identifier getter function can't be null");
this.fetchCallback = fetchCallBack;
this.countCallback = countCallback;
this.idGetter = identifierGetter;
}
@Override
public Stream<T> fetchFromBackEnd(Query<T, F> query) {
return fetchCallback.fetch(query);
}
@Override
protected int sizeInBackEnd(Query<T, F> query) {
return countCallback.count(query);
}
@Override
public Object getId(T item) {
Object itemId = idGetter.apply(item);
assert itemId != null : "CallbackDataProvider got null as an id for item: "
+ item;
return itemId;
}
}