[127] | 1 | package genius.gui.progress;
|
---|
| 2 |
|
---|
| 3 | import java.util.ArrayList;
|
---|
| 4 | import java.util.LinkedHashMap;
|
---|
| 5 | import java.util.List;
|
---|
| 6 | import java.util.Map;
|
---|
| 7 | import java.util.TreeMap;
|
---|
| 8 |
|
---|
| 9 | import javax.swing.table.AbstractTableModel;
|
---|
| 10 |
|
---|
| 11 | /**
|
---|
| 12 | * Table model for showing results that takes {@link DataKey}s to enhance type
|
---|
| 13 | * checking and support conversion and smart data inserting. This code
|
---|
| 14 | * determines how data actually is ordered for display. Only adding of rows
|
---|
| 15 | * (containing one result) is supported.
|
---|
| 16 | *
|
---|
| 17 | * @author W.Pasman 16jul15
|
---|
| 18 | *
|
---|
| 19 | */
|
---|
| 20 | public class DataKeyTableModel extends AbstractTableModel {
|
---|
| 21 | /**
|
---|
| 22 | *
|
---|
| 23 | */
|
---|
| 24 | private static final long serialVersionUID = 49325296249290419L;
|
---|
| 25 |
|
---|
| 26 | /**
|
---|
| 27 | * The column specification - the Integer is the multiplicity of each of the
|
---|
| 28 | * columns. Note that the default order of the keys is determined by the
|
---|
| 29 | * order of DataKey.
|
---|
| 30 | */
|
---|
| 31 | private final LinkedHashMap<DataKey, Integer> columnSpec;
|
---|
| 32 |
|
---|
| 33 | /**
|
---|
| 34 | * name of the rows
|
---|
| 35 | */
|
---|
| 36 | private final List<String> columns = new ArrayList<String>();
|
---|
| 37 | private final List<List<Object>> rows = new ArrayList<List<Object>>();
|
---|
| 38 |
|
---|
| 39 | /**
|
---|
| 40 | * @param colspec
|
---|
| 41 | * a {@link TreeMap} containing tuples [DataKey,Integer] that
|
---|
| 42 | * specifies the columns for the table. The DataKey is the column
|
---|
| 43 | * to show, the Integer is the maximum multiplicity of that
|
---|
| 44 | * column. When a column multiplicity has been set to a value
|
---|
| 45 | * >1, and a row is added that has a {@link List} for that
|
---|
| 46 | * {@link DataKey}, then the list is expanded to separate
|
---|
| 47 | * columns. All multiplicities must be ≥ 1.
|
---|
| 48 | *
|
---|
| 49 | * The order of the DataKeys determines the order of the columns.
|
---|
| 50 | */
|
---|
| 51 | public DataKeyTableModel(LinkedHashMap<DataKey, Integer> colspec) {
|
---|
| 52 | super();
|
---|
| 53 | if (colspec.isEmpty()) {
|
---|
| 54 | throw new IllegalArgumentException("table contains no columns");
|
---|
| 55 | }
|
---|
| 56 | columnSpec = colspec;
|
---|
| 57 | initColumns();
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | /**
|
---|
| 61 | * Get the real column names based on the {@link DataKey} and multiplicity
|
---|
| 62 | * of the {@link #columnSpec}.
|
---|
| 63 | */
|
---|
| 64 | private void initColumns() {
|
---|
| 65 | for (DataKey key : columnSpec.keySet()) {
|
---|
| 66 | int multiplicity = columnSpec.get(key);
|
---|
| 67 | if (multiplicity < 1) {
|
---|
| 68 | throw new IllegalArgumentException("column multiplicity must be >=1, found " + multiplicity);
|
---|
| 69 | }
|
---|
| 70 | if (multiplicity > 1) {
|
---|
| 71 | for (int n = 1; n <= multiplicity; n++) {
|
---|
| 72 | columns.add(key.getName() + " " + n);
|
---|
| 73 | }
|
---|
| 74 | } else {
|
---|
| 75 | columns.add(key.getName());
|
---|
| 76 | }
|
---|
| 77 | }
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | /**
|
---|
| 81 | * Adds a row with new values. The values from the [key,value] pairs in the
|
---|
| 82 | * map are inserted in the correct columns given the headers. When a column
|
---|
| 83 | * multiplicity has been set to a value >1 for {@link DataKey} K, and the
|
---|
| 84 | * value for K in the given map is a {@link List}, then the list is expanded
|
---|
| 85 | * to separate columns.
|
---|
| 86 | *
|
---|
| 87 | * @param newValues
|
---|
| 88 | * a {@link Map} with DataKeys and objects as values.
|
---|
| 89 | */
|
---|
| 90 | public void addRow(Map<DataKey, Object> newValues) {
|
---|
| 91 | List<Object> row = new ArrayList<Object>();
|
---|
| 92 |
|
---|
| 93 | for (DataKey key : columnSpec.keySet()) {
|
---|
| 94 | int multiplicity = columnSpec.get(key);
|
---|
| 95 | row.addAll(makeColumns(multiplicity, newValues.get(key)));
|
---|
| 96 | }
|
---|
| 97 | rows.add(row);
|
---|
| 98 |
|
---|
| 99 | fireTableRowsInserted(rows.size() - 1, rows.size() - 1);
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | /**
|
---|
| 103 | * Converts an object into exactly #multiplicity objects. if
|
---|
| 104 | * multiplicity==1, the returned list contains just that object. if
|
---|
| 105 | * multiplicity>1 but the object is not a list, the list contains the
|
---|
| 106 | * object as first element and filled out with empty elements.
|
---|
| 107 | *
|
---|
| 108 | * If object is a List, then the columns are filled with subsequential
|
---|
| 109 | * elements from the list. Too short lists lead to empty columns. Too long
|
---|
| 110 | * lists results in dropped elements.
|
---|
| 111 | *
|
---|
| 112 | * @param multiplicity
|
---|
| 113 | * @param object
|
---|
| 114 | * @return list with object as first element, or with the contents of object
|
---|
| 115 | * if object is a list
|
---|
| 116 | */
|
---|
| 117 | private ArrayList<Object> makeColumns(int multiplicity, Object object) {
|
---|
| 118 | List<Object> objList = null;
|
---|
| 119 | if (object instanceof List) {
|
---|
| 120 | objList = (List<Object>) object;
|
---|
| 121 | }
|
---|
| 122 |
|
---|
| 123 | ArrayList<Object> result = new ArrayList<Object>();
|
---|
| 124 | if (multiplicity == 1) {
|
---|
| 125 | result.add(object);
|
---|
| 126 | return result;
|
---|
| 127 | }
|
---|
| 128 | for (int n = 0; n < multiplicity; n++) {
|
---|
| 129 | if (objList == null) {
|
---|
| 130 | if (n == 0) {
|
---|
| 131 | result.add(object);
|
---|
| 132 | } else {
|
---|
| 133 | result.add("");
|
---|
| 134 | }
|
---|
| 135 | } else {
|
---|
| 136 | // object is a list.
|
---|
| 137 | if (n >= objList.size()) {
|
---|
| 138 | result.add("");
|
---|
| 139 | } else {
|
---|
| 140 | result.add(objList.get(n));
|
---|
| 141 | }
|
---|
| 142 | }
|
---|
| 143 | }
|
---|
| 144 | return result;
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | public int getColumnCount() {
|
---|
| 148 | return columns.size();
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | public int getRowCount() {
|
---|
| 152 | return rows.size();
|
---|
| 153 | }
|
---|
| 154 |
|
---|
| 155 | public String getColumnName(int col) {
|
---|
| 156 | return columns.get(col);
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | public Object getValueAt(int row, int col) {
|
---|
| 160 | return rows.get(row).get(col);
|
---|
| 161 | }
|
---|
| 162 |
|
---|
| 163 | }
|
---|