Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app.document.table.app / org.gvsig.app.document.table.app.mainplugin / src / main / java / org / gvsig / app / project / documents / table / TableOperations.java @ 42533

History | View | Annotate | Download (18.6 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
package org.gvsig.app.project.documents.table;
25

    
26
import java.awt.Component;
27
import java.awt.event.ActionEvent;
28
import java.awt.event.ActionListener;
29
import java.text.ParseException;
30
import java.util.ArrayList;
31
import java.util.Iterator;
32
import java.util.List;
33

    
34
import javax.swing.JOptionPane;
35
import javax.swing.event.TableModelListener;
36

    
37
import org.slf4j.Logger;
38
import org.slf4j.LoggerFactory;
39

    
40
import org.gvsig.andami.PluginServices;
41
import org.gvsig.andami.messages.NotificationManager;
42
import org.gvsig.app.ApplicationLocator;
43
import org.gvsig.app.project.documents.table.gui.CreateNewAttributePanel;
44
import org.gvsig.app.project.documents.table.gui.FeatureTableDocumentPanel;
45
import org.gvsig.editing.EditingNotification;
46
import org.gvsig.editing.EditingNotificationManager;
47
import org.gvsig.fmap.dal.DALLocator;
48
import org.gvsig.fmap.dal.DataManager;
49
import org.gvsig.fmap.dal.DataTypes;
50
import org.gvsig.fmap.dal.exception.DataException;
51
import org.gvsig.fmap.dal.feature.EditableFeature;
52
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
53
import org.gvsig.fmap.dal.feature.EditableFeatureType;
54
import org.gvsig.fmap.dal.feature.Feature;
55
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
56
import org.gvsig.fmap.dal.feature.FeatureSelection;
57
import org.gvsig.fmap.dal.feature.FeatureSet;
58
import org.gvsig.fmap.dal.feature.FeatureStore;
59
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
60
import org.gvsig.fmap.dal.feature.FeatureType;
61
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
62
import org.gvsig.fmap.mapcontrol.MapControlLocator;
63
import org.gvsig.fmap.mapcontrol.dal.feature.swing.FeatureTable;
64
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureTableModel;
65
import org.gvsig.i18n.Messages;
66
import org.gvsig.tools.dispose.DisposableIterator;
67

    
68
/**
69
 * Feature Table Operations.
70
 *
71
 * @author Vicente Caballero Navarro
72
 *
73
 */
74
public class TableOperations {
75

    
76
    private static Logger logger = LoggerFactory.getLogger(TableOperations.class);
77

    
78
    public static final int MAX_FIELD_LENGTH = 254;
79
    private static TableOperations fto = null;
80
    private ArrayList<Feature> selectedFeatures = new ArrayList<Feature>();
81
    private boolean cutting = false;
82

    
83
    private FeatureTableDocumentPanel tablePanel = null;
84
    private FeatureStore featureStore;
85

    
86
    public static TableOperations getInstance() {
87
        if (fto == null) {
88
            fto = new TableOperations();
89
        }
90
        return fto;
91
    }
92

    
93
    public void setTablePanel(FeatureTableDocumentPanel tp) {
94
        tablePanel = tp;
95
        featureStore = tp.getModel().getStore();
96
    }
97

    
98
    public void copyFeatures() throws DataException {
99
        cutting = false;
100
        copy();
101
    }
102

    
103
    public boolean hasSelection() {
104
        return !selectedFeatures.isEmpty();
105
    }
106

    
107
    public void pasteFeatures() throws DataException {
108
        if (cutting) {
109
            delete();
110
            cutting = false;
111
        }
112
        Iterator<Feature> features = selectedFeatures.iterator();
113
        while (features.hasNext()) {
114
            Feature feature = features.next();
115
            if( !insertFeature(feature.getEditable()) ) {
116
                break;
117
            }
118
        }
119
    }
120

    
121
    public void cutFeatures() throws DataException {
122
        cutting = true;
123
        copy();
124
    }
125

    
126
    private void copy() throws DataException {
127
        DisposableIterator features = null;
128
        try {
129
            features =
130
                ((FeatureSelection) featureStore.getSelection()).fastIterator();
131
            selectedFeatures.clear();
132
            while (features.hasNext()) {
133
                Feature feature = (Feature) features.next();
134
                selectedFeatures.add(feature);
135
            }
136
        } finally {
137
            if (features != null) {
138
                features.dispose();
139
            }
140
        }
141
    }
142

    
143
    private void delete() throws DataException {
144
        Iterator<Feature> features = selectedFeatures.iterator();
145
        while (features.hasNext()) {
146
            Feature feature = features.next();
147
            if( !deleteFeature(feature) ) {
148
                break;
149
            }
150
        }
151
    }
152

    
153
    public void deleteFeatures() throws DataException {
154

    
155
        FeatureTableModel _ftm = this.tablePanel.getTablePanel().getTableModel();
156
        List<TableModelListener> tmll = removeTableModelListeners(_ftm);
157
        DisposableIterator feat_iter = null;
158
        Feature feat = null;
159
        try {
160

    
161

    
162
            FeatureSelection selection = featureStore.createFeatureSelection();
163
            selection.select((FeatureSet) featureStore.getSelection());
164
            feat_iter = selection.fastIterator();
165
            while (feat_iter.hasNext()) {
166
                feat = (Feature) feat_iter.next();
167
                if( !deleteFeature(feat) ) {
168
                    return;
169
                }
170
            }
171

    
172

    
173
        } finally {
174
            if (feat_iter != null) {
175
                    feat_iter.dispose();
176
            }
177

    
178
            addTableModelListeners(_ftm, tmll);
179
        }
180
    }
181

    
182
    /**
183
     * @param _ftm
184
     * @param tmll
185
     */
186
    private void addTableModelListeners(
187
        FeatureTableModel _model,
188
        List<TableModelListener> _list) {
189

    
190
        Iterator<TableModelListener> iter = _list.iterator();
191
        while (iter.hasNext()) {
192
            _model.addTableModelListener(iter.next());
193
        }
194
        _model.fireTableDataChanged();
195
    }
196

    
197
    /**
198
     * @param ftm
199
     * @param class1
200
     * @return
201
     */
202
    private List<TableModelListener> removeTableModelListeners(FeatureTableModel ftm) {
203

    
204
        TableModelListener[] ll = ftm.getListeners(TableModelListener.class);
205
        List<TableModelListener> resp = new ArrayList<TableModelListener>();
206

    
207
        int n = ll.length;
208
        for (int i=0; i<n; i++) {
209
            resp.add(ll[i]);
210
            ftm.removeTableModelListener(ll[i]);
211
        }
212

    
213
        return resp;
214
    }
215

    
216
    public void insertNewFeature() throws DataException {
217
        EditableFeature feature = featureStore.createNewFeature();
218
        insertFeature(feature);
219
    }
220

    
221
    /*
222
     * Return false if the operation is canceled.
223
     */
224
    private boolean insertFeature(EditableFeature feature) throws DataException {
225
        EditingNotificationManager editingNotificationManager = MapControlLocator.getEditingNotificationManager();
226
        EditingNotification notification = editingNotificationManager.notifyObservers(
227
                this,
228
                EditingNotification.BEFORE_INSERT_FEATURE,
229
                tablePanel.getDocument(),
230
                featureStore,
231
                feature);
232
        if ( notification.isCanceled() ) {
233
            return false;
234
        }
235
        if( notification.shouldValidateTheFeature() ) {
236
            if ( !editingNotificationManager.validateFeature(feature) ) {
237
                return false;
238
            }
239
        }
240
        featureStore.insert(feature);
241
        editingNotificationManager.notifyObservers(
242
                this,
243
                EditingNotification.AFTER_INSERT_FEATURE,
244
                tablePanel.getDocument(),
245
                featureStore,
246
                feature);
247
        return true;
248
    }
249

    
250
    private boolean deleteFeature(Feature feature) throws DataException {
251
        EditingNotificationManager editingNotification = MapControlLocator.getEditingNotificationManager();
252
        EditingNotification notification = editingNotification.notifyObservers(
253
                this,
254
                EditingNotification.BEFORE_REMOVE_FEATURE,
255
                tablePanel.getDocument(),
256
                featureStore,
257
                feature);
258
        if ( notification.isCanceled() ) {
259
            return false;
260
        }
261
        featureStore.delete(feature);
262
        editingNotification.notifyObservers(
263
                this,
264
                EditingNotification.AFTER_REMOVE_FEATURE,
265
                tablePanel.getDocument(),
266
                featureStore,
267
                feature);
268
        return true;
269
    }
270

    
271
    private boolean updateFeatureType(EditableFeatureType featureType) throws DataException {
272

    
273
        EditingNotificationManager editingNotification = MapControlLocator.getEditingNotificationManager();
274
        EditingNotification notification = editingNotification.notifyObservers(
275
                this,
276
                EditingNotification.BEFORE_UPDATE_FEATURE_TYPE,
277
                tablePanel.getDocument(),
278
                featureStore,
279
                featureType);
280
        if ( notification.isCanceled() ) {
281
            return false;
282
        }
283
        featureStore.update(featureType);
284
        editingNotification.notifyObservers(
285
                this,
286
                EditingNotification.AFTER_UPDATE_FEATURE_TYPE,
287
                tablePanel.getDocument(),
288
                featureStore,
289
                featureType);
290
        return true;
291
    }
292

    
293
    public void deleteAttributes(FeatureTable table) throws DataException {
294
        EditableFeatureType eft =
295
            featureStore.getDefaultFeatureType().getEditable();
296
        FeatureAttributeDescriptor[] selecteds =
297
            table.getSelectedColumnsAttributeDescriptor();
298
        for (int i = 0; i < selecteds.length; i++) {
299
            eft.remove(selecteds[i].getName());
300
        }
301
        featureStore.update(eft);
302
    }
303

    
304
    public void insertAttributes(FeatureTable table) throws DataException {
305

    
306
                EditableFeatureType eft = featureStore.getDefaultFeatureType().getEditable();
307

    
308
                List<String> tmpfnames = new ArrayList<String>();
309
                int size = eft.size();
310
                for (int i = 0; i < size; i++) {
311
                        FeatureAttributeDescriptor ad = (FeatureAttributeDescriptor) eft.get(i);
312
                        tmpfnames.add(ad.getName());
313
                }
314

    
315
                CreateNewAttributePanel panelNewField = new CreateNewAttributePanel();
316
                panelNewField.setCurrentFieldNames(tmpfnames.toArray(new String[0]));
317
            DataManager dataManager = DALLocator.getDataManager();
318
            FeatureStoreProviderFactory factory =
319
                    (FeatureStoreProviderFactory) dataManager.
320
                    getStoreProviderFactory(featureStore.getProviderName());
321
                panelNewField.setMaxAttributeNameSize(factory.getMaxAttributeNameSize());
322
                panelNewField.setOkAction(new NewFieldActionListener(panelNewField, eft));
323
                ApplicationLocator.getManager().getUIManager().addWindow(panelNewField);
324
                featureStore.update(eft);
325
    }
326

    
327
    public void renameAttributes(FeatureTable table) throws DataException {
328

    
329
        FeatureType _ft = featureStore.getDefaultFeatureType();
330

    
331
        FeatureAttributeDescriptor[] selecteds =
332
            table.getSelectedColumnsAttributeDescriptor();
333

    
334
        for (int i = selecteds.length - 1; i >= 0; i--) {
335
            String newName =
336
                JOptionPane.showInputDialog((Component) PluginServices
337
                    .getMDIManager().getActiveWindow(),
338
                    PluginServices.getText(
339
                    this, "_Please_insert_new_field_name"),
340
                    selecteds[i]
341
                    .getName());
342
            if (newName == null || newName.length() == 0) {
343
                continue;
344
            }
345
            if (_ft.getIndex(newName) != -1) {
346
                NotificationManager.showMessageInfo(
347
                                Messages.getText("field_already_exists"), null);
348
                return;
349
            }
350

    
351
            renameAttribute(featureStore, selecteds[i].getName(), newName);
352
        }
353

    
354
        // featureStore.finishEditing();
355
        // featureStore.edit(FeatureStore.MODE_FULLEDIT);
356
    }
357

    
358
    /**
359
     * This method renames a field in three steps:
360
     *
361
     * (1) add new field using type and size of old field.
362
     * (2) copy value from old field to new field.
363
     * (3) remove old field.
364
     *
365
     * @param fs
366
     * @param name
367
     * @param newName
368
     * @return true if the change took place
369
     */
370
    private static boolean renameAttribute(FeatureStore fs, String name, String newName) {
371

    
372
        EditableFeatureType eft = null;
373
        FeatureType dft = null;
374
        try {
375
            dft = fs.getDefaultFeatureType();
376

    
377
            if (dft instanceof EditableFeatureType) {
378
                eft = (EditableFeatureType) dft;
379
            } else {
380
                eft = dft.getEditable();
381
            }
382

    
383
            EditableFeatureAttributeDescriptor efad =
384
                (EditableFeatureAttributeDescriptor) eft.getAttributeDescriptor(name);
385
            efad.setName(newName);
386
            fs.update(eft);
387

    
388
        } catch (DataException de) {
389

    
390
            Component root_comp =
391
                ApplicationLocator.getManager().getRootComponent();
392

    
393
            JOptionPane.showMessageDialog(
394
                root_comp,
395
                Messages.getText("_Unable_to_rename_attribute") +
396
                ": " + de.getMessage(),
397
                Messages.getText("_Unable_to_rename_attribute"),
398
                JOptionPane.ERROR_MESSAGE);
399
            return false;
400
        }
401
        return true;
402

    
403
        /*
404
        try {
405
            // ========== add new field
406
            eft = fs.getDefaultFeatureType().getEditable();
407
            FeatureAttributeDescriptor fad = eft.getAttributeDescriptor(name);
408
            eft.add(newName, fad.getType(), fad.getSize());
409
            fs.update(eft);
410
        } catch (DataException ex) {
411
            logger.info("Unable to rename attribute (" + name + " --> " + newName + ")", ex);
412
            ApplicationLocator.getManager().message(
413
                Messages.getText("_Unable_to_rename_attribute"),
414
                JOptionPane.ERROR_MESSAGE);
415
            // did not even add new field
416
            return false;
417
        }
418

419
        boolean error_when_inserting = false;
420
        try {
421
            // ========== copy value old field -> new field
422
            FeatureSet fset = fs.getFeatureSet();
423
            DisposableIterator diter = fset.fastIterator();
424
            Feature feat = null;
425
            Object val = null;
426
            EditableFeature efeat = null;
427
            while (diter.hasNext()) {
428
                feat = (Feature) diter.next();
429
                val = feat.get(name);
430
                efeat = feat.getEditable();
431
                efeat.set(newName, val);
432
                fset.update(efeat);
433
            }
434
            diter.dispose();
435

436
            // Closing editing to check that store admits new field
437
            fs.finishEditing();
438
        } catch (DataException ex) {
439

440
            logger.info("Error while renaming att to: " + newName, ex);
441
            String final_msg = getLastMessage(ex);
442
            JOptionPane.showMessageDialog(
443
                root_comp,
444
                Messages.getText("_Unable_to_rename_attribute")
445
                + ": " + final_msg,
446
                Messages.getText("_Rename_column"),
447
                JOptionPane.ERROR_MESSAGE);
448
            error_when_inserting = true;
449
        }
450

451
        if (error_when_inserting) {
452
            try {
453
                // Trying to remove new field and leave table as it was
454
                eft.remove(newName);
455
                fs.update(eft);
456
            } catch (DataException ex) {
457
                // Unable to remove added field but user was
458
                // already notified that something went wrong
459
            }
460
            // Not changed
461
            return false;
462
        }
463

464

465
        try {
466
            // Finally reopen editing and delete old field
467
            fs.edit(FeatureStore.MODE_FULLEDIT);
468
            eft = fs.getDefaultFeatureType().getEditable();
469
            eft.remove(name);
470
            fs.update(eft);
471

472
        } catch (DataException ex) {
473
            logger.info("Unable to rename attribute (" + name + " --> " + newName + ")", ex);
474
            ApplicationLocator.getManager().message(
475
                Messages.getText("_Unable_to_rename_attribute"),
476
                JOptionPane.ERROR_MESSAGE);
477
            return false;
478
        }
479
        return true;
480
        */
481

    
482
    }
483

    
484

    
485

    
486
    /**
487
     * Renames field in feature store
488
     *
489
     * @param fs
490
     * @param oldname
491
     * @param newname
492
     * @return
493
     * @throws DataException
494
     */
495
    public static void renameColumn(FeatureStore fs,
496
        String oldname, String newname) throws DataException {
497

    
498
        FeatureType _ft = fs.getDefaultFeatureType();
499
        if (_ft.getIndex(newname) != -1) {
500
            throw new StoreUpdateFeatureTypeException(
501
                new Exception("Attribute name already existed."),
502
                fs.getName());
503
        }
504
        renameAttribute(fs, oldname, newname);
505
        // fs.finishEditing();
506
    }
507

    
508
    public class NewFieldActionListener implements ActionListener {
509

    
510
            private CreateNewAttributePanel panel = null;
511
            private EditableFeatureType eft = null;
512

    
513
            public NewFieldActionListener(CreateNewAttributePanel p, EditableFeatureType t) {
514
                    eft = t;
515
                    panel = p;
516
            }
517

    
518
                public void actionPerformed(ActionEvent e) {
519
            try {
520
                EditableFeatureAttributeDescriptor ead = panel.loadFieldDescription(eft);
521
                if (ead == null) {
522
                    return;
523
                }
524
                if (ead.getType() == DataTypes.STRING
525
                    && ead.getSize() > TableOperations.MAX_FIELD_LENGTH) {
526
                    NotificationManager.showMessageInfo(
527
                        PluginServices.getText(this,
528
                            "max_length_is")
529
                            + ":"
530
                            + TableOperations.MAX_FIELD_LENGTH,
531
                        null);
532
                    ead.setSize(TableOperations.MAX_FIELD_LENGTH);
533
                }
534
                PluginServices.getMDIManager().closeWindow(panel);
535
            } catch (ParseException e2) {
536
                NotificationManager.addError(e2);
537
            }
538

    
539
                }
540

    
541
    }
542

    
543
}