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

History | View | Annotate | Download (30.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
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.Iterator;
34
import java.util.List;
35
import java.util.Locale;
36
import java.util.Map;
37

    
38
import javax.swing.SwingUtilities;
39
import javax.swing.Timer;
40
import javax.swing.event.TableModelEvent;
41
import javax.swing.table.AbstractTableModel;
42

    
43
import org.slf4j.Logger;
44
import org.slf4j.LoggerFactory;
45

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

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

    
68
    private static final long serialVersionUID = -8223987814719746492L;
69

    
70
    private static final Logger logger = LoggerFactory.getLogger(DefaultFeatureTableModel.class);
71

    
72
    private List<String> columnNames;
73

    
74
    private List<String> visibleColumnNames;
75

    
76
    private List<String> visibleColumnNamesOriginal;
77

    
78
    private Map<String, String> name2Alias;
79

    
80
    private Map<String, String> name2AliasOriginal;
81

    
82
    private Map<String,String> patterns = null;
83

    
84
    private Locale localeOfData;
85

    
86
    private final FeaturePagingHelper featurePager;
87

    
88
    /** Used to know if a modification in the FeatureStore is created by us. */
89
    private EditableFeature editableFeature;
90

    
91
    private boolean selectionLocked=false;
92

    
93
    private final DelayAction delayAction = new DelayAction();
94

    
95

    
96
    public DefaultFeatureTableModel(FeaturePagingHelper featurePager) {
97
        this.featurePager = featurePager;
98
        this.localeOfData = Locale.getDefault();
99
        this.initialize();
100
    }
101

    
102
    private void initialize() {
103
        this.getFeatureStore().addObserver(this);
104

    
105
        int columns = this.getOriginalColumnCount();
106

    
107
        // Initilize visible columns
108
        columnNames = new ArrayList<>(columns);
109
        visibleColumnNames = new ArrayList<>(columns);
110
        for (int i = 0; i < columns; i++) {
111
            FeatureAttributeDescriptor descriptor = this.getInternalColumnDescriptor(i);
112
            String columnName = descriptor.getName();
113
            columnNames.add(columnName);
114

    
115
            // By default, geometry columns will not be visible
116
            if (descriptor.getType() != DataTypes.GEOMETRY) {
117
                visibleColumnNames.add(columnName);
118
            }
119
        }
120
        visibleColumnNamesOriginal = new ArrayList<>(visibleColumnNames);
121

    
122
        // Initialize alias
123
        name2Alias = new HashMap<>(columns);
124
        name2AliasOriginal = new HashMap<>(columns);
125

    
126
        initializeFormatingPatterns();
127
        updatePagerWithHiddenColums();
128
    }
129

    
130
    private void initializeFormatingPatterns() {
131
        int columns = this.getOriginalColumnCount();
132

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

    
161
    }
162

    
163
    private void updatePagerWithHiddenColums() {
164
        FeatureQuery query = this.getFeaturePager().getFeatureQuery();
165
        if (this.getFeaturePager().getFeatureStore().isEditing()) {
166
            if (query.hasConstantsAttributeNames()) {
167
                query.clearConstantsAttributeNames();
168
            }
169
        } else {
170
            query.setConstantsAttributeNames(this.getHiddenColumnNames());
171
        }
172
        try {
173
            this.getFeaturePager().reload();
174
        } catch (BaseException ex) {
175
            logger.warn("Can't reload paging-helper.", ex);
176
        }
177
    }
178

    
179
    @Override
180
    public FeaturePagingHelper getFeaturePager() {
181
        return this.featurePager;
182
    }
183

    
184
    @Override
185
    public FeatureQuery getFeatureQuery() {
186
        return this.getFeaturePager().getFeatureQuery();
187
    }
188

    
189
    @Override
190
    public FeatureType getFeatureType() {
191
        return this.getFeaturePager().getFeatureType();
192
    }
193

    
194
    @Override
195
    public FeatureStore getFeatureStore() {
196
        return this.getFeaturePager().getFeatureStore();
197
    }
198

    
199
    @Override
200
    public int getColumnCount() {
201
        return visibleColumnNames.size();
202
    }
203

    
204
    public int getOriginalColumnCount() {
205
        FeatureType featureType = getFeatureType();
206
        return featureType.size();
207
    }
208

    
209
    @Override
210
    public String getColumnName(int column) {
211
        String columName = getOriginalColumnName(column);
212
        return this.getColumnAlias(columName);
213
    }
214

    
215
    @Override
216
    public Class<?> getColumnClass(int columnIndex) {
217
        int originalIndex = getOriginalColumnIndex(columnIndex);
218

    
219
        // Return the class of the FeatureAttributeDescriptor for the value
220
        FeatureAttributeDescriptor attributeDesc = this.getInternalColumnDescriptor(originalIndex);
221
        if (attributeDesc == null) {
222
                return super.getColumnClass(originalIndex);
223
        }
224
        Class<?> clazz = attributeDesc.getObjectClass();
225
        return (clazz == null ? super.getColumnClass(originalIndex) : clazz);
226
    }
227

    
228
    @Override
229
    public FeatureAttributeDescriptor getColumnDescriptor(int columnIndex) {
230
        int originalIndex = getOriginalColumnIndex(columnIndex);
231
        return this.getInternalColumnDescriptor(originalIndex);
232
    }
233

    
234
    protected FeatureAttributeDescriptor getInternalColumnDescriptor(int columnIndex) {
235
        FeatureType featureType = getFeatureType();
236
        if( featureType == null ) {
237
            return null;
238
        }
239
        return featureType.getAttributeDescriptor(columnIndex);
240
    }
241

    
242
    @Override
243
    public String getOriginalColumnName(int column) {
244
        return getInternalColumnDescriptor(column).getName();
245
    }
246

    
247
    @Override
248
    public void setColumnVisible(String name, boolean visible) {
249
        if (!columnNames.contains(name)) {
250
            throw new InvalidParameterException(name); // FIXME
251
        }
252
        if( visible ) {
253
            if ( !visibleColumnNames.contains(name) ) {
254
                visibleColumnNames.add(name);
255
                setVisibleColumns(visibleColumnNames);
256
            }
257
        } else {
258
            if ( visibleColumnNames.contains(name) ) {
259
                visibleColumnNames.remove(name);
260
                setVisibleColumns(visibleColumnNames);
261
                fireTableStructureChanged();
262
            }
263
        }
264
    }
265

    
266
    public void setFeatureType(FeatureType featureType) {
267
        // Check if there is a new column name
268
        List<String> newColumns = new ArrayList<>();
269
        List<String> renamedColumnsNewName = new ArrayList<>();
270

    
271
        Iterator<FeatureAttributeDescriptor> attrIter = featureType.iterator();
272
        FeatureAttributeDescriptor fad ;
273
        EditableFeatureAttributeDescriptor efad ;
274

    
275
        String colName;
276
        while (attrIter.hasNext()) {
277
            fad = attrIter.next();
278
            colName = fad.getName();
279
            if (!columnNames.contains(colName)) {
280
                if (fad instanceof EditableFeatureAttributeDescriptor) {
281
                    efad = (EditableFeatureAttributeDescriptor) fad;
282
                    /*
283
                     * If editable att descriptor,
284
                     * check original name
285
                     */
286
                    if (efad.getOriginalName() != null) {
287
                        if (!columnNames.contains(efad.getOriginalName())) {
288
                            /*
289
                             * Check with original name but add current name
290
                             */
291
                            newColumns.add(colName);
292
                        } else {
293
                            /*
294
                             * List of new names of renamed columns
295
                             */
296
                            renamedColumnsNewName.add(colName);
297
                        }
298
                    } else {
299
                        newColumns.add(colName);
300
                    }
301
                } else {
302
                    newColumns.add(colName);
303
                }
304
            }
305
        }
306

    
307
        // Update column names
308
        columnNames.clear();
309
        @SuppressWarnings("unchecked")
310
        Iterator<FeatureAttributeDescriptor> visibleAttrIter =
311
            featureType.iterator();
312
        while (visibleAttrIter.hasNext()) {
313
            fad = visibleAttrIter.next();
314
            colName = fad.getName();
315
            columnNames.add(colName);
316
            //If the column is added has to be visible
317
            if (!visibleColumnNames.contains(colName)) {
318

    
319
                if (((newColumns.contains(colName)
320
                    || renamedColumnsNewName.contains(colName)))
321
                    &&
322
                    fad.getType() != DataTypes.GEOMETRY) {
323
                    // Add new columns and renamed
324
                    visibleColumnNames.add(colName);
325
                    visibleColumnNamesOriginal.add(colName);
326
                }
327
                /*
328
                if (renamedColumnsNewName.contains(colName)) {
329
                    // Add renamed
330
                    insertWhereOldName(visibleColumnNames, colName, fad);
331
                    insertWhereOldName(visibleColumnNamesOriginal, colName, fad);
332
                }
333
                */
334
            }
335
        }
336

    
337
        // remove from visible columns removed columns
338
        visibleColumnNames = intersectKeepOrder(columnNames, visibleColumnNames);
339
        // instead of: visibleColumnNames.retainAll(columnNames);
340

    
341
        visibleColumnNamesOriginal = intersectKeepOrder(columnNames, visibleColumnNamesOriginal);
342
        // instead of: visibleColumnNamesOriginal.retainAll(columnNames);
343

    
344
        // remove from alias map removed columns
345
        name2Alias.keySet().retainAll(columnNames);
346
        name2AliasOriginal.keySet().retainAll(columnNames);
347

    
348
        initializeFormatingPatterns();
349

    
350
        getFeatureQuery().setFeatureType(featureType);
351
        reloadFeatures();
352
        //Selection must be locked to avoid losing it when the table is refreshed
353
        selectionLocked=true;
354
        //The table is refreshed
355
        try {
356
            fireTableStructureChanged();
357
        } catch (Exception e) {
358
            logger.warn("Couldn't reload changed table");
359
        }finally{
360
            //The locked selection is unlocked.
361
            selectionLocked=false;
362
        }
363

    
364
    }
365

    
366
    private void reloadFeatures() {
367
        try {
368
            this.getFeaturePager().reload();
369
        } catch (BaseException ex) {
370
            throw new FeaturesDataReloadException(ex);
371
        }
372
    }
373

    
374
    /**
375
     * keeps order of first parameter
376
     *
377
     * @param lista
378
     * @param listb
379
     * @return
380
     */
381
    private List<String> intersectKeepOrder(List<String> lista, List<String> listb) {
382

    
383
        List<String> resp = new ArrayList<>();
384
        resp.addAll(lista);
385
        resp.retainAll(listb);
386
        return resp;
387
    }
388

    
389
    public void setVisibleColumns(List<String> names) {
390
        // Recreate the visible column names list
391
        // to maintain the original order
392
        visibleColumnNames = new ArrayList<>(names.size());
393
        for (int i = 0; i < columnNames.size(); i++) {
394
            String columnName = columnNames.get(i);
395
            if (names.contains(columnName)) {
396
                visibleColumnNames.add(columnName);
397
            }
398
        }
399
        updatePagerWithHiddenColums();
400
        fireTableStructureChanged();
401
    }
402

    
403
    protected String[] getHiddenColumnNames() {
404
        List<String> hiddenColumns = new ArrayList<String>();
405
        hiddenColumns.addAll(columnNames);
406

    
407
        for (int i = 0; i < visibleColumnNames.size(); i++) {
408
            String columnName = visibleColumnNames.get(i);
409
            hiddenColumns.remove(columnName);
410
        }
411
        if( hiddenColumns.size()<1 ) {
412
            return null;
413
        }
414
        return (String[]) hiddenColumns.toArray(new String[hiddenColumns.size()]);
415
    }
416

    
417
    /**
418
     * Changes all columns to be visible.
419
     */
420
    public void setAllVisible() {
421
        visibleColumnNames.clear();
422
        visibleColumnNames.addAll(columnNames);
423
        fireTableStructureChanged();
424
    }
425

    
426
    @Override
427
    public void setColumnOrder(String name, boolean ascending)
428
        throws BaseException {
429
        FeatureQueryOrder order = this.getFeatureQuery().getOrder();
430
        if (order == null) {
431
            order = new FeatureQueryOrder();
432
            this.getFeatureQuery().setOrder(order);
433
        }
434
        order.clear();
435
        order.add(name, ascending);
436
        this.getFeaturePager().reload();
437
        fireTableChanged(new TableModelEvent(this, 0, this.getRowCount() - 1));
438
    }
439

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

    
457
    @Override
458
    public boolean isColumnVisible(String name) {
459
        return visibleColumnNames.contains(name);
460
    }
461

    
462
    @Override
463
    public String getColumnAlias(String name) {
464
        String alias = name2Alias.get(name);
465
        return alias == null ? name : alias;
466
    }
467

    
468
    @Override
469
    public void setColumnAlias(String name, String alias) {
470
        name2Alias.put(name, alias);
471
        fireTableStructureChanged();
472
    }
473

    
474
    @Override
475
    public int getOriginalColumnIndex(int columnIndex) {
476
        String columnName = visibleColumnNames.get(columnIndex);
477
        return columnNames.indexOf(columnName);
478
    }
479

    
480
    @Override
481
    public Object getValueAt(int rowIndex, int columnIndex) {
482
        // Get the Feature at row "rowIndex", and return the value of the
483
        // attribute at "columnIndex"
484
        Feature feature = getFeatureAt(rowIndex);
485
        return feature == null ? null : getFeatureValue(feature, columnIndex);
486
    }
487

    
488
    @Override
489
    public Feature getFeatureAt(int rowIndex) {
490
        try {
491
            return this.getFeaturePager().getFeatureAt(rowIndex);
492
        } catch (BaseException ex) {
493
            throw new GetFeatureAtException(rowIndex, ex);
494
        }
495
    }
496

    
497
    protected Object getFeatureValue(Feature feature, int columnIndex) {
498
        int realColumnIndex = getOriginalColumnIndex(columnIndex);
499
        return feature.get(realColumnIndex);
500
    }
501

    
502
    protected EditableFeature setFeatureValue(Feature feature, int columnIndex,
503
        Object value) {
504
        int realColumnIndex = getOriginalColumnIndex(columnIndex);
505
        EditableFeature editableFeature = feature.getEditable();
506
        editableFeature.set(realColumnIndex, value);
507
        return editableFeature;
508
    }
509

    
510

    
511
    public void acceptChanges() {
512
            visibleColumnNamesOriginal = new ArrayList<>(visibleColumnNames);
513
            name2AliasOriginal = new HashMap<>(name2Alias);
514
    }
515

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

    
522

    
523
    @Override
524
    public String getColumnFormattingPattern(int column) {
525
        String columnName = this.visibleColumnNames.get(column);
526
        return this.getColumnFormattingPattern(columnName);
527
    }
528

    
529
    @Override
530
    public String getColumnFormattingPattern(String columnName) {
531
        String pattern = this.patterns.get(columnName);
532
        return pattern;
533
    }
534

    
535
    @Override
536
    public void setColumnFormattingPattern(String columnName, String pattern) {
537
        this.patterns.put(columnName,pattern);
538
    }
539

    
540
    @Override
541
    public Locale getLocaleOfData() {
542
        return this.localeOfData;
543
    }
544

    
545
    @Override
546
    public void setLocaleOfData(Locale locale) {
547
        this.localeOfData = locale;
548
    }
549

    
550
    public boolean isSelectionLocked() {
551
        return selectionLocked;
552
    }
553

    
554
    @Override
555
    public boolean isSelectionUp() {
556
        return this.getFeaturePager().isSelectionUp();
557
    }
558

    
559
    @Override
560
    public void setSelectionUp(boolean selectionUp) {
561
        this.getFeaturePager().setSelectionUp(selectionUp);
562
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1));
563
    }
