Loading...
Important Notice - Forums is archived

To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Product icon
TUTORIAL

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.

GeneratedPropertyContainer - sorting of generated properties

Peter Stockinger
7 years ago Jul 10, 2015 7:12am

Hello,

I'm wondering how it is possible to sort generated properties added by

GeneratedPropertyContainer.addGeneratedProperty(id, new PropertyValueGenerator<...>()

Book of Vaadin only says (8.5.7. GeneratedPropertyContainer - Sorting)
"Even though the GeneratedPropertyContainer implements Container.Sortable, the wrapped container must also support it or otherwise sorting is disabled. Also, the generated properties are not normally sortable, but require special handling to enable sorting."

without explaining on what sort of special handling is required (I wrapped ye' olde IndexedContainer is anyone is wondering).

So far I've tried to

  • make sure the generated property is included in the sortablePropertyIds by adding
  • @Override
    public SortOrder getSortProperties(final SortOrder order) {
    return new SortOrder{new SortOrder(this, order.getDirection())};
    }

    to the PropertyValueGenerator - debug shows that the generated property is included.

  • implement a CustomItemSorter by extending the DefaultItemSorter, also calling the setSortProperties and passing the GeneratedPropertyContainer to it, but a debug shows that for whatever reason it only picks up the regular property in the container, not the generated one.

Tried it with 7.4.3 as well as 7.5.1.

Does anyone have more insight in this?

Peter Stockinger
7 years ago Jul 10, 2015 9:08am

Progress! I managed to get my generated property to sort - not sure if there is a better way but for those wondering:

First of all:

return new SortOrder{new SortOrder([b]this[/b], order.getDirection())};

of course has to be

return new SortOrder{new SortOrder([b]actualPropertyId[/b], order.getDirection())};

with the actualPropertyId (aka the pid of the property I'm - in my case - replacing with the generated one) being passed to the PropertyValueGenerator. I wonder if there is a better/easier way to get the pid?

Next I passed my CustomItemSorter a reference to the GeneratedPropertyContainer and made sure it will always use that one

@Override
    public void setSortProperties(final Sortable container, final Object propertyId, final boolean ascending) {
      super.setSortProperties(this.myGeneratedPropertyContainer, propertyId, ascending);
    }

this way when ItemSorter calls getSortableContainerPropertyIds() it will use the GeneratedPropertyContainer instead of the underlying IndexedContainer and pick up the generatedProperty.

Don't forget to override the compareProperty(...) method if neccessary.

Luan VO Thanh
7 years ago Dec 22, 2015 4:05am

could you please explain more detials and give some example code.
 

Martín López
5 years ago Mar 06, 2018 6:09pm

I know this post is old, but I've run into that same issue and here is a way of achieving this in Vaadin 7 (just paste it on a new UI):

protected void init(VaadinRequest vaadinRequest) {
        final VerticalLayout layout = new VerticalLayout();

        List<Item> items = Arrays.asList(new Item[] { new Item("John Doe", new Date(80, 1, 20)),
                new Item("John Smith", new Date(82, 2, 21)), new Item("Dave Doe", new Date(81, 5, 1)) });

        PropertyValueGenerator<Integer> pvg = new PropertyValueGenerator<Integer>() {
            @Override
            public Integer getValue(com.vaadin.data.Item item, Object itemId, Object propertyId) {
                Date birthday = (Date) item.getItemProperty("birthday").getValue();
                Date now = new Date();
                return (int) ((now.getTime() - birthday.getTime()) / (1000 * 60 * 60 * 24 * 365L));
            }

            @Override
            public Class<Integer> getType() {
                return Integer.class;
            }

            @Override
            public SortOrder[] getSortProperties(SortOrder order) {
                return new SortOrder[] { order };
            }
        };

        BeanItemContainer<Item> bic = new BeanItemContainer<Item>(Item.class, items) {
            @Override
            public Collection<?> getSortableContainerPropertyIds() {
                Set<Object> result = new HashSet<>(super.getSortableContainerPropertyIds());
                result.add("age");
                return result;
            }
        };
        bic.setItemSorter(new DefaultItemSorter() {
            @Override
            protected int compareProperty(Object propertyId, boolean sortDirection, com.vaadin.data.Item item1,
                    com.vaadin.data.Item item2) {
                if (propertyId.equals("age")) {
                    Integer value1 = pvg.getValue(item1, null, null);
                    Integer value2 = pvg.getValue(item2, null, null);
                    int c = value1.compareTo(value2);
                    return sortDirection ? c : -1;
                } else {
                    return super.compareProperty(propertyId, sortDirection, item1, item2);
                }
            }
        });

        GeneratedPropertyContainer gpc = new GeneratedPropertyContainer(bic);
        gpc.addGeneratedProperty("age", pvg);

        Grid people = new Grid();
        people.setContainerDataSource(gpc);

        layout.addComponents(people);
        layout.setMargin(true);
        layout.setSpacing(true);

        setContent(layout);
    }
johan elim
4 years ago Jul 19, 2018 9:42am