| MapTableModel.java |
1 /**
2 * Distribution License:
3 * JSword is free software; you can redistribute it and/or modify it under
4 * the terms of the GNU Lesser General Public License, version 2.1 as published by
5 * the Free Software Foundation. This program is distributed in the hope
6 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8 * See the GNU Lesser General Public License for more details.
9 *
10 * The License is available on the internet at:
11 * http://www.gnu.org/copyleft/lgpl.html
12 * or by writing to:
13 * Free Software Foundation, Inc.
14 * 59 Temple Place - Suite 330
15 * Boston, MA 02111-1307, USA
16 *
17 * Copyright: 2005
18 * The copyright to this program is held by it's authors.
19 *
20 * ID: $Id: MapTableModel.java 2230 2012-02-08 00:00:10Z dmsmith $
21 */
22 package org.crosswire.common.swing;
23
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.Serializable;
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32 import javax.swing.table.AbstractTableModel;
33
34 import org.crosswire.common.util.Convert;
35
36 /**
37 * TableModel using a Map internally. Note that an AbstractTableModel (this is-a
38 * AbstractTableModel) reports changes to the data to the table itself. However
39 * since a Map does not have a addChangeListener interface we can't do the same
40 * - SO if you change the Map while we are displaying it then don't expect the
41 * changes to be automatically reflected in the JTable.
42 *
43 * @see gnu.lgpl.License for license details.<br>
44 * The copyright to this program is held by it's authors.
45 * @author Joe Walker [joe at eireneh dot com]
46 */
47 public class MapTableModel extends AbstractTableModel {
48 /**
49 * Create an internal store from a 2D array
50 */
51 public MapTableModel() {
52 this(null);
53 }
54
55 /**
56 * Create an internal store from a 2D array
57 *
58 * @param map
59 * The table to model
60 */
61 public MapTableModel(Map map) {
62 list = new ArrayList<StringPair>();
63 setMap(map);
64 }
65
66 /**
67 * Change the map that we report on
68 *
69 * @param map
70 * The map we are getting our data from
71 */
72 public final void setMap(Map<Object, Object> map) {
73 this.map = map;
74 list.clear();
75 if (map != null) {
76 Iterator<Map.Entry<Object, Object>> iter = map.entrySet().iterator();
77 while (iter.hasNext()) {
78 Map.Entry<Object, Object> me = iter.next();
79 Object k = me.getKey();
80 Object v = me.getValue();
81 if (k == null || v == null) {
82 // perhaps log a warning?
83 continue;
84 }
85 String key = k.toString().trim();
86 String value = v.toString().trim();
87 if (key.length() == 0) {
88 // perhaps log a warning?
89 continue;
90 }
91 list.add(new StringPair(key, value));
92 }
93 }
94 fireTableDataChanged();
95 }
96
97 /**
98 * @param key
99 * @param aValue
100 */
101 public void add(String key, String aValue) {
102 String value = aValue;
103 if (value == null) {
104 value = "";
105 }
106
107 if (key == null || key.length() == 0) {
108 return;
109 }
110
111 if (map.containsKey(key) && value.equals(map.get(key))) {
112 return;
113 }
114
115 map.put(key, value);
116 setMap(map);
117 }
118
119 /**
120 * @param key
121 */
122 public void remove(String key) {
123 if (map != null) {
124 map.remove(key);
125 setMap(map);
126 }
127 }
128
129 /**
130 * @param oldkey
131 * @param newkey
132 * @param newvalue
133 */
134 public void update(String oldkey, String newkey, String newvalue) {
135 if (map != null) {
136 if (!oldkey.equals(newkey)) {
137 map.remove(oldkey);
138 }
139
140 add(newkey, newvalue);
141 }
142 }
143
144 /**
145 * Return a string version of the current value
146 *
147 * @return The current value
148 */
149 public String getValue() {
150 return Convert.map2String(map);
151 }
152
153 /**
154 * How many Cols are there in this store
155 *
156 * @return The number of columns
157 */
158 public int getColumnCount() {
159 if (list == null) {
160 return 0;
161 }
162 return 2;
163 }
164
165 /**
166 * How many Rows are there in this store
167 *
168 * @return the number of row in the TableModel = elements in the map
169 */
170 public int getRowCount() {
171 if (list == null) {
172 return 0;
173 }
174 return list.size();
175 }
176
177 /**
178 * Return the Object at row, col
179 *
180 * @param row
181 * The element in the list
182 * @param col
183 * 1=keys, 2=values
184 * @return The key/value of the given element
185 */
186 public Object getValueAt(int row, int col) {
187 if (list == null) {
188 return null;
189 }
190
191 StringPair entry = list.get(row);
192 if (col == 0) {
193 return entry.getKey();
194 }
195 return entry.getValue();
196 }
197
198 /**
199 * Get the default class
200 *
201 * @param col
202 * 1=keys, 2=values
203 * @return String.class
204 */
205 @Override
206 public Class<String> getColumnClass(int col) {
207 return String.class;
208 }
209
210 /**
211 * The name of the of the <code>col</code>th column
212 *
213 * @param col
214 * The column index
215 * @return The column name
216 */
217 @Override
218 public String getColumnName(int col) {
219 return colNames[col];
220 }
221
222 /**
223 * The name of the of the <code>col</code>th column
224 *
225 * @param col
226 * The column index
227 * @param name
228 * The column name
229 */
230 public void setColumnName(int col, String name) {
231 colNames[col] = name;
232 }
233
234 /**
235 * Serialization support.
236 *
237 * @param is
238 * @throws IOException
239 * @throws ClassNotFoundException
240 */
241 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
242 list = new ArrayList<StringPair>();
243 is.defaultReadObject();
244 }
245
246 /**
247 * The List that is a copy of the list. A list is used for direct access
248 * performance.
249 */
250 private transient List<StringPair> list;
251
252 /**
253 * The backing map
254 */
255 private Map<Object, Object> map;
256
257 /**
258 * The default column names
259 */
260 private String[] colNames = new String[] {
261 CWOtherMsg.lookupText("Keys"), CWOtherMsg.lookupText("Values"),
262 };
263
264 /**
265 * Serialization ID
266 */
267 private static final long serialVersionUID = 3546365041277352241L;
268
269 /**
270 * A simple holder of a key/value pair of Strings.
271 */
272 private static final class StringPair implements Serializable {
273 /**
274 * @param k
275 * The non-null key.
276 * @param v
277 * The non-null value.
278 */
279 public StringPair(String k, String v) {
280 key = k;
281 value = v;
282 }
283
284 /**
285 * @return Returns the key.
286 */
287 public String getKey() {
288 return key;
289 }
290
291 /**
292 * @return Returns the value.
293 */
294 public String getValue() {
295 return value;
296 }
297
298 /**
299 * <code>key</code> is the string representation of a Map entry key
300 */
301 private String key;
302
303 /**
304 * <code>value</code> is the string representation of a Map entry value
305 */
306 private String value;
307
308 /**
309 * Serialization ID
310 */
311 private static final long serialVersionUID = 1730905297956834949L;
312
313 }
314 }
315