Statistics
| Revision:

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 @ 43981

History | View | Annotate | Download (17.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
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
 * as published by the Free Software Foundation; either version 3
9
 * 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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
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
import java.text.SimpleDateFormat;
32
import java.util.ArrayList;
33
import java.util.HashMap;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Locale;
37
import java.util.Map;
38

    
39
import javax.swing.event.TableModelEvent;
40
import org.apache.commons.lang3.StringUtils;
41

    
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
import org.slf4j.Logger;
53
import org.slf4j.LoggerFactory;
54

    
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
    
67
    private static final Logger logger = LoggerFactory.getLogger(ConfigurableFeatureTableModel.class);
68

    
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
    private Map<String,String> patterns = null;
80

    
81
    private Locale localeOfData;    
82
    /**
83
     * @see FeatureTableModel#FeatureTableModel(FeatureStore, FeatureQuery)
84
     */
85
    public ConfigurableFeatureTableModel(FeatureStore featureStore,
86
        FeatureQuery featureQuery) throws BaseException {
87
        super(featureStore, featureQuery);
88
        this.localeOfData = Locale.getDefault();
89
    }
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
        try {
111
        int originalIndex = getOriginalColumnIndex(column);
112
        return getAliasForColumn(getOriginalColumnName(originalIndex));
113
        } catch (Exception ex) {
114
            return "C" + column;
115
        }
116
    }
117

    
118
    @Override
119
    public Class<?> getColumnClass(int columnIndex) {
120
        int originalIndex = getOriginalColumnIndex(columnIndex);
121
        return super.getColumnClass(originalIndex);
122
    }
123

    
124
    @Override
125
    public FeatureAttributeDescriptor getDescriptorForColumn(int columnIndex) {
126
        int originalIndex = getOriginalColumnIndex(columnIndex);
127
        return super.getDescriptorForColumn(originalIndex);
128
    }
129

    
130
    /**
131
     * Returns the original name of the column, ignoring the alias.
132
     * 
133
     * @param column
134
     *            the original index of the column
135
     * @return the original column name
136
     */
137
    public String getOriginalColumnName(int column) {
138
        return super.getColumnName(column);
139
    }
140

    
141
    /**
142
     * Sets the visibility of a table column.
143
     * 
144
     * @param columnIndex
145
     *            the index of the column to update
146
     * @param visible
147
     *            if the column will be visible or not
148
     */
149
    public void setVisible(String name, boolean visible) {
150
        // If we don't have already the column as visible,
151
        // add to the list, without order, and recreate
152
        // the visible columns list in the original order
153
        if (!columnNames.contains(name)) {
154
            throw new InvalidParameterException(name); // FIXME
155
        }
156
        if (visible && !visibleColumnNames.contains(name)) {
157
            visibleColumnNames.add(name);
158
            setVisibleColumns(visibleColumnNames);
159
        } else {
160
            visibleColumnNames.remove(name);
161
            setVisibleColumns(visibleColumnNames);
162
            fireTableStructureChanged();
163
        }
164

    
165
    }
166

    
167
    @Override