564

    
565
    private class DelayAction extends Timer implements ActionListener, Runnable {
566
        private static final int STATE_NONE = 0;
567
        private static final int STATE_NEED_RELOADALL = 1;
568
        private static final int STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED = 2;
569
        private static final int STATE_NEED_RELOAD_IF_FEATURE_UPDATED = 4;
570
        private static final int STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED = 8;
571
        private static final int STATE_NEED_RELOAD_FEATURE_TYPE = 16;
572
        private static final int STATE_NEED_SELECTION_UP = 32;
573
        private static final int STATE_NEED_RELOAD_ALL_FEATURES=64;
574

    
575
        private static final long serialVersionUID = -5692569125344166705L;
576

    
577
        private int state = STATE_NONE;
578
        private Feature feature;
579
        private FeatureType featureType;
580
        private boolean isSelecctionUp;
581

    
582
        public DelayAction() {
583
            super(1000,null);
584
            this.setRepeats(false);
585
            this.reset();
586
            this.addActionListener(this);
587
        }
588

    
589
        private void reset() {
590
            this.state = STATE_NONE;
591
            this.isSelecctionUp = false;
592
            this.feature = null;
593
            this.featureType = null;
594
        }
595

    
596
        public void actionPerformed(ActionEvent ae) {
597
            this.run();
598
        }
599

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

    
640
        public void nextState(int nextstate) {
641
            this.nextState(nextstate, null, null);
642
        }
643

    
644
        public void nextState(int nextstate, Feature feature) {
645
            this.nextState(nextstate, feature, null);
646
        }
647

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

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

    
732
    }
