Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.swing / org.gvsig.fmap.dal.swing.impl / src / main / java / org / gvsig / fmap / dal / swing / impl / featuretable / table / DefaultFeatureTableModel.java @ 45308

History | View | Annotate | Download (32.3 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
package org.gvsig.fmap.dal.swing.impl.featuretable.table;
26

    
27
import java.awt.event.ActionEvent;
28
import java.awt.event.ActionListener;
29
import java.security.InvalidParameterException;
30
import java.text.SimpleDateFormat;
31
import java.util.ArrayList;
32
import java.util.HashMap;
33
import java.util.HashSet;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Locale;
37
import java.util.Map;
38
import java.util.Set;
39

    
40
import javax.swing.SwingUtilities;
41
import javax.swing.Timer;
42
import javax.swing.event.ChangeEvent;
43
import javax.swing.event.ChangeListener;
44
import javax.swing.event.TableModelEvent;
45
import javax.swing.table.AbstractTableModel;
46

    
47
import org.slf4j.Logger;
48
import org.slf4j.LoggerFactory;
49

    
50
import org.gvsig.fmap.dal.DataTypes;
51
import org.gvsig.fmap.dal.exception.DataException;
52
import org.gvsig.fmap.dal.feature.EditableFeature;
53
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.Feature;
55
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
56
import org.gvsig.fmap.dal.feature.FeatureQuery;
57
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
58
import org.gvsig.fmap.dal.feature.FeatureSelection;
59
import org.gvsig.fmap.dal.feature.FeatureStore;
60
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
61
import org.gvsig.fmap.dal.feature.FeatureType;
62
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
63
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
64
import org.gvsig.fmap.dal.swing.impl.featuretable.table.renders.GetFeatureAtException;
65
import org.gvsig.tools.exception.BaseException;
66
import org.gvsig.tools.observer.ComplexNotification;
67
import org.gvsig.tools.observer.ComplexObserver;
68
import org.gvsig.tools.observer.Observable;
69

    
70
public class DefaultFeatureTableModel extends AbstractTableModel implements org.gvsig.fmap.dal.swing.FeatureTableModel,  ComplexObserver  {
71

    
72
    private static final long serialVersionUID = -8223987814719746492L;
73

    
74
    private static final Logger logger = LoggerFactory.getLogger(DefaultFeatureTableModel.class);
75

    
76
    private List<String> columnNames;
77

    
78
    private List<String> visibleColumnNames;
79

    
80
    private List<String> visibleColumnNamesOriginal;
81

    
82
    private Map<String, String> name2Alias;
83

    
84
    private Map<String, String> name2AliasOriginal;
85

    
86
    private Map<String,String> patterns = null;
87

    
88
    private Locale localeOfData;
89

    
90
    private final FeaturePagingHelper featurePager;
91

    
92
    /** Used to know if a modification in the FeatureStore is created by us. */
93
    private EditableFeature editableFeature;
94

    
95
    private boolean selectionLocked=false;
96

    
97
    private final DelayAction delayAction = new DelayAction();
98

    
99
    private FeatureSelection selection = null;
100

    
101
    private Set<ActionListener> changeListeners = null;
102
    
103
    public DefaultFeatureTableModel(FeaturePagingHelper featurePager) {
104
        this.featurePager = featurePager;
105
        this.localeOfData = Locale.getDefault();
106
        this.initialize();
107
    }
108

    
109
    private void initialize() {
110
        this.getFeatureStore().addObserver(this);
111

    
112
        int columns = this.getOriginalColumnCount();
113

    
114
        // Initilize visible columns
115
        columnNames = new ArrayList<>(columns);
116
        visibleColumnNames = new ArrayList<>(columns);
117
        for (int i = 0; i < columns; i++) {
118
            FeatureAttributeDescriptor descriptor = this.getInternalColumnDescriptor(i);
119
            String columnName = descriptor.getName();
120
            columnNames.add(columnName);
121

    
122
            // By default, geometry columns will not be visible
123
            if (descriptor.getType() != DataTypes.GEOMETRY) {
124
                visibleColumnNames.add(columnName);
125
            }
126
        }
127
        visibleColumnNamesOriginal = new ArrayList<>(visibleColumnNames);
128

    
129
        // Initialize alias
130
        name2Alias = new HashMap<>(columns);
131
        name2AliasOriginal = new HashMap<>(columns);
132

    
133
        initializeFormatingPatterns();
134
        updatePagerWithHiddenColums();
135
    }
136

    
137
    private void initializeFormatingPatterns() {
138
        int columns = this.getOriginalColumnCount();
139

    
140
        this.patterns = new HashMap<>();
141
        for (int i = 0; i < columns; i++) {
142
            FeatureAttributeDescriptor descriptor = this.getInternalColumnDescriptor(i);
143
            String columnName = descriptor.getName();
144
            switch(descriptor.getDataType().getType()) {
145
            case DataTypes.BYTE:
146
            case DataTypes.INT:
147
            case DataTypes.LONG:
148
                String defaultIntegerPattern = "#,##0";
149
                this.patterns.put(columnName,defaultIntegerPattern);
150
                break;
151
            case DataTypes.DOUBLE:
152
                String defaultDoublePattern = "#,##0.0000000000";
153
                this.patterns.put(columnName,defaultDoublePattern);
154
                break;
155
            case DataTypes.FLOAT:
156
                String defaultFloatPattern = "#,##0.0000";
157
                this.patterns.put(columnName,defaultFloatPattern);
158
                break;
159
            case DataTypes.DATE:
160
                String defaultDatePattern = new SimpleDateFormat().toPattern();
161
                this.patterns.put(columnName,defaultDatePattern);
162
                break;
163
            default:
164
                this.patterns.put(columnName,null);
165
            }
166
        }
167

    
168
    }
169

    
170
    private void updatePagerWithHiddenColums() {
171
            return;
172
            
173
//        FeatureQuery query = this.getFeaturePager().getFeatureQuery();
174
//        if (this.getFeaturePager().getFeatureStore().isEditing()) {
175
//            if (query.hasConstantsAttributeNames()) {
176
//                query.clearConstantsAttributeNames();
177
//            }
178
//        } else {
179
//            query.setConstantsAttributeNames(this.getHiddenColumnNames());
180
//        }
181
//        try {
182
//            this.getFeaturePager().reload();
183
//        } catch (BaseException ex) {
184
//            logger.warn("Can't reload paging-helper.", ex);
185
//        }
186
    }
187

    
188
    @Override
189
    public FeaturePagingHelper getFeaturePager() {
190
        return this.featurePager;
191
    }
192

    
193
    @Override
194
    public FeatureQuery getFeatureQuery() {
195
        return this.getFeaturePager().getFeatureQuery();
196
    }
197

    
198
    @Override
199
    public FeatureType getFeatureType() {
200
        return this.getFeaturePager().getFeatureType();
201
    }
202

    
203
    @Override
204
    public FeatureStore getFeatureStore() {
205
        return this.getFeaturePager().getFeatureStore();
206
    }
207

    
208
    @Override
209
    public int getColumnCount() {
210
        return visibleColumnNames.size();
211
    }
212

    
213
    public int getOriginalColumnCount() {
214
        FeatureType featureType = getFeatureType();
215
        return featureType.size();
216
    }
217

    
218
    @Override
219
    public String getColumnName(int column) {
220
        String columName = getOriginalColumnName(column);
221
        return this.getColumnAlias(columName);
222
    }
223

    
224
    @Override
225
    public Class<?> getColumnClass(int columnIndex) {
226
        int originalIndex = getOriginalColumnIndex(columnIndex);
227

    
228
        // Return the class of the FeatureAttributeDescriptor for the value
229
        FeatureAttributeDescriptor attributeDesc = this.getInternalColumnDescriptor(originalIndex);
230
        if (attributeDesc == null) {
231
                return super.getColumnClass(originalIndex);
232
        }
233
        Class<?> clazz = attributeDesc.getObjectClass();
234
        return (clazz == null ? super.getColumnClass(originalIndex) : clazz);
235
    }
236

    
237
    @Override
238
    public FeatureAttributeDescriptor getColumnDescriptor(int columnIndex) {
239
        int originalIndex = getOriginalColumnIndex(columnIndex);
240
        return this.getInternalColumnDescriptor(originalIndex);
241
    }
242

    
243
    protected FeatureAttributeDescriptor getInternalColumnDescriptor(int columnIndex) {
244
        FeatureType featureType = getFeatureType();
245
        if( featureType == null ) {
246
            return null;
247
        }
248
        return featureType.getAttributeDescriptor(columnIndex);
249
    }
250

    
251
    @Override
252
    public String getOriginalColumnName(int column) {
253
        return getInternalColumnDescriptor(column).getName();
254
    }
255

    
256
    @Override
257
    public void setColumnVisible(String name, boolean visible) {
258
        if (!columnNames.contains(name)) {
259
            throw new InvalidParameterException(name); // FIXME
260
        }
261
        if( visible ) {
262
            if ( !visibleColumnNames.contains(name) ) {
263
                visibleColumnNames.add(name);
264
                setVisibleColumns(visibleColumnNames);
265
            }
266
        } else {
267
            if ( visibleColumnNames.contains(name) ) {
268
                visibleColumnNames.remove(name);
269
                setVisibleColumns(visibleColumnNames);
270
                fireTableStructureChanged();
271
            }
272
        }
273
    }
274

    
275
    public void setFeatureType(FeatureType featureType) {
276
        // Check if there is a new column name
277
        List<String> newColumns = new ArrayList<>();
278
        List<String> renamedColumnsNewName = new ArrayList<>();
279

    
280
        Iterator<FeatureAttributeDescriptor> attrIter = featureType.iterator();
281
        FeatureAttributeDescriptor fad ;
282
        EditableFeatureAttributeDescriptor efad ;
283

    
284
        String colName;
285
        while (attrIter.hasNext()) {
286
            fad = attrIter.next();
287
            colName = fad.getName();
288
            if (!columnNames.contains(colName)) {
289
                if (fad instanceof EditableFeatureAttributeDescriptor) {
290
                    efad = (EditableFeatureAttributeDescriptor) fad;
291
                    /*
292
                     * If editable att descriptor,
293
                     * check original name
294
                     */
295
                    if (efad.getOriginalName() != null) {
296
                        if (!columnNames.contains(efad.getOriginalName())) {
297
                            /*
298
                             * Check with original name but add current name
299
                             */
300
                            newColumns.add(colName);
301
                        } else {
302
                            /*
303
                             * List of new names of renamed columns
304
                             */
305
                            renamedColumnsNewName.add(colName);
306
                        }
307
                    } else {
308
                        newColumns.add(colName);
309
                    }
310
                } else {
311
                    newColumns.add(colName);
312
                }
313
            }
314
        }
315

    
316
        // Update column names
317
        columnNames.clear();
318
        @SuppressWarnings("unchecked")
319
        Iterator<FeatureAttributeDescriptor> visibleAttrIter =
320
            featureType.iterator();
321
        while (visibleAttrIter.hasNext()) {
322
            fad = visibleAttrIter.next();
323
            colName = fad.getName();
324
            columnNames.add(colName);
325
            //If the column is added has to be visible
326
            if (!visibleColumnNames.contains(colName)) {
327

    
328
                if (((newColumns.contains(colName)
329
                    || renamedColumnsNewName.contains(colName)))
330
                    &&
331
                    fad.getType() != DataTypes.GEOMETRY) {
332
                    // Add new columns and renamed
333
                    visibleColumnNames.add(colName);
334
                    visibleColumnNamesOriginal.add(colName);
335
                }
336
                /*
337
                if (renamedColumnsNewName.contains(colName)) {
338
                    // Add renamed
339
                    insertWhereOldName(visibleColumnNames, colName, fad);
340
                    insertWhereOldName(visibleColumnNamesOriginal, colName, fad);
341
                }
342
                */
343
            }
344
        }
345

    
346
        // remove from visible columns removed columns
347
        visibleColumnNames = intersectKeepOrder(columnNames, visibleColumnNames);
348
        // instead of: visibleColumnNames.retainAll(columnNames);
349

    
350
        visibleColumnNamesOriginal = intersectKeepOrder(columnNames, visibleColumnNamesOriginal);
351
        // instead of: visibleColumnNamesOriginal.retainAll(columnNames);
352

    
353
        // remove from alias map removed columns
354
        name2Alias.keySet().retainAll(columnNames);
355
        name2AliasOriginal.keySet().retainAll(columnNames);
356

    
357
        initializeFormatingPatterns();
358

    
359
        getFeatureQuery().setFeatureType(featureType);
360
        reloadFeatures();
361
        //Selection must be locked to avoid losing it when the table is refreshed
362
        selectionLocked=true;
363
        //The table is refreshed
364
        try {
365
            fireTableStructureChanged();
366
        } catch (Exception e) {
367
            logger.warn("Couldn't reload changed table");
368
        }finally{
369
            //The locked selection is unlocked.
370
            selectionLocked=false;
371
        }
372

    
373
    }
374

    
375
    private void reloadFeatures() {
376
        try {
377
            this.getFeaturePager().reload();
378
        } catch (BaseException ex) {
379
            throw new FeaturesDataReloadException(ex);
380
        }
381
    }
382

    
383
    /**
384
     * keeps order of first parameter
385
     *
386
     * @param lista
387
     * @param listb
388
     * @return
389
     */
390
    private List<String> intersectKeepOrder(List<String> lista, List<String> listb) {
391

    
392
        List<String> resp = new ArrayList<>();
393
        resp.addAll(lista);
394
        resp.retainAll(listb);
395
        return resp;
396
    }
397

    
398
    public void setVisibleColumns(List<String> names) {
399
        // Recreate the visible column names list
400
        // to maintain the original order
401
        visibleColumnNames = new ArrayList<>(names.size());
402
        for (int i = 0; i < columnNames.size(); i++) {
403
            String columnName = columnNames.get(i);
404
            if (names.contains(columnName)) {
405
                visibleColumnNames.add(columnName);
406
            }
407
        }
408
        updatePagerWithHiddenColums();
409
        fireTableStructureChanged();
410
    }
411

    
412
    protected String[] getHiddenColumnNames() {
413
        List<String> hiddenColumns = new ArrayList<String>();
414
        hiddenColumns.addAll(columnNames);
415

    
416
        for (int i = 0; i < visibleColumnNames.size(); i++) {
417
            String columnName = visibleColumnNames.get(i);
418
            hiddenColumns.remove(columnName);
419
        }
420
        if( hiddenColumns.size()<1 ) {
421
            return null;
422
        }
423
        return (String[]) hiddenColumns.toArray(new String[hiddenColumns.size()]);
424
    }
425

    
426
    /**
427
     * Changes all columns to be visible.
428
     */
429
    public void setAllVisible() {
430
        visibleColumnNames.clear();
431
        visibleColumnNames.addAll(columnNames);
432
        fireTableStructureChanged();
433
    }
434

    
435
    @Override
436
    public void setColumnOrder(String name, boolean ascending)
437
        throws BaseException {
438
        FeatureQueryOrder order = this.getFeatureQuery().getOrder();
439
        order.clear();
440
        order.add(name, ascending);
441
        this.getFeaturePager().reload();
442
        fireTableChanged(new TableModelEvent(this, 0, this.getRowCount() - 1));
443
    }
444

    
445
    @Override
446
    public int getRowCount() {
447
        // Return the total size of the collection
448
        // If the size is bigger than INTEGER.MAX_VALUE, return that instead
449
        try {
450
            long totalSize = this.getFeaturePager().getTotalSize();
451
            if (totalSize > Integer.MAX_VALUE) {
452
                return Integer.MAX_VALUE;
453
            } else {
454
                return (int) totalSize;
455
            }
456
        } catch (ConcurrentDataModificationException e) {
457
            logger.debug("Error while getting the total size of the set", e);
458
            return 0;
459
        }
460
    }
461

    
462
    @Override
463
    public boolean isColumnVisible(String name) {
464
        return visibleColumnNames.contains(name);
465
    }
466

    
467
    @Override
468
    public String getColumnAlias(String name) {
469
        String alias = name2Alias.get(name);
470
        return alias == null ? name : alias;
471
    }
472

    
473
    @Override
474
    public void setColumnAlias(String name, String alias) {
475
        name2Alias.put(name, alias);
476
        fireTableStructureChanged();
477
    }
478

    
479
    @Override
480
    public int getOriginalColumnIndex(int columnIndex) {
481
        String columnName = visibleColumnNames.get(columnIndex);
482
        return columnNames.indexOf(columnName);
483
    }
484

    
485
    @Override
486
    public Object getValueAt(int rowIndex, int columnIndex) {
487
        // Get the Feature at row "rowIndex", and return the value of the
488
        // attribute at "columnIndex"
489
        Feature feature = getFeatureAt(rowIndex);
490
        return feature == null ? null : getFeatureValue(feature, columnIndex);
491
    }
492

    
493
    @Override
494
    public Feature getFeatureAt(int rowIndex) {
495
        try {
496
            return this.getFeaturePager().getFeatureAt(rowIndex);
497
        } catch (BaseException ex) {
498
            throw new GetFeatureAtException(rowIndex, ex);
499
        }
500
    }
501

    
502
    protected Object getFeatureValue(Feature feature, int columnIndex) {
503
        int realColumnIndex = getOriginalColumnIndex(columnIndex);
504
        return feature.get(realColumnIndex);
505
    }
506

    
507
    protected EditableFeature setFeatureValue(Feature feature, int columnIndex,
508
        Object value) {
509
        int realColumnIndex = getOriginalColumnIndex(columnIndex);
510
        EditableFeature editableFeature = feature.getEditable();
511
        editableFeature.set(realColumnIndex, value);
512
        return editableFeature;
513
    }
514

    
515

    
516
    public void acceptChanges() {
517
            visibleColumnNamesOriginal = new ArrayList<>(visibleColumnNames);
518
            name2AliasOriginal = new HashMap<>(name2Alias);
519
    }
520

    
521
    public void cancelChanges() {
522
            visibleColumnNames = new ArrayList<>(visibleColumnNamesOriginal);
523
            name2Alias = new HashMap<>(name2AliasOriginal);
524
            fireTableStructureChanged();
525
    }
526

    
527

    
528
    @Override
529
    public String getColumnFormattingPattern(int column) {
530
        String columnName = this.visibleColumnNames.get(column);
531
        return this.getColumnFormattingPattern(columnName);
532
    }
533

    
534
    @Override
535
    public String getColumnFormattingPattern(String columnName) {
536
        String pattern = this.patterns.get(columnName);
537
        return pattern;
538
    }
539

    
540
    @Override
541
    public void setColumnFormattingPattern(String columnName, String pattern) {
542
        this.patterns.put(columnName,pattern);
543
    }
544

    
545
    @Override
546
    public Locale getLocaleOfData() {
547
        return this.localeOfData;
548
    }
549

    
550
    @Override
551
    public void setLocaleOfData(Locale locale) {
552
        this.localeOfData = locale;
553
    }
554

    
555
    public boolean isSelectionLocked() {
556
        if( !this.getFeatureType().supportReferences() ) {
557
            return true;
558
        }
559
        return selectionLocked;
560
    }
561

    
562
    @Override
563
    public boolean isSelectionUp() {
564
        return this.getFeaturePager().isSelectionUp();
565
    }
566

    
567
    @Override
568
    public void setSelectionUp(boolean selectionUp) {
569
        this.getFeaturePager().setSelectionUp(selectionUp);
570
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1));
571
    }
