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 / FeatureTableModel.java @ 42456

History | View | Annotate | Download (25.2 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 FeatureCollection}
27
 */
28
package org.gvsig.fmap.mapcontrol.dal.feature.swing.table;
29

    
30
import java.awt.event.ActionEvent;
31
import java.awt.event.ActionListener;
32
import javax.swing.SwingUtilities;
33
import javax.swing.Timer;
34
import javax.swing.event.TableModelEvent;
35
import javax.swing.table.AbstractTableModel;
36
import org.gvsig.editing.EditingNotification;
37
import org.gvsig.editing.EditingNotificationManager;
38

    
39
import org.gvsig.fmap.dal.DALLocator;
40
import org.gvsig.fmap.dal.exception.DataException;
41
import org.gvsig.fmap.dal.feature.EditableFeature;
42
import org.gvsig.fmap.dal.feature.Feature;
43
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
44
import org.gvsig.fmap.dal.feature.FeatureQuery;
45
import org.gvsig.fmap.dal.feature.FeatureStore;
46
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
47
import org.gvsig.fmap.dal.feature.FeatureType;
48
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
49
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
50
import org.gvsig.fmap.mapcontrol.MapControlLocator;
51
import org.gvsig.tools.exception.BaseException;
52
import org.gvsig.tools.observer.ComplexNotification;
53
import org.gvsig.tools.observer.ComplexObserver;
54
import org.gvsig.tools.observer.Observable;
55
import org.slf4j.Logger;
56
import org.slf4j.LoggerFactory;
57

    
58
/**
59
 * TableModel to access data of Features.
60
 *
61
 * This table model can't handle a FeatureSet with more than Integer.MAX_VALUE
62
 * elements. In that case, only the first Integer.MAX_VALUE elements will be
63
 * shown.
64
 *
65
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
66
 */
