0

I have a JTable where several columns contain a number from an enums like the following:

public static enum IMPORT_CONF_OPERATION_RESULT {
    OK(0, "OK"),
    ERROR(1, "ERROR"),
    WAITING(2, "WAITING");
    /* ... */
}

So, I needed to override method getValueAt() of table model looping through enum values in order to decode and return the correspondent String for each row as, in the database from which data come from, the numeric values are stored. Now, if the user clicks on the correspondent header column, row are sorted according to numeric values but I would like to order them in alphabetical order. Shall I override sort() method of table model? Isn't looping so many times through enum values to get the description inefficient? Would it slow down table rendering?

UPDATE

This could be a solution following to what STaefi suggested, inside my extended DefaultTableModelField:

@Override
public void sort(int col, boolean ascendest) {
    ColumnProperties columnProperties = this.mapColumn.get(col);
    if (COLUMN_NAME_ENTITY.equals(columnProperties.getInfo()) ||
        COLUMN_OPERATION_TYPE.equals(columnProperties.getInfo()) ||
        COLUMN_OPERATION_RESULT.equals(columnProperties.getInfo()) ||
        COLUMN_ELABORATION_TYPE.equals(columnProperties.getInfo()) ||
        COLUMN_EVENT_STATE.equals(columnProperties.getInfo())) {
        Collections.sort((List<TableImportConfEvent>)this.value, new EnumColumnSorter(ascendest, columnProperties.getInfo()));
        this.fireTableDataChanged();
    }
    else {
        super.sort(col, ascendest);
    }
}

private class EnumColumnSorter implements Comparator<TableImportConfEvent> {

    private int ascending;
    private String columnName;
    public EnumColumnSorter(boolean ascendest, String columnName) {
        this.ascending = ascendest ? 1 : -1;
        this.columnName = columnName;
    }
    @Override
    public int compare(TableImportConfEvent o1, TableImportConfEvent o2) {
        String decodedString1 = "";
        String decodedString2 = "";
        if (COLUMN_NAME_ENTITY.equals(this.columnName)) {
            decodedString1 = getEntityName(o1.getEntityType());
            decodedString2 = getEntityName(o2.getEntityType());
        }
        else if (COLUMN_OPERATION_TYPE.equals(this.columnName)) {
            decodedString1 = getOperationName(o1.getOperationType());
            decodedString2 = getOperationName(o2.getOperationType());
        }
        else if (COLUMN_OPERATION_RESULT.equals(this.columnName)) {
            decodedString1 = getResultName(o1.getOperationResult());
            decodedString2 = getResultName(o2.getOperationResult());
        }
        else if (COLUMN_ELABORATION_TYPE.equals(this.columnName)) {
            decodedString1 = getResultName(o1.getOperationResult());
            decodedString2 = getResultName(o2.getOperationResult());
        }
        else if (COLUMN_EVENT_STATE.equals(this.columnName)) {
            decodedString1 = getStateName(o1.getEventState());
            decodedString2 = getStateName(o2.getEventState());
        }
        return (decodedString1.compareTo(decodedString2)) * this.ascending;
    }   
}
SagittariusA
  • 5,289
  • 15
  • 73
  • 127

1 Answers1

1

To avoid looping over the enum values for each row, you may want to create a static final HashMap<Integer,IMPORT_CONF_OPERATION_RESULT> to cache the map of values to corresponding labels and initialize it in a static block inside of your enum. Then you can have a public static String getLabelByValue(int value) to use cache and avoid O(n) for looking up the label each time.

For controlling the sort orders and sort actions you may want to go after TableRowSorter but when you have overriden the getValueAt for your model the default sorting should be sufficient. Other way is use a custom Comparator in your table model to manage the logic of sorting.

STaefi
  • 4,297
  • 1
  • 25
  • 43
  • Ok, now it's a little bit clearer but I'm afraid I'm missing something else. I mean, why should I use `HashMap` and not a `HashMap`? – SagittariusA Nov 16 '17 at 10:16
  • I've just updated my code following what you suggested. Unfortunately default `Sorter` class inside `DefaultTableModel` is not sufficient even if I had overriden `getValueAt()` because it still considers the original numeric value stored inside table model. That's why I added a custom `Comparator` switching the column header clicked by user. – SagittariusA Nov 16 '17 at 10:20
  • @LoryLory It's your choice, I think having the enum constant correspondent to the value would result in having access to its label with a single method call, and its more general and can be used in other parts of you application. – STaefi Nov 16 '17 at 10:22
  • You're right bu as our product is internationalized, the label in the enum is just used to get a correspondent one in the language set in the program by reading a file like . That's why i'm afraid I have to hold a `HashMap` where `String` is the internationalized label. Thank you for your help! – SagittariusA Nov 16 '17 at 11:14