572

    
573
    private class DelayAction extends Timer implements ActionListener, Runnable {
574
        private static final int STATE_NONE = 0;
575
        private static final int STATE_NEED_RELOADALL = 1;
576
        private static final int STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED = 2;
577
        private static final int STATE_NEED_RELOAD_IF_FEATURE_UPDATED = 4;
578
        private static final int STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED = 8;
579
        private static final int STATE_NEED_RELOAD_FEATURE_TYPE = 16;
580
        private static final int STATE_NEED_SELECTION_UP = 32;
581
        private static final int STATE_NEED_RELOAD_ALL_FEATURES=64;
582

    
583
        private static final long serialVersionUID = -5692569125344166705L;
584

    
585
        private int state = STATE_NONE;
586
        private Feature feature;
587
        private FeatureType featureType;
588
        private boolean isSelecctionUp;
589

    
590
        public DelayAction() {
591
            super(1000,null);
592
            this.setRepeats(false);
593
            this.reset();
594
            this.addActionListener(this);
595
        }
596

    
597
        private void reset() {
598
            this.state = STATE_NONE;
599
            this.isSelecctionUp = false;
600
            this.feature = null;
601
            this.featureType = null;
602
        }
603

    
604
        public void actionPerformed(ActionEvent ae) {
605
            this.run();
606
        }
607

    
608
        public void run() {
609
            if( !SwingUtilities.isEventDispatchThread() ) {
610
                SwingUtilities.invokeLater(this);
611
                return;
612
            }
613
            this.stop();
614
            logger.info("DelayAction.run["+this.state+"] begin");
615
            switch(this.state) {
616
            case STATE_NEED_RELOADALL:
617
                reloadAll();
618
                break;
619
            case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
620
                reloadIfFeatureCountChanged(feature);
621
                break;
622
            case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
623
                reloadIfFeatureUpdated(feature);
624
                break;
625
            case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
626
                reloadIfTypeChanged(featureType);
627
                break;
628
            case STATE_NEED_RELOAD_FEATURE_TYPE:
629
                reloadFeatureType();
630
                updatePagerWithHiddenColums();
631
                break;
632
            case STATE_NEED_RELOAD_ALL_FEATURES:
633
                reloadFeatures();
634
                fireTableChanged(new TableModelEvent(DefaultFeatureTableModel.this, 0, getRowCount()));
635
                break;
636
            case STATE_NEED_SELECTION_UP:
637
            case STATE_NONE:
638
            default:
639
                break;
640
            }
641
            if( isSelecctionUp ) {
642
                getFeaturePager().setSelectionUp(true);
643
            }
644
            this.reset();
645
            logger.info("DelayAction.run["+this.state+"] end");
646
        }
647

    
648
        public void nextState(int nextstate) {
649
            this.nextState(nextstate, null, null);
650
        }
651

    
652
        public void nextState(int nextstate, Feature feature) {
653
            this.nextState(nextstate, feature, null);
654
        }
655

    
656
        public void nextState(int nextstate, FeatureType featureType) {
657
            this.nextState(nextstate, null, featureType);
658
        }
659

    
660
        public void nextState(int nextstate, Feature feature, FeatureType featureType) {
661
            this.feature = feature;
662
            this.featureType = featureType;
663
            switch(nextstate) {
664
            case STATE_NEED_RELOADALL:
665
            case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
666
            case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
667
                switch(this.state) {
668
                case STATE_NEED_RELOADALL:
669
                case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
670
                //case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
671
                    this.state = STATE_NEED_RELOADALL;
672
                    break;
673
                case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
674
                case STATE_NEED_RELOAD_FEATURE_TYPE:
675
                    this.state = STATE_NEED_RELOAD_FEATURE_TYPE;
676
                    break;
677
                case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
678
                case STATE_NEED_RELOAD_ALL_FEATURES:
679
                    this.state=STATE_NEED_RELOAD_ALL_FEATURES;
680
                    break;
681
                case STATE_NEED_SELECTION_UP:
682
                    this.state = nextstate;
683
                    this.isSelecctionUp = true;
684
                    break;
685
                case STATE_NONE:
686
                default:
687
                    this.state = nextstate;
688
                    break;
689
                }
690
                break;
691
            case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
692
            case STATE_NEED_RELOAD_FEATURE_TYPE:
693
                switch(this.state) {
694
                case STATE_NEED_RELOADALL:
695
                case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
696
                case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
697
                case STATE_NEED_RELOAD_ALL_FEATURES:
698
                case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
699
                case STATE_NEED_RELOAD_FEATURE_TYPE:
700
                    this.state = STATE_NEED_RELOAD_FEATURE_TYPE;
701
                    break;
702
                case STATE_NEED_SELECTION_UP:
703
                    this.state = nextstate;
704
                    this.isSelecctionUp = true;
705
                    break;
706
                case STATE_NONE:
707
                default:
708
                    this.state = nextstate;
709
                    break;
710
                }
711
                break;
712
            case STATE_NEED_SELECTION_UP:
713
                switch(this.state) {
714
                case STATE_NEED_RELOADALL:
715
                case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
716
                case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
717
                case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
718
                case STATE_NEED_RELOAD_ALL_FEATURES:
719
                case STATE_NEED_RELOAD_FEATURE_TYPE:
720
                case STATE_NEED_SELECTION_UP:
721
                    this.isSelecctionUp = true;
722
                    break;
723
                case STATE_NONE:
724
                default:
725
                    this.state = nextstate;
726
                    this.isSelecctionUp = true;
727
                    break;
728
                }
729
                break;
730
            case STATE_NONE:
731
            default:
732
                this.state = STATE_NONE;
733
                break;
734
            }
735
            if( this.state != STATE_NONE ) {
736
                this.start();
737
            }
738
        }
739

    
740
    }
