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

History | View | Annotate | Download (19.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
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.gvsig.andami.PluginServices;
39
import org.gvsig.andami.messages.NotificationManager;
40
import org.gvsig.app.ApplicationLocator;
41
import org.gvsig.app.project.documents.table.gui.CreateNewAttributePanel;
42
import org.gvsig.app.project.documents.table.gui.FeatureTableDocumentPanel;
43
import org.gvsig.fmap.dal.DALLocator;
44
import org.gvsig.fmap.dal.DataManager;
45
import org.gvsig.fmap.dal.DataTypes;
46
import org.gvsig.fmap.dal.EditingNotification;
47
import org.gvsig.fmap.dal.EditingNotificationManager;
48
import org.gvsig.fmap.dal.exception.DataException;
49
import org.gvsig.fmap.dal.feature.EditableFeature;
50
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
51
import org.gvsig.fmap.dal.feature.EditableFeatureType;
52
import org.gvsig.fmap.dal.feature.Feature;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.FeatureSelection;
55
import org.gvsig.fmap.dal.feature.FeatureSet;
56
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
58
import org.gvsig.fmap.dal.feature.FeatureType;
59
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
60
import org.gvsig.fmap.dal.swing.DALSwingLocator;
61
import org.gvsig.fmap.mapcontrol.dal.feature.swing.FeatureTable;
62
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureTableModel;
63
import org.gvsig.i18n.Messages;
64
import org.gvsig.json.Json;
65
import org.gvsig.tools.dispose.DisposableIterator;
66
import org.gvsig.tools.swing.api.ToolsSwingLocator;
67
import org.slf4j.Logger;
68
import org.slf4j.LoggerFactory;
69

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

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

    
80
    public static final int MAX_FIELD_LENGTH = 254;
81
    private static TableOperations fto = null;
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
        copy();
100
    }
101

    
102
    public boolean hasSelection() {
103
        EditableFeature newFeature = null;
104
        try {
105
            String clipboard = ToolsSwingLocator.getToolsSwingManager().getFromClipboard();
106
            JsonArray array = Json.createArray(clipboard);
107
            if (array == null) {
108
                return false;
109
            }
110
            JsonValue jsonValue = array.get(0);
111
            newFeature = featureStore.createNewFeature((JsonObject) jsonValue);
112
        } catch (Exception e) {
113
            logger.warn("Can't paste from clipboard.", e);
114
        }
115
        return (newFeature != null);
116
    }
117

    
118
    public void pasteFeatures() throws DataException {
119
        try {
120
            String clipboard = ToolsSwingLocator.getToolsSwingManager().getFromClipboard();
121
            JsonArray array = Json.createArray(clipboard);
122
            if (array == null) {
123
                return;
124
            }
125
            for (JsonValue jsonValue : array) {
126
                EditableFeature newFeature = featureStore.createNewFeature((JsonObject) jsonValue);
127
                if (!insertFeature(newFeature)) {
128
                    break;
129
                }
130
            }
131
        } catch (Exception e) {
132
            logger.warn("Can't paste from clipboard.", e);
133
        }
134

    
135
    }
136

    
137
    private void copy() throws DataException {
138
        DisposableIterator features = null;
139
        try {
140
            ToolsSwingLocator.getToolsSwingManager().putInClipboard(((FeatureSelection) featureStore.getSelection()).toJSON().toString());
141
        } finally {
142
        }
143
    }
144

    
145
    public void deleteFeatures() throws DataException {
146

    
147
        FeatureTableModel _ftm = this.tablePanel.getTablePanel().getTableModel();
148
        List<TableModelListener> tmll = removeTableModelListeners(_ftm);
149
        DisposableIterator feat_iter = null;
150
        Feature feat = null;
151
        try {
152
            FeatureSelection selection = featureStore.createFeatureSelection();
153
            selection.select((FeatureSet) featureStore.getSelection());
154
            feat_iter = selection.fastIterator();
155
            while (feat_iter.hasNext()) {
156
                feat = (Feature) feat_iter.next();
157
                if (!deleteFeature(feat)) {
158
                    return;
159
                }
160
            }
161
        } finally {
162
            if (feat_iter != null) {
163
                feat_iter.dispose();
164
            }
165

    
166
            addTableModelListeners(_ftm, tmll);
167
        }
168
    }
