You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Leszek Gawron <lg...@apache.org> on 2014/04/26 15:39:51 UTC

DataTable's FilterToolbar generics broken

I started migrating my code from wicket 1.4.19 to 6. Finally ! :)

I found a FilterToolbar bug:

Once you were able to create DataTable<User> wrapped inside of
FilterForm<UserFilterDto>

currently FilterToolbar requires you for those two types to be identical:

public <T, S> FilterToolbar(final DataTable<T, S> table, final
FilterForm<T> form,
final IFilterStateLocator<T> stateLocator)

It looks like commit 9b3f9ca1df064fe9c6fde64ccc37fecc504b09a6
introduced a bug long time ago and it carried on:

-       public <T> FilterToolbar(final DataTable<?> table, final
FilterForm<T> form,
+       public <T> FilterToolbar(final DataTable<T> table, final
FilterForm<T> form,


FilterToolbar constructor should state:

public <T, F, S> FilterToolbar(final DataTable<T, S> table, final
FilterForm<F> form,
final IFilterStateLocator<F> stateLocator)


cheers.

-- 
Leszek Gawron

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: DataTable's FilterToolbar generics broken

Posted by Leszek Gawron <lg...@apache.org>.
Confused I am not :)


Let me give you three examples...

I. filtering with a subset of properties

This is a class that worked perfectly in 1.4.19:
public class CustomersDataProvider extends
HibernateDataProvider<Customer> implements
IFilterStateLocator<CustomerFilter> {
    @SuppressWarnings("unused")
    public static class CustomerFilter implements Serializable {
        private String    name;
        private String    nip;

        public String getName() {
            return name;
        }

        public void setName( String name ) {
            this.name = name;
        }

        public String getNip() {
            return nip;
        }

        public void setNip( String nip ) {
            this.nip = nip;
        }
    }

    private CustomerFilter    filter    = new CustomerFilter();

    public CustomersDataProvider() {
        super( Customer.class );
        setSort(    "name",
                    true );
    }

    @Override
    public CustomerFilter getFilterState() {
        return filter;
    }

    @Override
    public void setFilterState( CustomerFilter state ) {
        filter = (CustomerFilter) state;
    }

    @Override
    public IModel<Customer> model( Customer object ) {
        return new CustomerModel( object );
    }

    @Override
    protected void filter( Criteria c ) {
        CriteriaHelper.ilike(    c,
                                "name",
                                filter.getName() );
        CriteriaHelper.ilike(    c,
                                "nip",
                                filter.getNip() );
    }
}

why? Customer is a class with lots of properties. I am unable to
provide proper filtering for all properties so I create a
CustomerFilter having only two properties: name and nip. This way I am
stating to other developers that my IDataProvider filters by two
properties only.


II. filtering date properties

Let's have a Sale entity with "date" property. Dates are usually
filtered by date ranges. So in filter I need startDate and finishDate
with two inputs rather than one (Sale.date). It is impossible if the
filter does not differ from base collection type.

with wicket 1.4.19 it was:

@Getter @Setter
public class SaleFilter implements Serializable {
    private Date            dateFrom;
    private Date            dateTo;
    private String            customerName;
    private String            description;
    private Status            status;
    private GroupingMode    groupingMode;
}

class SalesDataProvider extends HibernateDataProvider<Sale> implements
IFilterStateLocator<SaleFilter> {
    private SaleFilter    filter    = new SaleFilter();
    private final Long    customerId;

    public SalesDataProvider( Long customerId ) {
        super( Sale.class );
        this.customerId = customerId;

        setSort(    "date",
                    false );
    }

    @Override
    protected Criteria setupCriteria( Session session ) {
        Criteria c = super.setupCriteria( session );
        c.createAlias(    "customer",
                        "customer" );
        return c;
    }

    @Override
    protected void filter( Criteria c ) {
        if ( customerId != null )
            c.add( Restrictions.eq( "customer.id",
                                    customerId ) );
        else if ( !StringUtils.isBlank( filter.getCustomerName() ) )
            CriteriaHelper.ilike(    c,
                                    "customer.name",
                                    filter.getCustomerName() );

        CriteriaHelper.dateFilter(    c,
                                    "date",
                                    filter.getDateFrom(),
                                    filter.getDateTo() );

        CriteriaHelper.ilike(    c,
                                "description",
                                filter.getDescription() );

        if ( filter.getStatus() != null )
            c.add( Restrictions.eq( "status",
                                    filter.getStatus() ) );

        if ( filter.getGroupingMode() != null )
            c.add( Restrictions.eq( "groupingMode",
                                    filter.getGroupingMode() ) );
    }

    @Override
    public IModel<Sale> model( Sale object ) {
        return new SaleModel( object );
    }

    @Override
    public SaleFilter getFilterState() {
        return filter;
    }

    @Override
    public void setFilterState( SaleFilter state ) {
        this.filter = state;
    }
}


III. filtering with a superset of properties

Lets design a data provider for Order.

How would you create a filter for orders containing a selected
product? Probably so:

@Getter @Setter
public class OrderFilter implements Serializable {
    private Date creationStartDate;
    private Date creationFinishDate;
    private String customerName;
    private Long selectedProductId;
}

In this case the filter contains MORE properties than the actual Order itself.

-- 
Leszek Gawron

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: DataTable's FilterToolbar generics broken

Posted by Paul Bors <pa...@bors.ws>.
I think you're confused.

If you want to filter a collection based on type T, then your filter your
extend T.
The idea here is that your model object type for the filter is the same as
that retrieved by the data provider.
As such you can have a POJO of the same type T on which you apply the
filtering.

Otherwise what would you filter the collection based on?
There will be no standard, will there?

~ Thank you,
   Paul Bors


On Sat, Apr 26, 2014 at 9:39 AM, Leszek Gawron <lg...@apache.org> wrote:

> I started migrating my code from wicket 1.4.19 to 6. Finally ! :)
>
> I found a FilterToolbar bug:
>
> Once you were able to create DataTable<User> wrapped inside of
> FilterForm<UserFilterDto>
>
> currently FilterToolbar requires you for those two types to be identical:
>
> public <T, S> FilterToolbar(final DataTable<T, S> table, final
> FilterForm<T> form,
> final IFilterStateLocator<T> stateLocator)
>
> It looks like commit 9b3f9ca1df064fe9c6fde64ccc37fecc504b09a6
> introduced a bug long time ago and it carried on:
>
> -       public <T> FilterToolbar(final DataTable<?> table, final
> FilterForm<T> form,
> +       public <T> FilterToolbar(final DataTable<T> table, final
> FilterForm<T> form,
>
>
> FilterToolbar constructor should state:
>
> public <T, F, S> FilterToolbar(final DataTable<T, S> table, final
> FilterForm<F> form,
> final IFilterStateLocator<F> stateLocator)
>
>
> cheers.
>
> --
> Leszek Gawron
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>