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

History | View | Annotate | Download (18.7 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.fmap.dal.DALLocator;
46
import org.gvsig.fmap.dal.DataManager;
47
import org.gvsig.fmap.dal.DataTypes;
48
import org.gvsig.fmap.dal.EditingNotification;
49
import org.gvsig.fmap.dal.EditingNotificationManager;
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.dal.swing.DALSwingLocator;
63
import org.gvsig.fmap.mapcontrol.MapControlLocator;
64
import org.gvsig.fmap.mapcontrol.dal.feature.swing.FeatureTable;
65
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureTableModel;
66
import org.gvsig.i18n.Messages;
67
import org.gvsig.tools.dispose.DisposableIterator;
68

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

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

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

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

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

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

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

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

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

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

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

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

    
154
    public void deleteFeatures() throws DataException {
155

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

    
162

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

    
173

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

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

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

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

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

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

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

    
214
        return resp;
215
    }
216

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

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

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

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

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

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

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

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

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

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

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

    
330
        FeatureType _ft = featureStore.getDefaultFeatureType();
331

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

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

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

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

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

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

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

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

    
389
        } catch (DataException de) {
390

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

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

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

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

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

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

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

465

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

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

    
483
    }
484

    
485

    
486

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

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

    
509
    public class NewFieldActionListener implements ActionListener {
510

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

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

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

    
540
                }
541

    
542
    }
543

    
544
}