168
    public void setFeatureType(FeatureType featureType) {
169
        // Check if there is a new column name
170
        List<String> newColumns = new ArrayList<String>();
171
        List<String> renamedColumnsNewName = new ArrayList<String>();
172
        
173
        @SuppressWarnings("unchecked")
174
        Iterator<FeatureAttributeDescriptor> attrIter = featureType.iterator();
175
        FeatureAttributeDescriptor fad = null;
176
        EditableFeatureAttributeDescriptor efad = null;
177
        
178
        String colName;
179
        while (attrIter.hasNext()) {
180
            fad = attrIter.next();
181
            colName = fad.getName();
182
            if (!columnNames.contains(colName)) {
183
                if (fad instanceof EditableFeatureAttributeDescriptor) {
184
                    efad = (EditableFeatureAttributeDescriptor) fad; 
185
                    /*
186
                     * If editable att descriptor,
187
                     * check original name
188
                     */
189
                    if (efad.getOriginalName() != null) {
190
                        if (!columnNames.contains(efad.getOriginalName())) {
191
                            /*
192
                             * Check with original name but add current name
193
                             */
194
                            newColumns.add(colName);
195
                        } else {
196
                            /*
197
                             * List of new names of renamed columns
198
                             */
199
                            renamedColumnsNewName.add(colName);
200
                        }
201
                    } else {
202
                        newColumns.add(colName);
203
                    }
204
                } else {
205
                    newColumns.add(colName);
206
                }
207
            }
208
        }
209

    
210
        // Update column names
211
        columnNames.clear();
212
        @SuppressWarnings("unchecked")
213
        Iterator<FeatureAttributeDescriptor> visibleAttrIter =
214
            featureType.iterator();
215
        while (visibleAttrIter.hasNext()) {
216
            fad = visibleAttrIter.next();
217
            colName = fad.getName();
218
            columnNames.add(colName);
219
            //If the column is added has to be visible
220
            if (!visibleColumnNames.contains(colName)) {
221

    
222
                if (((newColumns.contains(colName)
223
                    || renamedColumnsNewName.contains(colName)))
224
                    &&
225
                    fad.getType() != DataTypes.GEOMETRY) {
226
                    // Add new columns and renamed
227
                    visibleColumnNames.add(colName);
228
                    visibleColumnNamesOriginal.add(colName);
229
                }
230
                /*
231
                if (renamedColumnsNewName.contains(colName)) {
232
                    // Add renamed
233
                    insertWhereOldName(visibleColumnNames, colName, fad);
234
                    insertWhereOldName(visibleColumnNamesOriginal, colName, fad);
235
                }
236
                */
237
            }
238
        }
239

    
240
        // remove from visible columns removed columns
241
        visibleColumnNames = intersectKeepOrder(columnNames, visibleColumnNames);
242
        // instead of: visibleColumnNames.retainAll(columnNames);
243

    
244
        visibleColumnNamesOriginal = intersectKeepOrder(columnNames, visibleColumnNamesOriginal);
245
        // instead of: visibleColumnNamesOriginal.retainAll(columnNames);
246

    
247
        // remove from alias map removed columns
248
        name2Alias.keySet().retainAll(columnNames);
249
        name2AliasOriginal.keySet().retainAll(columnNames);
250

    
251
        super.setFeatureType(featureType);
252

    
253
    }
254

    
255
    /**
256
     * keeps order of first parameter
257
     * 
258
     * @param lista
259
     * @param listb
260
     * @return
261
     */
262
    private List<String> intersectKeepOrder(List<String> lista, List<String> listb) {
263
        
264
        List<String> resp = new ArrayList<String>();
265
        resp.addAll(lista);
266
        resp.retainAll(listb);
267
        return resp;
268
    }
