diff options
Diffstat (limited to 'framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java')
-rw-r--r-- | framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java new file mode 100644 index 00000000..d0fccb65 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java @@ -0,0 +1,304 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.ui.table; + +import com.google.common.collect.Sets; +import org.onosproject.ui.table.cell.DefaultCellComparator; +import org.onosproject.ui.table.cell.DefaultCellFormatter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * A simple model of table data. + * <p> + * Note that this is not a full MVC type model; the expected usage pattern + * is to create an empty table, add rows (by consulting the business model), + * sort rows (based on client request parameters), and finally produce the + * sorted list of rows. + * <p> + * The table also provides a mechanism for defining how cell values for a + * particular column should be formatted into strings, to help facilitate + * the encoding of the table data into a JSON structure. + * <p> + * Note that it is expected that all values for a particular column will + * be the same class. + */ +public class TableModel { + + private static final CellComparator DEF_CMP = DefaultCellComparator.INSTANCE; + private static final CellFormatter DEF_FMT = DefaultCellFormatter.INSTANCE; + + private final String[] columnIds; + private final Set<String> idSet; + private final Map<String, CellComparator> comparators = new HashMap<>(); + private final Map<String, CellFormatter> formatters = new HashMap<>(); + private final List<Row> rows = new ArrayList<>(); + + + /** + * Constructs a table (devoid of data) with the given column IDs. + * + * @param columnIds column identifiers + */ + public TableModel(String... columnIds) { + checkNotNull(columnIds, "columnIds cannot be null"); + checkArgument(columnIds.length > 0, "must be at least one column"); + + idSet = Sets.newHashSet(columnIds); + if (idSet.size() != columnIds.length) { + throw new IllegalArgumentException("duplicate column ID(s) detected"); + } + + this.columnIds = Arrays.copyOf(columnIds, columnIds.length); + } + + private void checkId(String id) { + checkNotNull(id, "must provide a column ID"); + if (!idSet.contains(id)) { + throw new IllegalArgumentException("unknown column id: " + id); + } + } + + /** + * Returns the number of rows in this table model. + * + * @return number of rows + */ + public int rowCount() { + return rows.size(); + } + + /** + * Returns the number of columns in this table model. + * + * @return number of columns + */ + public int columnCount() { + return columnIds.length; + } + + /** + * Returns the array of column IDs for this table model. + * <p> + * Implementation note: we are knowingly passing you a reference to + * our internal array to avoid copying. Don't mess with it. It's your + * table you'll break if you do! + * + * @return the column identifiers + */ + public String[] getColumnIds() { + return columnIds; + } + + /** + * Returns the raw {@link Row} representation of the rows in this table. + * + * @return raw table rows + */ + public Row[] getRows() { + return rows.toArray(new Row[rows.size()]); + } + + /** + * Sets a cell comparator for the specified column. + * + * @param columnId column identifier + * @param comparator comparator to use + */ + public void setComparator(String columnId, CellComparator comparator) { + checkNotNull(comparator, "must provide a comparator"); + checkId(columnId); + comparators.put(columnId, comparator); + } + + /** + * Returns the cell comparator to use on values in the specified column. + * + * @param columnId column identifier + * @return an appropriate cell comparator + */ + private CellComparator getComparator(String columnId) { + checkId(columnId); + CellComparator cmp = comparators.get(columnId); + return cmp == null ? DEF_CMP : cmp; + } + + /** + * Sets a cell formatter for the specified column. + * + * @param columnId column identifier + * @param formatter formatter to use + */ + public void setFormatter(String columnId, CellFormatter formatter) { + checkNotNull(formatter, "must provide a formatter"); + checkId(columnId); + formatters.put(columnId, formatter); + } + + /** + * Returns the cell formatter to use on values in the specified column. + * + * @param columnId column identifier + * @return an appropriate cell formatter + */ + public CellFormatter getFormatter(String columnId) { + checkId(columnId); + CellFormatter fmt = formatters.get(columnId); + return fmt == null ? DEF_FMT : fmt; + } + + /** + * Adds a row to the table model. + * + * @return the row, for chaining + */ + public Row addRow() { + Row r = new Row(); + rows.add(r); + return r; + } + + /** + * Sorts the table rows based on the specified column, in the + * specified direction. + * + * @param columnId column identifier + * @param dir sort direction + */ + public void sort(String columnId, SortDir dir) { + Collections.sort(rows, new RowComparator(columnId, dir)); + } + + + /** Designates sorting direction. */ + public enum SortDir { + /** Designates an ascending sort. */ + ASC, + /** Designates a descending sort. */ + DESC + } + + /** + * Row comparator. + */ + private class RowComparator implements Comparator<Row> { + private final String columnId; + private final SortDir dir; + private final CellComparator cellComparator; + + /** + * Constructs a row comparator based on the specified + * column identifier and sort direction. + * + * @param columnId column identifier + * @param dir sort direction + */ + public RowComparator(String columnId, SortDir dir) { + this.columnId = columnId; + this.dir = dir; + cellComparator = getComparator(columnId); + } + + @Override + public int compare(Row a, Row b) { + Object cellA = a.get(columnId); + Object cellB = b.get(columnId); + int result = cellComparator.compare(cellA, cellB); + return dir == SortDir.ASC ? result : -result; + } + } + + /** + * Model of a row. + */ + public class Row { + private final Map<String, Object> cells = new HashMap<>(); + + /** + * Sets the cell value for the given column of this row. + * + * @param columnId column identifier + * @param value value to set + * @return self, for chaining + */ + public Row cell(String columnId, Object value) { + checkId(columnId); + cells.put(columnId, value); + return this; + } + + /** + * Returns the value of the cell in the given column for this row. + * + * @param columnId column identifier + * @return cell value + */ + public Object get(String columnId) { + return cells.get(columnId); + } + + /** + * Returns the value of the cell as a string, using the + * formatter appropriate for the column. + * + * @param columnId column identifier + * @return formatted cell value + */ + String getAsString(String columnId) { + return getFormatter(columnId).format(get(columnId)); + } + + /** + * Returns the row as an array of formatted strings. + * + * @return the formatted row data + */ + public String[] getAsFormattedStrings() { + List<String> formatted = new ArrayList<>(columnCount()); + for (String c : columnIds) { + formatted.add(getAsString(c)); + } + return formatted.toArray(new String[formatted.size()]); + } + } + + private static final String DESC = "desc"; + + /** + * Returns the appropriate sort direction for the given string. + * <p> + * The expected strings are "asc" for {@link SortDir#ASC ascending} and + * "desc" for {@link SortDir#DESC descending}. Any other value will + * default to ascending. + * + * @param s sort direction string encoding + * @return sort direction + */ + public static SortDir sortDir(String s) { + return !DESC.equals(s) ? SortDir.ASC : SortDir.DESC; + } +} |