741

    
742
    /**
743
     * Reloads the table data if a feature has been changed, not through the
744
     * table.
745
     */
746
    private void reloadIfFeatureCountChanged(Feature feature) {
747
        // Is any data is changed in the FeatureStore, notify the model
748
        // listeners. Ignore the case where the updated feature is
749
        // changed through us.
750
        if (editableFeature == null || !editableFeature.equals(feature)) {
751
            reloadFeatures();
752
            //Selection must be locked to avoid losing it when the table is refreshed
753
            selectionLocked=true;
754
            //The table is refreshed
755
            try {
756
                fireTableDataChanged();
757
            } catch (Exception e) {
758
                logger.warn("Couldn't reload changed table");
759
            }finally{
760
                //The locked selection is unlocked.
761
                selectionLocked=false;
762
            }
763
        }
764
    }
765

    
766
    private void reloadIfFeatureUpdated(Feature feature) {
767
        // Is any data is changed in the FeatureStore, notify the model
768
        // listeners. Ignore the case where the updated feature is
769
        // changed through us.
770
        if (editableFeature == null || !editableFeature.equals(feature)) {
771
            reloadFeatures();
772
            fireTableChanged(new TableModelEvent(this, 0, getRowCount()));
773
        }
774
    }
775

    
776
    /**
777
     * Reloads data and structure if the {@link FeatureType} of the features
778
     * being shown has changed.
779
     */
