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

History | View | Annotate | Download (18.7 KB)

1 40558 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40558 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 40435 jjdelcerro
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8 40558 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * of the License, or (at your option) any later version.
10 40558 jjdelcerro
 *
11 40435 jjdelcerro
 * 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 40558 jjdelcerro
 *
16 40435 jjdelcerro
 * 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 40558 jjdelcerro
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 40435 jjdelcerro
 * MA  02110-1301, USA.
20 40558 jjdelcerro
 *
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 40435 jjdelcerro
 */
24
package org.gvsig.app.project.documents.table;
25
26
import java.awt.Component;
27 40729 jldominguez
import java.awt.event.ActionEvent;
28
import java.awt.event.ActionListener;
29 40435 jjdelcerro
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 42533 dmartinezizquierdo
import org.gvsig.fmap.dal.DALLocator;
46
import org.gvsig.fmap.dal.DataManager;
47 40435 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
48 42775 jjdelcerro
import org.gvsig.fmap.dal.EditingNotification;
49
import org.gvsig.fmap.dal.EditingNotificationManager;
50 40435 jjdelcerro
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 42533 dmartinezizquierdo
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
60 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
61
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
62 42775 jjdelcerro
import org.gvsig.fmap.dal.swing.DALSwingLocator;
63 41323 jjdelcerro
import org.gvsig.fmap.mapcontrol.MapControlLocator;
64 40435 jjdelcerro
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 42533 dmartinezizquierdo
 *
72 40435 jjdelcerro
 * @author Vicente Caballero Navarro
73 42533 dmartinezizquierdo
 *
74 40435 jjdelcerro
 */
75
public class TableOperations {
76
77
    private static Logger logger = LoggerFactory.getLogger(TableOperations.class);
78 42533 dmartinezizquierdo
79 40435 jjdelcerro
    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 42533 dmartinezizquierdo
84 40435 jjdelcerro
    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 41323 jjdelcerro
            if( !insertFeature(feature.getEditable()) ) {
117
                break;
118
            }
119 40435 jjdelcerro
        }
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 41323 jjdelcerro
            if( !deleteFeature(feature) ) {
149
                break;
150
            }
151 40435 jjdelcerro
        }
152
    }
153
154
    public void deleteFeatures() throws DataException {
155 42533 dmartinezizquierdo
156 40435 jjdelcerro
        FeatureTableModel _ftm = this.tablePanel.getTablePanel().getTableModel();
157
        List<TableModelListener> tmll = removeTableModelListeners(_ftm);
158 40628 jldominguez
        DisposableIterator feat_iter = null;
159
        Feature feat = null;
160 40435 jjdelcerro
        try {
161 42533 dmartinezizquierdo
162
163 40628 jldominguez
            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 41323 jjdelcerro
                if( !deleteFeature(feat) ) {
169
                    return;
170 40435 jjdelcerro
                }
171
            }
172 40628 jldominguez
173 41323 jjdelcerro
174 40435 jjdelcerro
        } finally {
175 40628 jldominguez
            if (feat_iter != null) {
176
                    feat_iter.dispose();
177 40435 jjdelcerro
            }
178 42533 dmartinezizquierdo
179 40435 jjdelcerro
            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 42533 dmartinezizquierdo
191 40435 jjdelcerro
        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 42533 dmartinezizquierdo
205 40435 jjdelcerro
        TableModelListener[] ll = ftm.getListeners(TableModelListener.class);
206
        List<TableModelListener> resp = new ArrayList<TableModelListener>();
207 42533 dmartinezizquierdo
208 40435 jjdelcerro
        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 41323 jjdelcerro
        insertFeature(feature);
220
    }
221
222
    /*
223
     * Return false if the operation is canceled.
224
     */
225
    private boolean insertFeature(EditableFeature feature) throws DataException {
226 42775 jjdelcerro
        EditingNotificationManager editingNotificationManager = DALSwingLocator.getEditingNotificationManager();
227 41335 jjdelcerro
        EditingNotification notification = editingNotificationManager.notifyObservers(
228 41323 jjdelcerro
                this,
229
                EditingNotification.BEFORE_INSERT_FEATURE,
230
                tablePanel.getDocument(),
231
                featureStore,
232
                feature);
233
        if ( notification.isCanceled() ) {
234
            return false;
235
        }
236 41335 jjdelcerro
        if( notification.shouldValidateTheFeature() ) {
237
            if ( !editingNotificationManager.validateFeature(feature) ) {
238
                return false;
239
            }
240
        }
241 40435 jjdelcerro
        featureStore.insert(feature);
242 41335 jjdelcerro
        editingNotificationManager.notifyObservers(
243 41323 jjdelcerro
                this,
244
                EditingNotification.AFTER_INSERT_FEATURE,
245
                tablePanel.getDocument(),
246
                featureStore,
247
                feature);
248
        return true;
249 40435 jjdelcerro
    }
