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

History | View | Annotate | Download (57.1 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.awt.Cursor;
30
import java.lang.ref.WeakReference;
31
import java.lang.reflect.InvocationTargetException;
32
import java.util.ArrayList;
33
import java.util.HashSet;
34
import java.util.List;
35
import java.util.Set;
36
import java.util.Stack;
37
import java.util.concurrent.BlockingQueue;
38
import java.util.concurrent.LinkedBlockingQueue;
39
import java.util.concurrent.TimeUnit;
40
import java.util.prefs.PreferenceChangeEvent;
41
import java.util.prefs.PreferenceChangeListener;
42
import java.util.prefs.Preferences;
43
import javax.swing.JComponent;
44
import javax.swing.JOptionPane;
45
import javax.swing.SwingUtilities;
46
import org.apache.commons.lang3.StringUtils;
47
import org.apache.commons.text.StringEscapeUtils;
48
import org.gvsig.expressionevaluator.ExpressionUtils;
49
import org.gvsig.expressionevaluator.Function;
50
import org.gvsig.expressionevaluator.SymbolTable;
51
import org.gvsig.fmap.dal.DataTypes;
52
import org.gvsig.fmap.dal.EditingNotification;
53
import org.gvsig.fmap.dal.EditingNotificationManager;
54
import org.gvsig.fmap.dal.exception.DataException;
55
import org.gvsig.fmap.dal.feature.Feature;
56
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57
import org.gvsig.fmap.dal.feature.FeatureSelection;
58
import org.gvsig.fmap.dal.feature.FeatureStore;
59
import org.gvsig.fmap.dal.feature.FeatureType;
60
import org.gvsig.fmap.dal.swing.DALSwingLocator;
61
import org.gvsig.fmap.geom.Geometry;
62
import org.gvsig.fmap.geom.GeometryLocator;
63
import org.gvsig.fmap.geom.primitive.Point;
64
import org.gvsig.fmap.geom.type.GeometryType;
65
import org.gvsig.fmap.mapcontext.MapContext;
66
import org.gvsig.fmap.mapcontext.layers.CancelationException;
67
import org.gvsig.fmap.mapcontext.layers.FLayer;
68
import org.gvsig.fmap.mapcontext.layers.FLayers;
69
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
70
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
71
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
72
import org.gvsig.fmap.mapcontext.layers.LayerListener;
73
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
74
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
75
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
76
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
77
import org.gvsig.fmap.mapcontrol.MapControl;
78
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
79
import org.gvsig.fmap.mapcontrol.tools.CompoundBehavior;
80
import org.gvsig.tools.ToolsLocator;
81
import org.gvsig.tools.dataTypes.Coercion;
82
import org.gvsig.tools.dispose.DisposableIterator;
83
import org.gvsig.tools.i18n.I18nManager;
84
import org.gvsig.tools.locator.LocatorException;
85
import org.gvsig.tools.observer.BaseNotification;
86
import org.gvsig.tools.observer.Notification;
87
import org.gvsig.tools.observer.ObservableHelper;
88
import org.gvsig.tools.observer.Observer;
89
import org.gvsig.tools.swing.api.ToolsSwingLocator;
90
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
91
import org.gvsig.tools.task.SimpleTaskStatus;
92
import org.gvsig.utils.console.JDockPanel;
93
import org.gvsig.utils.console.ResponseListener;
94
import org.gvsig.vectorediting.lib.api.EditingLocator;
95
import org.gvsig.vectorediting.lib.api.EditingManager;
96
import org.gvsig.vectorediting.lib.api.EditingService;
97
import org.gvsig.vectorediting.lib.api.EditingServiceInfo;
98
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
99
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
100
import org.gvsig.vectorediting.lib.api.exceptions.CreateEditingBehaviorException;
101
import org.gvsig.vectorediting.lib.api.exceptions.EndEditingException;
102
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
103
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
104
import org.gvsig.vectorediting.lib.api.exceptions.ParsePointException;
105
import org.gvsig.vectorediting.lib.api.exceptions.ParseValueException;
106
import org.gvsig.vectorediting.lib.api.exceptions.ServiceInformationException;
107
import org.gvsig.vectorediting.lib.api.exceptions.StartEditingException;
108
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
109
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
110
import org.gvsig.vectorediting.lib.api.exceptions.VectorEditingException;
111
import org.gvsig.vectorediting.swing.api.EditingContext;
112
import org.gvsig.vectorediting.swing.api.EditingSwingLocator;
113
import org.gvsig.vectorediting.swing.api.EditingSwingManager;
114
import org.gvsig.vectorediting.swing.api.console.EditingConsole;
115
import org.gvsig.vectorediting.swing.impl.console.DefaultEditingConsole;
116
import org.slf4j.Logger;
117
import org.slf4j.LoggerFactory;
118

    
119
public class DefaultEditingContext implements EditingContext {
120

    
121
    private static final Logger LOGGER = LoggerFactory
122
        .getLogger(EditingManager.class);
123

    
124
    private WeakReference<MapControl> mapControlReference;
125

    
126
    private WeakReference<MapContext> mapContextReference;
127

    
128
    private EditingCompoundBehavior editingCompoundBehavior;
129

    
130
    private Behavior[] lastAdditionalBehaviors;
131

    
132
    private final ObservableHelper observableHelper;
133

    
134
    private EditingConsole console;
135

    
136
    private JDockPanel dockConsole = null;
137

    
138
    private boolean isShowConsole = false;
139

    
140
    private final Stack<EditingService> serviceStack;
141

    
142
    private FLyrVect currentLayer;
143

    
144
    private EditingServiceParameter currentParam;
145

    
146
    private Behavior[] defaultBehaviors;
147
    
148
    private Set<FLyrVect> layersSpatialCacheEnabled = new HashSet<>();
149
    
150
//    private boolean processing;
151
    
152
    private int drawMode;
153

    
154
    private final LayerListener layerListener = new LayerListener() {
155

    
156
        @Override
157
        public void activationChanged(final LayerEvent e) {
158
            if( !SwingUtilities.isEventDispatchThread() ) {
159
                SwingUtilities.invokeLater(new Runnable() {
160

    
161
                    @Override
162
                    public void run() {
163
                        activationChanged(e);
164
                    }
165
                });
166
                return;
167
            }
168

    
169
            FLayer layer = e.getSource();
170
            final MapContext mapContext = layer.getMapContext();
171

    
172
            if (countActiveAndEditingLayers(mapContext) > 1) {
173
                hideConsole();
174
                return;
175
            }
176

    
177
            if (layer instanceof FLyrVect) {
178
                if (layer.isActive()) {
179
                    if(layer.isEditing()) {
180
                        // Al activar una capa en edicion esto hace que el usuario
181
                        // pierda la herramienta que tuvise activa.
182
//                        getMapControl().setTool(VECTOREDITING_TOOL_NAME);
183
                        setCurrentLayer((FLyrVect) layer);
184
                        showConsole();
185
                        return;
186
                    } else {
187
                        final SpatialCache spatialCache = ((FLyrVect) layer).getSpatialCache();
188
                        if(!spatialCache.isEnabled("active")){
189
                            spatialCache.setEnabled("active",true);
190
                            //We keep the list of layers whose spatial cache is enabled here.
191
                            layersSpatialCacheEnabled.add((FLyrVect) layer);
192
                            ((FLyrVect) layer).refreshSpatialCache(mapContext.getViewPort().getEnvelope());
193
                        }
194
                    }
195
                } else {
196
                    if(!layer.isEditing()) {
197
                        //We disabled the spatial cache of the layers that we had enabled here.
198
                        final SpatialCache spatialCache = ((FLyrVect) layer).getSpatialCache();
199
                        if(spatialCache.isEnabled("active") && layersSpatialCacheEnabled.contains((FLyrVect) layer)){
200
                            spatialCache.setEnabled("active",false);
201
                            layersSpatialCacheEnabled.remove((FLyrVect) layer);
202
                        }
203
                    }
204
                }
205
            }
206

    
207
            FLayer[] activeLayers =
208
                layer.getMapContext().getLayers().getActives();
209
            
210
            for (FLayer activeLayer : activeLayers) {
211
                if (activeLayer instanceof FLyrVect) {
212
                    if (activeLayer.isEditing()) {
213
//                        getMapControl().setTool(VECTOREDITING_TOOL_NAME);
214
                        setCurrentLayer((FLyrVect) activeLayer);
215
                        showConsole();
216
                        return;
217
                    }
218
                }
219
            }
220

    
221
            hideConsole();
222
//            if ((getMapControl().getCurrentTool() != null)
223
//                && getMapControl().getCurrentTool().equals(VECTOREDITING_TOOL_NAME)) {
224
//                getMapControl().setPrevTool();
225
//            }
226
        }
227

    
228
        @Override
229
        public void drawValueChanged(LayerEvent e) {
230
        }
231

    
232
        @Override
233
        public void editionChanged(final LayerEvent e) {
234
            if( !SwingUtilities.isEventDispatchThread() ) {
235
                SwingUtilities.invokeLater(new Runnable() {
236

    
237
                    @Override
238
                    public void run() {
239
                        editionChanged(e);
240
                    }
241
                });
242
                return;
243
            }
244
            FLayer layer = e.getSource();
245

    
246
            if (layer instanceof FLyrVect) {
247
                if (layer.isEditing()) {
248
                    synchronized (DefaultEditingContext.this) {
249
                        beginEdition((FLyrVect) layer);
250
                        showConsole();
251
                    }
252
                } else {
253
                    hideConsole();
254
                }
255
            }
256

    
257
        }
258

    
259
        @Override
260
        public void nameChanged(LayerEvent e) {
261
        }
262

    
263
        @Override
264
        public void visibilityChanged(LayerEvent e) {
265
        }
266
    };
267
    
268
    private int countActiveAndEditingLayers(MapContext mapcontext){
269
        int count = 0;
270
        
271
        FLayer[] activeLayers =
272
                mapcontext.getLayers().getActives();
273
            
274
        for (FLayer activeLayer : activeLayers) {
275
            if (activeLayer instanceof FLyrVect) {
276
                if (activeLayer.isEditing()) {
277
                    count++;
278
                }
279
            }
280
        }
281
        
282
        return count;
283
    }
284

    
285
    private final PreferenceChangeListener preferenceChangeListener =
286
        new PreferenceChangeListener() {
287

    
288
            @Override
289
            public void preferenceChange(PreferenceChangeEvent evt) {
290
                String key = evt.getKey();
291
                if (key.equalsIgnoreCase("apply-snappers")) {
292
                    boolean newValue = Boolean.parseBoolean(evt.getNewValue());
293
                    getMapControl().setRefentEnabled(newValue);
294
                }
295
            }
296
        };
297

    
298
    public DefaultEditingContext(MapControl mapControl) {
299
//        this.processing = false;
300
        this.mapControlReference = new WeakReference<>(mapControl);
301
        this.mapContextReference =
302
            new WeakReference<>(mapControl.getMapContext());
303
        this.observableHelper = new ObservableHelper();
304

    
305
        this.serviceStack = new Stack<>();
306
        
307
        this.drawMode = DRAWMODE_NORMAL;
308

    
309
        addLayerListeners();
310
        addPreferenceListener();
311
    }
312

    
313
    private void addPreferenceListener() {
314
        Preferences prefs = Preferences.userRoot().node("snappers");
315
        prefs.addPreferenceChangeListener(preferenceChangeListener);
316
    }
317

    
318
    @Override
319
    public void activateService(String name) {
320
        if( this.isProcessing() ) {
321
            return;
322
        }
323

    
324
        if ((getMapControl() != null)
325
            && getMapControl().hasTool(VECTOREDITING_TOOL_NAME)) {
326

    
327
            CompoundBehavior editingCompoundBehavior =
328
                getEditingCompoundBehavior();
329
            getMapControl().setTool(VECTOREDITING_TOOL_NAME);
330
            editingCompoundBehavior.setDrawnBehavior(
331
                EditingCompoundBehavior.EDITING_INDEX, true);
332

    
333
            EditingManager manager = EditingLocator.getManager();
334

    
335
            if (currentLayer != null) {
336
                IVectorLegend legend = null;
337
                try {
338
                    legend = (IVectorLegend) currentLayer.getLegend();
339
                } catch (Exception e) {
340
                    LOGGER.trace("Can't retrieve legend from layer.");
341
                    //DO NOTHING
342
                }
343

    
344
//                EditingService activeService = getActiveService();
345
//                if(activeService != null && !activeService.next().getTypes().contains(TYPE.GEOMETRY)) {
346
//                    activeService.setShowPreviewSymbol(true);
347
//                }
348
                EditingService service =
349
                    manager.getEditingService(name,
350
                        currentLayer.getFeatureStore(),
351
                        mapContextReference.get(), 
352
                        legend);
353

    
354
                if (service != null) {
355
//                     if(!serviceStack.isEmpty()) { service.setShowPreviewSymbol(false); }
356
                    this.enableSelection(false);
357

    
358
                    try {
359
                        service.activate();
360
                        service.start();
361
                        setDrawMode(DRAWMODE_NORMAL);
362
                    } catch (StartServiceException e) {
363

    
364
                        LOGGER.info(String.format(
365
                            "Can't start the service %1$s", service.getName()),
366
                            e);
367
                        cleanEditingContext();
368
                        return;
369

    
370
                    } catch (InvalidEntryException e) {
371

    
372
                        I18nManager i18nManager = ToolsLocator.getI18nManager();
373
                        showConsoleMessage("\n"
374
                            + i18nManager.getTranslation("invalid_option"));
375
                    }
376

    
377
                    if (!serviceStack.isEmpty()){
378
                        if(getActiveService().next().getTypes().contains(TYPE.GEOMETRY)) {
379
                            service.setShowPreviewSymbol(false);
380
                        } else {
381
//                            service.setShowPreviewSymbol(true);
382
//                            getActiveService().setShowPreviewSymbol(true);
383
                            serviceStack.pop();
384
                        }
385
                    }
386

    
387
                    setActiveService(service);
388

    
389
                    nextParameter();
390
                }
391
            }
392
        }
393
    }
394

    
395
    private void addBehaviors(Behavior[] additionalBehavior)
396
        throws CreateEditingBehaviorException {
397

    
398
        DefaultEditingBehavior editingBehavior;
399
        EditingCompoundBehavior editingCompoundBehavior;
400

    
401
        if (!getMapControl().hasTool(VECTOREDITING_TOOL_NAME)) {
402

    
403
            editingBehavior = new DefaultEditingBehavior(this);
404
            editingCompoundBehavior =
405
                new EditingCompoundBehavior(editingBehavior);
406
            setCompoundBehavior(editingCompoundBehavior);
407

    
408
            if (additionalBehavior != null) {
409

    
410
                Behavior[] behaviors =
411
                    new Behavior[additionalBehavior.length + 1];
412
                behaviors[0] = editingCompoundBehavior;
413

    
414
                System.arraycopy(additionalBehavior, 0, behaviors, 1, additionalBehavior.length);
415

    
416
                getMapControl().addBehavior(VECTOREDITING_TOOL_NAME, behaviors);
417

    
418
                lastAdditionalBehaviors = additionalBehavior;
419

    
420
            } else {
421
                getMapControl().addBehavior(VECTOREDITING_TOOL_NAME,
422
                    editingCompoundBehavior);
423
            }
424

    
425
        } else {
426
            editingCompoundBehavior = getEditingCompoundBehavior();
427
            editingBehavior =
428
                (DefaultEditingBehavior) editingCompoundBehavior
429
                    .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
430
            setCompoundBehavior(editingCompoundBehavior);
431
            cleanEditingContext();
432
        }
433

    
434
    }
435

    
436
    private void addLayerListeners() {
437

    
438
        FLayers layers = mapContextReference.get().getLayers();
439

    
440
        layers.addLayerListener(layerListener);
441

    
442
        layers.addLayerCollectionListener(new LayerCollectionListener() {
443

    
444
            public void addLayer(FLayer layer) {
445
                if (layer instanceof FLayers) {
446
                    FLayers layers = (FLayers) layer;
447
                    for (int i = 0; i < layers.getLayersCount(); i++) {
448
                        addLayer(layers.getLayer(i));
449
                    }
450
                } else if (layer instanceof FLyrVect) {
451
                    ((FLyrVect) layer).addLayerListener(layerListener);
452
                }
453
            }
454

    
455
            @Override
456
            public void layerAdded(LayerCollectionEvent e) {
457
                addLayer(e.getLayers());
458
            }
459

    
460
            @Override
461
            public void layerAdding(LayerCollectionEvent e)
462
                throws CancelationException {
463
            }
464

    
465
            @Override
466
            public void layerMoved(LayerPositionEvent e) {
467
            }
468

    
469
            @Override
470
            public void layerMoving(LayerPositionEvent e)
471
                throws CancelationException {
472
            }
473

    
474
            public void removeLayer(FLayer layer) {
475
                if (layer instanceof FLayers) {
476
                    FLayers layers = (FLayers) layer;
477
                    for (int i = 0; i < layers.getLayersCount(); i++) {
478
                        addLayer(layers.getLayer(i));
479
                    }
480
                } else if (layer instanceof FLyrVect) {
481
                    ((FLyrVect) layer).removeLayerListener(layerListener);
482
                }
483
            }
484

    
485
            @Override
486
            public void layerRemoved(LayerCollectionEvent e) {
487
                removeLayer(e.getLayers());
488
            }
489

    
490
            @Override
491
            public void layerRemoving(LayerCollectionEvent e)
492
                throws CancelationException {
493
            }
494

    
495
            @Override
496
            public void visibilityChanged(LayerCollectionEvent e)
497
                throws CancelationException {
498
            }
499
        });
500
    }
501

    
502
    @Override
503
    public void addObserver(Observer o) {
504
        this.observableHelper.addObserver(o);
505
    }
506

    
507
    private void askQuestion(EditingServiceParameter param) {
508
        I18nManager i18nManager = ToolsLocator.getI18nManager();
509
        String translation = i18nManager.getTranslation(param.getDescription());
510
        String activeServiceName =
511
            i18nManager.getTranslation(getActiveService().getName());
512

    
513
        String strDefaultValue = param.getConsoleDefaultValue();
514
        
515
        if(StringUtils.isBlank(strDefaultValue)) {
516
            showConsoleMessage("\n" + activeServiceName + "# " + translation + " : ");
517
        } else {
518
            showConsoleMessage("\n" + activeServiceName + "# " + translation + "<" + strDefaultValue + "> : ");
519
        }
520
    }
521

    
522
    @Override
523
    public synchronized void beginEdition(FLyrVect layer,
524
        Behavior[] additionalBehaviors) {
525

    
526
        try{
527
            throw new Exception("Deprecated method");
528
        } catch (Exception e){
529
            LOGGER.info("Deprecated method", e);
530
        }
531

    
532
        beginEdition(layer);
533
        try {
534
            addBehaviors(additionalBehaviors);
535
        } catch (CreateEditingBehaviorException e1) {
536
            LOGGER.info("Problems adding behaviors to editing context", e1);
537
            getMapControl().setTool("pan");
538
        }
539
    }
540

    
541
    @Override
542
    public synchronized void beginEdition(FLyrVect layer) {
543

    
544

    
545
        setCurrentLayer(layer);
546

    
547
        FeatureStore featureStore = layer.getFeatureStore();
548
        if (!featureStore.isEditing()) {
549
            EditingNotificationManager editingNotificationManager =
550
                DALSwingLocator.getEditingNotificationManager();
551

    
552
            EditingNotification notification =
553
                editingNotificationManager.notifyObservers(this,
554
                    EditingNotification.BEFORE_ENTER_EDITING_STORE, null, layer,layer.getFeatureStore());
555

    
556
            if (notification.isCanceled() || notification.isAborted() ) {
557
                String msg =
558
                    String.format("Edit layer %1$s canceled by somme observer.",
559
                        layer.getName());
560
                LOGGER.info(msg, new StartEditingException(msg, null));
561
                return;
562
            }
563
            try {
564
                featureStore.edit();
565
            } catch (Exception e) {
566
                String msg =
567
                    String.format("Can't set %1$s in edit mode",
568
                        featureStore.getName());
569
                LOGGER.info(msg, new VectorEditingException(e));
570
                cleanEditingContext();
571
                return;
572
            }
573
            editingNotificationManager.notifyObservers(this,
574
                EditingNotification.AFTER_ENTER_EDITING_STORE, null, layer, layer.getFeatureStore());
575

    
576
        }
577

    
578
        featureStore.addObserver(getMapControl());
579

    
580
        enableSnapping();
581
    }
582

    
583
    @SuppressWarnings({ "rawtypes", "unchecked" })
584
    private void enableSnapping() {
585
        Preferences prefs = Preferences.userRoot().node("snappers");
586
         getMapControl().setRefentEnabled(prefs.getBoolean("apply-snappers", false));
587
         if (currentLayer != null) {
588
            Set<FLyrVect> layersToSnap = getMapControl().getMapContext().getLayersToSnap();
589
            if (!layersToSnap.contains(currentLayer)) {
590
                layersToSnap.add(currentLayer);
591
            }
592
        }
593
    }
594

    
595
    @SuppressWarnings("rawtypes")
596
    private void disableSnapping() {
597
        Set<FLyrVect> layersToSnap =
598
            getMapControl().getMapContext().getLayersToSnap();
599
        if (layersToSnap.contains(currentLayer)) {
600
            layersToSnap.remove(currentLayer);
601
        }
602
    }
603

    
604
    private void changeSelectedTool(String name) {
605
        if (name.equalsIgnoreCase(DEFAULT_TOOL)) {
606
            name = DEFAULT_ACTION_NAME;
607
            this.getMapControl().setTool(DEFAULT_TOOL_NAME);
608
//            notifyChangeSelectedTool();
609
        }
610
    }
611
    
612
    private void notifyChangeSelectedTool() {
613
        Notification notification = new BaseNotification(
614
            EditingContext.CHANGE_SELECTED_TOOL_NOTIFICATION,
615
            null
616
        );
617
        this.observableHelper.notifyObservers(this, notification);
618
    }
619

    
620
    private void notifyChangeSelectedTool(String actionName) {
621
        Notification notification = new BaseNotification(
622
            EditingContext.CHANGE_SELECTED_TOOL_NOTIFICATION,
623
            new String[] { actionName }
624
        );
625
        this.observableHelper.notifyObservers(this, notification);
626
    }
627

    
628

    
629
    private void cleanEditingContext() {
630
        serviceStack.clear();
631
        currentParam = null;
632
        
633
        I18nManager i18n = ToolsLocator.getI18nManager();
634
        showConsoleMessage("\n" + i18n.getTranslation("select_new_tool") + "\n");
635

    
636
        changeSelectedTool(DEFAULT_TOOL);
637
        notifyChangeSelectedTool(DEFAULT_ACTION_NAME);
638
    }
639

    
640
    @Override
641
    public void deleteObserver(Observer o) {
642
        this.observableHelper.deleteObserver(o);
643
    }
644

    
645
    @Override
646
    public void deleteObservers() {
647
        this.observableHelper.deleteObservers();
648
    }
649

    
650
    private void discardChanges(FLyrVect layer) throws EndEditingException {
651
        FeatureStore featureStore = layer.getFeatureStore();
652
        try {
653
            featureStore.cancelEditing();
654
        } catch (Exception e) {
655
            throw new EndEditingException(e);
656
        }
657
    }
658

    
659
    private void doAction(FLyrVect layer, int option) {
660
        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
661
        I18nManager i18n = ToolsLocator.getI18nManager();
662
        
663
        switch (option) {
664
        case SAVE_CHANGES:
665
            try {
666
                saveChanges(layer);
667
            } catch (VectorEditingException e) {
668
                String msg =
669
                    String.format("Changes can not be saved in %1$s",
670
                        layer.getName());
671
                LOGGER.info(msg, e);
672
                dialogs.messageDialog(                   
673
                    i18n.getTranslation("_There_are_problems_saving_changes")+"\n\n"+
674
                    i18n.getTranslation("_See_error_log_for_more_information"), 
675
                    null, 
676
                    i18n.getTranslation("_Warning"), 
677
                    JOptionPane.WARNING_MESSAGE, 
678
                    "Vectorediting_cant_save_changes"
679
                );
680
                return;
681
            }
682
            break;
683

    
684
        case DISCARD_CHANGES:
685
            try {
686
                discardChanges(layer);
687
            } catch (VectorEditingException e) {
688
                String msg =
689
                    String.format("Changes can not be discared in %1$s",
690
                        layer.getName());
691
                LOGGER.info(msg, e);
692
                dialogs.messageDialog(                   
693
                    i18n.getTranslation("_There_are_problems_discarding_changes")+"\n"+
694
                    "\n" + i18n.getTranslation("_See_error_log_for_more_information"), 
695
                    null, 
696
                    i18n.getTranslation("_Warning"), 
697
                    JOptionPane.WARNING_MESSAGE, 
698
                    "Vectorediting_cant_discard_changes"
699
                );
700
                return;
701
            }
702
            break;
703

    
704
        case EXPORT_LAYER:
705
            try {
706
                exportLayer(layer);
707
            } catch (VectorEditingException e) {
708
                String msg =
709
                    String.format("Changes of %1$s can not be exported",
710
                        layer.getName());
711
                LOGGER.info(msg, e);
712
                dialogs.messageDialog(                   
713
                    i18n.getTranslation("_There_are_problems_exporting_changes")+"\n\n"+
714
                    i18n.getTranslation("_See_error_log_for_more_information"), 
715
                    null, 
716
                    i18n.getTranslation("_Warning"), 
717
                    JOptionPane.WARNING_MESSAGE, 
718
                    "Vectorediting_cant_export_changes"
719
                );
720
                return;
721
            }
722
            break;
723

    
724
        case CANCEL:
725
            return;
726
        }
727

    
728
        cleanEditingContext();
729
        hideConsole();
730
        disableSnapping();
731
        changeSelectedTool(DEFAULT_TOOL);
732

    
733
        FeatureStore featureStore = layer.getFeatureStore();
734
        featureStore.deleteObserver(getMapControl());
735

    
736
    }
737

    
738
    private void enableSelection(boolean enableSelection) {
739
        this.getEditingCompoundBehavior().setDrawnBehavior(
740
                EditingCompoundBehavior.SELECTION_INDEX, enableSelection);
741
    }
742

    
743
    @Override
744
    public void endEdition(FLyrVect layer) {
745
        if( this.isProcessing() ) {
746
            return;
747
        }
748
        if (layer.isEditing()) {
749
            EditingNotificationManager editingNotificationManager =
750
                DALSwingLocator.getEditingNotificationManager();
751

    
752
            EditingNotification notification =
753
                editingNotificationManager.notifyObservers(this,
754
                    EditingNotification.BEFORE_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
755

    
756
            if (notification.isCanceled()) {
757
                String msg =
758
                    String.format(
759
                        "Stop edit layer %1$s canceled by somme observer.",
760
                        layer.getName());
761
                LOGGER.info(msg, new EndEditingException(msg, null));
762

    
763
            }
764

    
765
            getMapControl().getCanceldraw().setCanceled(true);
766
            int option;
767
            EditingSwingManager swingManager =
768
                EditingSwingLocator.getSwingManager();
769

    
770

    
771
            if (layer.isWritable() && getMapControl().getProjection().equals(layer.getProjection()) ) {
772
                option =
773
                    swingManager.showPanelSaveOrDiscard(getMapControl(),
774
                        layer.getName());
775
            } else {
776
                option =
777
                    swingManager.showPanelExportOrDiscard(getMapControl(),
778
                        layer.getName());
779
            }
780

    
781
            doAction(layer, option);
782

    
783
            editingNotificationManager.notifyObservers(this,
784
                EditingNotification.AFTER_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
785

    
786
        }
787

    
788
    }
789

    
790
    private void exportLayer(FLyrVect layer) throws EndEditingException {
791
        Notification notification = new BaseNotification(EditingContext.EXPORT_LAYER_NOTIFICATION,1);
792
        notification.setValue(layer);
793
        this.observableHelper.notifyObservers(this, notification);
794
    }
795

    
796
    protected void finishService() {
797
        enqueueTask(() -> {
798
            doFinishService();
799
        });
800
        refreshMenusAndToolBars();
801
    }
802

    
803
    private void doFinishService() {
804
        try {
805
            EditingService lastService = serviceStack.pop();
806
            try {
807
                if (!serviceStack.isEmpty()
808
                        && getActiveService().next().getTypes().contains(TYPE.GEOMETRY)) {
809
                    Geometry geometry = lastService.finish();
810
                    lastService.setShowPreviewSymbol(true);
811
                    if (geometry != null) {
812
                        getActiveService().setValue(geometry);
813
                    }
814
                } else {
815
                    lastService.finishAndStore();
816
                    getMapControl().rePaintDirtyLayers();
817
                    refreshMenusAndToolBars();
818

    
819
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
820
                    showConsoleMessage("\n"
821
                            + i18nManager.getTranslation(lastService.getName()) + "# "
822
                            + i18nManager.getTranslation("finished") + "\n");
823
//                lastService.stop();
824
                    setActiveService(lastService);
825
//                lastService.start();
826
                    lastService.restart();
827
                    setDrawMode(DRAWMODE_NORMAL);
828
                    changeSelectedTool(getActiveService().getName());
829
                }
830

    
831
            } catch (FinishServiceException ex) {
832
                showConsoleMessage("\n"+ex.getLocalizedMessage());
833
                cleanEditingContext();
834
                return;
835
            } catch (InvalidEntryException ex) {
836
                I18nManager i18nManager = ToolsLocator.getI18nManager();
837
                showConsoleMessage("\n"
838
                        + i18nManager.getTranslation("invalid_option"));
839
                changeSelectedTool(getActiveService().getName());
840
            } catch (Exception ex) {
841
                LOGGER.warn("Can't finish " + lastService.getName(), ex);
842
                I18nManager i18nManager = ToolsLocator.getI18nManager();
843
                showConsoleMessage("\n"+i18nManager.getTranslation("_An_error_has_occurred"));
844
                cleanEditingContext();
845
                return;
846
            }
847

    
848
            doNextParameter();
849
        } finally {
850
            refreshMenusAndToolBars();
851
        }
852
    }
853

    
854
    public EditingService getActiveService() {
855
        if (!serviceStack.isEmpty()) {
856
            return serviceStack.peek();
857
        }
858
        return null;
859
    }
860

    
861
    public EditingConsole getConsolePanel() {
862
        if (console == null) {
863
            console = new DefaultEditingConsole(new ResponseListener() {
864

    
865
                @Override
866
                public void acceptResponse(String response) {
867
                    textEntered(response);
868
                }
869
            });
870
        }
871
        return console;
872
    }
873

    
874
    protected FLyrVect getCurrentLayer() {
875
        return this.currentLayer;
876
    }
877

    
878
    protected EditingServiceParameter getCurrentParam() {
879
        return this.currentParam;
880
    }
881

    
882
    private Component getDockConsole() {
883
        if (dockConsole == null) {
884
            dockConsole = new JDockPanel((JComponent) getConsolePanel());
885
        }
886
        return dockConsole;
887
    }
888

    
889
    private DefaultEditingBehavior getEditingBehavior() {
890
        if (editingCompoundBehavior != null) {
891
            return (DefaultEditingBehavior) editingCompoundBehavior
892
                .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
893
        }
894
        return null;
895
    }
896

    
897
    private EditingCompoundBehavior getEditingCompoundBehavior() {
898
        if (editingCompoundBehavior != null) {
899
            return editingCompoundBehavior;
900
        } else {
901
            EditingCompoundBehavior editingCompoundBehavior;
902

    
903
            CompoundBehavior compoundBehavior =
904
                (CompoundBehavior) getMapControl().getMapTool(VECTOREDITING_TOOL_NAME);
905

    
906
            if (compoundBehavior instanceof EditingCompoundBehavior) {
907
                editingCompoundBehavior =
908
                    (EditingCompoundBehavior) compoundBehavior;
909
            } else {
910
                editingCompoundBehavior =
911
                    (EditingCompoundBehavior) compoundBehavior.getBehavior(0);
912
            }
913

    
914
            setCompoundBehavior(editingCompoundBehavior);
915
            return editingCompoundBehavior;
916
        }
917
    }
918

    
919
    @Override
920
    public MapControl getMapControl() {
921
        return mapControlReference.get();
922
    }
923

    
924
    
925
    @Override
926
    public void nextParameter() {
927
        enqueueTask(() -> {
928
            doNextParameter();
929
        });
930
    }
931
    
932
    private void doNextParameter() {
933
        if ((getMapControl().getCurrentTool() != null)
934
            && !getMapControl().getCurrentTool().equals(VECTOREDITING_TOOL_NAME)) {
935
            getMapControl().setTool(VECTOREDITING_TOOL_NAME);
936
        }
937
        EditingService activeService = getActiveService();
938
        currentParam = activeService.next();
939

    
940
        if (currentParam == null) {
941
            doFinishService();
942
        } else {
943
            askQuestion(currentParam);
944
            if (currentParam.getTypes().contains(TYPE.SELECTION)) {
945
                enableSelection(true);
946
            } else if (currentParam.getTypes().contains(TYPE.MULTILAYER_SELECTION)) {
947
                enableSelection(true);
948
            } else if (currentParam.getTypes().contains(TYPE.GEOMETRY)) {
949
                refreshMenusAndToolBars();
950
            }
951
        }
952
    }
953

    
954
    protected Stack<EditingService> getServiceStack() {
955
        return this.serviceStack;
956
    }
957

    
958
    private void hideConsole() {
959
        isShowConsole = false;
960
        if( !SwingUtilities.isEventDispatchThread() ) {
961
            try {
962
                SwingUtilities.invokeAndWait(new Runnable() {
963

    
964
                    @Override
965
                    public void run() {
966
                        hideConsole();
967
                    }
968
                });
969
                return;
970
            } catch (InterruptedException | InvocationTargetException ex) {
971
                LOGGER.warn("Can't hide editing console.",ex);
972
            }
973
            return;
974
        }
975
        getDockConsole().setVisible(false);
976
    }
977

    
978
    @Override
979
    public boolean isServiceCompatible(String name) {
980
        DefaultEditingBehavior editingBehavior = getEditingBehavior();
981

    
982
        if (editingBehavior != null) {
983

    
984
            try {
985
                EditingManager manager = EditingLocator.getManager();
986
                EditingServiceInfo serviceInfo = manager.getServiceInfo(name);
987
                GeometryType geoType = null;
988

    
989
                for (EditingService editingService : getServiceStack()) {
990
                    EditingServiceParameter parameter = editingService.next();
991
                    if (parameter != null) {
992
                        if (parameter.getTypes().contains(TYPE.GEOMETRY)) {
993

    
994
                            int geometryType = parameter.getGeometryType();
995
                            int subType = -1;
996

    
997
                            try {
998
                                subType
999
                                        = getCurrentLayer().getFeatureStore()
1000
                                                .getDefaultFeatureType()
1001
                                                .getDefaultGeometryAttribute()
1002
                                                .getGeomType().getSubType();
1003

    
1004
                                geoType
1005
                                        = GeometryLocator.getGeometryManager()
1006
                                                .getGeometryType(geometryType, subType);
1007
                            } catch (Exception e) {
1008

    
1009
                                String msg
1010
                                        = String.format(
1011
                                                "Problems getting default feature"
1012
                                                + " type of %1$s or getting geometry"
1013
                                                + " type of %2$s %3$s",
1014
                                                getCurrentLayer().getName(), geometryType,
1015
                                                subType);
1016

    
1017
                                throw new ServiceInformationException(msg, e);
1018
                            }
1019

    
1020
                            return serviceInfo.isCompatibleWith(geoType)
1021
                                    && serviceInfo.createsNewGeometries();
1022
                        }
1023
                    }
1024
                }
1025

    
1026
                if (getCurrentLayer() != null) {
1027
                    try {
1028
                        geoType
1029
                                = getCurrentLayer().getFeatureStore()
1030
                                        .getDefaultFeatureType()
1031
                                        .getDefaultGeometryAttribute().getGeomType();
1032

    
1033
                        if (serviceInfo.isCompatibleWith(geoType)) {
1034
                            return true;
1035
                        }
1036
                    } catch (DataException e) {
1037
                        String msg
1038
                                = String.format("Problems getting default "
1039
                                        + "feature type of %1$s", getCurrentLayer()
1040
                                                .getName());
1041
                        throw new ServiceInformationException(msg, e);
1042
                    }
1043
                }
1044

    
1045
                return false;
1046
            } catch (ServiceInformationException e) {
1047
                LOGGER.warn(
1048
                    "Problems getting if editing context is compatible with "
1049
                        + name, e);
1050
            }
1051
        }
1052
        return false;
1053
    }
1054
     
1055
    private static final EditingContextSymbolTable contextSymbolTable = new EditingContextSymbolTable();
1056
    
1057
    @Override
1058
    public SymbolTable getContextSymbolTable() {
1059
        return contextSymbolTable;
1060
    }
1061
    
1062
    @Override
1063
    public Point parsePoint(String response) throws ParsePointException {
1064
        response = fixResponseUsingBookmarks(response);
1065
        
1066
        try {
1067
            Object x = ExpressionUtils.evaluate(contextSymbolTable, response);
1068
            if( x instanceof Point ) {
1069
                contextSymbolTable.addPoint((Point) x);
1070
                return (Point) x;
1071
            }
1072
        } catch(Exception ex) {
1073
            LOGGER.debug("Can't evaluate: "+StringEscapeUtils.escapeJava(response),ex);
1074
        }
1075
        String s = "ST_MakePoint("+response+")";
1076
        try {
1077
            Object x = ExpressionUtils.evaluate(contextSymbolTable, s);
1078
            if( x instanceof Point ) {
1079
                contextSymbolTable.addPoint((Point) x);
1080
                return (Point) x;
1081
            }
1082
        } catch(Exception ex) {
1083
            throw new ParsePointException(ex);
1084
        }
1085
        throw new ParsePointException(null);
1086
    }
1087
    
1088
    private Double parseValue(String response) throws ParseValueException {
1089
        response = fixResponseUsingBookmarks(response);
1090

    
1091
        try {
1092
            Object x = ExpressionUtils.evaluate(contextSymbolTable, response);
1093
            if( x instanceof Double ) {
1094
                return (Double) x;
1095
            }  
1096
            if( x==null ) {
1097
                throw new ParseValueException(new NullPointerException());
1098
            }
1099
            Coercion toDouble = ToolsLocator.getDataTypesManager().get(DataTypes.DOUBLE).getCoercion();
1100
            return (Double) toDouble.coerce(x);
1101
        } catch(Exception ex) {
1102
            throw new ParseValueException(ex);
1103
        }
1104

    
1105
    }
1106

    
1107
    protected String fixResponseUsingBookmarks(String response) throws LocatorException {
1108
        if( response != null ) {
1109
            response = response.trim();
1110
            int n = StringUtils.indexOf(response, " ");
1111
            if(n>0){
1112
                String name = StringUtils.left(response, n);
1113
                Function fn = contextSymbolTable.function(name);
1114
                if(fn != null){
1115
                    response = name+"("+response.substring(n)+")";
1116
                }
1117
            }
1118
        }
1119
        return response;
1120
    }
1121

    
1122
    protected void refreshMenusAndToolBars() {
1123
        if (!SwingUtilities.isEventDispatchThread()) {
1124
            SwingUtilities.invokeLater(() -> { refreshMenusAndToolBars(); });
1125
            return;
1126
        }
1127
        Notification notification = new BaseNotification(
1128
                EditingContext.REFRESH_TOOLS_NOTIFICATION,
1129
                null
1130
        );
1131
        this.observableHelper.notifyObservers(this, notification);
1132
    }
1133

    
1134
    private void saveChanges(FLyrVect layer) throws EndEditingException {
1135
        FeatureStore featureStore = layer.getFeatureStore();
1136
        try {
1137
            featureStore.finishEditing();
1138
        } catch (Exception e) {
1139
            throw new EndEditingException(e);
1140
        }
1141
    }
1142

    
1143
    private void setActiveService(EditingService service) {
1144
        //Si se hace este metodo publico hay que comprobar el isProcessing
1145
        serviceStack.add(service);
1146
        notifyChangeSelectedTool(service.getName());
1147
    }
1148

    
1149
    private void setCompoundBehavior(EditingCompoundBehavior compoundBehavior) {
1150
        if( this.isProcessing() ) {
1151
            return;
1152
        }
1153
        this.editingCompoundBehavior = compoundBehavior;
1154
    }
1155

    
1156
    private void setCurrentLayer(FLyrVect layer) {
1157
        if( this.isProcessing() ) {
1158
            return;
1159
        }
1160
        if (this.currentLayer != layer) {
1161
            this.currentLayer = layer;
1162
            if( !this.serviceStack.isEmpty() ) {
1163
                EditingService x = this.serviceStack.firstElement();
1164
                if( x != null && this.isServiceCompatible(x.getName())) {
1165
                    String name = x.getName();
1166
                    cleanEditingContext();
1167
                    this.serviceStack.clear();
1168
                    this.activateService(name);
1169
                } else {
1170
                    cleanEditingContext();
1171
                }
1172
            }
1173
        }
1174

    
1175
    }
1176

    
1177
    @Override
1178
    public void setMapControl(MapControl mapControl) {
1179
        if( this.isProcessing() ) {
1180
            return;
1181
        }
1182

    
1183
        this.mapControlReference = new WeakReference<>(mapControl);
1184
        this.mapContextReference =
1185
            new WeakReference<>(mapControl.getMapContext());
1186

    
1187
        // When mapControl is updated we have to add older additional behaviors
1188
        // to new mapControl
1189
        if (lastAdditionalBehaviors != null) {
1190
            try {
1191
                addBehaviors(lastAdditionalBehaviors);
1192
            } catch (CreateEditingBehaviorException e1) {
1193
                LOGGER.info("Problems adding behaviors to editing context", e1);
1194
                getMapControl().setTool("pan");
1195
            }
1196
        }
1197
    }
1198

    
1199
    private void showConsole() {
1200
        if (isShowConsole) {
1201
            return;
1202
        }
1203
        if( !SwingUtilities.isEventDispatchThread() ) {
1204
            try {
1205
                SwingUtilities.invokeAndWait(new Runnable() {
1206

    
1207
                    @Override
1208
                    public void run() {
1209
                        showConsole();
1210
                    }
1211
                });
1212
                return;
1213
            } catch (InterruptedException | InvocationTargetException ex) {
1214
                LOGGER.warn("Can't show editing console.",ex);
1215
            }
1216
            return;
1217
        }
1218
        isShowConsole = true;
1219
        getMapControl().remove(getDockConsole());
1220
        getMapControl().setLayout(new BorderLayout());
1221
        getMapControl().add(getDockConsole(), BorderLayout.SOUTH);
1222
        getDockConsole().setVisible(true);
1223
    }
1224

    
1225
    protected void showConsoleMessage(final String text) {
1226
        if (!SwingUtilities.isEventDispatchThread()) {
1227
            SwingUtilities.invokeLater(new Runnable() {
1228

    
1229
                @Override
1230
                public void run() {
1231
                    showConsoleMessage(text);
1232
                }
1233
            });
1234
            return;
1235
        }
1236
        getConsolePanel().addText(text);
1237
    }
1238

    
1239
    @Override
1240
    public void cancelActiveService() {
1241
        this.textEntered(null);
1242
    }
1243
    
1244
//    protected void selectedValue(Object value) {
1245
//        EditingService activeService = getActiveService();
1246
//        I18nManager i18nManager = ToolsLocator.getI18nManager();
1247
//        
1248
//        try {
1249
//            activeService.setValue(value);
1250
//        } catch (InvalidEntryException ex) {
1251
//            showConsoleMessage("\n"
1252
//                    + i18nManager.getTranslation("invalid_option"));
1253
//        }
1254
//
1255
//        activeService = getActiveService();
1256
//        if (activeService != null) {
1257
//            nextParameter();
1258
//        } else {
1259
//            cleanEditingContext();
1260
//        }
1261
//
1262
//    }
1263
    
1264
    protected void textEntered(String response) {
1265
        if( this.isProcessing() ) {
1266
            return;
1267
        }
1268
        FeatureStore featureStore = getCurrentLayer().getFeatureStore();        
1269
        if (response == null) {
1270
            EditingService activeService = getActiveService();
1271
            if (activeService != null) {
1272
                try {
1273
                    activeService.stop();
1274
                    serviceStack.pop();
1275
                    if (serviceStack.isEmpty()) {
1276
                        featureStore
1277
                            .getFeatureSelection().deselectAll();
1278
                        changeSelectedTool(DEFAULT_TOOL);
1279
                    } else {
1280
                        changeSelectedTool(activeService.getName());
1281
                    }
1282

    
1283
                    refreshMenusAndToolBars();
1284
                    activeService = getActiveService();
1285
                    if (activeService != null) {
1286
                        nextParameter();
1287
                    } else {
1288
                        cleanEditingContext();
1289
                    }
1290

    
1291
                } catch (StopServiceException e) {
1292
                    LOGGER
1293
                        .info("Can't stop " + activeService.getName(), e);
1294
                } catch (DataException e) {
1295
                    LOGGER.info("Can't get selection of "
1296
                        + featureStore.getFullName(), e);
1297
                }
1298
            }
1299
        } else {
1300
            enqueueTask(() -> {
1301
                try {
1302
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
1303
                    EditingService activeService = getActiveService();
1304
                    if (getCurrentParam() != null) {
1305
                        try {
1306
                            Object coercedValue = coerceInputParameter(getCurrentParam(), response);
1307
                            activeService.setValue(coercedValue);
1308
                        } catch (InvalidEntryException ex) {
1309
                            showConsoleMessage("\n"
1310
                                    + i18nManager.getTranslation("invalid_option"));
1311
                        }
1312
                    }
1313

    
1314
                    activeService = getActiveService();
1315
                    if (activeService != null) {
1316
                        doNextParameter();
1317
                    } else {
1318
                        cleanEditingContext();
1319
                    }
1320
                } finally {
1321
                    refreshMenusAndToolBars();
1322
                }
1323
            });
1324
            refreshMenusAndToolBars();
1325
        }
1326
    }
1327
    
1328
    private Object coerceInputParameter(EditingServiceParameter parameter, String input) throws InvalidEntryException {
1329
        if (parameter != null) {
1330
            FeatureStore featureStore = getCurrentLayer().getFeatureStore();
1331
            Set<TYPE> types = parameter.getTypes();
1332
            Point point = null;
1333
            Double value = null;
1334
            Point defaultPoint = null;
1335
            Object defaultValue = parameter.getDefaultValue();
1336

    
1337
//            boolean insertedValue = false;
1338
            if ((types.contains(TYPE.POSITION))
1339
                    || types.contains(TYPE.LIST_POSITIONS)) {
1340

    
1341
                if(defaultValue instanceof Point){
1342
                    defaultPoint = (Point) defaultValue;
1343
                }
1344
                try {
1345
                    if (StringUtils.isEmpty(input.replace("\n", ""))) {
1346
                        point = defaultPoint;
1347
                    } else {
1348
                        point = parsePoint(input);
1349
                    }
1350

    
1351
                    if (point != null) {
1352
                        return point;
1353
                    }
1354

    
1355
                } catch (ParsePointException e) {
1356
                    // Do nothing to try other types
1357
                }
1358
            }
1359
            if (types.contains(TYPE.VALUE)) {
1360

    
1361
                try {
1362
                    value = parseValue(input);
1363
                    if (value != null) {
1364
                        return value;
1365
                    }
1366

    
1367
                } catch (ParseValueException e) {
1368
                    // Do nothing to try other types
1369
                }
1370

    
1371
            }
1372
            if (types.contains(TYPE.OPTION)) {
1373
                input = input.replace("\n", "");
1374
                return input;
1375
            }
1376

    
1377
            if (types.contains(TYPE.SELECTION)) {
1378
                if (input.equalsIgnoreCase("\n")) {
1379
                    enableSelection(false);
1380

    
1381
                    FeatureSelection clonedSelection;
1382
                    try {
1383
                        clonedSelection = (FeatureSelection) featureStore
1384
                                .getFeatureSelection().clone();
1385
                        if (!clonedSelection.isEmpty()) {
1386
                            return clonedSelection;
1387
                        }
1388
                    } catch (Exception e) {
1389
                        LOGGER.warn("Can't access to selection.", e);
1390
                        throw new InvalidEntryException(e);
1391
                    }
1392
                }
1393
            }
1394

    
1395
            if (types.contains(TYPE.MULTILAYER_SELECTION)) {
1396
                if (input.equalsIgnoreCase("\n")) {
1397
                    enableSelection(false);
1398
                    MapContext mapContext = this.getMapControl().getMapContext();
1399
                    List<Feature> features = new ArrayList<>();
1400
                    for (FLayer lyrActive : mapContext.getLayers().getActives()) {
1401
                        if(lyrActive instanceof FLyrVect){
1402
                            if(!((FLyrVect) lyrActive).getFeatureStore().isFeatureSelectionEmpty()) {
1403
                                this.getSelectedFeaturesCopy(features, ((FLyrVect) lyrActive).getFeatureStore().getFeatureSelectionQuietly());
1404
                            }
1405
                        }
1406
                    }
1407
                    if(!features.isEmpty()){
1408
                        return features;
1409
                    }
1410
                }
1411
            }
1412
        }
1413
        return null;
1414
    }
1415
    
1416
    private List<Feature> getSelectedFeaturesCopy(List<Feature> features, FeatureSelection selection)  {
1417
        SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Loading selection");
1418
        try {
1419
            status.add();
1420
            status.setAutoremove(true);
1421
            status.setRangeOfValues(0, selection.size());
1422
            if(features == null){
1423
                features = new ArrayList<>();
1424
            }
1425
            DisposableIterator it = selection.fastIterator();
1426
            while (it.hasNext()) {
1427
                if( status.isCancellationRequested() ) {
1428
                    status.cancel();
1429
                    return features;
1430
                }
1431
                Feature feature = (Feature) it.next();
1432
                if( feature.getDefaultGeometry()==null ) {
1433
                    continue;
1434
                }
1435
                features.add(feature.getCopy());
1436
                status.incrementCurrentValue();
1437
            }
1438
            status.terminate();
1439
            return features;
1440
        } catch (DataException ex) {
1441
            status.abort();
1442
            throw new RuntimeException("Can't calculate selected features", ex);
1443
        }
1444
    }
1445

    
1446
    @Override
1447
    public void setDefaultBehaviors(Behavior[] defaultBehaviors) {
1448
        if( this.isProcessing() ) {
1449
            return;
1450
        }
1451
        this.defaultBehaviors = defaultBehaviors;
1452
        try {
1453
            addBehaviors(defaultBehaviors);
1454
        } catch (CreateEditingBehaviorException e1) {
1455
            LOGGER.info("Problems adding behaviors to editing context", e1);
1456
            getMapControl().setTool("pan");
1457
        }
1458
    }
1459

    
1460
    @Override
1461
    public Behavior[] getDefaultBehaviors() {
1462
        return this.defaultBehaviors;
1463
    }
1464

    
1465
    @Override
1466
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
1467
        setValue(parameter, value, false);
1468
    }
1469
    
1470
    private static class TasksDispatcher extends Thread {
1471
        private BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();
1472
        private boolean processing = false;
1473
        private final JComponent component;
1474
        private Cursor lastNoBusyCursor = null;
1475

    
1476
        public TasksDispatcher(JComponent component) {
1477
            this.component = component;
1478
        }
1479

    
1480
        public void setMouseBusy(boolean busy) {
1481
            if (busy) {
1482
                if (lastNoBusyCursor == null) {
1483
                    this.lastNoBusyCursor = component.getCursor();
1484
                }
1485
                component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1486
            } else {
1487
                component.setCursor(lastNoBusyCursor);
1488
                lastNoBusyCursor = null;
1489
            }
1490
        }
1491

    
1492
        public void run() {
1493
            while (true){
1494
                try {
1495
                    Runnable task = tasks.poll(1, TimeUnit.MINUTES);
1496
                    if(task == null){
1497
                        return;
1498
                    }
1499
                    this.processing = true;
1500
                    setMouseBusy(true);
1501
                    task.run();
1502
                    if(tasks.isEmpty()){
1503
                        this.processing = false;
1504
                        setMouseBusy(false);
1505
                    }
1506
                    
1507
                } catch (Throwable t) {
1508
                    LOGGER.warn("Can't proccess task", t);
1509
                }
1510
            }
1511
        }
1512
        public void add(Runnable task){
1513
            try {
1514
                this.tasks.put(task);
1515
            } catch (InterruptedException ex) {
1516
                throw new RuntimeException("Can't addd task", ex);
1517
            }
1518
        }
1519
        public boolean isProcessing() {
1520
            if(!this.isAlive()){
1521
                return false;
1522
            }
1523
            return this.processing;
1524
        }
1525
    }
1526

    
1527
    TasksDispatcher tasksDispatcher = null;
1528
    
1529
    @Override
1530
    public void setValue(EditingServiceParameter parameter, Object value, boolean next) throws InvalidEntryException {
1531
        
1532
        
1533
        if( value instanceof CharSequence){
1534
            value = coerceInputParameter(parameter, value.toString());
1535
        } else if( value instanceof Point) {
1536
            contextSymbolTable.addPoint((Point) value);
1537
        }
1538
        Object v = value;
1539
        Runnable task = () -> {
1540
            try {
1541
                getActiveService().setValue(parameter, v);
1542
                if(next){
1543
                    doNextParameter();
1544
                }
1545
            } catch (InvalidEntryException ex) {
1546
                I18nManager i18nManager = ToolsLocator.getI18nManager();
1547
                String stateMessage = ex.getStateMessage();
1548
                if(StringUtils.isBlank(stateMessage)){
1549
                    showConsoleMessage("\n"+ i18nManager.getTranslation("invalid_option"));
1550
                } else {
1551
                    showConsoleMessage("\n"+ i18nManager.getTranslation("invalid_option")+": "+StringUtils.defaultIfBlank(ex.getStateMessage(), ""));
1552
                }
1553
                doNextParameter();
1554
            } catch (Exception ex) {
1555
                LOGGER.warn("Can't set value", ex);
1556
                cleanEditingContext();
1557
                return;
1558
            } finally {
1559
                refreshMenusAndToolBars();
1560
            }
1561
        };
1562
        enqueueTask(task);
1563
        refreshMenusAndToolBars();
1564
        
1565
        
1566
    }
1567

    
1568
    private void enqueueTask(Runnable task) {
1569
        if(this.tasksDispatcher == null || !this.tasksDispatcher.isAlive()){
1570
            this.tasksDispatcher = new TasksDispatcher(this.getMapControl());
1571
            this.tasksDispatcher.start();
1572
        }
1573
        this.tasksDispatcher.add(task);
1574
    }
1575

    
1576
    public GeometryType getGeometryType() {
1577
        if( this.currentLayer==null ) {
1578
            return null;
1579
        }
1580
        FeatureStore store = this.currentLayer.getFeatureStore();
1581
        if( store == null ) {
1582
            return null;
1583
        }
1584
        FeatureType ftype = store.getDefaultFeatureTypeQuietly();
1585
        if( ftype == null ) {
1586
            return null;
1587
        }
1588
        FeatureAttributeDescriptor geomattr = ftype.getDefaultGeometryAttribute();
1589
        if( geomattr == null ) {
1590
            return null;
1591
        }
1592
        return geomattr.getGeomType();
1593
    }    
1594
    
1595
    public boolean isProcessing() {
1596
        if(this.tasksDispatcher == null){
1597
            return false;
1598
        }
1599
        return this.tasksDispatcher.isProcessing();
1600
    }
1601
    
1602
    @Override
1603
    public int getDrawMode() {
1604
        return this.drawMode;
1605
    }
1606

    
1607
    @Override
1608
    public void setDrawMode(int mode) {
1609
        this.drawMode = mode;
1610
        refreshMenusAndToolBars();
1611
    }
1612
}