169

    
170
    /**
171
     * @param _ftm
172
     * @param tmll
173
     */
174
    private void addTableModelListeners(
175
            FeatureTableModel _model,
176
            List<TableModelListener> _list) {
177

    
178
        Iterator<TableModelListener> iter = _list.iterator();
179
        while (iter.hasNext()) {
180
            _model.addTableModelListener(iter.next());
181
        }
182
        _model.fireTableDataChanged();
183
    }
184

    
185
    /**
186
     * @param ftm
187
     * @param class1
188
     * @return
189
     */
190
    private List<TableModelListener> removeTableModelListeners(FeatureTableModel ftm) {
191

    
192
        TableModelListener[] ll = ftm.getListeners(TableModelListener.class);
193
        List<TableModelListener> resp = new ArrayList<>();
194

    
195
        int n = ll.length;
196
        for (int i = 0; i < n; i++) {
197
            resp.add(ll[i]);
198
            ftm.removeTableModelListener(ll[i]);
199
        }
200

    
201
        return resp;
202
    }
203

    
204
    public void insertNewFeature() throws DataException {
205
        EditableFeature feature = featureStore.createNewFeature();
206
        insertFeature(feature);
207
    }
208

    
209
    /*
210
     * Return false if the operation is canceled.
211
     */
212
    private boolean insertFeature(EditableFeature feature) throws DataException {
213
        EditingNotificationManager editingNotificationManager = DALSwingLocator.getEditingNotificationManager();
214
        EditingNotification notification = editingNotificationManager.notifyObservers(
215
                this,
216
                EditingNotification.BEFORE_INSERT_FEATURE,
217
                tablePanel.getDocument(),
218
                featureStore,
219
                feature);
220
        if (notification.isCanceled()) {
221
            return false;
222
        }
223
        if (notification.shouldValidateTheFeature()) {
224
            if (!editingNotificationManager.validateFeature(feature)) {
225
                return false;
226
            }
227
        }
228
        featureStore.insert(feature);
229
        editingNotificationManager.notifyObservers(
230
                this,
231
                EditingNotification.AFTER_INSERT_FEATURE,
232
                tablePanel.getDocument(),
233
                featureStore,
234
                feature);
235
        return true;
236
    }
237

    
238
    private boolean deleteFeature(Feature feature) throws DataException {
239
        EditingNotificationManager editingNotification = DALSwingLocator.getEditingNotificationManager();
240
        EditingNotification notification = editingNotification.notifyObservers(
241
                this,
242
                EditingNotification.BEFORE_REMOVE_FEATURE,
243
                tablePanel.getDocument(),
244
                featureStore,
245
                feature);
246
        if (notification.isCanceled()) {
247
            return false;
248
        }
249
        featureStore.delete(feature);
250
        editingNotification.notifyObservers(
251
                this,
252
                EditingNotification.AFTER_REMOVE_FEATURE,
253
                tablePanel.getDocument(),
254
                featureStore,
255
                feature);
256
        return true;
257
    }
258

    
259
    private boolean updateFeatureType(EditableFeatureType featureType) throws DataException {
260

    
261
        EditingNotificationManager editingNotification = DALSwingLocator.getEditingNotificationManager();
262
        EditingNotification notification = editingNotification.notifyObservers(
263
                this,
264
                EditingNotification.BEFORE_UPDATE_FEATURE_TYPE,
265
                tablePanel.getDocument(),
266
                featureStore,
267
                featureType);
268
        if (notification.isCanceled()) {
269
            return false;
270
        }
271
        featureStore.update(featureType);
272
        editingNotification.notifyObservers(
273
                this,
274
                EditingNotification.AFTER_UPDATE_FEATURE_TYPE,
275
                tablePanel.getDocument(),
276
                featureStore,
277
                featureType);
278
        return true;
279
    }