67
public class FeatureTableModel extends AbstractTableModel implements ComplexObserver {
68

    
69

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

    
73
    private static final long serialVersionUID = -2488157521902851301L;
74

    
75
    private FeaturePagingHelper helper;
76

    
77
    /** Used to know if a modification in the FeatureStore is created by us. */
78
    private EditableFeature editableFeature;
79

    
80
    /**
81
     * Constructs a TableModel from the features of a FeatureStore, with the
82
     * default page size.
83
     *
84
     * @param featureStore
85
     *            to extract the features from
86
     * @param featureQuery
87
     *            the query to get the features from the store
88
     * @throws BaseException
89
     *             if there is an error reading data from the FeatureStore
90
     */
91
    public FeatureTableModel(FeatureStore featureStore,
92
        FeatureQuery featureQuery) throws BaseException {
93
        this(featureStore, featureQuery, FeaturePagingHelper.DEFAULT_PAGE_SIZE);
94
    }
95

    
96
    /**
97
     * Constructs a TableModel from the features of a FeatureStore, with the
98
     * default page size.
99
     *
100
     * @param featureStore
101
     *            to extract the features from
102
     * @param featureQuery
103
     *            the query to get the features from the store
104
     * @param pageSize
105
     *            the number of elements per page data
106
     * @throws BaseException
107
     *             if there is an error reading data from the FeatureStore
108
     */
109
    public FeatureTableModel(FeatureStore featureStore,
110
        FeatureQuery featureQuery, int pageSize) throws BaseException {
111
        this(DALLocator.getDataManager().createFeaturePagingHelper(
112
            featureStore, featureQuery, pageSize));
113
    }
114

    
115
    /**
116
     * Constructs a TableModel from a FeatureCollection and a Paging helper.
117
     *
118
     * @param featureCollection
119
     *            to extract data from
120
     * @param helper
121
     *            the paging helper
122
     * @throws DataException
123
     *             if there is an error reading data from the FeatureStore
124
     */
125
    protected FeatureTableModel(FeaturePagingHelper helper) {
126
        this.helper = helper;
127
        initialize();
128
    }
129

    
130
    public int getColumnCount() {
131
        // Return the number of fields of the Features
132
        FeatureType featureType = getFeatureType();
133
        return featureType.size();
134
    }
135

    
136
    public int getRowCount() {
137
        // Return the total size of the collection
138
        // If the size is bigger than INTEGER.MAX_VALUE, return that instead
139
            try {
140
                long totalSize = getHelper().getTotalSize();
141
                if (totalSize > Integer.MAX_VALUE) {
142
                    return Integer.MAX_VALUE;
143
                } else {
144
                    return (int) totalSize;
145
                }
146
            } catch (ConcurrentDataModificationException e) {
147
                        logger.debug("Error while getting the total size of the set", e);
148
                        return 0;
149
                }
150
    }
151

    
152
    public Object getValueAt(int rowIndex, int columnIndex) {
153
        // Get the Feature at row "rowIndex", and return the value of the
154
        // attribute at "columnIndex"
155
        Feature feature = getFeatureAt(rowIndex);
156
        return feature == null ? null : getFeatureValue(feature, columnIndex);
157
    }
158

    
159
    /**
160
     * Returns the value for a row position.
161
     *
162
     * @param rowIndex
163
     *            the row position
164
     * @return the Feature
165
     */
166
    public Feature getFeatureAt(int rowIndex) {
167
        try {
168
            return getHelper().getFeatureAt(rowIndex);
169
        } catch (BaseException ex) {
170
            throw new GetFeatureAtException(rowIndex, ex);
171
        }
172
    }
173

    
174
    public Class<?> getColumnClass(int columnIndex) {
175
        // Return the class of the FeatureAttributeDescriptor for the value
176
        FeatureAttributeDescriptor attributeDesc =
177
            internalGetFeatureDescriptorForColumn(columnIndex);
178
        if (attributeDesc == null) {
179
                return super.getColumnClass(columnIndex);
180
        }
181
        Class<?> clazz = attributeDesc.getObjectClass();
182
        return (clazz == null ? super.getColumnClass(columnIndex) : clazz);
183
    }
184

    
185
    public String getColumnName(int column) {
186
        // Return the Feature attribute name
187
        FeatureAttributeDescriptor attributeDesc =
188
            internalGetFeatureDescriptorForColumn(column);
189
        return attributeDesc.getName();
190
    }
191

    
192
    @Override
193
    public boolean isCellEditable(int rowIndex, int columnIndex) {
194
        if (getFeatureStore().isEditing()) {
195
            FeatureAttributeDescriptor attributeDesc =
196
                internalGetFeatureDescriptorForColumn(columnIndex);
197
            return !attributeDesc.isReadOnly();
198
        }
199

    
200
        return false;
201
    }
202

    
203
    @Override
204
    public void setValueAt(Object value, int rowIndex, int columnIndex) {
205
        // Get the feature at rowIndex
206
        Feature feature = getFeatureAt(rowIndex);
207
        // Only set the value if the feature exists
208
        if (feature != null) {
209
            // We only need to update if the value to set is not equal to the
210
            // current value
211
            Object currentValue = getFeatureValue(feature, columnIndex);
212
            if (value != currentValue
213
                && (value == null || !value.equals(currentValue))) {
214
                try {
215
                    // Store the editable feature to ignore the related store
216
                    // change notification
217
                    editableFeature =
218
                        setFeatureValue(feature, columnIndex, value);
219
                    EditingNotificationManager editingNotificationManager = MapControlLocator.getEditingNotificationManager();
220
                    EditingNotification notification = editingNotificationManager.notifyObservers(
221
                            this,
222
                            EditingNotification.BEFORE_UPDATE_FEATURE,
223
                            null,
224
                            this.getHelper().getFeatureStore(),
225
                            editableFeature);
226
                    if( notification.isCanceled() ) {
227
                        return;
228
                    }
229
                    if( notification.shouldValidateTheFeature() ) {
230
                        if ( !editingNotificationManager.validateFeature(feature) ) {
231
                            return;
232
                        }
233
                    }
234
                    this.getHelper().update(editableFeature);
235
                    // We'll have already received the event, so we can forget
236
                    // about it
237
                    getHelper().reloadCurrentPage();
238
                    fireTableCellUpdated(rowIndex, columnIndex);
239

    
240
                    editingNotificationManager.notifyObservers(
241
                            this,
242
                            EditingNotification.AFTER_UPDATE_FEATURE,
243
                            null,
244
                            this.getHelper().getFeatureStore(),
245
                            editableFeature);
246
                    editableFeature = null;
247

    
248
                } catch (BaseException ex) {
249
                    throw new SetFeatureValueException(rowIndex, columnIndex,
250
                        value, ex);
251
                } finally {
252
                    // Just in case
253
                    editableFeature = null;
254
                }
255
            }
256
        }
257
    }
258

    
259
    /**
260
     * Returns a reference to the Paging Helper used to load the data from the
261
     * DataStore.
262
     *
263
     * @return the paging helper
264
     */
265
    public FeaturePagingHelper getHelper() {
266
        return helper;
267
    }
268

    
269
    /**
270
     * Sets the FeatureType to show in the table. Used for FeatureStores with
271
     * many simultaneous FeatureTypes supported. Will cause a reload of the
272
     * current data.
273
     *
274
     * @param featureType
275
     *            the FeatureType of the Features
276
     * @throws DataException
277
     *             if there is an error loading the data
278
     */
279
    public void setFeatureType(FeatureType featureType) {
280
        getFeatureQuery().setFeatureType(featureType);
281
        reloadFeatures();
282
        fireTableStructureChanged();
283
    }
284

    
285
    /**
286
     * Sets that the selected Features get returned first.
287
     */
288
    public void setSelectionUp(boolean selectionUp) {
289
        getHelper().setSelectionUp(selectionUp);
290
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1));
291
    }