733

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

    
758
    private void reloadIfFeatureUpdated(Feature feature) {
759
        // Is any data is changed in the FeatureStore, notify the model
760
        // listeners. Ignore the case where the updated feature is
761
        // changed through us.
762
        if (editableFeature == null || !editableFeature.equals(feature)) {
763
            reloadFeatures();
764
            fireTableChanged(new TableModelEvent(this, 0, getRowCount()));
765
        }
766
    }
767

    
768
    /**
769
     * Reloads data and structure if the {@link FeatureType} of the features
770
     * being shown has changed.
771
     */
772
    private void reloadIfTypeChanged(FeatureType updatedType) {
773
        // If the updated featured type is the one currently being
774
        // shown, reload the table.
775
        if (updatedType != null
776
            && updatedType.getId().equals(getFeatureType().getId())) {
777
            setFeatureType(updatedType);
778
        }
779
    }
780

    
781
    private void reloadAll() {
782
            reloadFeatureType();
783
    }
784

    
785
    private void reloadFeatureType() {
786
        try {
787
            FeatureType featureType = this.getFeaturePager().getFeatureType();
788
            FeatureStore store = this.getFeaturePager().getFeatureStore();
789
            this.setFeatureType( store.getFeatureType(featureType.getId()) );
790
        } catch (DataException e) {
791
            throw new FeaturesDataReloadException(e);
792
        }
793
    }
