Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.swing / org.gvsig.vectorediting.swing.impl / src / main / java / org / gvsig / vectorediting / swing / impl / DefaultEditingContext.java @ 1143

History | View | Annotate | Download (41 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 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 2
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

    
25
package org.gvsig.vectorediting.swing.impl;
26

    
27
import java.awt.BorderLayout;
28
import java.awt.Component;
29
import java.lang.ref.WeakReference;
30
import java.lang.reflect.InvocationTargetException;
31
import java.util.ArrayList;
32
import java.util.Set;
33
import java.util.Stack;
34
import java.util.logging.Level;
35
import java.util.prefs.PreferenceChangeEvent;
36
import java.util.prefs.PreferenceChangeListener;
37
import java.util.prefs.Preferences;
38

    
39
import javax.swing.JComponent;
40
import javax.swing.SwingUtilities;
41

    
42
import org.gvsig.fmap.dal.exception.DataException;
43
import org.gvsig.fmap.dal.feature.FeatureSelection;
44
import org.gvsig.fmap.dal.feature.FeatureStore;
45
import org.gvsig.fmap.geom.Geometry;
46
import org.gvsig.fmap.geom.GeometryLocator;
47
import org.gvsig.fmap.geom.GeometryManager;
48
import org.gvsig.fmap.geom.primitive.Point;
49
import org.gvsig.fmap.geom.type.GeometryType;
50
import org.gvsig.fmap.mapcontext.MapContext;
51
import org.gvsig.fmap.mapcontext.layers.CancelationException;
52
import org.gvsig.fmap.mapcontext.layers.FLayer;
53
import org.gvsig.fmap.mapcontext.layers.FLayers;
54
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
55
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
56
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
57
import org.gvsig.fmap.mapcontext.layers.LayerListener;
58
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
59
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
60
import org.gvsig.fmap.mapcontrol.MapControl;
61
import org.gvsig.fmap.mapcontrol.tools.CompoundBehavior;
62
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
63
import org.gvsig.tools.ToolsLocator;
64
import org.gvsig.tools.i18n.I18nManager;
65
import org.gvsig.tools.observer.BaseNotification;
66
import org.gvsig.tools.observer.Notification;
67
import org.gvsig.tools.observer.ObservableHelper;
68
import org.gvsig.tools.observer.Observer;
69
import org.gvsig.utils.console.JDockPanel;
70
import org.gvsig.utils.console.ResponseListener;
71
import org.gvsig.vectorediting.lib.api.EditingLocator;
72
import org.gvsig.vectorediting.lib.api.EditingManager;
73
import org.gvsig.vectorediting.lib.api.EditingService;
74
import org.gvsig.vectorediting.lib.api.EditingServiceInfo;
75
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
76
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
77
import org.gvsig.vectorediting.lib.api.exceptions.CreateEditingBehaviorException;
78
import org.gvsig.vectorediting.lib.api.exceptions.EndEditingException;
79
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
80
import org.gvsig.vectorediting.lib.api.exceptions.ParsePointException;
81
import org.gvsig.vectorediting.lib.api.exceptions.ParseValueException;
82
import org.gvsig.vectorediting.lib.api.exceptions.ServiceInformationException;
83
import org.gvsig.vectorediting.lib.api.exceptions.StartEditingException;
84
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
85
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
86
import org.gvsig.vectorediting.lib.api.exceptions.VectorEditingException;
87
import org.gvsig.vectorediting.swing.api.EditingContext;
88
import org.gvsig.vectorediting.swing.api.EditingSwingLocator;
89
import org.gvsig.vectorediting.swing.api.EditingSwingManager;
90
import org.gvsig.vectorediting.swing.api.console.EditingConsole;
91
import org.gvsig.vectorediting.swing.impl.console.DefaultEditingConsole;
92

    
93
import org.apache.commons.lang3.StringUtils;
94

    
95
import org.gvsig.fmap.dal.EditingNotification;
96
import org.gvsig.fmap.dal.EditingNotificationManager;
97
import org.gvsig.fmap.dal.swing.DALSwingLocator;
98

    
99
import org.slf4j.Logger;
100
import org.slf4j.LoggerFactory;
101

    
102
public class DefaultEditingContext implements EditingContext {
103

    
104
    private static final Logger logger = LoggerFactory
105
        .getLogger(EditingManager.class);
106

    
107
    private WeakReference<MapControl> mapControlReference;
108

    
109
    private WeakReference<MapContext> mapContextReference;
110

    
111
    private EditingCompoundBehavior editingCompoundBehavior;
112

    
113
    private Behavior[] lastAdditionalBehaviors;
114

    
115
    private ObservableHelper observableHelper;
116

    
117
    private EditingConsole console;
118

    
119
    private JDockPanel dockConsole = null;
120

    
121
    private boolean isShowConsole = false;
122

    
123
    private Stack<EditingService> serviceStack;
124

    
125
    private FLyrVect currentLayer;
126

    
127
    private EditingServiceParameter currentParam;
128

    
129
    private Behavior[] defaultBehaviors;
130

    
131
    private LayerListener layerListener = new LayerListener() {
132

    
133
        @Override
134
        public void activationChanged(final LayerEvent e) {
135
            if( !SwingUtilities.isEventDispatchThread() ) {
136
                SwingUtilities.invokeLater(new Runnable() {
137

    
138
                    @Override
139
                    public void run() {
140
                        activationChanged(e);
141
                    }
142
                });
143
                return;
144
            }
145

    
146
            FLayer layer = e.getSource();
147

    
148
            FLayer[] activeLayers =
149
                layer.getMapContext().getLayers().getActives();
150

    
151
            if ((activeLayers.length == 1) && (layer instanceof FLyrVect)) {
152
                if (layer.isActive() && layer.isEditing()) {
153
                    getMapControl().setTool("VectorEditing");
154
                    setCurrentLayer((FLyrVect) layer);
155
                    showConsole();
156
                    return;
157
                }
158
            }
159

    
160
            hideConsole();
161
            if ((getMapControl().getCurrentTool() != null)
162
                && getMapControl().getCurrentTool().equals("VectorEditing")) {
163
                getMapControl().setPrevTool();
164
            }
165
        }
166

    
167
        public void drawValueChanged(LayerEvent e) {
168
        }
169

    
170
        @Override
171
        public void editionChanged(final LayerEvent e) {
172
            if( !SwingUtilities.isEventDispatchThread() ) {
173
                SwingUtilities.invokeLater(new Runnable() {
174

    
175
                    @Override
176
                    public void run() {
177
                        editionChanged(e);
178
                    }
179
                });
180
                return;
181
            }
182
            FLayer layer = e.getSource();
183

    
184
            if (layer instanceof FLyrVect) {
185
                if (layer.isEditing()) {
186
                    synchronized (DefaultEditingContext.this) {
187
                        beginEdition((FLyrVect) layer);
188
                        showConsole();
189
                    }
190
                } else {
191
                    hideConsole();
192
                }
193
            }
194

    
195
        }
196

    
197
        public void nameChanged(LayerEvent e) {
198
        }
199

    
200
        public void visibilityChanged(LayerEvent e) {
201
        }
202
    };
203

    
204
    private PreferenceChangeListener preferenceChangeListener =
205
        new PreferenceChangeListener() {
206

    
207
            public void preferenceChange(PreferenceChangeEvent evt) {
208
                String key = evt.getKey();
209
                if (key.equalsIgnoreCase("apply-snappers")) {
210
                    boolean newValue = Boolean.parseBoolean(evt.getNewValue());
211
                    getMapControl().setRefentEnabled(newValue);
212
                }
213
            }
214
        };
215

    
216
    public DefaultEditingContext(MapControl mapControl) {
217

    
218
        this.mapControlReference = new WeakReference<MapControl>(mapControl);
219
        this.mapContextReference =
220
            new WeakReference<MapContext>(mapControl.getMapContext());
221
        this.observableHelper = new ObservableHelper();
222

    
223
        this.serviceStack = new Stack<EditingService>();
224

    
225
        addLayerListeners();
226
        addPreferenceListener();
227
    }
228

    
229
    private void addPreferenceListener() {
230
        Preferences prefs = Preferences.userRoot().node("snappers");
231
        prefs.addPreferenceChangeListener(preferenceChangeListener);
232
    }
233

    
234
    public void activateService(String name) {
235

    
236
        if ((getMapControl() != null)
237
            && getMapControl().hasTool("VectorEditing")) {
238

    
239
            CompoundBehavior editingCompoundBehavior =
240
                getEditingCompoundBehavior();
241
            getMapControl().setTool("VectorEditing");
242
            editingCompoundBehavior.setDrawnBehavior(
243
                EditingCompoundBehavior.EDITING_INDEX, true);
244

    
245
            EditingManager manager = EditingLocator.getManager();
246

    
247
            if (currentLayer != null) {
248

    
249
                EditingService service =
250
                    manager.getEditingService(name,
251
                        currentLayer.getFeatureStore(),
252
                        mapContextReference.get());
253

    
254
                if (service != null) {
255

    
256
                    this.enableSelection(false);
257

    
258
                    try {
259
                        service.start();
260
                    } catch (StartServiceException e) {
261

    
262
                        logger.info(String.format(
263
                            "Can't start the service %1$s", service.getName()),
264
                            e);
265
                        cleanEditingContext();
266
                        return;
267

    
268
                    } catch (InvalidEntryException e) {
269

    
270
                        I18nManager i18nManager = ToolsLocator.getI18nManager();
271
                        showConsoleMessage("\n"
272
                            + i18nManager.getTranslation("invalid_option"));
273
                    }
274

    
275
                    if (!serviceStack.isEmpty()
276
                        && !getActiveService().next().getTypes()
277
                            .contains(TYPE.GEOMETRY)) {
278
                        serviceStack.pop();
279
                    }
280

    
281
                    setActiveService(service);
282

    
283
                    getNextParameter();
284
                }
285
            }
286
        }
287
    }
288

    
289
    private void addBehaviors(Behavior[] additionalBehavior)
290
        throws CreateEditingBehaviorException {
291

    
292
        DefaultEditingBehavior editingBehavior;
293
        EditingCompoundBehavior editingCompoundBehavior;
294

    
295
        if (!getMapControl().hasTool("VectorEditing")) {
296

    
297
            editingBehavior = new DefaultEditingBehavior(this);
298
            editingCompoundBehavior =
299
                new EditingCompoundBehavior(editingBehavior);
300
            setCompoundBehavior(editingCompoundBehavior);
301

    
302
            if (additionalBehavior != null) {
303

    
304
                Behavior[] behaviors =
305
                    new Behavior[additionalBehavior.length + 1];
306
                behaviors[0] = editingCompoundBehavior;
307

    
308
                for (int i = 0; i < additionalBehavior.length; i++) {
309
                    behaviors[i + 1] = additionalBehavior[i];
310
                }
311

    
312
                getMapControl().addBehavior("VectorEditing", behaviors);
313

    
314
                lastAdditionalBehaviors = additionalBehavior;
315

    
316
            } else {
317
                getMapControl().addBehavior("VectorEditing",
318
                    editingCompoundBehavior);
319
            }
320

    
321
        } else {
322
            editingCompoundBehavior = getEditingCompoundBehavior();
323
            editingBehavior =
324
                (DefaultEditingBehavior) editingCompoundBehavior
325
                    .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
326
            setCompoundBehavior(editingCompoundBehavior);
327
            cleanEditingContext();
328
        }
329

    
330
    }
331

    
332
    private void addLayerListeners() {
333

    
334
        FLayers layers = mapContextReference.get().getLayers();
335

    
336
        layers.addLayerListener(layerListener);
337

    
338
        layers.addLayerCollectionListener(new LayerCollectionListener() {
339

    
340
            public void addLayer(FLayer layer) {
341
                if (layer instanceof FLayers) {
342
                    FLayers layers = (FLayers) layer;
343
                    for (int i = 0; i < layers.getLayersCount(); i++) {
344
                        addLayer(layers.getLayer(i));
345
                    }
346
                } else if (layer instanceof FLyrVect) {
347
                    ((FLyrVect) layer).addLayerListener(layerListener);
348
                }
349
            }
350

    
351
            public void layerAdded(LayerCollectionEvent e) {
352
                addLayer(e.getLayers());
353
            }
354

    
355
            public void layerAdding(LayerCollectionEvent e)
356
                throws CancelationException {
357
            }
358

    
359
            public void layerMoved(LayerPositionEvent e) {
360
            }
361

    
362
            public void layerMoving(LayerPositionEvent e)
363
                throws CancelationException {
364
            }
365

    
366
            public void removeLayer(FLayer layer) {
367
                if (layer instanceof FLayers) {
368
                    FLayers layers = (FLayers) layer;
369
                    for (int i = 0; i < layers.getLayersCount(); i++) {
370
                        addLayer(layers.getLayer(i));
371
                    }
372
                } else if (layer instanceof FLyrVect) {
373
                    ((FLyrVect) layer).removeLayerListener(layerListener);
374
                }
375
            }
376

    
377
            public void layerRemoved(LayerCollectionEvent e) {
378
                removeLayer(e.getLayers());
379
            }
380

    
381
            public void layerRemoving(LayerCollectionEvent e)
382
                throws CancelationException {
383
            }
384

    
385
            public void visibilityChanged(LayerCollectionEvent e)
386
                throws CancelationException {
387
            }
388
        });
389
    }
390

    
391
    public void addObserver(Observer o) {
392
        this.observableHelper.addObserver(o);
393
    }
394

    
395
    private void askQuestion(EditingServiceParameter param) {
396
        I18nManager i18nManager = ToolsLocator.getI18nManager();
397
        String translation = i18nManager.getTranslation(param.getDescription());
398
        String activeServiceName =
399
            i18nManager.getTranslation(getActiveService().getName());
400

    
401
        Object defaultValue = param.getDefaultValue();
402
        String strDefaultValue;
403

    
404
        if (defaultValue != null) {
405
            if (defaultValue instanceof String) {
406
                strDefaultValue = (String) defaultValue;
407
                strDefaultValue =
408
                    i18nManager.getTranslation((String) defaultValue);
409
            } else {
410
                if(defaultValue instanceof Point){
411
                    Point point = (Point)defaultValue;
412
                    StringBuilder builder = new StringBuilder();
413
                    for(int i=0; i<point.getDimension(); i++){
414
                        builder.append(point.getCoordinateAt(i));
415
                        if(i < point.getDimension()-1){
416
                            builder.append(" , ");
417
                        }
418
                    }
419
                    strDefaultValue = builder.toString();
420
                } else {
421
                    strDefaultValue = defaultValue.toString();
422
                }
423
            }
424
            showConsoleMessage("\n" + activeServiceName + "# " + translation
425
                + "<" + strDefaultValue + "> : ");
426
        } else {
427
            showConsoleMessage("\n" + activeServiceName + "# " + translation
428
                + " : ");
429
        }
430
    }
431

    
432
    public synchronized void beginEdition(FLyrVect layer,
433
        Behavior[] additionalBehaviors) {
434

    
435
        try{
436
            throw new Exception("Deprecated method");
437
        } catch (Exception e){
438
            logger.info("Deprecated method", e);
439
        }
440

    
441
        beginEdition(layer);
442
        try {
443
            addBehaviors(additionalBehaviors);
444
        } catch (CreateEditingBehaviorException e1) {
445
            logger.info("Problems adding behaviors to editing context", e1);
446
            getMapControl().setTool("pan");
447
            return;
448
        }
449
    }
450

    
451
    public synchronized void beginEdition(FLyrVect layer) {
452

    
453
        EditingNotificationManager editingNotificationManager =
454
            DALSwingLocator.getEditingNotificationManager();
455

    
456
        EditingNotification notification =
457
            editingNotificationManager.notifyObservers(this,
458
                EditingNotification.BEFORE_ENTER_EDITING_STORE, null, layer,layer.getFeatureStore());
459

    
460
        if (notification.isCanceled()) {
461
            String msg =
462
                String.format("Edit layer %1$s canceled by somme observer.",
463
                    layer.getName());
464
            logger.info(msg, new StartEditingException(msg, null));
465
            return;
466
        }
467

    
468
        setCurrentLayer(layer);
469

    
470
        FeatureStore featureStore = layer.getFeatureStore();
471
        if (!featureStore.isEditing()) {
472
            try {
473
                featureStore.edit();
474
            } catch (Exception e) {
475
                String msg =
476
                    String.format("Can't set %1$s in edit mode",
477
                        featureStore.getName());
478
                logger.info(msg, new VectorEditingException(e));
479
                cleanEditingContext();
480
                return;
481
            }
482
        }
483

    
484
        featureStore.addObserver(getMapControl());
485

    
486
        editingNotificationManager.notifyObservers(this,
487
            EditingNotification.AFTER_ENTER_EDITING_STORE, null, layer, layer.getFeatureStore());
488

    
489
        enableSnapping();
490
    }
491

    
492
    @SuppressWarnings({ "rawtypes", "unchecked" })
493
    private void enableSnapping() {
494
        Preferences prefs = Preferences.userRoot().node("snappers");
495
         getMapControl().setRefentEnabled(prefs.getBoolean("apply-snappers", false));
496
         if (currentLayer != null) {
497
            ArrayList layersToSnap =
498
                getMapControl().getMapContext().getLayersToSnap();
499
            if (!layersToSnap.contains(currentLayer)) {
500
                layersToSnap.add(currentLayer);
501
            }
502
        }
503
    }
504

    
505
    @SuppressWarnings("rawtypes")
506
    private void disableSnapping() {
507
        ArrayList layersToSnap =
508
            getMapControl().getMapContext().getLayersToSnap();
509
        if (layersToSnap.contains(currentLayer)) {
510
            layersToSnap.remove(currentLayer);
511
        }
512
    }
513

    
514
    private void changeSelectedTool(String name) {
515
        if (name.equalsIgnoreCase(DEFAULT_TOOL)) {
516
            name = "selection-simple-select-view";
517
            this.getMapControl().setTool("pointSelection");
518
        }
519
        Notification notification =
520
            new BaseNotification(
521
                EditingContext.CHANGE_SELECTED_TOOL_NOTIFICATION,
522
                new Object[] { name });
523
        this.observableHelper.notifyObservers(this, notification);
524
    }
525

    
526
    private void cleanEditingContext() {
527
        serviceStack.clear();
528
        currentParam = null;
529
        this.enableSelection(false);
530
        refreshMenusAndToolBars();
531

    
532
        I18nManager i18nManager = ToolsLocator.getI18nManager();
533
        showConsoleMessage("\n" + i18nManager.getTranslation("select_new_tool")
534
            + "\n");
535
    }
536

    
537
    public void deleteObserver(Observer o) {
538
        this.observableHelper.deleteObserver(o);
539
    }
540

    
541
    public void deleteObservers() {
542
        this.observableHelper.deleteObservers();
543
    }
544

    
545
    private void discardChanges(FLyrVect layer) throws EndEditingException {
546
        FeatureStore featureStore = layer.getFeatureStore();
547
        try {
548
            featureStore.cancelEditing();
549
        } catch (Exception e) {
550
            throw new EndEditingException(e);
551
        }
552
    }
553

    
554
    private void doAction(FLyrVect layer, int option) {
555
        switch (option) {
556
        case SAVE_CHANGES:
557
            try {
558
                saveChanges(layer);
559
            } catch (VectorEditingException e) {
560
                String msg =
561
                    String.format("Changes can not be saved in %1$s",
562
                        layer.getName());
563
                logger.info(msg, e);
564
                return;
565
            }
566
            break;
567

    
568
        case DISCARD_CHANGES:
569
            try {
570
                discardChanges(layer);
571
            } catch (VectorEditingException e) {
572
                String msg =
573
                    String.format("Changes can not be discared in %1$s",
574
                        layer.getName());
575
                logger.info(msg, e);
576
                return;
577
            }
578
            break;
579

    
580
        case EXPORT_LAYER:
581
            try {
582
                exportLayer(layer);
583
            } catch (VectorEditingException e) {
584
                String msg =
585
                    String.format("Changes of %1$s can not be exported",
586
                        layer.getName());
587
                logger.info(msg, e);
588
                return;
589
            }
590
            break;
591

    
592
        case CANCEL:
593
            return;
594
        }
595

    
596
        cleanEditingContext();
597
        hideConsole();
598
        disableSnapping();
599
        changeSelectedTool(DEFAULT_TOOL);
600

    
601
        FeatureStore featureStore = layer.getFeatureStore();
602
        featureStore.deleteObserver(getMapControl());
603

    
604
    }
605

    
606
    private void enableSelection(boolean enableSelection) {
607
        this.editingCompoundBehavior.setDrawnBehavior(
608
            EditingCompoundBehavior.SELECTION_INDEX, enableSelection);
609
    }
610

    
611
    public void endEdition(FLyrVect layer) {
612
        if (layer.isEditing()) {
613
            EditingNotificationManager editingNotificationManager =
614
                DALSwingLocator.getEditingNotificationManager();
615

    
616
            EditingNotification notification =
617
                editingNotificationManager.notifyObservers(this,
618
                    EditingNotification.BEFORE_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
619

    
620
            if (notification.isCanceled()) {
621
                String msg =
622
                    String.format(
623
                        "Stop edit layer %1$s canceled by somme observer.",
624
                        layer.getName());
625
                logger.info(msg, new EndEditingException(msg, null));
626

    
627
            }
628

    
629
            getMapControl().getCanceldraw().setCanceled(true);
630
            int option;
631
            EditingSwingManager swingManager =
632
                EditingSwingLocator.getSwingManager();
633

    
634

    
635
            if (layer.isWritable() && getMapControl().getProjection().equals(layer.getProjection()) ) {
636
                option =
637
                    swingManager.showPanelSaveOrDiscard(getMapControl(),
638
                        layer.getName());
639
            } else {
640
                option =
641
                    swingManager.showPanelExportOrDiscard(getMapControl(),
642
                        layer.getName());
643
            }
644

    
645
            doAction(layer, option);
646

    
647
            editingNotificationManager.notifyObservers(this,
648
                EditingNotification.AFTER_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
649

    
650
        }
651

    
652
    }
653

    
654
    private void exportLayer(FLyrVect layer) throws EndEditingException {
655
        Notification notification = new BaseNotification(EditingContext.EXPORT_LAYER_NOTIFICATION,1);
656
        notification.setValue(layer);
657
        this.observableHelper.notifyObservers(this, notification);
658
    }
659

    
660
    protected void finishService() {
661
        EditingService lastService = serviceStack.pop();
662
        try {
663

    
664
            if (!serviceStack.isEmpty()
665
                && getActiveService().next().getTypes().contains(TYPE.GEOMETRY)) {
666
                Geometry geometry = lastService.finish();
667
                if (geometry != null) {
668
                    getActiveService().setValue(geometry);
669
                }
670
            } else {
671
                lastService.finishAndStore();
672
                getMapControl().rePaintDirtyLayers();
673

    
674
                I18nManager i18nManager = ToolsLocator.getI18nManager();
675
                showConsoleMessage("\n"
676
                    + i18nManager.getTranslation(lastService.getName()) + "# "
677
                    + i18nManager.getTranslation("finished") + "\n");
678
                lastService.stop();
679
                setActiveService(lastService);
680
                lastService.start();
681
                changeSelectedTool(getActiveService().getName());
682
            }
683

    
684
        } catch (InvalidEntryException ex) {
685
            I18nManager i18nManager = ToolsLocator.getI18nManager();
686
            showConsoleMessage("\n"
687
                + i18nManager.getTranslation("invalid_option"));
688
            changeSelectedTool(getActiveService().getName());
689
        } catch (VectorEditingException ex) {
690
            logger.info("Can't finish " + lastService.getName(), ex);
691
            cleanEditingContext();
692
            return;
693
        }
694

    
695
        getNextParameter();
696
    }
697

    
698
    protected EditingService getActiveService() {
699
        if (!serviceStack.isEmpty()) {
700
            return serviceStack.peek();
701
        }
702
        return null;
703
    }
704

    
705
    private EditingConsole getConsolePanel() {
706
        if (console == null) {
707
            console = new DefaultEditingConsole(new ResponseListener() {
708

    
709
                public void acceptResponse(String response) {
710
                    textEntered(response);
711
                }
712
            });
713
        }
714
        return console;
715
    }
716

    
717
    protected FLyrVect getCurrentLayer() {
718
        return this.currentLayer;
719
    }
720

    
721
    protected EditingServiceParameter getCurrentParam() {
722
        return this.currentParam;
723
    }
724

    
725
    private Component getDockConsole() {
726
        if (dockConsole == null) {
727
            dockConsole = new JDockPanel((JComponent) getConsolePanel());
728
        }
729
        return dockConsole;
730
    }
731

    
732
    private DefaultEditingBehavior getEditingBehavior() {
733
        if (editingCompoundBehavior != null) {
734
            return (DefaultEditingBehavior) editingCompoundBehavior
735
                .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
736
        }
737
        return null;
738
    }
739

    
740
    private EditingCompoundBehavior getEditingCompoundBehavior() {
741
        if (editingCompoundBehavior != null) {
742
            return editingCompoundBehavior;
743
        } else {
744
            EditingCompoundBehavior editingCompoundBehavior;
745

    
746
            CompoundBehavior compoundBehavior =
747
                (CompoundBehavior) getMapControl().getMapTool("VectorEditing");
748

    
749
            if (compoundBehavior instanceof EditingCompoundBehavior) {
750
                editingCompoundBehavior =
751
                    (EditingCompoundBehavior) compoundBehavior;
752
            } else {
753
                editingCompoundBehavior =
754
                    (EditingCompoundBehavior) compoundBehavior.getBehavior(0);
755
            }
756

    
757
            setCompoundBehavior(editingCompoundBehavior);
758
            return editingCompoundBehavior;
759
        }
760
    }
761

    
762
    public MapControl getMapControl() {
763
        return mapControlReference.get();
764
    }
765

    
766
    protected void getNextParameter() {
767
        if ((getMapControl().getCurrentTool() != null)
768
            && !getMapControl().getCurrentTool().equals("VectorEditing")) {
769
            getMapControl().setTool("VectorEditing");
770
        }
771
        currentParam = getActiveService().next();
772

    
773
        if (currentParam == null) {
774
            finishService();
775
        } else {
776
            askQuestion(currentParam);
777
            if (currentParam.getTypes().contains(TYPE.SELECTION)) {
778
                enableSelection(true);
779
            } else if (currentParam.getTypes().contains(TYPE.GEOMETRY)) {
780
                refreshMenusAndToolBars();
781
            }
782
        }
783
    }
784

    
785
    protected Stack<EditingService> getServiceStack() {
786
        return this.serviceStack;
787
    }
788

    
789
    private void hideConsole() {
790
        isShowConsole = false;
791
        if( !SwingUtilities.isEventDispatchThread() ) {
792
            try {
793
                SwingUtilities.invokeAndWait(new Runnable() {
794

    
795
                    @Override
796
                    public void run() {
797
                        hideConsole();
798
                    }
799
                });
800
                return;
801
            } catch (InterruptedException | InvocationTargetException ex) {
802
                logger.warn("Can't hide editing console.",ex);
803
            }
804
            return;
805
        }
806
        getDockConsole().setVisible(false);
807
    }
808

    
809
    public boolean isServiceCompatible(String name) {
810
        DefaultEditingBehavior editingBehavior = getEditingBehavior();
811

    
812
        if (editingBehavior != null) {
813

    
814
            try {
815
                EditingManager manager = EditingLocator.getManager();
816
                EditingServiceInfo serviceInfo = manager.getServiceInfo(name);
817
                GeometryType geoType = null;
818

    
819
                for (EditingService editingService : getServiceStack()) {
820
                    EditingServiceParameter parameter = editingService.next();
821
                    if (parameter != null
822
                        && parameter.getTypes().contains(TYPE.GEOMETRY)) {
823

    
824
                        int geometryType = parameter.getGeometryType();
825
                        int subType = -1;
826

    
827
                        try {
828
                            subType =
829
                                getCurrentLayer().getFeatureStore()
830
                                    .getDefaultFeatureType()
831
                                    .getDefaultGeometryAttribute()
832
                                    .getGeomType().getSubType();
833

    
834
                            geoType =
835
                                GeometryLocator.getGeometryManager()
836
                                    .getGeometryType(geometryType, subType);
837
                        } catch (Exception e) {
838

    
839
                            String msg =
840
                                String.format(
841
                                    "Problems getting default feature"
842
                                        + " type of %1$s or getting geometry"
843
                                        + " type of %2$s %3$s",
844
                                    getCurrentLayer().getName(), geometryType,
845
                                    subType);
846

    
847
                            throw new ServiceInformationException(msg, e);
848
                        }
849

    
850
                        return serviceInfo.isCompatibleWith(geoType)
851
                            && serviceInfo.createsNewGeometries();
852
                    }
853
                }
854

    
855
                if (getCurrentLayer() != null) {
856
                    try {
857
                        geoType =
858
                            getCurrentLayer().getFeatureStore()
859
                                .getDefaultFeatureType()
860
                                .getDefaultGeometryAttribute().getGeomType();
861
                    } catch (DataException e) {
862
                        String msg =
863
                            String.format("Problems getting default "
864
                                + "feature type of %1$s", getCurrentLayer()
865
                                .getName());
866
                        throw new ServiceInformationException(msg, e);
867
                    }
868

    
869
                    return serviceInfo.isCompatibleWith(geoType);
870
                }
871

    
872
                return false;
873
            } catch (ServiceInformationException e) {
874
                logger.warn(
875
                    "Problems getting if editing context is compatible with "
876
                        + name, e);
877
            }
878
        }
879
        return false;
880
    }
881

    
882
    private Point parsePoint(String response) throws ParsePointException {
883
        String[] numbers = new String[1];
884
        numbers[0] = response;
885
        numbers = response.split(",");
886
        int dimension = numbers.length;
887
        if (dimension >= 2 && dimension <= 4) {
888

    
889
            if (numbers[0].startsWith("(") && numbers[dimension-1].endsWith(")\n")) { // CCS
890
                numbers[0] = numbers[0].replace("(", "");
891
                numbers[dimension-1] = numbers[dimension-1].replace(")\n", "");
892
            }
893

    
894
            Point point;
895
            try {
896
                GeometryManager geomManager =
897
                    GeometryLocator.getGeometryManager();
898
                int subType;
899
                switch (dimension) {
900
                case 3:
901
                    subType = Geometry.SUBTYPES.GEOM3D;
902
                    break;
903
                case 4:
904
                    subType = Geometry.SUBTYPES.GEOM3DM;
905
                    break;
906
                default:
907
                    subType = Geometry.SUBTYPES.GEOM2D;
908
                    break;
909
                }
910
                point = (Point) geomManager.create(geomManager.getGeometryType(Geometry.TYPES.POINT, subType));
911
                for (int i = 0; i < dimension; i++) {
912
                    point.setCoordinateAt(i, Double.parseDouble(numbers[i]));
913
                }
914

    
915
            } catch (Exception e) {
916
                throw new ParsePointException(e);
917
            }
918
            return point;
919
        } else {
920
            throw new ParsePointException(null);
921
        }
922
    }
923

    
924
    private Double parseValue(String response) throws ParseValueException {
925
        try {
926
            return Double.valueOf(response);
927
        } catch (Exception e) {
928
            throw new ParseValueException(e);
929
        }
930

    
931
    }
932

    
933
    protected void refreshMenusAndToolBars() {
934
        if (!SwingUtilities.isEventDispatchThread()) {
935
            SwingUtilities.invokeLater(new Runnable() {
936

    
937
                @Override
938
                public void run() {
939
                    refreshMenusAndToolBars();
940
                }
941
            });
942
            return;
943
        }
944
        Notification notification = new BaseNotification(
945
                EditingContext.REFRESH_TOOLS_NOTIFICATION,
946
                null
947
        );
948
        this.observableHelper.notifyObservers(this, notification);
949
    }
950

    
951
    private void saveChanges(FLyrVect layer) throws EndEditingException {
952
        FeatureStore featureStore = layer.getFeatureStore();
953
        try {
954
            featureStore.finishEditing();
955
        } catch (Exception e) {
956
            throw new EndEditingException(e);
957
        }
958
    }
959

    
960
    private void setActiveService(EditingService service) {
961
        serviceStack.add(service);
962
    }
963

    
964
    private void setCompoundBehavior(EditingCompoundBehavior compoundBehavior) {
965
        this.editingCompoundBehavior = compoundBehavior;
966
    }
967

    
968
    private void setCurrentLayer(FLyrVect layer) {
969

    
970
        if (this.currentLayer != layer) {
971
            this.currentLayer = layer;
972
            cleanEditingContext();
973
        }
974

    
975
    }
976

    
977
    public void setMapControl(MapControl mapControl) {
978

    
979
        this.mapControlReference = new WeakReference<MapControl>(mapControl);
980
        this.mapContextReference =
981
            new WeakReference<MapContext>(mapControl.getMapContext());
982

    
983
        // When mapControl is updated we have to add older additional behaviors
984
        // to new mapControl
985
        if (lastAdditionalBehaviors != null) {
986
            try {
987
                addBehaviors(lastAdditionalBehaviors);
988
            } catch (CreateEditingBehaviorException e1) {
989
                logger.info("Problems adding behaviors to editing context", e1);
990
                getMapControl().setTool("pan");
991
                return;
992
            }
993
        }
994
    }
995

    
996
    private void showConsole() {
997
        if (isShowConsole) {
998
            return;
999
        }
1000
        if( !SwingUtilities.isEventDispatchThread() ) {
1001
            try {
1002
                SwingUtilities.invokeAndWait(new Runnable() {
1003

    
1004
                    @Override
1005
                    public void run() {
1006
                        showConsole();
1007
                    }
1008
                });
1009
                return;
1010
            } catch (InterruptedException | InvocationTargetException ex) {
1011
                logger.warn("Can't show editing console.",ex);
1012
            }
1013
            return;
1014
        }
1015
        isShowConsole = true;
1016
        getMapControl().remove(getDockConsole());
1017
        getMapControl().setLayout(new BorderLayout());
1018
        getMapControl().add(getDockConsole(), BorderLayout.SOUTH);
1019
        getDockConsole().setVisible(true);
1020
    }
1021

    
1022
    protected void showConsoleMessage(final String text) {
1023
        if (!SwingUtilities.isEventDispatchThread()) {
1024
            SwingUtilities.invokeLater(new Runnable() {
1025

    
1026
                @Override
1027
                public void run() {
1028
                    showConsoleMessage(text);
1029
                }
1030
            });
1031
            return;
1032
        }
1033
        getConsolePanel().addText(text);
1034
    }
1035

    
1036
    protected void textEntered(String response) {
1037
        FeatureStore featureStore = getCurrentLayer().getFeatureStore();
1038
        EditingService activeService = getActiveService();
1039
        if (response == null) {
1040
            if (activeService != null) {
1041
                try {
1042
                    activeService.stop();
1043
                    serviceStack.pop();
1044
                    if (serviceStack.isEmpty()) {
1045
                        featureStore
1046
                            .getFeatureSelection().deselectAll();
1047
                        changeSelectedTool(DEFAULT_TOOL);
1048
                    } else {
1049
                        changeSelectedTool(activeService.getName());
1050
                    }
1051

    
1052
                    refreshMenusAndToolBars();
1053
                    activeService = getActiveService();
1054
                    if (activeService != null) {
1055
                        getNextParameter();
1056
                    } else {
1057
                        cleanEditingContext();
1058
                    }
1059

    
1060
                } catch (StopServiceException e) {
1061
                    logger
1062
                        .info("Can't stop " + activeService.getName(), e);
1063
                    return;
1064
                } catch (DataException e) {
1065
                    logger.info("Can't get selection of "
1066
                        + featureStore.getFullName(), e);
1067
                    return;
1068
                }
1069
            }
1070
        } else {
1071

    
1072
            if (getCurrentParam() != null) {
1073
                Set<TYPE> types = getCurrentParam().getTypes();
1074
                Point point = null;
1075
                Double value = null;
1076
                Point defaultPoint = null;
1077
                Object defaultValue = getCurrentParam().getDefaultValue();
1078
//                int dimension = 2;
1079
//                if(defaultValue != null && defaultValue instanceof Point){
1080
                    defaultPoint = (Point)defaultValue;
1081
//                    dimension = defaultPoint.getDimension();
1082
//                }
1083

    
1084
                boolean insertedValue = false;
1085
                if ((!insertedValue && types.contains(TYPE.POSITION))
1086
                    || types.contains(TYPE.LIST_POSITIONS)) {
1087

    
1088
                    try {
1089
                        if(StringUtils.isEmpty(response.replace("\n", ""))){
1090
                            point = defaultPoint;
1091
                        } else {
1092
                            point = parsePoint(response);
1093
                        }
1094

    
1095
                        if (point != null) {
1096
                            activeService.setValue(point);
1097
                            insertedValue = true;
1098
                        }
1099

    
1100
                    } catch (VectorEditingException e) {
1101
                        // Do nothing to try other types
1102
                    }
1103
                }
1104
                if (!insertedValue && types.contains(TYPE.VALUE)) {
1105

    
1106
                    try {
1107

    
1108
                        value = parseValue(response);
1109
                        if (value != null) {
1110
                            activeService.setValue(value);
1111
                            insertedValue = true;
1112
                        }
1113

    
1114
                    } catch (VectorEditingException e) {
1115
                        // Do nothing to try other types
1116
                    }
1117

    
1118
                }
1119
                if (!insertedValue && types.contains(TYPE.OPTION)) {
1120

    
1121
                    try {
1122

    
1123
                        response = response.replace("\n", "");
1124
                        if (response != null) {
1125
                            activeService.setValue(response);
1126
                            insertedValue = true;
1127
                        }
1128

    
1129
                    } catch (VectorEditingException e) {
1130
                        // Do nothing to try other types
1131
                    }
1132
                }
1133
                if (!insertedValue && types.contains(TYPE.SELECTION)) {
1134
                    if (response.equalsIgnoreCase("\n")) {
1135
                        enableSelection(false);
1136
                        insertedValue = true;
1137

    
1138
                        try {
1139

    
1140
                            FeatureSelection clonedSelection = (FeatureSelection)featureStore
1141
                                .getFeatureSelection().clone();
1142
                            if(clonedSelection.isEmpty()){
1143
                               throw new InvalidEntryException(null);
1144
                            }
1145
                            activeService.setValue(
1146
                                clonedSelection);
1147

    
1148
                        } catch (InvalidEntryException e) {
1149
                            I18nManager i18nManager =
1150
                                ToolsLocator.getI18nManager();
1151
                            showConsoleMessage("\n"
1152
                                + i18nManager.getTranslation("invalid_option"));
1153
                        } catch (Exception e) {
1154
                            logger.info("Can't access to selection.", e);
1155
                            cleanEditingContext();
1156
                            return;
1157
                        }
1158
                    }
1159
                }
1160
                if (!insertedValue) {
1161
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
1162
                    showConsoleMessage("\n"
1163
                        + i18nManager.getTranslation("invalid_option"));
1164
                }
1165
                getNextParameter();
1166
            }
1167
        }
1168
    }
1169

    
1170
    public void setDefaultBehaviors(Behavior[] defaultBehaviors) {
1171
        this.defaultBehaviors = defaultBehaviors;
1172
        try {
1173
            addBehaviors(defaultBehaviors);
1174
        } catch (CreateEditingBehaviorException e1) {
1175
            logger.info("Problems adding behaviors to editing context", e1);
1176
            getMapControl().setTool("pan");
1177
            return;
1178
        }
1179
    }
1180

    
1181
    public Behavior[] getDefaultBehaviors() {
1182
        return this.defaultBehaviors;
1183
    }
1184
}