280

    
281
    public void deleteAttributes(FeatureTable table) throws DataException {
282
        EditableFeatureType eft
283
                = featureStore.getDefaultFeatureType().getEditable();
284
        FeatureAttributeDescriptor[] selecteds
285
                = table.getSelectedColumnsAttributeDescriptor();
286
        for (FeatureAttributeDescriptor selected : selecteds) {
287
            eft.remove(selected.getName());
288
        }
289
        featureStore.update(eft);
290
    }
291

    
292
    public void insertAttributes(FeatureTable table) throws DataException {
293

    
294
        EditableFeatureType eft = featureStore.getDefaultFeatureType().getEditable();
295

    
296
        List<String> tmpfnames = new ArrayList<>();
297
        int size = eft.size();
298
        for (int i = 0; i < size; i++) {
299
            FeatureAttributeDescriptor ad = (FeatureAttributeDescriptor) eft.get(i);
300
            tmpfnames.add(ad.getName());
301
        }
302

    
303
        CreateNewAttributePanel panelNewField = new CreateNewAttributePanel(featureStore);
304
        panelNewField.setCurrentFieldNames(tmpfnames.toArray(new String[0]));
305
        DataManager dataManager = DALLocator.getDataManager();
306
        FeatureStoreProviderFactory factory
307
                = (FeatureStoreProviderFactory) dataManager.
308
                        getStoreProviderFactory(featureStore.getProviderName());
309
        panelNewField.setMaxAttributeNameSize(factory.getMaxAttributeNameSize());
310
        panelNewField.setOkAction(new NewFieldActionListener(panelNewField, eft));
311
        ApplicationLocator.getManager().getUIManager().addWindow(panelNewField);
312
        featureStore.update(eft);
313
    }
314

    
315
    public void renameAttributes(FeatureTable table) throws DataException {
316

    
317
        FeatureType _ft = featureStore.getDefaultFeatureType();
318

    
319
        FeatureAttributeDescriptor[] selecteds
320
                = table.getSelectedColumnsAttributeDescriptor();
321

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

    
342
            renameAttribute(featureStore, selecteds[i].getName(), newName);
343
        }
344
    }
345

    
346
    /**
347
     * This method renames a field in three steps:
348
     *
349
     * (1) add new field using type and size of old field. (2) copy value from
350
     * old field to new field. (3) remove old field.
351
     *
352
     * @param fs
353
     * @param name
354
     * @param newName
355
     * @return true if the change took place
356
     */