794

    
795
    @Override
796
    public void update(final Observable observable, final Object notification) {
797
        if (notification instanceof ComplexNotification) {
798
            // A lot of things might have happened in the store, so don't
799
            // bother looking into each notification.
800
            this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
801
//            reloadAll();
802
        } else if (observable.equals(getFeatureStore())
803
                && notification instanceof FeatureStoreNotification) {
804
            FeatureStoreNotification fsNotification
805
                    = (FeatureStoreNotification) notification;
806
            String type = fsNotification.getType();
807

    
808
            // If there are new, updated or deleted features
809
            // reload the table data
810
            if (FeatureStoreNotification.AFTER_DELETE.equals(type)
811
                    || FeatureStoreNotification.AFTER_INSERT.equals(type)) {
812
//                reloadIfFeatureCountChanged(fsNotification.getFeature());
813
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED, fsNotification.getFeature());
814

    
815
            } else if (FeatureStoreNotification.AFTER_UPDATE.equals(type)) {
816
//                reloadIfFeatureUpdated(fsNotification.getFeature());
817
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_UPDATED, fsNotification.getFeature());
818

    
819
            } else if (FeatureStoreNotification.AFTER_UPDATE_TYPE.equals(type)) {
820
//                reloadIfTypeChanged(fsNotification.getFeatureType());
821
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED, fsNotification.getFeatureType());
822

    
823
            } else if (FeatureStoreNotification.TRANSFORM_CHANGE.equals(type)
824
                    || FeatureStoreNotification.AFTER_UNDO.equals(type)
825
                    || FeatureStoreNotification.AFTER_REDO.equals(type)
826
                    || FeatureStoreNotification.AFTER_REFRESH.equals(type))  {
827
//                reloadAll();
828
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
829

    
830
            } else if (FeatureStoreNotification.AFTER_FINISHEDITING.equals(type)
831
                    || FeatureStoreNotification.AFTER_STARTEDITING.equals(type)
832
                    || FeatureStoreNotification.AFTER_CANCELEDITING.equals(type)) {
833
                /*
834
                No tengo nada claro por que es necesario llamar al reloadFeatureType
835
                pero si no se incluye hay problemas si durante la edicion se a?aden
836
                campos a la tabla. Sin esto, al cerrar la edicion, los campos a?adidos
837
                desaparecen de la tabla aunque estan en el fichero.
838
                Ver ticket #2434 https://devel.gvsig.org/redmine/issues/2434
839
                */
840
//                reloadFeatureType();
841
//                updatePaginHelperWithHiddenColums();
842
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_FEATURE_TYPE, fsNotification.getFeatureType());
843
            } else if (FeatureStoreNotification.SELECTION_CHANGE.equals(type)) {
844
                if( this.isSelectionUp() ) {
845
                    this.setSelectionUp(true);
846
                    this.delayAction.nextState(DelayAction.STATE_NEED_SELECTION_UP);
847
                }
848
            }
849
        }
850
    }
851

    
852
    @Override
853
    public int getSelectionCount() {
854
        try {
855
            FeatureSelection selection = this.getFeatureStore().getFeatureSelection();
856
            return (int) selection.getSize();
857
        } catch (DataException ex) {
858
            throw new RuntimeException("Can't get selection of the FeatureTableModel",ex);
859
        }
860
    }
861

    
862

    
863
}