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

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
import javax.json.JsonArray;
34
import javax.json.JsonObject;
35
import javax.json.JsonValue;
36
import javax.swing.JOptionPane;
37
import javax.swing.event.TableModelListener;
38
import org.apache.bcel.generic.DALOAD;
39
import org.apache.commons.collections.CollectionUtils;
40
import org.apache.commons.collections.ListUtils;
41
import org.gvsig.andami.PluginServices;
42
import org.gvsig.andami.messages.NotificationManager;
43
import org.gvsig.app.ApplicationLocator;
44
import org.gvsig.app.project.documents.table.gui.CreateNewAttributePanel;
45
import org.gvsig.app.project.documents.table.gui.FeatureTableDocumentPanel;
46
import org.gvsig.fmap.dal.DALLocator;
47
import org.gvsig.fmap.dal.DataManager;
48
import org.gvsig.fmap.dal.DataTypes;
49
import org.gvsig.fmap.dal.EditingNotification;
50
import org.gvsig.fmap.dal.EditingNotificationManager;
51
import org.gvsig.fmap.dal.exception.DataException;
52
import org.gvsig.fmap.dal.feature.EditableFeature;
53
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.EditableFeatureType;
55
import org.gvsig.fmap.dal.feature.Feature;
56
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57
import org.gvsig.fmap.dal.feature.FeatureSelection;
58
import org.gvsig.fmap.dal.feature.FeatureSet;
59
import org.gvsig.fmap.dal.feature.FeatureStore;
60
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
61
import org.gvsig.fmap.dal.feature.FeatureType;
62
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
63
import org.gvsig.fmap.dal.swing.DALSwingLocator;
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.json.Json;
68
import org.gvsig.tools.dispose.DisposableIterator;
69
import org.gvsig.tools.swing.api.ToolsSwingLocator;
70
import org.slf4j.Logger;
71
import org.slf4j.LoggerFactory;
72

    
73
/**
74
 * Feature Table Operations.
75
 *
76
 * @author Vicente Caballero Navarro
77
 *
78
 */
