I wonder if there is a best practice for implementing sortable columns that have arbitrary components which currently don’t implement the Comparable interface.
In my setup some table data is fetched from DB* and some (batch progress) data is fetched from other servers and presented in the table. What I want is to be able to click on a column header and have the data sorted according to the preferences of that column header, given the data type it’s been set to present. The only way I’'ve been able to achieve this with arbitrary components is to have those components implement the
Comparable<
MyComponent
>
interface.
It feels akward to have to implement that interface for all kinds of comparisons I’d like a table to make for standard Vaadin components and self made components, depending on what the column shall base its sorting on, for example:
...
indexedContainer.addContainerProperty("Checkbox", MyCheckBox.class, ""); // no luck with sorting CheckBox
indexedContainer.addContainerProperty("Name", MyButton.class, ""); // no luck with sorting Button
indexedContainer.addContainerProperty("Description", String.class, ""); // works fine
indexedContainer.addContainerProperty("Progress", MyComplexProgressComponent.class, "");
...
table.setContainerDataSource(indexedContainer);
MyCheckBox extends CheckBox implements Comparable<MyCheckBox> {
@Override
public int compareTo(MyCheckBox o) {
return booleanValue().compareTo(o.booleanValue());
}
MyButton extends Button implements Comparable<MyButton> {
@Override
public int compareTo(MyButton o) {
return getCaption().toLowerCase().compareTo(o.getCaption().toLowerCase());
}
MyComplexProgressComponent extends HorDashLayout implements Comparable<MyComplexProgressComponent > {
private Label caption;
// a bunch of Vaadin components
@Override
public int compareTo(MyComplexProgressComponent o) {
return caption.toLowerCase().compareTo(o.caption.toLowerCase());
}
}
I also have a bad feeling about not implementing equals and hashcode, but how should one best implement equals and hashcode if the self made component uses a bunch of Vaadin components?
I tried to use the
ItemSorter
but I don’t really understand how it’s supposed to be used:
private class MyTableSpecificItemSorter implements ItemSorter {
private String selectedColumnId;
private boolean ascendingOrder;
private final static Map<String, MyClientObject.Property> COLUMN_TO_PROPERTY =
new HashMap<String, MyClientObject.Property>();
static {
COLUMN_TO_PROPERTY.put("Checkbox", //??? );
COLUMN_TO_PROPERTY.put("Name", MyClientObject.Property.NAME);
COLUMN_TO_PROPERTY.put("Description", MyClientObject.Property.DESCRIPTION);
COLUMN_TO_PROPERTY.put("Progress", //???);
}
@Override
public void setSortProperties(Container.Sortable sortable, Object[] objects, boolean[]
booleans) {
selectedColumnId = (String) objects[0]
;
ascendingOrder = booleans[0]
;
}
@Override
public int compare(Object o, Object o1) {
// Here I have no handle to the Checkbox or MyComplexProgressComponent since parameters
// o and o1 are of type MyClientObject (the registered item ID), so I'm unable to
// sort those columns correctly, otherwise I can do:
MyClientObject clientObject1 = (MyClientObject) o;
MyClientObject clientObject2 = (MyClientObject) o1;
MyClientObject.Property propertyToCompare = COLUMN_TO_PROPERTY.get(selectedColumnId);
int result = clientObject1.getProperty(propertyToCompare).compareTo(clientObject2.getProperty(propertyToCompare));
return ascendingOrder ? result : result * -1;
}
}
What I’d like to be able to do is to add a specific Comparator for each column that executes independent of the columns data type’s implementation of, or lack of implementation of, the Comparable interface:
indexedContainer.addContainerProperty("Checkbox", CheckBox.class, "", new MyCheckBoxComparator());
indexedContainer.addContainerProperty("Name", Button.class, "", new MyButtonComparator());
indexedContainer.addContainerProperty("Description", String.class, "");
indexedContainer.addContainerProperty("Progress", MyComplexProgressComponent.class, "", new MyComplexProgressComponentComparator());
To summarize:
Do you extend and implement the Comparable interface; or use the ItemSorter; or some other approach?
Thanks
- When the web layer (Vaadin) wants to fetch domain data from DB an ‘EJB controller’ is used by the Vaadin view controller. The EJB controller in turn uses a DAO (through Hibernate) which retrieves the domain object which the EJB controller then maps to a kind of client object; where the members of the domain object are put into a property map for validation and I18N handling, for example myDomainObject.getName() would be accessed through myClientObject.getProperty(MyClientObject.Property.NAME).