269

    
270
    private void insertWhereOldNamee(
271
        List<String> str_list,
272
        String str,
273
        FeatureAttributeDescriptor fad) {
274
        
275
        if (fad instanceof EditableFeatureAttributeDescriptor) {
276
            EditableFeatureAttributeDescriptor efad =
277
                (EditableFeatureAttributeDescriptor) fad;
278
            if (efad.getOriginalName() != null) {
279
                int old_ind = str_list.indexOf(efad.getOriginalName());
280
                if (old_ind != -1) {
281
                    // Insert before old name
282
                    str_list.add(old_ind, str);
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
        } else {
292
            // Insert anyway (add)
293
            str_list.add(str);
294
        }
295
    }
296

    
297
    /**
298
     * Sets the current visible columns list, in the original order.
299
     * 
300
     * @param names
301
     *            the names of the columns to set as visible
302
     */
303
    public void setVisibleColumns(List<String> names) {
304
        // Recreate the visible column names list
305
        // to maintain the original order        
306
        visibleColumnNames = new ArrayList<String>(names.size());
307
        for (int i = 0; i < columnNames.size(); i++) {
308
            String columnName = columnNames.get(i);
309
            if (names.contains(columnName)) {
310
                visibleColumnNames.add(columnName);
311
            }
312
        }
313
        updatePaginHelperWithHiddenColums();
314
        fireTableStructureChanged();
315
    }
316

    
317
    protected String[] getHiddenColumnNames() {
318
        List<String> hiddenColumns = new ArrayList<String>();
319
        hiddenColumns.addAll(columnNames);
320
        
321
        for (int i = 0; i < visibleColumnNames.size(); i++) {
322
            String columnName = visibleColumnNames.get(i);
323
            hiddenColumns.remove(columnName);
324
        }
325
        if( hiddenColumns.size()<1 ) {
326
            return null;
327
        }
328
        return (String[]) hiddenColumns.toArray(new String[hiddenColumns.size()]);
329
    }
330
        
331
    /**
332
     * Changes all columns to be visible.
333
     */
334
    public void setAllVisible() {
335
        visibleColumnNames.clear();
336
        visibleColumnNames.addAll(columnNames);
337
        fireTableStructureChanged();
338
    }
339

    
340
    /**
341
     * Sets the alias for a column.
342
     * 
343
     * @param name
344
     *            the name of the column
345
     * @param alias
346
     *            the alias for the column
347
     */
348
    public void setAlias(String name, String alias) {
349
        name2Alias.put(name, alias);
350
        fireTableStructureChanged();
351
    }
352

    
353
    public void orderByColumn(String name, boolean ascending)
354
        throws BaseException {
355
        FeatureQueryOrder order = getHelper().getFeatureQuery().getOrder();
356
        if (order == null) {
357
            order = new FeatureQueryOrder();
358
            getHelper().getFeatureQuery().setOrder(order);
359
        }
360
        order.clear();
361
        order.add(name, ascending);
362
        getHelper().reload();
363
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1));
364
    }
365

    
366
    @Override
367
    protected void initialize() {
368
        super.initialize();
369

    
370
        initializeVisibleColumns();
371
        initializeAliases();
372
        updatePaginHelperWithHiddenColums();
373
    }
374

    
375
    /**
376
     * Returns if a column is visible.
377
     * 
378
     * @param name
379
     *            the name of the column
380
     * @return if the column is visible
381
     */
382
    public boolean isVisible(String name) {
383
        return visibleColumnNames.contains(name);
384
    }
385

    
386
    /**
387
     * Initializes the table name aliases.
388
     */
389
    private void initializeAliases() {
390
        int columns = super.getColumnCount();
391
        name2Alias = new HashMap<String, String>(columns);
392
        name2AliasOriginal = new HashMap<String, String>(columns);
393
    }
394

    
395
    /**
396
     * Initializes the table visible columns.
397
     */
398
    protected void initializeVisibleColumns() {
399
        int columns = super.getColumnCount();
400
        columnNames = new ArrayList<String>(columns);
401
        visibleColumnNames = new ArrayList<String>(columns);
402

    
403
        for (int i = 0; i < columns; i++) {
404
            String columnName = super.getColumnName(i);
405
            columnNames.add(columnName);
406

    
407
            // By default, geometry columns will not be visible
408
            FeatureAttributeDescriptor descriptor =
409
                super.getDescriptorForColumn(i);
410
            if (descriptor.getType() != DataTypes.GEOMETRY) {
411
                visibleColumnNames.add(columnName);
412
            }
413
        }
414
        
415
        visibleColumnNamesOriginal = new ArrayList<String>(visibleColumnNames);
416
    }
417

    
418
    /**
419
     * Returns the alias for the name of a column.
420
     * 
421
     * @param name
422
     *            of the column
423
     * @return the alias
424
     */
425
    protected String getAliasForColumn(String name) {
426
        String alias = name2Alias.get(name);
427
        return alias == null ? name : alias;
428
    }
429

    
430
    /**
431
     * Returns the original position of a column.
432
     * 
433
     * @param columnIndex
434
     *            the current visible column index
435
     * @return the original column index
436
     */