79
public class TableOperations {
80

    
81
    private static final Logger logger = LoggerFactory.getLogger(TableOperations.class);
82

    
83
    public static final int MAX_FIELD_LENGTH = 254;
84
    private static TableOperations fto = null;
85

    
86
    private FeatureTableDocumentPanel tablePanel = null;
87
    private FeatureStore featureStore;
88

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

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

    
101
    public void copyFeatures() throws DataException {
102
        copy();
103
    }
104

    
105
    public boolean hasSelection() {
106
        return !ToolsSwingLocator.getToolsSwingManager().isClipboardEmpty();
107
    }
108

    
109
    public void pasteFeatures() throws DataException {
110
        try {
111
            if( featureStore==null ) {
112
                return;
113
            }
114
            List<EditableFeature> features = DALLocator.getDataManager().getFeaturesFromClipboard(
115
                    featureStore,
116
                    null
117
            );
118
            if( CollectionUtils.isEmpty(features) ) {
119
                return;
120
            }
121
            for (EditableFeature feature : features) {
122
                if (!insertFeature(feature) ) {
123
                    break;
124
                }
125
            }
126
        } catch (Exception e) {
127
            logger.warn("Can't paste from clipboard.", e);
128
        }
129

    
130
    }
131

    
132
    private void copy() throws DataException {
133
        DALLocator.getDataManager().putFeaturesInClipboard(featureStore.getFeatureSelection());
134
    }
135

    
136
    public void deleteFeatures() throws DataException {
137

    
138
        FeatureTableModel _ftm = this.tablePanel.getTablePanel().getTableModel();
139
        List<TableModelListener> tmll = removeTableModelListeners(_ftm);
140
        DisposableIterator feat_iter = null;
141
        Feature feat = null;
142
        try {
143
            FeatureSelection selection = featureStore.createFeatureSelection();
144
            selection.select((FeatureSet) featureStore.getSelection());
145
            feat_iter = selection.fastIterator();
146
            while (feat_iter.hasNext()) {
147
                feat = (Feature) feat_iter.next();
148
                if (!deleteFeature(feat)) {
149
                    return;
150
                }
151
            }
152
        } finally {
153
            if (feat_iter != null) {
154
                feat_iter.dispose();
155
            }
156

    
157
            addTableModelListeners(_ftm, tmll);
158
        }
159
    }
160

    
161
    /**
162
     * @param _ftm
163
     * @param tmll
164
     */
165
    private void addTableModelListeners(
166
            FeatureTableModel _model,
167
            List<TableModelListener> _list) {
168

    
169
        Iterator<TableModelListener> iter = _list.iterator();
170
        while (iter.hasNext()) {
171
            _model.addTableModelListener(iter.next());
172
        }
173
        _model.fireTableDataChanged();
174
    }
175

    
176
    /**
177
     * @param ftm
178
     * @param class1
179
     * @return
180
     */
181
    private List<TableModelListener> removeTableModelListeners(FeatureTableModel ftm) {
182

    
183
        TableModelListener[] ll = ftm.getListeners(TableModelListener.class);
184
        List<TableModelListener> resp = new ArrayList<>();
185

    
186
        int n = ll.length;
187
        for (int i = 0; i < n; i++) {
188
            resp.add(ll[i]);
189
            ftm.removeTableModelListener(ll[i]);
190
        }
191

    
192
        return resp;
193
    }
194

    
195
    public void insertNewFeature() throws DataException {
196
        EditableFeature feature = featureStore.createNewFeature();
197
        insertFeature(feature);
198
    }
199

    
200
    /*
201
     * Return false if the operation is canceled.
202
     */
203
    private boolean insertFeature(EditableFeature feature) throws DataException {
204
        EditingNotificationManager editingNotificationManager = DALSwingLocator.getEditingNotificationManager();
205
        EditingNotification notification = editingNotificationManager.notifyObservers(
206
                this,
207
                EditingNotification.BEFORE_INSERT_FEATURE,
208
                tablePanel.getDocument(),
209
                featureStore,
210
                feature);
211
        if (notification.isCanceled()) {
212
            return false;
213
        }
214
        if (notification.shouldValidateTheFeature()) {
215
            if (!editingNotificationManager.validateFeature(feature)) {
216
                return false;
217
            }
218
        }
219
        featureStore.insert(feature);
220
        editingNotificationManager.notifyObservers(
221
                this,
222
                EditingNotification.AFTER_INSERT_FEATURE,
223
                tablePanel.getDocument(),
224
                featureStore,
225
                feature);
226
        return true;
227
    }
228

    
229
    private boolean deleteFeature(Feature feature) throws DataException {
230
        EditingNotificationManager editingNotification = DALSwingLocator.getEditingNotificationManager();
231
        EditingNotification notification = editingNotification.notifyObservers(
232
                this,
233
                EditingNotification.BEFORE_REMOVE_FEATURE,
234
                tablePanel.getDocument(),
235
                featureStore,
236
                feature);
237
        if (notification.isCanceled()) {
238
            return false;
239
        }
240
        featureStore.delete(feature);
241
        editingNotification.notifyObservers(
242
                this,
243
                EditingNotification.AFTER_REMOVE_FEATURE,
244
                tablePanel.getDocument(),
245
                featureStore,
246
                feature);
247
        return true;
248
    }
249

    
250
    private boolean updateFeatureType(EditableFeatureType featureType) throws DataException {
251

    
252
        EditingNotificationManager editingNotification = DALSwingLocator.getEditingNotificationManager();
253
        EditingNotification notification = editingNotification.notifyObservers(
254
                this,
255
                EditingNotification.BEFORE_UPDATE_FEATURE_TYPE,
256
                tablePanel.getDocument(),
257
                featureStore,
258
                featureType);
259
        if (notification.isCanceled()) {
260
            return false;
261
        }
262
        featureStore.update(featureType);
263
        editingNotification.notifyObservers(
264
                this,
265
                EditingNotification.AFTER_UPDATE_FEATURE_TYPE,
266
                tablePanel.getDocument(),
267
                featureStore,
268
                featureType);
269
        return true;
270
    }
271

    
272
    public void deleteAttributes(FeatureTable table) throws DataException {
273
        EditableFeatureType eft
274
                = featureStore.getDefaultFeatureType().getEditable();
275
        FeatureAttributeDescriptor[] selecteds
276
                = table.getSelectedColumnsAttributeDescriptor();
277
        for (FeatureAttributeDescriptor selected : selecteds) {
278
            eft.remove(selected.getName());
279
        }
280
        featureStore.update(eft);
281
    }
282

    
283
    public void insertAttributes(FeatureTable table) throws DataException {
284

    
285
        EditableFeatureType eft = featureStore.getDefaultFeatureType().getEditable();
286

    
287
        List<String> tmpfnames = new ArrayList<>();
288
        int size = eft.size();
289
        for (int i = 0; i < size; i++) {
290
            FeatureAttributeDescriptor ad = (FeatureAttributeDescriptor) eft.get(i);
291
            tmpfnames.add(ad.getName());
292
        }
293

    
294
        CreateNewAttributePanel panelNewField = new CreateNewAttributePanel(featureStore);
295
        panelNewField.setCurrentFieldNames(tmpfnames.toArray(new String[0]));
296
        DataManager dataManager = DALLocator.getDataManager();
297
        FeatureStoreProviderFactory factory
298
                = (FeatureStoreProviderFactory) dataManager.
299
                        getStoreProviderFactory(featureStore.getProviderName());
300
        panelNewField.setMaxAttributeNameSize(factory.getMaxAttributeNameSize());
301
        panelNewField.setOkAction(new NewFieldActionListener(panelNewField, eft));
302
        ApplicationLocator.getManager().getUIManager().addWindow(panelNewField);
303
        featureStore.update(eft);
304
    }
305

    
306
    public void renameAttributes(FeatureTable table) throws DataException {
307

    
308
        FeatureType _ft = featureStore.getDefaultFeatureType();
309

    
310
        FeatureAttributeDescriptor[] selecteds
311
                = table.getSelectedColumnsAttributeDescriptor();
312

    
313
        for (int i = selecteds.length - 1; i >= 0; i--) {
314
            String newName
315
                    = JOptionPane.showInputDialog((Component) PluginServices
316
                            .getMDIManager().getActiveWindow(),
317
                            PluginServices.getText(
318
                                    this, "_Please_insert_new_field_name"),
319
                            selecteds[i]
320
                                    .getName());
321
            if (newName == null || newName.length() == 0) {
322
                continue;
323
            }
324
            FeatureAttributeDescriptor attr = _ft.getAttributeDescriptor(newName);
325
            // To be able to change the name of the attribute when it is changed
326
            // from uppercase to lowercase or vice versa
327
            if (attr != null && attr.getName().equals(newName)) {
328
                NotificationManager.showMessageInfo(
329
                        Messages.getText("field_already_exists"), null);
330
                return;
331
            }
332

    
333
            renameAttribute(featureStore, selecteds[i].getName(), newName);
334
        }
335
    }
336

    
337
    /**
338
     * This method renames a field in three steps:
339
     *
340
     * (1) add new field using type and size of old field. (2) copy value from
341
     * old field to new field. (3) remove old field.
342
     *
343
     * @param fs
344
     * @param name
345
     * @param newName
346
     * @return true if the change took place
347
     */
348
    private static boolean renameAttribute(FeatureStore fs, String name, String newName) {
349

    
350
        EditableFeatureType eft = null;
351
        FeatureType dft = null;
352
        try {
353
            dft = fs.getDefaultFeatureType();
354

    
355
            if (dft instanceof EditableFeatureType) {
356
                eft = (EditableFeatureType) dft;
357
            } else {
358
                eft = dft.getEditable();
359
            }
360

    
361
            EditableFeatureAttributeDescriptor efad
362
                    = (EditableFeatureAttributeDescriptor) eft.getAttributeDescriptor(name);
363
            efad.setName(newName);
364
            fs.update(eft);
365

    
366
        } catch (DataException de) {
367

    
368
            Component root_comp
369
                    = ApplicationLocator.getManager().getRootComponent();
370

    
371
            JOptionPane.showMessageDialog(
372
                    root_comp,
373
                    Messages.getText("_Unable_to_rename_attribute")
374
                    + ": " + de.getMessage(),
375
                    Messages.getText("_Unable_to_rename_attribute"),
376
                    JOptionPane.ERROR_MESSAGE);
377
            return false;
378
        }
379
        return true;
380

    
381
        /*
382
        try {
383
            // ========== add new field
384
            eft = fs.getDefaultFeatureType().getEditable();
385
            FeatureAttributeDescriptor fad = eft.getAttributeDescriptor(name);
386
            eft.add(newName, fad.getType(), fad.getSize());
387
            fs.update(eft);
388
        } catch (DataException ex) {
389
            logger.info("Unable to rename attribute (" + name + " --> " + newName + ")", ex);
390
            ApplicationLocator.getManager().message(
391
                Messages.getText("_Unable_to_rename_attribute"),
392
                JOptionPane.ERROR_MESSAGE);
393
            // did not even add new field
394
            return false;
395
        }
396

397
        boolean error_when_inserting = false;
398
        try {
399
            // ========== copy value old field -> new field
400
            FeatureSet fset = fs.getFeatureSet();
401
            DisposableIterator diter = fset.fastIterator();
402
            Feature feat = null;
403
            Object val = null;
404
            EditableFeature efeat = null;
405
            while (diter.hasNext()) {
406
                feat = (Feature) diter.next();
407
                val = feat.get(name);
408
                efeat = feat.getEditable();
409
                efeat.set(newName, val);
410
                fset.update(efeat);
411
            }
412
            diter.dispose();
413

414
            // Closing editing to check that store admits new field
415
            fs.finishEditing();
416
        } catch (DataException ex) {
417

418
            logger.info("Error while renaming att to: " + newName, ex);
419
            String final_msg = getLastMessage(ex);
420
            JOptionPane.showMessageDialog(
421
                root_comp,
422
                Messages.getText("_Unable_to_rename_attribute")
423
                + ": " + final_msg,
424
                Messages.getText("_Rename_column"),
425
                JOptionPane.ERROR_MESSAGE);
426
            error_when_inserting = true;
427
        }
428

429
        if (error_when_inserting) {
430
            try {
431
                // Trying to remove new field and leave table as it was
432
                eft.remove(newName);
433
                fs.update(eft);
434
            } catch (DataException ex) {
435
                // Unable to remove added field but user was
436
                // already notified that something went wrong
437
            }
438
            // Not changed
439
            return false;
440
        }
441

442

443
        try {
444
            // Finally reopen editing and delete old field
445
            fs.edit(FeatureStore.MODE_FULLEDIT);
446
            eft = fs.getDefaultFeatureType().getEditable();
447
            eft.remove(name);
448
            fs.update(eft);
449

450
        } catch (DataException ex) {
451
            logger.info("Unable to rename attribute (" + name + " --> " + newName + ")", ex);
452
            ApplicationLocator.getManager().message(
453
                Messages.getText("_Unable_to_rename_attribute"),
454
                JOptionPane.ERROR_MESSAGE);
455
            return false;
456
        }
457
        return true;
458
         */
459
    }
460

    
461
    /**
462
     * Renames field in feature store
463
     *
464
     * @param fs
465
     * @param oldname
466
     * @param newname
467
     * @throws DataException
468
     */
469
    public static void renameColumn(FeatureStore fs,
470
            String oldname, String newname) throws DataException {
471

    
472
        FeatureType _ft = fs.getDefaultFeatureType();
473
        if (_ft.getIndex(newname) != -1) {
474
            throw new StoreUpdateFeatureTypeException(
475
                    new Exception("Attribute name already existed."),
476
                    fs.getName());
477
        }
478
        renameAttribute(fs, oldname, newname);
479
        // fs.finishEditing();
480
    }
481

    
482
    public class NewFieldActionListener implements ActionListener {
483

    
484
        private CreateNewAttributePanel panel = null;
485
        private EditableFeatureType eft = null;
486

    
487
        public NewFieldActionListener(CreateNewAttributePanel p, EditableFeatureType t) {
488
            eft = t;
489
            panel = p;
490
        }
491

    
492
        @Override
493
        public void actionPerformed(ActionEvent e) {
494
            try {
495
                EditableFeatureAttributeDescriptor ead = panel.loadFieldDescription(eft);
496
                if (ead == null) {
497
                    return;
498
                }
499
                if (ead.getType() == DataTypes.STRING
500
                        && ead.getSize() > TableOperations.MAX_FIELD_LENGTH) {
501
                    NotificationManager.showMessageInfo(
502
                            PluginServices.getText(this,
503
                                    "max_length_is")
504
                            + ":"
505
                            + TableOperations.MAX_FIELD_LENGTH,
506
                            null);
507
                    ead.setSize(TableOperations.MAX_FIELD_LENGTH);
508
                }
509
                PluginServices.getMDIManager().closeWindow(panel);
510
            } catch (ParseException e2) {
511
                NotificationManager.addError(e2);
512
            }
513

    
514
        }
515

    
516
    }
517

    
518
}