292

    
293
    private class DelayAction extends Timer implements ActionListener, Runnable {
294
        private static final int STATE_NONE = 0;
295
        private static final int STATE_NEED_RELOADALL = 1;
296
        private static final int STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED = 2;
297
        private static final int STATE_NEED_RELOAD_IF_FEATURE_UPDATED = 4;
298
        private static final int STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED = 8;
299
        private static final int STATE_NEED_RELOAD_FEATURE_TYPE = 16;
300
        private static final int STATE_NEED_SELECTION_UP = 32;
301
        private static final int STATE_NEED_RELOAD_ALL_FEATURES=64;
302

    
303
        private int state = STATE_NONE;
304
        private Feature feature;
305
        private FeatureType featureType;
306
        private boolean isSelecctionUp;
307

    
308
        public DelayAction() {
309
            super(1000,null);
310
            this.setRepeats(false);
311
            this.reset();
312
            this.addActionListener(this);
313
        }
314

    
315
        public void reset() {
316
            this.state = STATE_NONE;
317
            this.isSelecctionUp = false;
318
            this.feature = null;
319
            this.featureType = null;
320
        }
321

    
322
        public void actionPerformed(ActionEvent ae) {
323
            this.run();
324
        }
325

    
326
        public void run() {
327
            if( !SwingUtilities.isEventDispatchThread() ) {
328
                SwingUtilities.invokeLater(this);
329
                return;
330
            }
331
            this.stop();
332
            logger.info("DelayAction.run["+this.state+"] begin");
333
            switch(this.state) {
334
            case STATE_NEED_RELOADALL:
335
                reloadAll();
336
                break;
337
            case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
338
                reloadIfFeatureCountChanged(feature);
339
                break;
340
            case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
341
                reloadIfFeatureUpdated(feature);
342
                break;
343
            case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
344
                reloadIfTypeChanged(featureType);
345
                break;
346
            case STATE_NEED_RELOAD_FEATURE_TYPE:
347
                reloadFeatureType();
348
                updatePaginHelperWithHiddenColums();
349
                break;
350
            case STATE_NEED_RELOAD_ALL_FEATURES:
351
                reloadFeatures();
352
                fireTableChanged(new TableModelEvent(FeatureTableModel.this, 0, getRowCount()));
353
                break;
354
            case STATE_NEED_SELECTION_UP:
355
            case STATE_NONE:
356
            default:
357
                break;
358
            }
359
            if( isSelecctionUp ) {
360
                getHelper().setSelectionUp(true);
361
            }
362
            this.reset();
363
            logger.info("DelayAction.run["+this.state+"] end");
364
        }
365

    
366
        public void nextState(int nextstate) {
367
            this.nextState(nextstate, null, null);
368
        }
369

    
370
        public void nextState(int nextstate, Feature feature) {
371
            this.nextState(nextstate, feature, null);
372
        }
373

    
374
        public void nextState(int nextstate, FeatureType featureType) {
375
            this.nextState(nextstate, null, featureType);
376
        }
377

    
378
        public void nextState(int nextstate, Feature feature, FeatureType featureType) {
379
            this.feature = feature;
380
            this.featureType = featureType;
381
            switch(nextstate) {
382
            case STATE_NEED_RELOADALL:
383
            case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
384
            case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
385
                switch(this.state) {
386
                case STATE_NEED_RELOADALL:
387
                case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
388
                //case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
389
                    this.state = STATE_NEED_RELOADALL;
390
                    break;
391
                case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
392
                case STATE_NEED_RELOAD_FEATURE_TYPE:
393
                    this.state = STATE_NEED_RELOAD_FEATURE_TYPE;
394
                    break;
395
                case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
396
                case STATE_NEED_RELOAD_ALL_FEATURES:
397
                    this.state=STATE_NEED_RELOAD_ALL_FEATURES;
398
                    break;
399
                case STATE_NEED_SELECTION_UP:
400
                    this.state = nextstate;
401
                    this.isSelecctionUp = true;
402
                    break;
403
                case STATE_NONE:
404
                default:
405
                    this.state = nextstate;
406
                    break;
407
                }
408
                break;
409
            case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
410
            case STATE_NEED_RELOAD_FEATURE_TYPE:
411
                switch(this.state) {
412
                case STATE_NEED_RELOADALL:
413
                case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
414
                case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
415
                case STATE_NEED_RELOAD_ALL_FEATURES:
416
                case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
417
                case STATE_NEED_RELOAD_FEATURE_TYPE:
418
                    this.state = STATE_NEED_RELOAD_FEATURE_TYPE;
419
                    break;
420
                case STATE_NEED_SELECTION_UP:
421
                    this.state = nextstate;
422
                    this.isSelecctionUp = true;
423
                    break;
424
                case STATE_NONE:
425
                default:
426
                    this.state = nextstate;
427
                    break;
428
                }
429
                break;
430
            case STATE_NEED_SELECTION_UP:
431
                switch(this.state) {
432
                case STATE_NEED_RELOADALL:
433
                case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
434
                case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
435
                case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
436
                case STATE_NEED_RELOAD_ALL_FEATURES:
437
                case STATE_NEED_RELOAD_FEATURE_TYPE:
438
                case STATE_NEED_SELECTION_UP:
439
                    this.isSelecctionUp = true;
440
                    break;
441
                case STATE_NONE:
442
                default:
443
                    this.state = nextstate;
444
                    this.isSelecctionUp = true;
445
                    break;
446
                }
447
                break;
448
            case STATE_NONE:
449
            default:
450
                this.state = STATE_NONE;
451
                break;
452
            }
453
            if( this.state != STATE_NONE ) {
454
                this.start();
455
            }
456
        }
457

    
458
    }