250
251 41323 jjdelcerro
    private boolean deleteFeature(Feature feature) throws DataException {
252 42775 jjdelcerro
        EditingNotificationManager editingNotification = DALSwingLocator.getEditingNotificationManager();
253 41323 jjdelcerro
        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 42533 dmartinezizquierdo
272 41323 jjdelcerro
    private boolean updateFeatureType(EditableFeatureType featureType) throws DataException {
273 42533 dmartinezizquierdo
274 42775 jjdelcerro
        EditingNotificationManager editingNotification = DALSwingLocator.getEditingNotificationManager();
275 41323 jjdelcerro
        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 40435 jjdelcerro
    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 42533 dmartinezizquierdo
307 40729 jldominguez
                EditableFeatureType eft = featureStore.getDefaultFeatureType().getEditable();
308 40435 jjdelcerro
309 40729 jldominguez
                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 40435 jjdelcerro
316 40729 jldominguez
                CreateNewAttributePanel panelNewField = new CreateNewAttributePanel();
317
                panelNewField.setCurrentFieldNames(tmpfnames.toArray(new String[0]));
318 42533 dmartinezizquierdo
            DataManager dataManager = DALLocator.getDataManager();
319
            FeatureStoreProviderFactory factory =
320
                    (FeatureStoreProviderFactory) dataManager.
321
                    getStoreProviderFactory(featureStore.getProviderName());
322
                panelNewField.setMaxAttributeNameSize(factory.getMaxAttributeNameSize());
323 40729 jldominguez
                panelNewField.setOkAction(new NewFieldActionListener(panelNewField, eft));
324
                ApplicationLocator.getManager().getUIManager().addWindow(panelNewField);
325
                featureStore.update(eft);
326 40435 jjdelcerro
    }
327
328
    public void renameAttributes(FeatureTable table) throws DataException {
329 42533 dmartinezizquierdo
330 40435 jjdelcerro
        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 40732 jldominguez
                    this, "_Please_insert_new_field_name"),
341 40435 jjdelcerro
                    selecteds[i]
342
                    .getName());
343 40729 jldominguez
            if (newName == null || newName.length() == 0) {
344
                continue;
345 40435 jjdelcerro
            }
346
            if (_ft.getIndex(newName) != -1) {
347
                NotificationManager.showMessageInfo(
348 40729 jldominguez
                                Messages.getText("field_already_exists"), null);
349 40435 jjdelcerro
                return;
350
            }
351 42533 dmartinezizquierdo
352 40435 jjdelcerro
            renameAttribute(featureStore, selecteds[i].getName(), newName);
353
        }
354 42533 dmartinezizquierdo
355 40435 jjdelcerro
        // featureStore.finishEditing();
356
        // featureStore.edit(FeatureStore.MODE_FULLEDIT);
357
    }
358
359
    /**
360
     * This method renames a field in three steps:
361 42533 dmartinezizquierdo
     *
362 40435 jjdelcerro
     * (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 42533 dmartinezizquierdo
     *
366 40435 jjdelcerro
     * @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 42533 dmartinezizquierdo
378 40435 jjdelcerro
            if (dft instanceof EditableFeatureType) {
379
                eft = (EditableFeatureType) dft;
380
            } else {
381
                eft = dft.getEditable();
382
            }
383 42533 dmartinezizquierdo
384 40435 jjdelcerro
            EditableFeatureAttributeDescriptor efad =
385
                (EditableFeatureAttributeDescriptor) eft.getAttributeDescriptor(name);
386
            efad.setName(newName);
387
            fs.update(eft);
388 42533 dmartinezizquierdo
389 40435 jjdelcerro
        } catch (DataException de) {
390 42533 dmartinezizquierdo
391 40435 jjdelcerro
            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 42533 dmartinezizquierdo

420 40435 jjdelcerro
        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 42533 dmartinezizquierdo

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

441 40435 jjdelcerro
            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 42533 dmartinezizquierdo

452 40435 jjdelcerro
        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 42533 dmartinezizquierdo

466 40435 jjdelcerro
        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 42533 dmartinezizquierdo

473 40435 jjdelcerro
        } 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 40955 jldominguez
486 42533 dmartinezizquierdo
487 40435 jjdelcerro
    /**
488
     * Renames field in feature store
489 42533 dmartinezizquierdo
     *
490 40435 jjdelcerro
     * @param fs
491
     * @param oldname
492
     * @param newname
493 42533 dmartinezizquierdo
     * @return
494 40435 jjdelcerro
     * @throws DataException
495
     */
496
    public static void renameColumn(FeatureStore fs,
497
        String oldname, String newname) throws DataException {
498 42533 dmartinezizquierdo
499 40435 jjdelcerro
        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 42533 dmartinezizquierdo
509 40729 jldominguez
    public class NewFieldActionListener implements ActionListener {
510 40435 jjdelcerro
511 40729 jldominguez
            private CreateNewAttributePanel panel = null;
512
            private EditableFeatureType eft = null;
513 42533 dmartinezizquierdo
514 40729 jldominguez
            public NewFieldActionListener(CreateNewAttributePanel p, EditableFeatureType t) {
515
                    eft = t;
516
                    panel = p;
517
            }
518 42533 dmartinezizquierdo
519 40729 jldominguez
                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 42533 dmartinezizquierdo
540 40729 jldominguez
                }
541 42533 dmartinezizquierdo
542 40729 jldominguez
    }
543
544 40435 jjdelcerro
}