780
    private void reloadIfTypeChanged(FeatureType updatedType) {
781
        // If the updated featured type is the one currently being
782
        // shown, reload the table.
783
        if (updatedType != null
784
            && updatedType.getId().equals(getFeatureType().getId())) {
785
            setFeatureType(updatedType);
786
        }
787
    }
788

    
789
    private void reloadAll() {
790
            reloadFeatureType();
791
    }
792

    
793
    private void reloadFeatureType() {
794
        try {
795
            FeatureType featureType = this.getFeaturePager().getFeatureType();
796
            FeatureStore store = this.getFeaturePager().getFeatureStore();
797
            this.setFeatureType( store.getFeatureType(featureType.getId()) );
798
        } catch (DataException e) {
799
            throw new FeaturesDataReloadException(e);
800
        }
801
    }
802

    
803
    @Override
804
    public void update(final Observable observable, final Object notification) {
805
        if (notification instanceof ComplexNotification) {
806
            // A lot of things might have happened in the store, so don't
807
            // bother looking into each notification.
808
            this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
809
//            reloadAll();
810
        } else if (observable.equals(getFeatureStore())
811
                && notification instanceof FeatureStoreNotification) {
812
            FeatureStoreNotification fsNotification
813
                    = (FeatureStoreNotification) notification;
814
            String type = fsNotification.getType();
815

    
816
            // If there are new, updated or deleted features
817
            // reload the table data
818
            if (FeatureStoreNotification.AFTER_DELETE.equals(type)
819
                    || FeatureStoreNotification.AFTER_INSERT.equals(type)) {
820
//                reloadIfFeatureCountChanged(fsNotification.getFeature());
821
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED, fsNotification.getFeature());
822

    
823
            } else if (FeatureStoreNotification.AFTER_UPDATE.equals(type)) {
824
//                reloadIfFeatureUpdated(fsNotification.getFeature());
825
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_UPDATED, fsNotification.getFeature());
826

    
827
            } else if (FeatureStoreNotification.AFTER_UPDATE_TYPE.equals(type)) {
828
//                reloadIfTypeChanged(fsNotification.getFeatureType());
829
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED, fsNotification.getFeatureType());
830

    
831
            } else if (FeatureStoreNotification.TRANSFORM_CHANGE.equals(type)
832
                    || FeatureStoreNotification.AFTER_UNDO.equals(type)
833
                    || FeatureStoreNotification.AFTER_REDO.equals(type)
834
                    || FeatureStoreNotification.AFTER_REFRESH.equals(type))  {
835
//                reloadAll();
836
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
837

    
838
            } else if (FeatureStoreNotification.AFTER_FINISHEDITING.equals(type)
839
                    || FeatureStoreNotification.AFTER_STARTEDITING.equals(type)
840
                    || FeatureStoreNotification.AFTER_CANCELEDITING.equals(type)) {
841
                /*
842
                No tengo nada claro por que es necesario llamar al reloadFeatureType
843
                pero si no se incluye hay problemas si durante la edicion se a?aden
844
                campos a la tabla. Sin esto, al cerrar la edicion, los campos a?adidos
845
                desaparecen de la tabla aunque estan en el fichero.
846
                Ver ticket #2434 https://devel.gvsig.org/redmine/issues/2434
847
                */
848
//                reloadFeatureType();
849
//                updatePaginHelperWithHiddenColums();
850
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_FEATURE_TYPE, fsNotification.getFeatureType());
851
            } else if (FeatureStoreNotification.SELECTION_CHANGE.equals(type)) {
852
                if( this.isSelectionUp() ) {
853
                    this.setSelectionUp(true);
854
                    this.delayAction.nextState(DelayAction.STATE_NEED_SELECTION_UP);
855
                }
856
            }