459

    
460
    private DelayAction delayAction = new DelayAction();
461

    
462
    public void update(final Observable observable, final Object notification) {
463
        if (notification instanceof ComplexNotification) {
464
            // A lot of things might have happened in the store, so don't
465
            // bother looking into each notification.
466
            this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
467
//            reloadAll();
468
        } else if (observable.equals(getFeatureStore())
469
                && notification instanceof FeatureStoreNotification) {
470
            FeatureStoreNotification fsNotification
471
                    = (FeatureStoreNotification) notification;
472
            String type = fsNotification.getType();
473

    
474
            // If there are new, updated or deleted features
475
            // reload the table data
476
            if (FeatureStoreNotification.AFTER_DELETE.equals(type)
477
                    || FeatureStoreNotification.AFTER_INSERT.equals(type)) {
478
//                reloadIfFeatureCountChanged(fsNotification.getFeature());
479
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED, fsNotification.getFeature());
480

    
481
            } else if (FeatureStoreNotification.AFTER_UPDATE.equals(type)) {
482
//                reloadIfFeatureUpdated(fsNotification.getFeature());
483
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_UPDATED, fsNotification.getFeature());
484

    
485
            } else if (FeatureStoreNotification.AFTER_UPDATE_TYPE.equals(type)) {
486
//                reloadIfTypeChanged(fsNotification.getFeatureType());
487
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED, fsNotification.getFeatureType());
488

    
489
            } else if (FeatureStoreNotification.TRANSFORM_CHANGE.equals(type)
490
                    || FeatureStoreNotification.AFTER_UNDO.equals(type)
491
                    || FeatureStoreNotification.AFTER_REDO.equals(type)
492
                    || FeatureStoreNotification.AFTER_REFRESH.equals(type))  {
493
//                reloadAll();
494
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
495

    
496
            } else if (FeatureStoreNotification.AFTER_FINISHEDITING.equals(type)
497
                    || FeatureStoreNotification.AFTER_STARTEDITING.equals(type)
498
                    || FeatureStoreNotification.AFTER_CANCELEDITING.equals(type)) {
499
                /*
500
                No tengo nada claro por que es necesario llamar al reloadFeatureType
501
                pero si no se incluye hay problemas si durante la edicion se a?aden
502
                campos a la tabla. Sin esto, al cerrar la edicion, los campos a?adidos
503
                desaparecen de la tabla aunque estan en el fichero.
504
                Ver ticket #2434 https://devel.gvsig.org/redmine/issues/2434
505
                */
506
//                reloadFeatureType();
507
//                updatePaginHelperWithHiddenColums();
508
                this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_FEATURE_TYPE, fsNotification.getFeatureType());
