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
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +
18 +package org.onosproject.ui.table;
19 +
20 +/**
21 + * Defines a formatter for cell values.
22 + */
23 +public interface CellFormatter {
24 +
25 + /**
26 + * Formats the specified value into a string appropriate for displaying
27 + * in a table cell.
28 + *
29 + * @param value the value
30 + * @return the formatted string
31 + */
32 + String format(Object value);
33 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +
18 +package org.onosproject.ui.table;
19 +
20 +/**
21 + * A default cell formatter. Uses the object's toString() method.
22 + */
23 +public class DefaultCellFormatter implements CellFormatter {
24 + @Override
25 + public String format(Object value) {
26 + return value == null ? "" : value.toString();
27 + }
28 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.ui.table;
18 +
19 +import com.google.common.collect.Sets;
20 +
21 +import java.util.ArrayList;
22 +import java.util.Arrays;
23 +import java.util.HashMap;
24 +import java.util.List;
25 +import java.util.Map;
26 +import java.util.Set;
27 +
28 +import static com.google.common.base.Preconditions.checkArgument;
29 +import static com.google.common.base.Preconditions.checkNotNull;
30 +
31 +/**
32 + * A model of table data.
33 + */
34 +public class TableModel {
35 +
36 + private static final CellFormatter DEF_FMT = new DefaultCellFormatter();
37 +
38 + private final String[] columnIds;
39 + private final Set<String> idSet;
40 + private final Map<String, CellFormatter> formatters = new HashMap<>();
41 + private final List<Row> rows = new ArrayList<>();
42 +
43 +
44 + /**
45 + * Constructs a table (devoid of data) with the given column IDs.
46 + *
47 + * @param columnIds column identifiers
48 + */
49 + public TableModel(String... columnIds) {
50 + checkNotNull(columnIds, "columnIds cannot be null");
51 + checkArgument(columnIds.length > 0, "must be at least one column");
52 +
53 + idSet = Sets.newHashSet(columnIds);
54 + if (idSet.size() != columnIds.length) {
55 + throw new IllegalArgumentException("duplicate column ID(s) detected");
56 + }
57 +
58 + this.columnIds = Arrays.copyOf(columnIds, columnIds.length);
59 + }
60 +
61 + private void checkId(String id) {
62 + checkNotNull(id, "must provide a column ID");
63 + if (!idSet.contains(id)) {
64 + throw new IllegalArgumentException("unknown column id: " + id);
65 + }
66 + }
67 +
68 + /**
69 + * Returns the number of rows in this table model.
70 + *
71 + * @return number of rows
72 + */
73 + public int rowCount() {
74 + return rows.size();
75 + }
76 +
77 + /**
78 + * Returns the number of columns in this table model.
79 + *
80 + * @return number of columns
81 + */
82 + public int columnCount() {
83 + return columnIds.length;
84 + }
85 +
86 + /**
87 + * Returns the {@link TableRow} representation of the rows in this table.
88 + *
89 + * @return formatted table rows
90 + */
91 + public TableRow[] getTableRows() {
92 + return new TableRow[0];
93 + }
94 +
95 + /**
96 + * Returns the raw {@link Row} representation of the rows in this table.
97 + *
98 + * @return raw table rows
99 + */
100 + public Row[] getRows() {
101 + return rows.toArray(new Row[rows.size()]);
102 + }
103 +
104 + /**
105 + * Sets a cell formatter for the specified column.
106 + *
107 + * @param columnId column identifier
108 + * @param formatter formatter to use
109 + */
110 + public void setFormatter(String columnId, CellFormatter formatter) {
111 + checkNotNull(formatter, "must provide a formatter");
112 + checkId(columnId);
113 + formatters.put(columnId, formatter);
114 + }
115 +
116 + /**
117 + * Returns the cell formatter to use on values in the specified column.
118 + *
119 + * @param columnId column identifier
120 + * @return an appropriate cell formatter
121 + */
122 + public CellFormatter getFormatter(String columnId) {
123 + checkId(columnId);
124 + CellFormatter fmt = formatters.get(columnId);
125 + return fmt == null ? DEF_FMT : fmt;
126 + }
127 +
128 + /**
129 + * Adds a row to the table model.
130 + *
131 + * @return the row, for chaining
132 + */
133 + public Row addRow() {
134 + Row r = new Row();
135 + rows.add(r);
136 + return r;
137 + }
138 +
139 + /**
140 + * Model of a row.
141 + */
142 + public class Row {
143 + private final Map<String, Object> cells = new HashMap<>();
144 +
145 + /**
146 + * Sets the cell value for the given column of this row.
147 + *
148 + * @param columnId column identifier
149 + * @param value value to set
150 + * @return self, for chaining
151 + */
152 + public Row cell(String columnId, Object value) {
153 + checkNotNull(value, "Must supply some value");
154 + checkId(columnId);
155 + cells.put(columnId, value);
156 + return this;
157 + }
158 +
159 + /**
160 + * Returns the value of the cell in the given column for this row.
161 + *
162 + * @param columnId column identifier
163 + * @return cell value
164 + */
165 + public Object get(String columnId) {
166 + return cells.get(columnId);
167 + }
168 + }
169 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +
18 +package org.onosproject.ui.table;
19 +
20 +import org.junit.Test;
21 +
22 +import static org.junit.Assert.assertEquals;
23 +
24 +/**
25 + * Unit tests for {@link DefaultCellFormatter}.
26 + */
27 +public class DefaultCellFormatterTest {
28 +
29 + private static final String UNEX = "Unexpected result";
30 + private static final String SOME_STRING = "SoMeStRiNg";
31 +
32 + private static class TestClass {
33 + @Override
34 + public String toString() {
35 + return SOME_STRING;
36 + }
37 + }
38 +
39 + private CellFormatter fmt = new DefaultCellFormatter();
40 +
41 + @Test
42 + public void formatNull() {
43 + assertEquals(UNEX, "", fmt.format(null));
44 + }
45 +
46 + @Test
47 + public void formatInteger() {
48 + assertEquals(UNEX, "3", fmt.format(3));
49 + }
50 +
51 + @Test
52 + public void formatTrue() {
53 + assertEquals(UNEX, "true", fmt.format(true));
54 + }
55 +
56 + @Test
57 + public void formatFalse() {
58 + assertEquals(UNEX, "false", fmt.format(false));
59 + }
60 +
61 + @Test
62 + public void formatString() {
63 + assertEquals(UNEX, "FOO", fmt.format("FOO"));
64 + }
65 +
66 + @Test
67 + public void formatObject() {
68 + assertEquals(UNEX, SOME_STRING, fmt.format(new TestClass()));
69 + }
70 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.ui.table;
18 +
19 +import org.junit.Test;
20 +
21 +import static org.junit.Assert.assertEquals;
22 +import static org.junit.Assert.assertTrue;
23 +
24 +/**
25 + * Unit tests for {@link TableModel}.
26 + */
27 +public class TableModelTest {
28 +
29 + private static final String FOO = "foo";
30 + private static final String BAR = "bar";
31 + private static final String BAZ = "baz";
32 + private static final String ZOO = "zoo";
33 +
34 + private static class TestFmtr implements CellFormatter {
35 + @Override
36 + public String format(Object value) {
37 + return "(" + value + ")";
38 + }
39 + }
40 +
41 + private TableModel tm;
42 + private TableRow[] rows;
43 + private CellFormatter fmt;
44 +
45 + @Test(expected = NullPointerException.class)
46 + public void guardAgainstNull() {
47 + tm = new TableModel(null);
48 + }
49 +
50 + @Test(expected = IllegalArgumentException.class)
51 + public void guardAgainstEmpty() {
52 + tm = new TableModel();
53 + }
54 +
55 + @Test(expected = IllegalArgumentException.class)
56 + public void guardAgainstDuplicateCols() {
57 + tm = new TableModel(FOO, BAR, FOO);
58 + }
59 +
60 + @Test
61 + public void basic() {
62 + tm = new TableModel(FOO, BAR);
63 + assertEquals("column count", 2, tm.columnCount());
64 + assertEquals("row count", 0, tm.rowCount());
65 +
66 + rows = tm.getTableRows();
67 + assertEquals("row count alt", 0, rows.length);
68 + }
69 +
70 + @Test
71 + public void defaultFormatter() {
72 + tm = new TableModel(FOO);
73 + fmt = tm.getFormatter(FOO);
74 + assertTrue("Wrong formatter", fmt instanceof DefaultCellFormatter);
75 + }
76 +
77 + @Test(expected = IllegalArgumentException.class)
78 + public void formatterBadColumn() {
79 + tm = new TableModel(FOO);
80 + fmt = tm.getFormatter(BAR);
81 + }
82 +
83 + @Test
84 + public void altFormatter() {
85 + tm = new TableModel(FOO, BAR);
86 + tm.setFormatter(BAR, new TestFmtr());
87 +
88 + fmt = tm.getFormatter(FOO);
89 + assertTrue("Wrong formatter", fmt instanceof DefaultCellFormatter);
90 + assertEquals("Wrong result", "2", fmt.format(2));
91 +
92 + fmt = tm.getFormatter(BAR);
93 + assertTrue("Wrong formatter", fmt instanceof TestFmtr);
94 + assertEquals("Wrong result", "(2)", fmt.format(2));
95 + }
96 +
97 + @Test
98 + public void emptyRow() {
99 + tm = new TableModel(FOO, BAR);
100 + tm.addRow();
101 + assertEquals("bad row count", 1, tm.rowCount());
102 + }
103 +
104 + @Test(expected = IllegalArgumentException.class)
105 + public void rowBadColumn() {
106 + tm = new TableModel(FOO, BAR);
107 + tm.addRow().cell(ZOO, 2);
108 + }
109 +
110 + @Test(expected = NullPointerException.class)
111 + public void rowNullValue() {
112 + tm = new TableModel(FOO, BAR);
113 + tm.addRow().cell(FOO, null);
114 + }
115 +
116 + @Test
117 + public void simpleRow() {
118 + tm = new TableModel(FOO, BAR);
119 + tm.addRow().cell(FOO, 3).cell(BAR, true);
120 + assertEquals("bad row count", 1, tm.rowCount());
121 + TableModel.Row r = tm.getRows()[0];
122 + assertEquals("bad cell", 3, r.get(FOO));
123 + assertEquals("bad cell", true, r.get(BAR));
124 + }
125 +}