Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter type support in Data View interfaces #8874

Merged
merged 4 commits into from
Aug 24, 2020

Conversation

mshabarov
Copy link
Contributor

@mshabarov mshabarov commented Aug 20, 2020

Part of https://github.com/vaadin/vaadin-combo-box-flow/issues/355

  1. HasDataView and HasLazyDataView now contains F filter generic type in their declarations.
  2. AbstractDataView requires a query supplier instead of just creating a Query with no filter and sorting. Components implies to provide such a query populated with their internal filter or sorting. Basically it delegates to DataCommunicator::buildQuery. For Select and CheckBoxGroup it will be new Query() like previously, because those components do not have them.
  3. setItems(InMemoryDataProvider) is now supplemented with a filter converter, because it's impossible to just delegate it to generic setItems because of filter type in declaration. Old setItems(InMemoryDataProvider) methods proposed to be removed.

Grid vaadin/vaadin-grid-flow#1100
ComboBox vaadin/vaadin-combo-box-flow#380

Select TBD
CheckBoxGroup TBD

* InMemoryDataProvider to use, not <code>null</code>
* @param filterConverter a function which converts a component's
* internal filter into a predicate to be
* applied to the all items of data provider
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"...into a predicate applied to the data provider"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for now this method looks as a candidate for being only in ComboBox, it will be fixed in ComboBox accordingly.


/**
* Sets an in-memory data provider for the component to use, taking into
* account only in-memory filtering from data provider.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if the filtering here is that important, since the setItems(DataProvider) neither mentions anything about it.
Maybe it would be OK to clarify in a later sentence that if the component has inbuilt filtering, then it the other method with filter converter should be used instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be mentioned in combobox that using "no converter" method overload throws, and ask to use the "with converter" method overload.

// TODO: probably we should just remove this methods, because it has a
// significant drawback: it ignores the component's filter quietly, even
// though it described in javadoc, so the developer can easily make a
// mistake here.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since ComboBox is still the only component with inbuilt filtering, it might be OK even still to just force the components to implement this method always (not have default implementation at all) and then make CB throw in the implementation, and point to the method with the filter converter instead, which would only be in CB.

I cannot say at the moment which is better or worse option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I like this idea, because: 1. The implementation in custom components/addons might be not only in delegating to setItems(DataProvider<T, F> dataProvider) 2. Component's author will be responsible for handling the input data provider in implementation and he will decide whether ignore the filter or not.

* Sets an in-memory data provider for the component to use.
* Sets an in-memory data provider for the component to use, taking into
* account both in-memory filtering from data provider and component
* specific internal filter.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to start why one should use this method instead of explaining how it works:
"Sets an in-memory data provider to use with a component that has internal filtering, like {@code ComboBox}. For components without inbuilt filtering use ...... instead."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be done on ComboBox side

@@ -45,12 +48,11 @@
*
* @param fetchCallback
* function that returns a stream of items from the backend based
* on the offset and limit provided by the query object
* on the filter, offset and limit provided by the query object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since filter is basically optional, I would maybe mention that one last as "...and an optional filter"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

extends Serializable {

/**
* Supply items lazily with a callback from a backend. The component will
* automatically fetch more items and adjust its size until the backend runs
* out of items. Usage example:
* <p>
* {@code component.setItems(query -> orderService.getOrders(query.getOffset(), query.getLimit());}
* {@code component.setItems(query -> orderService.getOrders(
* query.getFilter, query.getOffset(), query.getLimit());}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move filter to be last since it is not valid for components which don't provide a filter.
Maybe even better to leave it out completely (keep it as it was) and add
"Usage example without component provided filter:"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

* query -> orderService.getSize());}
* query -> orderService.getOrders(query.getFilter,
* query.getOffset, query.getLimit()),
* query -> orderService.getSize(query.getFilter));}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, maybe for simplicity the filter could be kept out of this and then another comment could follow the example stating that "If the component supports filtering, it can be fetched with query.getFilter()."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

* query -> orderService.getOrders(query.getOffset, query.getLimit()),
* query -> orderService.getSize());}
* query -> orderService.getOrders(query.getFilter,
* query.getOffset, query.getLimit()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing () x 2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obsolete, because getFilter has been removed from example. Done

@@ -37,6 +38,7 @@
protected static final String NULL_IDENTIFIER_ERROR_MESSAGE = "Identity provider should not return null";

protected SerializableSupplier<? extends DataProvider<T, ?>> dataProviderSupplier;
protected SerializableBiFunction<Integer, Integer, Query<T, ?>> querySupplier;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed as a property instead of just keeping the buildQuery method abstract ? Is it going to change on the fly ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also keep expectations clearer by having this as an abstract method only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it so initially, but there is an obstacle:

The goal of this method is to provide a query with component's actual filtering and sorting filled up. Making this method abstract means we will have to create a anonymous class just to put the values there:

public ComboBoxDataView<T> getGenericDataView() {
   return new AbstractDataView(dataCommunicator, this) {
       @Override
       public Query buildQuery(int offset, int limit) {
            return new Query(offset, limit, sortOrder, inMemorySorting, lastFilter);
       }
   }
}

I don't want go this way, but create a regular class implementation instead.

Sorry, I might be wrong, but it needs a link to component's filter and sorting anyway, through the supplier, or through component's public method.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I think if combo box is the only component that needs this type of callback, then it can have a data view implementation which get those from the component when it constructs the data view for itself. For other purposes, this feels a bit of an antipattern that makes everything else overly complex. That is at least my feeling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, then I could just revert my changes and just include this kind of supplier in ComboBoxDataView and ComboBoxListDataView only. It would be much simpler, thanks!

pleku
pleku previously approved these changes Aug 21, 2020
Component component) {
super(dataProviderSupplier, querySupplier, component);
super(dataProviderSupplier, component);
}

@Override
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noting here that both Grid and ComboBox need to have the getItems() method overridden for DataView and ListDataView due to sorting (grid) and filtering (cb). LazyDataView is safe because it uses data communicator

Copy link
Contributor Author

@mshabarov mshabarov Aug 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, GridDataView and GridListDataView already override getItems and delegate to dataCommunicator.buildQuery(0, Integer.MAX_VALUE), will check and do the same for CB

@vaadin-bot
Copy link
Collaborator

SonarQube analysis reported 2 issues

Note: The following issues were found on lines that were not modified in the pull request. Because these issues can't be reported as line comments, they are summarized here:

  1. MINOR AbstractListDataView.java#L85: Cast one of the operands of this addition operation to a "long". rule
  2. MINOR AbstractListDataView.java#L94: Cast one of the operands of this subtraction operation to a "long". rule

@mshabarov mshabarov marked this pull request as ready for review August 24, 2020 07:13
@pleku pleku merged commit 91c7e18 into master Aug 24, 2020
OLD Vaadin Flow ongoing work (Vaadin 10+) automation moved this from Iteration Reviews to Done - pending release Aug 24, 2020
@pleku pleku deleted the 8646-add-filter-to-lazydataview branch August 24, 2020 07:32
pleku pushed a commit that referenced this pull request Aug 24, 2020
Moves setItemCountCallback to Grid and ComboBox.

Related to vaadin/vaadin-combo-box-flow#355
pleku pushed a commit that referenced this pull request Aug 24, 2020
Moves setItemCountCallback to Grid and ComboBox.

Related to vaadin/vaadin-combo-box-flow#355
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
OLD Vaadin Flow ongoing work (Vaadin ...
  
Done - pending release
Development

Successfully merging this pull request may close these issues.

None yet

4 participants