509
            } else if (FeatureStoreNotification.SELECTION_CHANGE.equals(type)) {
510
                if( this.getHelper().isSelectionUp() ) {
511
                    getHelper().setSelectionUp(true);
512
                    this.delayAction.nextState(DelayAction.STATE_NEED_SELECTION_UP);
513
                }
514
            }
515
        }
516
    }
517

    
518
    protected void updatePaginHelperWithHiddenColums() {
519
        FeatureQuery query = this.getHelper().getFeatureQuery();
520
        if (this.getHelper().getFeatureStore().isEditing()) {
521
            if (query.hasConstantsAttributeNames()) {
522
                query.clearConstantsAttributeNames();
523
            }
524
        } else {
525
            query.setConstantsAttributeNames(this.getHiddenColumnNames());
526
        }
527
        try {
528
            this.getHelper().reload();
529
        } catch (BaseException ex) {
530
            logger.warn("Can't reload paging-helper.", ex);
531
        }
532
    }
533

    
534
    protected String[] getHiddenColumnNames() {
535
        return null;
536
    }
537

    
538
    /**
539
     * Returns the FeatureStore of the Collection.
540
     *
541
     * @return the FeatureStore
542
     */
543
    public FeatureStore getFeatureStore() {
544
        return getHelper().getFeatureStore();
545
    }
546

    
547
    /**
548
     * Returns the descriptor of a Feature attribute for a table column.
549
     *
550
     * @param columnIndex
551
     *            the column index
552
     */
553
    public FeatureAttributeDescriptor getDescriptorForColumn(int columnIndex) {
554
        return internalGetFeatureDescriptorForColumn(columnIndex);
555
    }
556

    
557
    /**
558
     * @param columnIndex
559
     * @return
560
     */