357
    private static boolean renameAttribute(FeatureStore fs, String name, String newName) {
358

    
359
        EditableFeatureType eft = null;
360
        FeatureType dft = null;
361
        try {
362
            dft = fs.getDefaultFeatureType();
363

    
364
            if (dft instanceof EditableFeatureType) {
365
                eft = (EditableFeatureType) dft;
366
            } else {
367
                eft = dft.getEditable();
368
            }
369

    
370
            EditableFeatureAttributeDescriptor efad
371
                    = (EditableFeatureAttributeDescriptor) eft.getAttributeDescriptor(name);
372
            efad.setName(newName);
373
            fs.update(eft);
374

    
375
        } catch (DataException de) {
376

    
377
            Component root_comp
378
                    = ApplicationLocator.getManager().getRootComponent();
379

    
380
            JOptionPane.showMessageDialog(
381
                    root_comp,
382
                    Messages.getText("_Unable_to_rename_attribute")
383
                    + ": " + de.getMessage(),
384
                    Messages.getText("_Unable_to_rename_attribute"),
385
                    JOptionPane.ERROR_MESSAGE);
386
            return false;
387
        }
388
        return true;
389

    
390
        /*
391
        try {
392
            // ========== add new field
393
            eft = fs.getDefaultFeatureType().getEditable();
394
            FeatureAttributeDescriptor fad = eft.getAttributeDescriptor(name);
395
            eft.add(newName, fad.getType(), fad.getSize());
396
            fs.update(eft);
397
        } catch (DataException ex) {
398
            logger.info("Unable to rename attribute (" + name + " --> " + newName + ")", ex);
399
            ApplicationLocator.getManager().message(
400
                Messages.getText("_Unable_to_rename_attribute"),
401
                JOptionPane.ERROR_MESSAGE);
402
            // did not even add new field
403
            return false;
404
        }
405

406
        boolean error_when_inserting = false;
407
        try {
408
            // ========== copy value old field -> new field
409
            FeatureSet fset = fs.getFeatureSet();
410
            DisposableIterator diter = fset.fastIterator();
411
            Feature feat = null;
412
            Object val = null;
413
            EditableFeature efeat = null;
414
            while (diter.hasNext()) {
415
                feat = (Feature) diter.next();
416
                val = feat.get(name);
417
                efeat = feat.getEditable();
418
                efeat.set(newName, val);
419
                fset.update(efeat);
420
            }
421
            diter.dispose();
422

423
            // Closing editing to check that store admits new field
424
            fs.finishEditing();
425
        } catch (DataException ex) {
426

427
            logger.info("Error while renaming att to: " + newName, ex);
428
            String final_msg = getLastMessage(ex);
429
            JOptionPane.showMessageDialog(
430
                root_comp,
431
                Messages.getText("_Unable_to_rename_attribute")
432
                + ": " + final_msg,
433
                Messages.getText("_Rename_column"),
434
                JOptionPane.ERROR_MESSAGE);
435
            error_when_inserting = true;
436
        }
437

438
        if (error_when_inserting) {
439
            try {
440
                // Trying to remove new field and leave table as it was
441
                eft.remove(newName);
442
                fs.update(eft);
443
            } catch (DataException ex) {
444
                // Unable to remove added field but user was
445
                // already notified that something went wrong
446
            }
447
            // Not changed
448
            return false;
449
        }
450

451

452
        try {
453
            // Finally reopen editing and delete old field
454
            fs.edit(FeatureStore.MODE_FULLEDIT);
455
            eft = fs.getDefaultFeatureType().getEditable();
456
            eft.remove(name);
457
            fs.update(eft);
458

459
        } catch (DataException ex) {
460
            logger.info("Unable to rename attribute (" + name + " --> " + newName + ")", ex);
461
            ApplicationLocator.getManager().message(
462
                Messages.getText("_Unable_to_rename_attribute"),
463
                JOptionPane.ERROR_MESSAGE);
464
            return false;
465
        }
466
        return true;
467
         */
468
    }
469

    
470
    /**
471
     * Renames field in feature store
472
     *
473
     * @param fs
474
     * @param oldname
475
     * @param newname
476
     * @throws DataException
477
     */
478
    public static void renameColumn(FeatureStore fs,
479
            String oldname, String newname) throws DataException {
480

    
481
        FeatureType _ft = fs.getDefaultFeatureType();
482
        if (_ft.getIndex(newname) != -1) {
483
            throw new StoreUpdateFeatureTypeException(
484
                    new Exception("Attribute name already existed."),
485
                    fs.getName());
486
        }
487
        renameAttribute(fs, oldname, newname);
488
        // fs.finishEditing();
489
    }
490

    
491
    public class NewFieldActionListener implements ActionListener {
492

    
493
        private CreateNewAttributePanel panel = null;
494
        private EditableFeatureType eft = null;
495

    
496
        public NewFieldActionListener(CreateNewAttributePanel p, EditableFeatureType t) {
497
            eft = t;
498
            panel = p;
499
        }
500

    
501
        @Override
502
        public void actionPerformed(ActionEvent e) {
503
            try {
504
                EditableFeatureAttributeDescriptor ead = panel.loadFieldDescription(eft);
505
                if (ead == null) {
506
                    return;
507
                }
508
                if (ead.getType() == DataTypes.STRING
509
                        && ead.getSize() > TableOperations.MAX_FIELD_LENGTH) {
510
                    NotificationManager.showMessageInfo(
511
                            PluginServices.getText(this,
512
                                    "max_length_is")
513
                            + ":"
514
                            + TableOperations.MAX_FIELD_LENGTH,
515
                            null);
516
                    ead.setSize(TableOperations.MAX_FIELD_LENGTH);
517
                }
518
                PluginServices.getMDIManager().closeWindow(panel);
519
            } catch (ParseException e2) {
520
                NotificationManager.addError(e2);
521
            }
522

    
523
        }
524

    
525
    }
526

    
527
}