Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.swing / org.gvsig.fmap.dal.swing.impl / src / main / java / org / gvsig / featureform / swing / impl / DefaultJFeaturesForm.java @ 44262

History | View | Annotate | Download (22.8 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2014 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.featureform.swing.impl;
24

    
25
import java.awt.BorderLayout;
26
import java.awt.Dimension;
27
import java.awt.event.ActionEvent;
28
import java.util.ArrayList;
29
import java.util.List;
30
import java.util.logging.Level;
31
import javax.swing.AbstractAction;
32
import javax.swing.Action;
33
import static javax.swing.Action.ACTION_COMMAND_KEY;
34
import static javax.swing.Action.NAME;
35
import static javax.swing.Action.SHORT_DESCRIPTION;
36
import static javax.swing.Action.SMALL_ICON;
37

    
38
import javax.swing.JComponent;
39
import javax.swing.JOptionPane;
40
import javax.swing.JPanel;
41
import org.gvsig.expressionevaluator.Expression;
42
import org.gvsig.expressionevaluator.ExpressionUtils;
43
import org.gvsig.expressionevaluator.swing.JExpressionBuilder;
44

    
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47

    
48
import org.gvsig.featureform.swing.JFeaturesForm;
49
import org.gvsig.fmap.dal.DALLocator;
50
import org.gvsig.fmap.dal.DataManager;
51
import org.gvsig.fmap.dal.DataStore;
52
import org.gvsig.fmap.dal.StoresRepository;
53
import org.gvsig.fmap.dal.exception.DataException;
54
import org.gvsig.fmap.dal.expressionevaluator.ExpressionEvaluator;
55
import org.gvsig.fmap.dal.feature.Feature;
56
import org.gvsig.fmap.dal.feature.FacadeOfAFeature;
57
import org.gvsig.fmap.dal.feature.FeatureQuery;
58
import org.gvsig.fmap.dal.feature.FeatureStore;
59
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
60
import org.gvsig.fmap.dal.feature.FeatureType;
61
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
62
import org.gvsig.fmap.dal.swing.DALSwingLocator;
63
import org.gvsig.fmap.dal.swing.DataSwingManager;
64
import org.gvsig.fmap.dal.swing.impl.DefaultDataSwingManager;
65
import org.gvsig.tools.ToolsLocator;
66
import org.gvsig.tools.dynform.AbortActionException;
67
import org.gvsig.tools.dynform.DynFormDefinition;
68
import org.gvsig.tools.dynform.DynFormLocator;
69
import org.gvsig.tools.dynform.DynFormManager;
70
import org.gvsig.tools.dynform.JDynForm;
71
import org.gvsig.tools.dynform.JDynFormSet;
72
import org.gvsig.tools.dynform.JDynFormSet.JDynFormSetListener;
73
import org.gvsig.tools.dynobject.DynClass;
74
import org.gvsig.tools.dynobject.DynObject;
75
import org.gvsig.tools.evaluator.Evaluator;
76
import org.gvsig.tools.exception.BaseException;
77
import org.gvsig.tools.i18n.I18nManager;
78
import org.gvsig.tools.observer.Observable;
79
import org.gvsig.tools.observer.Observer;
80
import org.gvsig.tools.service.ServiceException;
81
import org.gvsig.tools.swing.api.ToolsSwingLocator;
82
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
83
import org.gvsig.tools.swing.api.windowmanager.Dialog;
84
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
85
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
86
import org.gvsig.tools.swing.api.windowmanager.WindowManager.MODE;
87
import org.gvsig.tools.swing.icontheme.IconTheme;
88
import org.gvsig.tools.util.ResourcesStorage;
89

    
90
/**
91
 * @author fdiaz
92
 *
93
 */
94
@SuppressWarnings("UseSpecificCatch")
95
public class DefaultJFeaturesForm implements JFeaturesForm {
96

    
97
    public class DefaultFeaturesFormContext implements FeaturesFormContext {
98

    
99
        private DefaultFeaturesFormContext() {
100
            
101
        }
102

    
103
        public FeatureStore getFeatureStore() {
104
            return store;
105
        }
106
        
107
        public FeatureType getFeatureType() {
108
            try {
109
                return store.getDefaultFeatureType();
110
            } catch (DataException ex) {
111
                return null;
112
            }
113
        }
114
        
115
        @Override
116
        public ResourcesStorage getResourcesStorage() {
117
            return store.getResourcesStorage();
118
        }
119

    
120
        @Override
121
        public StoresRepository getStoresRepository() {
122
            return store.getStoresRepository();
123
        }
124
        
125
    }
126
    
127
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJFeaturesForm.class);
128

    
129
    private static final int PAGE_SIZE = 500;
130
    private final JPanel panel;
131
    private JDynFormSet formset;
132
    private FeatureStore store;
133
    private FeaturePagingHelper ph;
134
    private DynFormDefinition definition = null;
135
    private FeatureQuery currentQuery;
136
    private final List<Action> otherActions;
137

    
138
    public DefaultJFeaturesForm() {
139
        this.panel = new JPanel(new BorderLayout());
140
        this.otherActions = new ArrayList<>();
141
    }
142

    
143
    @Override
144
    public void setPreferredSize(Dimension dimension) {
145
//        panel.setPreferredSize(dimension);
146
    }
147

    
148
    private void updateForm() {
149
        if (this.formset == null) {
150
            this.panel.add(this.getFormset().asJComponent(), BorderLayout.CENTER);
151
        }
152
        try {
153
            this.ph = DALLocator.getDataManager().createFeaturePagingHelper(store, this.currentQuery, PAGE_SIZE);
154
            this.formset.setValues(ph.asListOfDynObjects());
155
        } catch (Exception ex) {
156
            throw new RuntimeException("Can't update form", ex);
157
        }
158
    }
159

    
160
    @Override
161
    public JComponent asJComponent() {
162
        if (this.ph == null) {
163
            try {
164
                updateForm();
165
            } catch (Exception ex) {
166
                throw new RuntimeException(ex);
167
            }
168
        }
169
        return this.panel;
170
    }
171

    
172
    @Override
173
    public void bind(FeatureStore store) {
174
        if (store == null) {
175
            throw new IllegalArgumentException("bind need a store as parameter, not a null.");
176
        }
177
        try {
178
            DefaultDataSwingManager manager = (DefaultDataSwingManager) DALSwingLocator.getSwingManager();
179
            DynClass theDefinition = manager.featureType2DynClass(store, store.getDefaultFeatureType());
180
            this.bind(store, theDefinition);
181
        } catch (Exception ex) {
182
            throw new RuntimeException("Can't bind store '" + store.getName() + "' to form", ex);
183
        }
184
    }
185

    
186
    public void bind(FeatureStore store, DynClass definition) throws ServiceException, DataException {
187
        if (this.store == store) {
188
            return;
189
        }
190
        DynFormManager formManager = DynFormLocator.getDynFormManager();
191
        this.definition = formManager.getDefinition(definition);
192
        if (formset != null) {
193
            this.panel.remove(formset.asJComponent());
194
            this.formset = null;
195
        }
196
        this.store = store;
197
        this.ph = null;
198

    
199
    }
200

    
201
    @Override
202
    public JDynFormSet getFormset() {
203
        if (this.formset == null) {
204
            DynFormManager formManager = DynFormLocator.getDynFormManager();
205
            this.formset = formManager.createJDynFormSet(
206
                    new DefaultFeaturesFormContext(),
207
                    this.definition,
208
                    null
209
            );
210
            List<String> groups = this.definition.getGroups();
211
            if( groups.size()==1 && groups.get(0)==null ) {
212
                this.formset.setLayoutMode(JDynForm.USE_PLAIN);
213
            } else {
214
                this.formset.setLayoutMode(JDynForm.USE_TABS);
215
            }
216
            this.formset.setAllowNew(true);
217
            this.formset.setAllowDelete(true);
218
            this.formset.setAllowUpdate(true);
219
            this.formset.setAllowClose(true);
220
            this.formset.setAllowSearch(true);
221
            this.formset.setAutosave(true);
222

    
223
            this.formset.addAction(new StartEditingAction());
224
            this.formset.addAction(new FinishEditingAction());
225
            for( Action action : this.otherActions ) {
226
                this.formset.addAction(action);
227
            }
228

    
229
            this.formset.addListener(new FormSetListener());
230
        }
231
        if( this.store.isEditing() ) {
232
            this.formset.setReadOnly(false);
233
            formset.setActionVisible("startEditing", false);
234
            formset.setActionEnabled("startEditing", false);
235
            formset.setActionVisible("finishEditing", true);
236
            formset.setActionEnabled("finishEditing", true);
237
        } else {
238
            this.formset.setReadOnly(true);
239
            formset.setActionVisible("startEditing", true);
240
            formset.setActionEnabled("startEditing", true);
241
            formset.setActionVisible("finishEditing", false);
242
            formset.setActionEnabled("finishEditing", false);
243
        }
244
        return this.formset;
245
    }
246

    
247
    @Override
248
    public void addAction(Action action) {
249
        this.otherActions.add(action);
250
        if( this.formset!=null ) {
251
            this.formset.addAction(action);
252
        }
253
    }
254

    
255
    @Override
256
    public long getCurrentIndex() {
257
        if( this.formset==null ) {
258
            return -1;
259
        }
260
        return this.formset.getCurrentIndex();
261
    }
262

    
263
    @Override
264
    public Feature get(long index) {
265
        if( this.formset==null || this.ph==null ) {
266
            return null;
267
        }
268
        try {
269
            return this.ph.getFeatureAt(index);
270
        } catch (BaseException ex) {
271
            return null;
272
        }
273
    }
274

    
275
    private class FinishEditingAction extends AbstractAction implements Observer {
276

    
277
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
278
        public FinishEditingAction() {
279
            I18nManager i18nManager = ToolsLocator.getI18nManager();
280
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
281

    
282
            this.putValue(NAME,null);
283
            this.putValue(SHORT_DESCRIPTION,i18nManager.getTranslation("_Stop_editing"));
284
            this.putValue(SMALL_ICON, iconTheme.get("table-stop-editing"));
285
            this.putValue(ACTION_COMMAND_KEY, "finishEditing");
286

    
287
            this.setEnabled(store.isEditing());
288
            store.addObserver(this);
289
        }
290

    
291
        @Override
292
        public void actionPerformed(ActionEvent ae) {
293
            if( store.isEditing() ) {
294
                try {
295
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
296
                    ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
297
                    int x = dialogManager.confirmDialog(
298
                            "? Desea terminar edicion y guardar los cambios ?\n\nPulse cancelar para cancelar la edicion y los cambios.",
299
                            i18nManager.getTranslation("_Stop_editing"),
300
                            JOptionPane.YES_NO_CANCEL_OPTION,
301
                            JOptionPane.QUESTION_MESSAGE
302
                    );
303
                    switch(x) {
304
                        case JOptionPane.YES_OPTION:
305
                            store.finishEditing();
306
                            break;
307
                        case JOptionPane.NO_OPTION:
308
                            break;
309
                        case JOptionPane.CANCEL_OPTION:
310
                            store.cancelEditing();
311
                            break;
312
                    }
313
                } catch (DataException ex) {
314
                    LOGGER.warn("Can't finish editing in FeatureForm ("+store.getName()+").",ex);
315
                }
316
            }
317
        }
318

    
319
        @Override
320
        public void update(Observable observable, Object notification) {
321
            if( notification instanceof FeatureStoreNotification ) {
322
                FeatureStoreNotification n =  (FeatureStoreNotification) notification;
323
                switch( n.getType() )  {
324
                    case FeatureStoreNotification.AFTER_STARTEDITING:
325
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
326
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
327
                        if( store.isEditing() ) {
328
                            formset.setReadOnly(false);
329
                            formset.setActionVisible("finishEditing", true);
330
                            formset.setActionEnabled("finishEditing", true);
331
                        } else {
332
                            formset.setReadOnly(true);
333
                            formset.setActionVisible("finishEditing", false);
334
                            formset.setActionEnabled("finishEditing", false);
335
                        }
336
                        break;
337
                }
338
            }
339
        }
340

    
341
    }
342

    
343
    private class StartEditingAction extends AbstractAction implements Observer {
344

    
345
        @SuppressWarnings({"OverridableMethodCallInConstructor", "LeakingThisInConstructor"})
346
        public StartEditingAction() {
347
            I18nManager i18nManager = ToolsLocator.getI18nManager();
348
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getDefault();
349

    
350
            this.putValue(NAME,null);
351
            this.putValue(SHORT_DESCRIPTION,i18nManager.getTranslation("_Start_editing"));
352
            this.putValue(SMALL_ICON, iconTheme.get("table-start-editing"));
353
            this.putValue(ACTION_COMMAND_KEY, "startEditing");
354

    
355
            this.setEnabled(!store.isEditing());
356
            store.addObserver(this);
357
        }
358

    
359
        @Override
360
        public void actionPerformed(ActionEvent ae) {
361
            if( !store.isEditing() ) {
362
                try {
363
                    store.edit();
364
                } catch (DataException ex) {
365
                    LOGGER.warn("Can't finish editing in FeatureForm ("+store.getName()+").",ex);
366
                }
367
            }
368
        }
369

    
370
        @Override
371
        public void update(Observable observable, Object notification) {
372
            if( notification instanceof FeatureStoreNotification ) {
373
                FeatureStoreNotification n =  (FeatureStoreNotification) notification;
374
                switch( n.getType() )  {
375
                    case FeatureStoreNotification.AFTER_STARTEDITING:
376
                    case FeatureStoreNotification.AFTER_FINISHEDITING:
377
                    case FeatureStoreNotification.AFTER_CANCELEDITING:
378
                        if( store.isEditing() ) {
379
                            formset.setReadOnly(false);
380
                            formset.setActionVisible("startEditing", false);
381
                            formset.setActionEnabled("startEditing", false);
382
                        } else {
383
                            formset.setReadOnly(true);
384
                            formset.setActionVisible("startEditing", true);
385
                            formset.setActionEnabled("startEditing", true);
386
                        }
387
                        break;
388
                }
389
            }
390
        }
391

    
392
    }
393

    
394
    @Override
395
    public void setQuery(FeatureQuery query) {
396
        if (this.ph != null) {
397
            if (this.formset != null && !formset.isReadOnly() && this.formset.isAutosave() && this.formset.countValues() > 0) {
398
                if (!store.isEditing()) {
399
                    try {
400
                        store.edit();
401
                    } catch (DataException e1) {
402
                        throw new RuntimeException("Can't set query", e1);
403
                    }
404
                }
405
                saveChanges(this.formset);
406
            }
407
        }
408
        this.currentQuery = query;
409
        updateForm();
410
    }
411

    
412
    private FeatureQuery getCurrentQuery() {
413
        return this.currentQuery;
414
    }
415
    
416
    @Override
417
    public void showForm(MODE mode) {
418
        this.panel.add(this.getFormset().asJComponent(), BorderLayout.CENTER);
419
        WindowManager winmgr = ToolsSwingLocator.getWindowManager();
420
        String title = this.definition.getLabel();
421
        winmgr.showWindow(this.asJComponent(), title, mode);
422
    }
423

    
424
    private void saveChanges(JDynFormSet dynformSet) {
425
        if( dynformSet.isInNewState() ) {
426
            Feature feat = null;
427
            try {
428
                feat = store.createNewFeature(false);
429
            } catch (DataException ex) {
430
                LOGGER.warn("Can't create new feature.",ex);
431
                I18nManager i18nManager = ToolsLocator.getI18nManager();
432
                dynformSet.message(i18nManager.getTranslation("error_saving_data_will_not_save"));
433
                throw new RuntimeException("Can't new save values");
434
            }
435
            DynObject dynObject = feat.getAsDynObject();
436
            dynformSet.getFormValues(dynObject);
437
            try {
438
                ph.insert(((FacadeOfAFeature)dynObject).getEditableFeature());
439
            } catch (BaseException e) {
440
                throw new RuntimeException("Can't save values", e);
441
            }
442
            try {
443
                this.formset.setValues(ph.asListOfDynObjects());
444
                this.formset.setCurrentIndex((int)(ph.getTotalSize())-1);
445
            } catch(Exception ex) {
446
                LOGGER.warn("Can't reload form data after insert.",ex);
447
            }
448
        } else {
449
            int index = dynformSet.getCurrentIndex();
450
            DynObject dynObject = dynformSet.get(index);
451

    
452
            if ( !(dynObject instanceof FacadeOfAFeature) ) {
453
                LOGGER.warn("Can't get the associated feature index " + index);
454
                I18nManager i18nManager = ToolsLocator.getI18nManager();
455
                dynformSet.message(i18nManager.getTranslation("error_saving_data_will_not_save"));
456
                throw new RuntimeException("Can't save values");
457
            }
458
            dynformSet.getFormValues(dynObject);
459
            try {
460
                ph.update(((FacadeOfAFeature)dynObject).getEditableFeature());
461
            } catch (BaseException e) {
462
                throw new RuntimeException("Can't save values", e);
463
            }
464
        }
465

    
466
    }
467

    
468
    @Override
469
    public void saveChanges() {
470
        if (this.formset != null && this.formset.countValues() > 0) {
471
            if (store != null && !store.isEditing()) {
472
                try {
473
                    store.edit();
474
                } catch (DataException e1) {
475
                    LOGGER.warn("Can't edit the store " + store.getName());
476
                    throw new RuntimeException("Can't save changes.", e1);
477
                }
478
            }
479
            this.saveChanges(this.formset);
480
        }
481
    }
482

    
483
    @Override
484
    public long getDataSetSize() {
485
        if (this.ph != null) {
486
            return ph.getTotalSize();
487
        }
488
        return 0;
489
    }
490

    
491
    @Override
492
    public FeatureStore getFeatureStore() {
493
        return this.store;
494
    }
495

    
496
    private class FormSetListener implements JDynFormSetListener {
497

    
498
        @Override
499
        public void formMessage(String message) {
500
        }
501

    
502
        @Override
503
        public void formClose() {
504
            panel.setVisible(false);
505
        }
506

    
507
        @Override
508
        public void formMovedTo(int currentPosition) throws AbortActionException {
509
            LOGGER.trace("formMovedTo " + currentPosition);
510
        }
511

    
512
        @Override
513
        public void formBeforeSave(JDynFormSet dynformSet) throws AbortActionException {
514
            LOGGER.trace("formBeforeSave");
515
            if (!store.isEditing()) {
516
                try {
517
                    store.edit();
518
                } catch (DataException e1) {
519
                    throw new StoreEditException(e1, store.getName());
520
                }
521
            }
522
        }
523

    
524
        @Override
525
        public void formBeforeNew(JDynFormSet dynformSet) throws AbortActionException {
526
            LOGGER.trace("formBeforeNew");
527
        }
528

    
529
        @Override
530
        public void formBeforeDelete(JDynFormSet dynformSet) throws AbortActionException {
531
            LOGGER.trace("formBeforeDelete");
532
        }
533

    
534
        @Override
535
        public void formAfterSave(JDynFormSet dynformSet) throws AbortActionException {
536
            LOGGER.trace("formAfterSave");
537
            saveChanges(dynformSet);
538
        }
539

    
540
        @Override
541
        public void formAfterNew(JDynFormSet dynformSet) throws AbortActionException {
542
            LOGGER.trace("formAfterNew");
543
        }
544

    
545
        @Override
546
        public void formAfterDelete(JDynFormSet dynformSet) throws AbortActionException {
547
            LOGGER.trace("formAfterDelete");
548
        }
549

    
550
        @Override
551
        public void formBeforeSearch(JDynFormSet dynformSet) throws AbortActionException {
552
            LOGGER.trace("formBeforeSearch");
553
            DataSwingManager dataSwingmanager = DALSwingLocator.getSwingManager();
554
            WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
555

    
556
            JExpressionBuilder builder = dataSwingmanager.createQueryFilterExpresion(store);
557
            FeatureQuery currentQuery = getCurrentQuery();
558
            if( currentQuery!=null ) {
559
                Evaluator filter = currentQuery.getFilter();
560
                if( filter instanceof ExpressionEvaluator ) {
561
                    Expression expression = ((ExpressionEvaluator)filter).getExpression();
562
                    builder.setExpression(expression);
563
                }
564
            }
565
            Dialog dialog = winmgr.createDialog(
566
                    builder.asJComponent(),
567
                    "Filtro",
568
                    "Creacion de filtro sobre '"+store.getName()+"'",
569
                    WindowManager_v2.BUTTONS_OK_CANCEL
570
            );
571
            dialog.show(WindowManager.MODE.DIALOG);
572
            if( dialog.getAction() == WindowManager_v2.BUTTON_OK ) {
573
                Expression expresion = builder.getExpression();
574
                try {
575
                    FeatureQuery query = store.createFeatureQuery();
576
                    if( ExpressionUtils.isPhraseEmpty(expresion) ) {
577
                        query.clearFilter();
578
                    } else {
579
                        query.setFilter(expresion);
580
                    }
581
                    setQuery(query);
582
                } catch (Exception ex) {
583
                    LOGGER.warn("Can't apply filter '" + expresion + "'.", ex);
584
                }
585
            }
586
        }
587

    
588
        @Override
589
        public void formAfterSearch(JDynFormSet dynformSet) throws AbortActionException {
590
            LOGGER.trace("formAfterSearch");
591
        }
592

    
593
        @Override
594
        public void formBeforeCancelNew(JDynFormSet dynformSet) throws AbortActionException {
595
            LOGGER.trace("formBeforeCancelNew");
596
        }
597

    
598
        @Override
599
        public void formAfterCancelNew(JDynFormSet dynformSet) throws AbortActionException {
600
            LOGGER.trace("formAfterCancelNew");
601
        }
602
    }
603

    
604
    private static class StoreEditException extends AbortActionException {
605

    
606
        /**
607
         *
608
         */
609
        private static final long serialVersionUID = -7682017811778577130L;
610

    
611
        public StoreEditException(Throwable cause, String storename) {
612
            super("Can't edit the store '%(storename)'", cause, "cant_edit_the store_XstorenameX", serialVersionUID);
613
            setValue("storename", storename);
614
        }
615
    }
616
}