561
        protected FeatureAttributeDescriptor internalGetFeatureDescriptorForColumn(
562
                        int columnIndex) {
563
                FeatureType featureType = getFeatureType();
564
                return featureType == null ? null : featureType
565
                                .getAttributeDescriptor(columnIndex);
566
        }
567

    
568
    /**
569
     * Initialize the TableModel
570
     */
571
    protected void initialize() {
572
        // Add as observable to the FeatureStore, to detect data and selection
573
        // changes
574
        helper.getFeatureStore().addObserver(this);
575
    }
576

    
577
    /**
578
     * Returns the value of a Feature attribute, at the given position.
579
     *
580
     * @param feature
581
     *            the feature to get the value from
582
     * @param columnIndex
583
     *            the Feature attribute position
584
     * @return the value
585
     */
586
    protected Object getFeatureValue(Feature feature, int columnIndex) {
587
        return feature.get(columnIndex);
588
    }
589

    
590
    /**
591
     * Sets the value of an Feature attribute at the given position.
592
     *
593
     * @param feature
594
     *            the feature to update
595
     * @param columnIndex
596
     *            the attribute position
597
     * @param value
598
     *            the value to set
599
     * @throws IsNotFeatureSettingException
600
     *             if there is an error setting the value
601
     */
602
    protected EditableFeature setFeatureValue(Feature feature, int columnIndex,
603
        Object value) {
604
        EditableFeature editableFeature = feature.getEditable();
605
        editableFeature.set(columnIndex, value);
606
        return editableFeature;
607
    }
608

    
609
    /**
610
     * Returns the FeatureQuery used to get the Features.
611
     *
612
     * @return the FeatureQuery
613
     */
614
    public FeatureQuery getFeatureQuery() {
615
        return getHelper().getFeatureQuery();
616
    }
617

    
618
    /**
619
     * Returns the type of the features.
620
     */
621
    protected FeatureType getFeatureType() {
622
        return getHelper().getFeatureType();
623
    }
624

    
625
    /**
626
     * Reloads the table data if a feature has been changed, not through the
627
     * table.
628
     */
629
    private void reloadIfFeatureCountChanged(Feature feature) {
630
        // Is any data is changed in the FeatureStore, notify the model
631
        // listeners. Ignore the case where the updated feature is
632
        // changed through us.
633
        if (editableFeature == null || !editableFeature.equals(feature)) {
634
            reloadFeatures();
635
            fireTableDataChanged();
636
        }
637
    }
638

    
639
    private void reloadIfFeatureUpdated(Feature feature) {
640
        // Is any data is changed in the FeatureStore, notify the model
641
        // listeners. Ignore the case where the updated feature is
642
        // changed through us.
643
        if (editableFeature == null || !editableFeature.equals(feature)) {
644
            reloadFeatures();
645
            fireTableChanged(new TableModelEvent(this, 0, getRowCount()));
646
        }
647
    }
648

    
649
    /**
650
     * Reloads data and structure if the {@link FeatureType} of the features
651
     * being shown has changed.
652
     */
653
    private void reloadIfTypeChanged(FeatureType updatedType) {
654
        // If the updated featured type is the one currently being
655
        // shown, reload the table.
656
        if (updatedType != null
657
            && updatedType.getId().equals(getFeatureType().getId())) {
658
            setFeatureType(updatedType);
659
        }
660
    }
661

    
662
    private void reloadAll() {
663
            reloadFeatureType();
664
    }
665

    
666
    private void reloadFeatureType() {
667
        try {
668
            setFeatureType(getHelper().getFeatureStore().getFeatureType(
669
                getHelper().getFeatureType().getId()));
670
        } catch (DataException e) {
671
            throw new FeaturesDataReloadException(e);
672
        }
673
    }
674

    
675
    /**
676
     * Reloads the features shown on the table.
677
     */
678
    private void reloadFeatures() {
679
        try {
680
            getHelper().reload();
681
        } catch (BaseException ex) {
682
            throw new FeaturesDataReloadException(ex);
683
        }
684
    }
685
}