Simon Hunt
Committed by Gerrit Code Review

GUI -- Initial cut at a simple table/row/cell model to allow us more control ove…

…r the comparison / formatting of cell values for GUI tables.

Change-Id: I1a163259f1e80b2765a92cda654ffe092c835e6d
/*
* 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;
/**
* Defines a formatter for cell values.
*/
public interface CellFormatter {
/**
* Formats the specified value into a string appropriate for displaying
* in a table cell.
*
* @param value the value
* @return the formatted string
*/
String format(Object value);
}
/*
* 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;
/**
* A default cell formatter. Uses the object's toString() method.
*/
public class DefaultCellFormatter implements CellFormatter {
@Override
public String format(Object value) {
return value == null ? "" : value.toString();
}
}
/*
* 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 java.util.ArrayList;
import java.util.Arrays;
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 model of table data.
*/
public class TableModel {
private static final CellFormatter DEF_FMT = new DefaultCellFormatter();
private final String[] columnIds;
private final Set<String> idSet;
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 {@link TableRow} representation of the rows in this table.
*
* @return formatted table rows
*/
public TableRow[] getTableRows() {
return new TableRow[0];
}
/**
* 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 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;
}
/**
* 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) {
checkNotNull(value, "Must supply some 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);
}
}
}
/*
* 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 org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Unit tests for {@link DefaultCellFormatter}.
*/
public class DefaultCellFormatterTest {
private static final String UNEX = "Unexpected result";
private static final String SOME_STRING = "SoMeStRiNg";
private static class TestClass {
@Override
public String toString() {
return SOME_STRING;
}
}
private CellFormatter fmt = new DefaultCellFormatter();
@Test
public void formatNull() {
assertEquals(UNEX, "", fmt.format(null));
}
@Test
public void formatInteger() {
assertEquals(UNEX, "3", fmt.format(3));
}
@Test
public void formatTrue() {
assertEquals(UNEX, "true", fmt.format(true));
}
@Test
public void formatFalse() {
assertEquals(UNEX, "false", fmt.format(false));
}
@Test
public void formatString() {
assertEquals(UNEX, "FOO", fmt.format("FOO"));
}
@Test
public void formatObject() {
assertEquals(UNEX, SOME_STRING, fmt.format(new TestClass()));
}
}
/*
* 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 org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Unit tests for {@link TableModel}.
*/
public class TableModelTest {
private static final String FOO = "foo";
private static final String BAR = "bar";
private static final String BAZ = "baz";
private static final String ZOO = "zoo";
private static class TestFmtr implements CellFormatter {
@Override
public String format(Object value) {
return "(" + value + ")";
}
}
private TableModel tm;
private TableRow[] rows;
private CellFormatter fmt;
@Test(expected = NullPointerException.class)
public void guardAgainstNull() {
tm = new TableModel(null);
}
@Test(expected = IllegalArgumentException.class)
public void guardAgainstEmpty() {
tm = new TableModel();
}
@Test(expected = IllegalArgumentException.class)
public void guardAgainstDuplicateCols() {
tm = new TableModel(FOO, BAR, FOO);
}
@Test
public void basic() {
tm = new TableModel(FOO, BAR);
assertEquals("column count", 2, tm.columnCount());
assertEquals("row count", 0, tm.rowCount());
rows = tm.getTableRows();
assertEquals("row count alt", 0, rows.length);
}
@Test
public void defaultFormatter() {
tm = new TableModel(FOO);
fmt = tm.getFormatter(FOO);
assertTrue("Wrong formatter", fmt instanceof DefaultCellFormatter);
}
@Test(expected = IllegalArgumentException.class)
public void formatterBadColumn() {
tm = new TableModel(FOO);
fmt = tm.getFormatter(BAR);
}
@Test
public void altFormatter() {
tm = new TableModel(FOO, BAR);
tm.setFormatter(BAR, new TestFmtr());
fmt = tm.getFormatter(FOO);
assertTrue("Wrong formatter", fmt instanceof DefaultCellFormatter);
assertEquals("Wrong result", "2", fmt.format(2));
fmt = tm.getFormatter(BAR);
assertTrue("Wrong formatter", fmt instanceof TestFmtr);
assertEquals("Wrong result", "(2)", fmt.format(2));
}
@Test
public void emptyRow() {
tm = new TableModel(FOO, BAR);
tm.addRow();
assertEquals("bad row count", 1, tm.rowCount());
}
@Test(expected = IllegalArgumentException.class)
public void rowBadColumn() {
tm = new TableModel(FOO, BAR);
tm.addRow().cell(ZOO, 2);
}
@Test(expected = NullPointerException.class)
public void rowNullValue() {
tm = new TableModel(FOO, BAR);
tm.addRow().cell(FOO, null);
}
@Test
public void simpleRow() {
tm = new TableModel(FOO, BAR);
tm.addRow().cell(FOO, 3).cell(BAR, true);
assertEquals("bad row count", 1, tm.rowCount());
TableModel.Row r = tm.getRows()[0];
assertEquals("bad cell", 3, r.get(FOO));
assertEquals("bad cell", true, r.get(BAR));
}
}