svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.fmap.control / src / main / java / org / gvsig / fmap / mapcontrol / dal / feature / swing / table / ConfigurableFeatureTableModel.java @ 41707
History | View | Annotate | Download (17.6 KB)
1 | 40559 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40435 | jjdelcerro | *
|
4 | 40559 | jjdelcerro | * Copyright (C) 2007-2013 gvSIG Association.
|
5 | 40435 | jjdelcerro | *
|
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | 40559 | jjdelcerro | * as published by the Free Software Foundation; either version 3
|
9 | 40435 | jjdelcerro | * of the License, or (at your option) any later version.
|
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
19 | * MA 02110-1301, USA.
|
||
20 | *
|
||
21 | 40559 | jjdelcerro | * For any additional information, do not hesitate to contact us
|
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 40435 | jjdelcerro | */
|
24 | /*
|
||
25 | * AUTHORS (In addition to CIT):
|
||
26 | * 2008 {DiSiD Technologies} {Create a JTable TableModel for a FeatureQuery}
|
||
27 | */
|
||
28 | package org.gvsig.fmap.mapcontrol.dal.feature.swing.table; |
||
29 | |||
30 | import java.security.InvalidParameterException; |
||
31 | 41699 | jjdelcerro | import java.text.SimpleDateFormat; |
32 | 40435 | jjdelcerro | import java.util.ArrayList; |
33 | import java.util.HashMap; |
||
34 | import java.util.Iterator; |
||
35 | import java.util.List; |
||
36 | 41699 | jjdelcerro | import java.util.Locale; |
37 | 40435 | jjdelcerro | import java.util.Map; |
38 | |||
39 | import javax.swing.event.TableModelEvent; |
||
40 | 41707 | jjdelcerro | import org.apache.commons.lang3.StringUtils; |
41 | 40435 | jjdelcerro | |
42 | import org.gvsig.fmap.dal.DataTypes; |
||
43 | import org.gvsig.fmap.dal.feature.EditableFeature; |
||
44 | import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor; |
||
45 | import org.gvsig.fmap.dal.feature.Feature; |
||
46 | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
||
47 | import org.gvsig.fmap.dal.feature.FeatureQuery; |
||
48 | import org.gvsig.fmap.dal.feature.FeatureQueryOrder; |
||
49 | import org.gvsig.fmap.dal.feature.FeatureStore; |
||
50 | import org.gvsig.fmap.dal.feature.FeatureType; |
||
51 | import org.gvsig.tools.exception.BaseException; |
||
52 | 41212 | jjdelcerro | import org.slf4j.Logger; |
53 | import org.slf4j.LoggerFactory; |
||
54 | 40435 | jjdelcerro | |
55 | /**
|
||
56 | * Extends the FeatureTableModel to add more configurable options, like the
|
||
57 | * visible columns, column name aliases and row order.
|
||
58 | *
|
||
59 | * TODO: a?adir la persistencia.
|
||
60 | *
|
||
61 | * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
|
||
62 | */
|
||
63 | public class ConfigurableFeatureTableModel extends FeatureTableModel { |
||
64 | |||
65 | private static final long serialVersionUID = -8223987814719746492L; |
||
66 | 41212 | jjdelcerro | |
67 | private static final Logger logger = LoggerFactory.getLogger(ConfigurableFeatureTableModel.class); |
||
68 | 40435 | jjdelcerro | |
69 | private List<String> columnNames; |
||
70 | |||
71 | private List<String> visibleColumnNames; |
||
72 | |||
73 | private List<String> visibleColumnNamesOriginal; |
||
74 | |||
75 | private Map<String, String> name2Alias; |
||
76 | |||
77 | private Map<String, String> name2AliasOriginal; |
||
78 | |||
79 | 41699 | jjdelcerro | private Map<String,String> patterns = null; |
80 | |||
81 | private Locale localeOfData; |
||
82 | 40435 | jjdelcerro | /**
|
83 | * @see FeatureTableModel#FeatureTableModel(FeatureStore, FeatureQuery)
|
||
84 | */
|
||
85 | public ConfigurableFeatureTableModel(FeatureStore featureStore,
|
||
86 | FeatureQuery featureQuery) throws BaseException {
|
||
87 | super(featureStore, featureQuery);
|
||
88 | 41699 | jjdelcerro | this.localeOfData = Locale.getDefault(); |
89 | 40435 | jjdelcerro | } |
90 | |||
91 | /**
|
||
92 | * @see FeatureTableModel#FeatureTableModel(FeatureStore, FeatureQuery, int)
|
||
93 | */
|
||
94 | public ConfigurableFeatureTableModel(FeatureStore featureStore,
|
||
95 | FeatureQuery featureQuery, int pageSize) throws BaseException { |
||
96 | super(featureStore, featureQuery, pageSize);
|
||
97 | } |
||
98 | |||
99 | @Override
|
||
100 | public int getColumnCount() { |
||
101 | return visibleColumnNames.size();
|
||
102 | } |
||
103 | |||
104 | public int getOriginalColumnCount() { |
||
105 | return super.getColumnCount(); |
||
106 | } |
||
107 | |||
108 | @Override
|
||
109 | public String getColumnName(int column) { |
||
110 | int originalIndex = getOriginalColumnIndex(column);
|
||
111 | return getAliasForColumn(getOriginalColumnName(originalIndex));
|
||
112 | } |
||
113 | |||
114 | @Override
|
||
115 | public Class<?> getColumnClass(int columnIndex) { |
||
116 | int originalIndex = getOriginalColumnIndex(columnIndex);
|
||
117 | return super.getColumnClass(originalIndex); |
||
118 | } |
||
119 | |||
120 | @Override
|
||
121 | public FeatureAttributeDescriptor getDescriptorForColumn(int columnIndex) { |
||
122 | int originalIndex = getOriginalColumnIndex(columnIndex);
|
||
123 | return super.getDescriptorForColumn(originalIndex); |
||
124 | } |
||
125 | |||
126 | /**
|
||
127 | * Returns the original name of the column, ignoring the alias.
|
||
128 | *
|
||
129 | * @param column
|
||
130 | * the original index of the column
|
||
131 | * @return the original column name
|
||
132 | */
|
||
133 | public String getOriginalColumnName(int column) { |
||
134 | return super.getColumnName(column); |
||
135 | } |
||
136 | |||
137 | /**
|
||
138 | * Sets the visibility of a table column.
|
||
139 | *
|
||
140 | * @param columnIndex
|
||
141 | * the index of the column to update
|
||
142 | * @param visible
|
||
143 | * if the column will be visible or not
|
||
144 | */
|
||
145 | public void setVisible(String name, boolean visible) { |
||
146 | // If we don't have already the column as visible,
|
||
147 | // add to the list, without order, and recreate
|
||
148 | // the visible columns list in the original order
|
||
149 | if (!columnNames.contains(name)) {
|
||
150 | throw new InvalidParameterException(name); // FIXME |
||
151 | } |
||
152 | if (visible && !visibleColumnNames.contains(name)) {
|
||
153 | visibleColumnNames.add(name); |
||
154 | setVisibleColumns(visibleColumnNames); |
||
155 | } else {
|
||
156 | visibleColumnNames.remove(name); |
||
157 | 41212 | jjdelcerro | setVisibleColumns(visibleColumnNames); |
158 | 40435 | jjdelcerro | fireTableStructureChanged(); |
159 | } |
||
160 | |||
161 | } |
||
162 | |||
163 | @Override
|
||
164 | public void setFeatureType(FeatureType featureType) { |
||
165 | // Check if there is a new column name
|
||
166 | List<String> newColumns = new ArrayList<String>(); |
||
167 | List<String> renamedColumnsNewName = new ArrayList<String>(); |
||
168 | |||
169 | @SuppressWarnings("unchecked") |
||
170 | Iterator<FeatureAttributeDescriptor> attrIter = featureType.iterator();
|
||
171 | FeatureAttributeDescriptor fad = null;
|
||
172 | EditableFeatureAttributeDescriptor efad = null;
|
||
173 | |||
174 | String colName;
|
||
175 | while (attrIter.hasNext()) {
|
||
176 | fad = attrIter.next(); |
||
177 | colName = fad.getName(); |
||
178 | if (!columnNames.contains(colName)) {
|
||
179 | if (fad instanceof EditableFeatureAttributeDescriptor) { |
||
180 | efad = (EditableFeatureAttributeDescriptor) fad; |
||
181 | /*
|
||
182 | * If editable att descriptor,
|
||
183 | * check original name
|
||
184 | */
|
||
185 | if (efad.getOriginalName() != null) { |
||
186 | if (!columnNames.contains(efad.getOriginalName())) {
|
||
187 | /*
|
||
188 | * Check with original name but add current name
|
||
189 | */
|
||
190 | newColumns.add(colName); |
||
191 | } else {
|
||
192 | /*
|
||
193 | * List of new names of renamed columns
|
||
194 | */
|
||
195 | renamedColumnsNewName.add(colName); |
||
196 | } |
||
197 | } else {
|
||
198 | newColumns.add(colName); |
||
199 | } |
||
200 | } else {
|
||
201 | newColumns.add(colName); |
||
202 | } |
||
203 | } |
||
204 | } |
||
205 | |||
206 | // Update column names
|
||
207 | columnNames.clear(); |
||
208 | @SuppressWarnings("unchecked") |
||
209 | Iterator<FeatureAttributeDescriptor> visibleAttrIter =
|
||
210 | featureType.iterator(); |
||
211 | while (visibleAttrIter.hasNext()) {
|
||
212 | fad = visibleAttrIter.next(); |
||
213 | colName = fad.getName(); |
||
214 | columnNames.add(colName); |
||
215 | //If the column is added has to be visible
|
||
216 | if (!visibleColumnNames.contains(colName)) {
|
||
217 | |||
218 | 41093 | jldominguez | if (((newColumns.contains(colName)
|
219 | || renamedColumnsNewName.contains(colName))) |
||
220 | && |
||
221 | fad.getType() != DataTypes.GEOMETRY) { |
||
222 | 40435 | jjdelcerro | // Add new columns and renamed
|
223 | visibleColumnNames.add(colName); |
||
224 | visibleColumnNamesOriginal.add(colName); |
||
225 | } |
||
226 | /*
|
||
227 | if (renamedColumnsNewName.contains(colName)) {
|
||
228 | // Add renamed
|
||
229 | insertWhereOldName(visibleColumnNames, colName, fad);
|
||
230 | insertWhereOldName(visibleColumnNamesOriginal, colName, fad);
|
||
231 | }
|
||
232 | */
|
||
233 | } |
||
234 | } |
||
235 | |||
236 | // remove from visible columns removed columns
|
||
237 | visibleColumnNames = intersectKeepOrder(columnNames, visibleColumnNames); |
||
238 | // instead of: visibleColumnNames.retainAll(columnNames);
|
||
239 | |||
240 | visibleColumnNamesOriginal = intersectKeepOrder(columnNames, visibleColumnNamesOriginal); |
||
241 | // instead of: visibleColumnNamesOriginal.retainAll(columnNames);
|
||
242 | |||
243 | // remove from alias map removed columns
|
||
244 | name2Alias.keySet().retainAll(columnNames); |
||
245 | name2AliasOriginal.keySet().retainAll(columnNames); |
||
246 | |||
247 | super.setFeatureType(featureType);
|
||
248 | |||
249 | } |
||
250 | |||
251 | /**
|
||
252 | * keeps order of first parameter
|
||
253 | *
|
||
254 | * @param lista
|
||
255 | * @param listb
|
||
256 | * @return
|
||
257 | */
|
||
258 | private List<String> intersectKeepOrder(List<String> lista, List<String> listb) { |
||
259 | |||
260 | List<String> resp = new ArrayList<String>(); |
||
261 | resp.addAll(lista); |
||
262 | resp.retainAll(listb); |
||
263 | return resp;
|
||
264 | } |
||
265 | |||
266 | private void insertWhereOldNamee( |
||
267 | List<String> str_list, |
||
268 | String str,
|
||
269 | FeatureAttributeDescriptor fad) { |
||
270 | |||
271 | if (fad instanceof EditableFeatureAttributeDescriptor) { |
||
272 | EditableFeatureAttributeDescriptor efad = |
||
273 | (EditableFeatureAttributeDescriptor) fad; |
||
274 | if (efad.getOriginalName() != null) { |
||
275 | int old_ind = str_list.indexOf(efad.getOriginalName());
|
||
276 | if (old_ind != -1) { |
||
277 | // Insert before old name
|
||
278 | str_list.add(old_ind, str); |
||
279 | } else {
|
||
280 | // Insert anyway (add)
|
||
281 | str_list.add(str); |
||
282 | } |
||
283 | } else {
|
||
284 | // Insert anyway (add)
|
||
285 | str_list.add(str); |
||
286 | } |
||
287 | } else {
|
||
288 | // Insert anyway (add)
|
||
289 | str_list.add(str); |
||
290 | } |
||
291 | } |
||
292 | |||
293 | /**
|
||
294 | * Sets the current visible columns list, in the original order.
|
||
295 | *
|
||
296 | * @param names
|
||
297 | * the names of the columns to set as visible
|
||
298 | */
|
||
299 | public void setVisibleColumns(List<String> names) { |
||
300 | // Recreate the visible column names list
|
||
301 | 41212 | jjdelcerro | // to maintain the original order
|
302 | 40435 | jjdelcerro | visibleColumnNames = new ArrayList<String>(names.size()); |
303 | for (int i = 0; i < columnNames.size(); i++) { |
||
304 | String columnName = columnNames.get(i);
|
||
305 | if (names.contains(columnName)) {
|
||
306 | visibleColumnNames.add(columnName); |
||
307 | } |
||
308 | } |
||
309 | 41212 | jjdelcerro | updatePaginHelperWithHiddenColums(); |
310 | 40435 | jjdelcerro | fireTableStructureChanged(); |
311 | } |
||
312 | |||
313 | 41212 | jjdelcerro | protected String[] getHiddenColumnNames() { |
314 | List<String> hiddenColumns = new ArrayList<String>(); |
||
315 | hiddenColumns.addAll(columnNames); |
||
316 | |||
317 | for (int i = 0; i < visibleColumnNames.size(); i++) { |
||
318 | String columnName = visibleColumnNames.get(i);
|
||
319 | hiddenColumns.remove(columnName); |
||
320 | } |
||
321 | if( hiddenColumns.size()<1 ) { |
||
322 | return null; |
||
323 | } |
||
324 | return (String[]) hiddenColumns.toArray(new String[hiddenColumns.size()]); |
||
325 | } |
||
326 | |||
327 | 40435 | jjdelcerro | /**
|
328 | * Changes all columns to be visible.
|
||
329 | */
|
||
330 | public void setAllVisible() { |
||
331 | visibleColumnNames.clear(); |
||
332 | visibleColumnNames.addAll(columnNames); |
||
333 | fireTableStructureChanged(); |
||
334 | } |
||
335 | |||
336 | /**
|
||
337 | * Sets the alias for a column.
|
||
338 | *
|
||
339 | * @param name
|
||
340 | * the name of the column
|
||
341 | * @param alias
|
||
342 | * the alias for the column
|
||
343 | */
|
||
344 | public void setAlias(String name, String alias) { |
||
345 | name2Alias.put(name, alias); |
||
346 | fireTableStructureChanged(); |
||
347 | } |
||
348 | |||
349 | public void orderByColumn(String name, boolean ascending) |
||
350 | throws BaseException {
|
||
351 | FeatureQueryOrder order = getHelper().getFeatureQuery().getOrder(); |
||
352 | if (order == null) { |
||
353 | order = new FeatureQueryOrder();
|
||
354 | getHelper().getFeatureQuery().setOrder(order); |
||
355 | } |
||
356 | order.clear(); |
||
357 | order.add(name, ascending); |
||
358 | getHelper().reload(); |
||
359 | fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1)); |
||
360 | } |
||
361 | |||
362 | @Override
|
||
363 | protected void initialize() { |
||
364 | super.initialize();
|
||
365 | |||
366 | initializeVisibleColumns(); |
||
367 | initializeAliases(); |
||
368 | 41212 | jjdelcerro | updatePaginHelperWithHiddenColums(); |
369 | 40435 | jjdelcerro | } |
370 | |||
371 | /**
|
||
372 | * Returns if a column is visible.
|
||
373 | *
|
||
374 | * @param name
|
||
375 | * the name of the column
|
||
376 | * @return if the column is visible
|
||
377 | */
|
||
378 | public boolean isVisible(String name) { |
||
379 | return visibleColumnNames.contains(name);
|
||
380 | } |
||
381 | |||
382 | /**
|
||
383 | * Initializes the table name aliases.
|
||
384 | */
|
||
385 | private void initializeAliases() { |
||
386 | int columns = super.getColumnCount(); |
||
387 | name2Alias = new HashMap<String, String>(columns); |
||
388 | name2AliasOriginal = new HashMap<String, String>(columns); |
||
389 | } |
||
390 | |||
391 | /**
|
||
392 | * Initializes the table visible columns.
|
||
393 | */
|
||
394 | protected void initializeVisibleColumns() { |
||
395 | int columns = super.getColumnCount(); |
||
396 | columnNames = new ArrayList<String>(columns); |
||
397 | visibleColumnNames = new ArrayList<String>(columns); |
||
398 | |||
399 | for (int i = 0; i < columns; i++) { |
||
400 | String columnName = super.getColumnName(i); |
||
401 | columnNames.add(columnName); |
||
402 | |||
403 | // By default, geometry columns will not be visible
|
||
404 | FeatureAttributeDescriptor descriptor = |
||
405 | super.getDescriptorForColumn(i);
|
||
406 | if (descriptor.getType() != DataTypes.GEOMETRY) {
|
||
407 | visibleColumnNames.add(columnName); |
||
408 | } |
||
409 | } |
||
410 | |||
411 | visibleColumnNamesOriginal = new ArrayList<String>(visibleColumnNames); |
||
412 | } |
||
413 | |||
414 | /**
|
||
415 | * Returns the alias for the name of a column.
|
||
416 | *
|
||
417 | * @param name
|
||
418 | * of the column
|
||
419 | * @return the alias
|
||
420 | */
|
||
421 | protected String getAliasForColumn(String name) { |
||
422 | String alias = name2Alias.get(name);
|
||
423 | return alias == null ? name : alias; |
||
424 | } |
||
425 | |||
426 | /**
|
||
427 | * Returns the original position of a column.
|
||
428 | *
|
||
429 | * @param columnIndex
|
||
430 | * the current visible column index
|
||
431 | * @return the original column index
|
||
432 | */
|
||
433 | 41707 | jjdelcerro | public int getOriginalColumnIndex(int columnIndex) { |
434 | 40435 | jjdelcerro | String columnName = visibleColumnNames.get(columnIndex);
|
435 | return columnNames.indexOf(columnName);
|
||
436 | } |
||
437 | |||
438 | @Override
|
||
439 | protected Object getFeatureValue(Feature feature, int columnIndex) { |
||
440 | int realColumnIndex = getOriginalColumnIndex(columnIndex);
|
||
441 | return super.getFeatureValue(feature, realColumnIndex); |
||
442 | } |
||
443 | |||
444 | @Override
|
||
445 | protected EditableFeature setFeatureValue(Feature feature, int columnIndex, |
||
446 | Object value) {
|
||
447 | int realColumnIndex = getOriginalColumnIndex(columnIndex);
|
||
448 | return super.setFeatureValue(feature, realColumnIndex, value); |
||
449 | } |
||
450 | |||
451 | /**
|
||
452 | * Make current changes in configuration (visible columns and aliases)
|
||
453 | * as definitive.
|
||
454 | */
|
||
455 | public void acceptChanges() { |
||
456 | visibleColumnNamesOriginal = new ArrayList<String>(visibleColumnNames); |
||
457 | name2AliasOriginal = new HashMap<String, String>(name2Alias); |
||
458 | } |
||
459 | |||
460 | /**
|
||
461 | * Cancel current changes in configuration (visible columns and aliases)
|
||
462 | * and return to previous status.
|
||
463 | */
|
||
464 | public void cancelChanges() { |
||
465 | visibleColumnNames = new ArrayList<String>(visibleColumnNamesOriginal); |
||
466 | name2Alias = new HashMap<String, String>(name2AliasOriginal); |
||
467 | fireTableStructureChanged(); |
||
468 | } |
||
469 | 41699 | jjdelcerro | |
470 | protected void initializeFormattingPatterns() { |
||
471 | this.patterns = new HashMap<String, String>(); |
||
472 | |||
473 | int columns = super.getColumnCount(); |
||
474 | |||
475 | for (int i = 0; i < columns; i++) { |
||
476 | String columnName = super.getColumnName(i); |
||
477 | 41707 | jjdelcerro | initializeFormattingPattern(columnName); |
478 | 41699 | jjdelcerro | } |
479 | } |
||
480 | |||
481 | 41707 | jjdelcerro | protected void initializeFormattingPattern(String columnName) { |
482 | FeatureAttributeDescriptor descriptor = |
||
483 | this.getFeatureType().getAttributeDescriptor(columnName);
|
||
484 | |||
485 | switch(descriptor.getDataType().getType()) {
|
||
486 | case DataTypes.BYTE:
|
||
487 | case DataTypes.INT:
|
||
488 | case DataTypes.LONG:
|
||
489 | String defaultIntegerPattern = "#,##0"; |
||
490 | this.patterns.put(columnName,defaultIntegerPattern);
|
||
491 | break;
|
||
492 | case DataTypes.DOUBLE:
|
||
493 | case DataTypes.FLOAT:
|
||
494 | String defaultDecimalPattern = "#,##0.000"; |
||
495 | this.patterns.put(columnName,defaultDecimalPattern);
|
||
496 | break;
|
||
497 | case DataTypes.DATE:
|
||
498 | String defaultDatePattern = new SimpleDateFormat().toPattern(); |
||
499 | this.patterns.put(columnName,defaultDatePattern);
|
||
500 | break;
|
||
501 | default:
|
||
502 | this.patterns.put(columnName,null); |
||
503 | } |
||
504 | } |
||
505 | |||
506 | 41699 | jjdelcerro | public String getFormattingPattern(int column) { |
507 | String columnName = this.visibleColumnNames.get(column); |
||
508 | return this.getFormattingPattern(columnName); |
||
509 | } |
||
510 | |||
511 | public String getFormattingPattern(String columnName) { |
||
512 | if( this.patterns==null ) { |
||
513 | initializeFormattingPatterns(); |
||
514 | } |
||
515 | 41707 | jjdelcerro | String pattern = this.patterns.get(columnName); |
516 | if( StringUtils.isBlank(pattern) ) {
|
||
517 | initializeFormattingPattern(columnName); |
||
518 | } |
||
519 | return pattern;
|
||
520 | 41699 | jjdelcerro | } |
521 | |||
522 | public void setFormattingPattern(String columnName, String pattern) { |
||
523 | if( this.patterns==null ) { |
||
524 | initializeFormattingPatterns(); |
||
525 | } |
||
526 | this.patterns.put(columnName,pattern);
|
||
527 | } |
||
528 | |||
529 | public Locale getLocaleOfData() { |
||
530 | return this.localeOfData; |
||
531 | } |
||
532 | |||
533 | public void setLocaleOfData(Locale locale) { |
||
534 | this.localeOfData = locale;
|
||
535 | } |
||
536 | |||
537 | |||
538 | 40435 | jjdelcerro | } |