437
    public int getOriginalColumnIndex(int columnIndex) {
438
        String columnName = visibleColumnNames.get(columnIndex);
439
        return columnNames.indexOf(columnName);
440
    }
441

    
442
    @Override
443
    protected Object getFeatureValue(Feature feature, int columnIndex) {
444
        int realColumnIndex = getOriginalColumnIndex(columnIndex);
445
        return super.getFeatureValue(feature, realColumnIndex);
446
    }
447

    
448
    @Override
449
    protected EditableFeature setFeatureValue(Feature feature, int columnIndex,
450
        Object value) {
451
        int realColumnIndex = getOriginalColumnIndex(columnIndex);
452
        return super.setFeatureValue(feature, realColumnIndex, value);
453
    }
454
    
455
    /**
456
     * Make current changes in configuration (visible columns and aliases)
457
     * as definitive.
458
     */
459
    public void acceptChanges() {
460
            visibleColumnNamesOriginal = new ArrayList<String>(visibleColumnNames);
461
            name2AliasOriginal = new HashMap<String, String>(name2Alias);
462
    }
463
    
464
    /**
465
     * Cancel current changes in configuration (visible columns and aliases)
466
     * and return to previous status.
467
     */
468
    public void cancelChanges() {
469
            visibleColumnNames = new ArrayList<String>(visibleColumnNamesOriginal);
470
            name2Alias = new HashMap<String, String>(name2AliasOriginal);
471
            fireTableStructureChanged();
472
    }
473

    
474
    protected void initializeFormattingPatterns() {
475
        this.patterns = new HashMap<String, String>();
476

    
477
        int columns = super.getColumnCount();
478

    
479
        for (int i = 0; i < columns; i++) {
480
            String columnName = super.getColumnName(i);
481
            initializeFormattingPattern(columnName);
482
        }
483
    } 
484
    
485
    protected void initializeFormattingPattern(String columnName) {
486
        FeatureAttributeDescriptor descriptor = 
487
                this.getFeatureType().getAttributeDescriptor(columnName);
488

    
489
        switch(descriptor.getDataType().getType()) {
490
        case DataTypes.BYTE:
491
        case DataTypes.INT:
492
        case DataTypes.LONG:
493
            String defaultIntegerPattern = "#,##0";
494
            this.patterns.put(columnName,defaultIntegerPattern);
495
            break;
496
        case DataTypes.DOUBLE:
497
            String defaultDoublePattern = "#,##0.0000000000";
498
            this.patterns.put(columnName,defaultDoublePattern);
499
            break;
500
        case DataTypes.FLOAT:
501
            String defaultFloatPattern = "#,##0.0000";
502
            this.patterns.put(columnName,defaultFloatPattern);
503
            break;
504
        case DataTypes.DATE:
505
            String defaultDatePattern = new SimpleDateFormat().toPattern();
506
            this.patterns.put(columnName,defaultDatePattern);
507
            break;
508
        default:
509
            this.patterns.put(columnName,null);
510
        }
511
    }
512
    
513
    public String getFormattingPattern(int column) {
514
        String columnName = this.visibleColumnNames.get(column);
515
        return this.getFormattingPattern(columnName);
516
    }
517
    
518
    public String getFormattingPattern(String columnName) {
519
        if( this.patterns==null ) {
520
            initializeFormattingPatterns();
521
        }
522
        String pattern = this.patterns.get(columnName);
523
        if( StringUtils.isBlank(pattern) ) {
524
            initializeFormattingPattern(columnName);
525
        }
526
        return pattern;
527
    }
528
    
529
    public void setFormattingPattern(String columnName, String pattern) {
530
        if( this.patterns==null ) {
531
            initializeFormattingPatterns();
532
        }
533
        this.patterns.put(columnName,pattern);
534
    }
535
    
536
    public Locale getLocaleOfData() {
537
        return this.localeOfData;
538
    }
539
    
540
    public void setLocaleOfData(Locale locale) {
541
        this.localeOfData = locale;
542
    }
543
    
544

    
545
}