Skip to content

Commit

Permalink
feat: add API for disabling data fetching to DC (#9070)
Browse files Browse the repository at this point in the history
Part of vaadin/vaadin-combo-box-flow#355
  • Loading branch information
mshabarov committed Sep 30, 2020
1 parent 66475ba commit c4ffe6c
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ public class DataCommunicator<T> implements Serializable {
// Paged queries are enabled by default
private boolean pagingEnabled = true;

private boolean fetchDisabled;

/**
* In-memory data provider with no items.
* <p>
Expand Down Expand Up @@ -179,10 +181,40 @@ public void accept(T t) {
public DataCommunicator(DataGenerator<T> dataGenerator,
ArrayUpdater arrayUpdater,
SerializableConsumer<JsonArray> dataUpdater, StateNode stateNode) {
this(dataGenerator, arrayUpdater, dataUpdater, stateNode, false);
}

/**
* Creates a new instance.
* <p>
* Allows to setup whether the data communicator will ignore fetch and size
* queries to data provider until further configuration. This mode is useful
* when the component needs to postpone the calls to data provider until
* some event, i.e. dropdown open event of the combo box, but needs to
* configure the data communicator preliminary.
*
* @param dataGenerator
* the data generator function
* @param arrayUpdater
* array updater strategy
* @param dataUpdater
* data updater strategy
* @param stateNode
* the state node used to communicate for
* @param fetchDisabled
* if {@code fetchDisabled} is {@code true} then the data
* provider won't be called to fetch the items and/or to get the
* items count until it's set to {@code false}
*/
public DataCommunicator(DataGenerator<T> dataGenerator,
ArrayUpdater arrayUpdater,
SerializableConsumer<JsonArray> dataUpdater, StateNode stateNode,
boolean fetchDisabled) {
this.dataGenerator = dataGenerator;
this.arrayUpdater = arrayUpdater;
this.dataUpdater = dataUpdater;
this.stateNode = stateNode;
this.fetchDisabled = fetchDisabled;

stateNode.addAttachListener(this::handleAttach);
stateNode.addDetachListener(this::handleDetach);
Expand Down Expand Up @@ -518,7 +550,7 @@ public void setItemCountEstimateIncrease(int itemCountEstimateIncrease) {
"itemCountEstimateIncrease cannot be less than 1");
}
this.itemCountEstimateIncrease = itemCountEstimateIncrease;
this.countCallback = null;
countCallback = null;
definedSize = false;
}

Expand Down Expand Up @@ -671,6 +703,36 @@ public void setPagingEnabled(boolean pagingEnabled) {
this.pagingEnabled = pagingEnabled;
}

/**
* Returns whether the data communicator will call Data Provider for
* fetching the items and/or getting the items count, or ignore such a
* calls.
*
* @return {@code true} if the calls to data provider are ignored,
* {@code false} otherwise
*/
public boolean isFetchDisabled() {
return fetchDisabled;
}

/**
* Sets whether the data communicator will call Data Provider for fetching
* the items and/or getting the items count, or ignore such a calls.
* <p>
* One may need to disable the data provider calls in order to configure the
* data communicator and to postpone these calls until some event, i.e.
* dropdown open event of the combo box.
* <p>
* This sets to {@code false} by default.
*
* @param fetchDisabled
* if {@code true} then the calls to data provider are ignored,
* otherwise the data provider is queried when needed.
*/
public void setFetchDisabled(boolean fetchDisabled) {
this.fetchDisabled = fetchDisabled;
}

/**
* Getter method for determining the item count of the data. Can be
* overridden by a subclass that uses a specific type of DataProvider and/or
Expand Down Expand Up @@ -848,7 +910,7 @@ private void requestFlush() {
}

private void requestFlush(boolean forced) {
if (flushRequest == null || forced) {
if ((flushRequest == null || forced) && !fetchDisabled) {
flushRequest = context -> {
if (!context.isClientSideInitialized()) {
reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,57 @@ public void fetchFromProvider_backendRunsOutOfItems_secondPageRequestSkipped() {
.fetch(Mockito.any(Query.class));
}

@Test
public void fetchDisabled_getItemCount_stillReturnsItemsCount() {
dataCommunicator.setFetchDisabled(true);
Assert.assertEquals(0, dataCommunicator.getItemCount());

// data provider stores 100 items
dataCommunicator.setDataProvider(createDataProvider(), null);
Assert.assertEquals(100, dataCommunicator.getItemCount());
}

@Test
public void fetchDisabled_getItem_stillReturnsItem() {
dataCommunicator.setFetchDisabled(true);

// data provider stores 100 items
dataCommunicator.setDataProvider(createDataProvider(), null);
Assert.assertNotNull(dataCommunicator.getItem(42));
}

@Test
public void fetchDisabled_requestRange_fetchIgnored() {
DataCommunicator<Item> dataCommunicator = new DataCommunicator<>(
dataGenerator, arrayUpdater, data -> {
}, element.getNode(), true);
dataCommunicator.setPageSize(pageSize);

DataProvider<Item, ?> dataProvider = Mockito
.spy(DataProvider.ofItems(new Item(0)));

dataCommunicator.setDataProvider(dataProvider, null);
dataCommunicator.setRequestedRange(0, 0);

fakeClientCommunication();

Mockito.verify(dataProvider, Mockito.times(0))
.fetch(Mockito.any(Query.class));
Mockito.verify(dataProvider, Mockito.times(0))
.size(Mockito.any(Query.class));

// Switch back to normal mode
dataCommunicator.setFetchDisabled(false);
dataCommunicator.setRequestedRange(0, 10);

fakeClientCommunication();

Mockito.verify(dataProvider)
.fetch(Mockito.any(Query.class));
Mockito.verify(dataProvider)
.size(Mockito.any(Query.class));
}

@Tag("test-component")
private static class TestComponent extends Component {
}
Expand Down

0 comments on commit c4ffe6c

Please sign in to comment.