857
        }
858
    }
859
    
860
    @Override
861
    public FeatureSelection getFeatureSelection() {
862
        if (selection == null) {
863
            try {
864
                return getFeatureStore().getFeatureSelection();
865
            } catch (Exception e) {
866
                logger.warn("Error getting the selection", e);
867
            }
868
        }
869
        return selection;
870
    }
871
    
872
    @Override
873
    public void setFeatureSelection(FeatureSelection selection) {
874
        this.selection = selection;
875
        this.featurePager.setSelection(selection);
876
        this.fireChangeListeners(new ActionEvent(this, 0,CHANGE_SELECTION));
877
    }
878
    
879
    public void addChangeListener(ActionListener listener) {
880
        if( this.changeListeners==null) {
881
            this.changeListeners = new HashSet<>();
882
        }
883
        this.changeListeners.add(listener);
884
    }
885
    
886
    public void fireChangeListeners(ActionEvent event) {
887
        if( this.changeListeners == null ) {
888
            return;
889
        }
890
        for( ActionListener listener : this.changeListeners ) {
891
            try {
892
                listener.actionPerformed(event);
893
            } catch(Exception ex) {
894
                // Ignore
895
            }
896
        }
897
    }
898
    
899
    @Override
900
    public int getSelectionCount() {
901
        try {
902
            FeatureSelection selection = this.getFeatureSelection();
903
            return (int) selection.getSize();
904
        } catch (DataException ex) {
905
            throw new RuntimeException("Can't get selection of the FeatureTableModel",ex);
906
        }
907
    }
908

    
909

    
910
}