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 159 llmarques
/**
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 89 llmarques
 */
24 159 llmarques
25 89 llmarques
package org.gvsig.vectorediting.swing.impl;
26
27
import java.awt.BorderLayout;
28
import java.awt.Component;
29 3140 jjdelcerro
import java.awt.Cursor;
30 150 llmarques
import java.lang.ref.WeakReference;
31 876 jjdelcerro
import java.lang.reflect.InvocationTargetException;
32 366 llmarques
import java.util.ArrayList;
33 2444 fdiaz
import java.util.HashSet;
34 3618 fdiaz
import java.util.List;
35 226 llmarques
import java.util.Set;
36
import java.util.Stack;
37 3321 fdiaz
import java.util.concurrent.BlockingQueue;
38
import java.util.concurrent.LinkedBlockingQueue;
39
import java.util.concurrent.TimeUnit;
40 366 llmarques
import java.util.prefs.PreferenceChangeEvent;
41
import java.util.prefs.PreferenceChangeListener;
42
import java.util.prefs.Preferences;
43 376 llmarques
import javax.swing.JComponent;
44 1234 jjdelcerro
import javax.swing.JOptionPane;
45 876 jjdelcerro
import javax.swing.SwingUtilities;
46 2444 fdiaz
import org.apache.commons.lang3.StringUtils;
47 2611 jjdelcerro
import org.apache.commons.text.StringEscapeUtils;
48 2444 fdiaz
import org.gvsig.expressionevaluator.ExpressionUtils;
49 2611 jjdelcerro
import org.gvsig.expressionevaluator.Function;
50
import org.gvsig.expressionevaluator.SymbolTable;
51 2444 fdiaz
import org.gvsig.fmap.dal.DataTypes;
52
import org.gvsig.fmap.dal.EditingNotification;
53
import org.gvsig.fmap.dal.EditingNotificationManager;
54 226 llmarques
import org.gvsig.fmap.dal.exception.DataException;
55 3618 fdiaz
import org.gvsig.fmap.dal.feature.Feature;
56 2611 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57 1143 fdiaz
import org.gvsig.fmap.dal.feature.FeatureSelection;
58 89 llmarques
import org.gvsig.fmap.dal.feature.FeatureStore;
59 2611 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
60 2444 fdiaz
import org.gvsig.fmap.dal.swing.DALSwingLocator;
61 226 llmarques
import org.gvsig.fmap.geom.Geometry;
62
import org.gvsig.fmap.geom.GeometryLocator;
63 2444 fdiaz
import org.gvsig.fmap.geom.primitive.Point;
64 226 llmarques
import org.gvsig.fmap.geom.type.GeometryType;
65 89 llmarques
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 2444 fdiaz
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
75 89 llmarques
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
76 2616 fdiaz
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
77 89 llmarques
import org.gvsig.fmap.mapcontrol.MapControl;
78 2444 fdiaz
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
79 89 llmarques
import org.gvsig.fmap.mapcontrol.tools.CompoundBehavior;
80 226 llmarques
import org.gvsig.tools.ToolsLocator;
81 2444 fdiaz
import org.gvsig.tools.dataTypes.Coercion;
82 3618 fdiaz
import org.gvsig.tools.dispose.DisposableIterator;
83 226 llmarques
import org.gvsig.tools.i18n.I18nManager;
84 2609 fdiaz
import org.gvsig.tools.locator.LocatorException;
85 303 fdiaz
import org.gvsig.tools.observer.BaseNotification;
86
import org.gvsig.tools.observer.Notification;
87 157 llmarques
import org.gvsig.tools.observer.ObservableHelper;
88
import org.gvsig.tools.observer.Observer;
89 2444 fdiaz
import org.gvsig.tools.swing.api.ToolsSwingLocator;
90
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
91 3618 fdiaz
import org.gvsig.tools.task.SimpleTaskStatus;
92 89 llmarques
import org.gvsig.utils.console.JDockPanel;
93
import org.gvsig.utils.console.ResponseListener;
94 226 llmarques
import org.gvsig.vectorediting.lib.api.EditingLocator;
95 89 llmarques
import org.gvsig.vectorediting.lib.api.EditingManager;
96 226 llmarques
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 89 llmarques
import org.gvsig.vectorediting.lib.api.exceptions.CreateEditingBehaviorException;
101
import org.gvsig.vectorediting.lib.api.exceptions.EndEditingException;
102 3225 fdiaz
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
103 226 llmarques
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 157 llmarques
import org.gvsig.vectorediting.lib.api.exceptions.ServiceInformationException;
107 89 llmarques
import org.gvsig.vectorediting.lib.api.exceptions.StartEditingException;
108 226 llmarques
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
109
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
110 89 llmarques
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 376 llmarques
import org.gvsig.vectorediting.swing.api.console.EditingConsole;
115
import org.gvsig.vectorediting.swing.impl.console.DefaultEditingConsole;
116 547 llmarques
import org.slf4j.Logger;
117
import org.slf4j.LoggerFactory;
118 89 llmarques
119
public class DefaultEditingContext implements EditingContext {
120
121 2616 fdiaz
    private static final Logger LOGGER = LoggerFactory
122 109 llmarques
        .getLogger(EditingManager.class);
123 89 llmarques
124 150 llmarques
    private WeakReference<MapControl> mapControlReference;
125 89 llmarques
126 383 llmarques
    private WeakReference<MapContext> mapContextReference;
127 150 llmarques
128 109 llmarques
    private EditingCompoundBehavior editingCompoundBehavior;
129 89 llmarques
130 155 llmarques
    private Behavior[] lastAdditionalBehaviors;
131 150 llmarques
132 2109 fdiaz
    private final ObservableHelper observableHelper;
133 157 llmarques
134 376 llmarques
    private EditingConsole console;
135 89 llmarques
136 109 llmarques
    private JDockPanel dockConsole = null;
137 89 llmarques
138 109 llmarques
    private boolean isShowConsole = false;
139 89 llmarques
140 2109 fdiaz
    private final Stack<EditingService> serviceStack;
141 226 llmarques
142
    private FLyrVect currentLayer;
143
144
    private EditingServiceParameter currentParam;
145
146 438 fdiaz
    private Behavior[] defaultBehaviors;
147 2444 fdiaz
148
    private Set<FLyrVect> layersSpatialCacheEnabled = new HashSet<>();
149 3140 jjdelcerro
150 3321 fdiaz
//    private boolean processing;
151 3226 fdiaz
152
    private int drawMode;
153 438 fdiaz
154 2109 fdiaz
    private final LayerListener layerListener = new LayerListener() {
155 89 llmarques
156 876 jjdelcerro
        @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 1095 fdiaz
169 109 llmarques
            FLayer layer = e.getSource();
170 2109 fdiaz
            final MapContext mapContext = layer.getMapContext();
171 89 llmarques
172 2109 fdiaz
            if (countActiveAndEditingLayers(mapContext) > 1) {
173
                hideConsole();
174
                return;
175
            }
176 130 llmarques
177 2109 fdiaz
            if (layer instanceof FLyrVect) {
178 2444 fdiaz
                if (layer.isActive()) {
179
                    if(layer.isEditing()) {
180 3430 jjdelcerro
                        // 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 2444 fdiaz
                        setCurrentLayer((FLyrVect) layer);
184
                        showConsole();
185
                        return;
186
                    } else {
187
                        final SpatialCache spatialCache = ((FLyrVect) layer).getSpatialCache();
188 2943 fdiaz
                        if(!spatialCache.isEnabled("active")){
189
                            spatialCache.setEnabled("active",true);
190 2444 fdiaz
                            //We keep the list of layers whose spatial cache is enabled here.
191
                            layersSpatialCacheEnabled.add((FLyrVect) layer);
192 3618 fdiaz
                            ((FLyrVect) layer).refreshSpatialCache(mapContext.getViewPort().getEnvelope());
193 2444 fdiaz
                        }
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 2943 fdiaz
                        if(spatialCache.isEnabled("active") && layersSpatialCacheEnabled.contains((FLyrVect) layer)){
200
                            spatialCache.setEnabled("active",false);
201 2444 fdiaz
                            layersSpatialCacheEnabled.remove((FLyrVect) layer);
202
                        }
203
                    }
204 127 llmarques
                }
205
            }
206 109 llmarques
207 2109 fdiaz
            FLayer[] activeLayers =
208
                layer.getMapContext().getLayers().getActives();
209
210
            for (FLayer activeLayer : activeLayers) {
211
                if (activeLayer instanceof FLyrVect) {
212
                    if (activeLayer.isEditing()) {
213 3430 jjdelcerro
//                        getMapControl().setTool(VECTOREDITING_TOOL_NAME);
214 2109 fdiaz
                        setCurrentLayer((FLyrVect) activeLayer);
215
                        showConsole();
216
                        return;
217
                    }
218
                }
219
            }
220
221 127 llmarques
            hideConsole();
222 3430 jjdelcerro
//            if ((getMapControl().getCurrentTool() != null)
223
//                && getMapControl().getCurrentTool().equals(VECTOREDITING_TOOL_NAME)) {
224
//                getMapControl().setPrevTool();
225
//            }
226 89 llmarques
        }
227 109 llmarques
228 2109 fdiaz
        @Override
229 109 llmarques
        public void drawValueChanged(LayerEvent e) {
230 89 llmarques
        }
231
232 876 jjdelcerro
        @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 438 fdiaz
            FLayer layer = e.getSource();
245
246
            if (layer instanceof FLyrVect) {
247
                if (layer.isEditing()) {
248
                    synchronized (DefaultEditingContext.this) {
249 546 llmarques
                        beginEdition((FLyrVect) layer);
250 438 fdiaz
                        showConsole();
251
                    }
252
                } else {
253
                    hideConsole();
254
                }
255
            }
256
257 109 llmarques
        }
258 89 llmarques
259 2109 fdiaz
        @Override
260 109 llmarques
        public void nameChanged(LayerEvent e) {
261
        }
262 89 llmarques
263 2109 fdiaz
        @Override
264 109 llmarques
        public void visibilityChanged(LayerEvent e) {
265
        }
266
    };
267 2109 fdiaz
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 89 llmarques
285 2109 fdiaz
    private final PreferenceChangeListener preferenceChangeListener =
286 366 llmarques
        new PreferenceChangeListener() {
287
288 2109 fdiaz
            @Override
289 366 llmarques
            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 109 llmarques
    public DefaultEditingContext(MapControl mapControl) {
299 3321 fdiaz
//        this.processing = false;
300 2109 fdiaz
        this.mapControlReference = new WeakReference<>(mapControl);
301 383 llmarques
        this.mapContextReference =
302 2109 fdiaz
            new WeakReference<>(mapControl.getMapContext());
303 385 llmarques
        this.observableHelper = new ObservableHelper();
304 205 llmarques
305 2109 fdiaz
        this.serviceStack = new Stack<>();
306 3226 fdiaz
307
        this.drawMode = DRAWMODE_NORMAL;
308 226 llmarques
309 163 llmarques
        addLayerListeners();
310 366 llmarques
        addPreferenceListener();
311 109 llmarques
    }
312 89 llmarques
313 366 llmarques
    private void addPreferenceListener() {
314
        Preferences prefs = Preferences.userRoot().node("snappers");
315
        prefs.addPreferenceChangeListener(preferenceChangeListener);
316
    }
317
318 2109 fdiaz
    @Override
319 109 llmarques
    public void activateService(String name) {
320 3141 fdiaz
        if( this.isProcessing() ) {
321
            return;
322
        }
323 226 llmarques
324 227 llmarques
        if ((getMapControl() != null)
325 3430 jjdelcerro
            && getMapControl().hasTool(VECTOREDITING_TOOL_NAME)) {
326 226 llmarques
327 109 llmarques
            CompoundBehavior editingCompoundBehavior =
328
                getEditingCompoundBehavior();
329 3430 jjdelcerro
            getMapControl().setTool(VECTOREDITING_TOOL_NAME);
330 109 llmarques
            editingCompoundBehavior.setDrawnBehavior(
331
                EditingCompoundBehavior.EDITING_INDEX, true);
332 226 llmarques
333
            EditingManager manager = EditingLocator.getManager();
334
335
            if (currentLayer != null) {
336 2616 fdiaz
                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 226 llmarques
344 2616 fdiaz
//                EditingService activeService = getActiveService();
345
//                if(activeService != null && !activeService.next().getTypes().contains(TYPE.GEOMETRY)) {
346
//                    activeService.setShowPreviewSymbol(true);
347
//                }
348 226 llmarques
                EditingService service =
349 227 llmarques
                    manager.getEditingService(name,
350 383 llmarques
                        currentLayer.getFeatureStore(),
351 2616 fdiaz
                        mapContextReference.get(),
352
                        legend);
353 226 llmarques
354
                if (service != null) {
355 2616 fdiaz
//                     if(!serviceStack.isEmpty()) { service.setShowPreviewSymbol(false); }
356 226 llmarques
                    this.enableSelection(false);
357
358
                    try {
359 2444 fdiaz
                        service.activate();
360 3226 fdiaz
                        service.start();
361
                        setDrawMode(DRAWMODE_NORMAL);
362 226 llmarques
                    } catch (StartServiceException e) {
363 252 llmarques
364 2616 fdiaz
                        LOGGER.info(String.format(
365 226 llmarques
                            "Can't start the service %1$s", service.getName()),
366
                            e);
367
                        cleanEditingContext();
368
                        return;
369 252 llmarques
370
                    } catch (InvalidEntryException e) {
371
372
                        I18nManager i18nManager = ToolsLocator.getI18nManager();
373 376 llmarques
                        showConsoleMessage("\n"
374
                            + i18nManager.getTranslation("invalid_option"));
375 226 llmarques
                    }
376
377 2616 fdiaz
                    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 226 llmarques
                    }
386
387
                    setActiveService(service);
388 252 llmarques
389 2125 fdiaz
                    nextParameter();
390 226 llmarques
                }
391
            }
392 109 llmarques
        }
393
    }
394 89 llmarques
395 227 llmarques
    private void addBehaviors(Behavior[] additionalBehavior)
396
        throws CreateEditingBehaviorException {
397
398
        DefaultEditingBehavior editingBehavior;
399
        EditingCompoundBehavior editingCompoundBehavior;
400
401 3430 jjdelcerro
        if (!getMapControl().hasTool(VECTOREDITING_TOOL_NAME)) {
402 227 llmarques
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 2109 fdiaz
                System.arraycopy(additionalBehavior, 0, behaviors, 1, additionalBehavior.length);
415 227 llmarques
416 3430 jjdelcerro
                getMapControl().addBehavior(VECTOREDITING_TOOL_NAME, behaviors);
417 227 llmarques
418
                lastAdditionalBehaviors = additionalBehavior;
419
420
            } else {
421 3430 jjdelcerro
                getMapControl().addBehavior(VECTOREDITING_TOOL_NAME,
422 227 llmarques
                    editingCompoundBehavior);
423
            }
424
425
        } else {
426
            editingCompoundBehavior = getEditingCompoundBehavior();
427
            editingBehavior =
428
                (DefaultEditingBehavior) editingCompoundBehavior
429 245 llmarques
                    .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
430 227 llmarques
            setCompoundBehavior(editingCompoundBehavior);
431
            cleanEditingContext();
432
        }
433
434
    }
435
436
    private void addLayerListeners() {
437
438 383 llmarques
        FLayers layers = mapContextReference.get().getLayers();
439 227 llmarques
440
        layers.addLayerListener(layerListener);
441
442
        layers.addLayerCollectionListener(new LayerCollectionListener() {
443
444 546 llmarques
            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 227 llmarques
                    }
450 546 llmarques
                } else if (layer instanceof FLyrVect) {
451
                    ((FLyrVect) layer).addLayerListener(layerListener);
452 227 llmarques
                }
453
            }
454 842 fdiaz
455 2109 fdiaz
            @Override
456 546 llmarques
            public void layerAdded(LayerCollectionEvent e) {
457
                addLayer(e.getLayers());
458
            }
459 227 llmarques
460 2109 fdiaz
            @Override
461 227 llmarques
            public void layerAdding(LayerCollectionEvent e)
462
                throws CancelationException {
463
            }
464
465 2109 fdiaz
            @Override
466 227 llmarques
            public void layerMoved(LayerPositionEvent e) {
467
            }
468
469 2109 fdiaz
            @Override
470 227 llmarques
            public void layerMoving(LayerPositionEvent e)
471
                throws CancelationException {
472
            }
473 842 fdiaz
474 547 llmarques
            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 227 llmarques
                    }
480 547 llmarques
                } else if (layer instanceof FLyrVect) {
481
                    ((FLyrVect) layer).removeLayerListener(layerListener);
482 227 llmarques
                }
483
            }
484
485 2109 fdiaz
            @Override
486 547 llmarques
            public void layerRemoved(LayerCollectionEvent e) {
487
                removeLayer(e.getLayers());
488
            }
489
490 2109 fdiaz
            @Override
491 227 llmarques
            public void layerRemoving(LayerCollectionEvent e)
492
                throws CancelationException {
493
            }
494
495 2109 fdiaz
            @Override
496 227 llmarques
            public void visibilityChanged(LayerCollectionEvent e)
497
                throws CancelationException {
498
            }
499
        });
500
    }
501
502 2109 fdiaz
    @Override
503 227 llmarques
    public void addObserver(Observer o) {
504
        this.observableHelper.addObserver(o);
505
    }
506
507
    private void askQuestion(EditingServiceParameter param) {
508 245 llmarques
        I18nManager i18nManager = ToolsLocator.getI18nManager();
509
        String translation = i18nManager.getTranslation(param.getDescription());
510
        String activeServiceName =
511
            i18nManager.getTranslation(getActiveService().getName());
512 365 llmarques
513 2870 fdiaz
        String strDefaultValue = param.getConsoleDefaultValue();
514
515
        if(StringUtils.isBlank(strDefaultValue)) {
516
            showConsoleMessage("\n" + activeServiceName + "# " + translation + " : ");
517 365 llmarques
        } else {
518 2870 fdiaz
            showConsoleMessage("\n" + activeServiceName + "# " + translation + "<" + strDefaultValue + "> : ");
519 365 llmarques
        }
520 227 llmarques
    }
521 842 fdiaz
522 2109 fdiaz
    @Override
523 438 fdiaz
    public synchronized void beginEdition(FLyrVect layer,
524
        Behavior[] additionalBehaviors) {
525 842 fdiaz
526 546 llmarques
        try{
527
            throw new Exception("Deprecated method");
528
        } catch (Exception e){
529 2616 fdiaz
            LOGGER.info("Deprecated method", e);
530 546 llmarques
        }
531 842 fdiaz
532 546 llmarques
        beginEdition(layer);
533
        try {
534
            addBehaviors(additionalBehaviors);
535
        } catch (CreateEditingBehaviorException e1) {
536 2616 fdiaz
            LOGGER.info("Problems adding behaviors to editing context", e1);
537 546 llmarques
            getMapControl().setTool("pan");
538
        }
539
    }
540 842 fdiaz
541 2109 fdiaz
    @Override
542 842 fdiaz
    public synchronized void beginEdition(FLyrVect layer) {
543
544 89 llmarques
545 226 llmarques
        setCurrentLayer(layer);
546 127 llmarques
547 438 fdiaz
        FeatureStore featureStore = layer.getFeatureStore();
548
        if (!featureStore.isEditing()) {
549 3726 jjdelcerro
            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 4065 jjdelcerro
            if (notification.isCanceled() || notification.isAborted() ) {
557 3726 jjdelcerro
                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 438 fdiaz
            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 2616 fdiaz
                LOGGER.info(msg, new VectorEditingException(e));
570 438 fdiaz
                cleanEditingContext();
571
                return;
572
            }
573 3726 jjdelcerro
            editingNotificationManager.notifyObservers(this,
574
                EditingNotification.AFTER_ENTER_EDITING_STORE, null, layer, layer.getFeatureStore());
575
576 109 llmarques
        }
577 89 llmarques
578 438 fdiaz
        featureStore.addObserver(getMapControl());
579 89 llmarques
580 366 llmarques
        enableSnapping();
581 89 llmarques
    }
582
583 366 llmarques
    @SuppressWarnings({ "rawtypes", "unchecked" })
584
    private void enableSnapping() {
585
        Preferences prefs = Preferences.userRoot().node("snappers");
586 1095 fdiaz
         getMapControl().setRefentEnabled(prefs.getBoolean("apply-snappers", false));
587
         if (currentLayer != null) {
588 3413 jjdelcerro
            Set<FLyrVect> layersToSnap = getMapControl().getMapContext().getLayersToSnap();
589 366 llmarques
            if (!layersToSnap.contains(currentLayer)) {
590
                layersToSnap.add(currentLayer);
591
            }
592
        }
593
    }
594
595
    @SuppressWarnings("rawtypes")
596
    private void disableSnapping() {
597 3413 jjdelcerro
        Set<FLyrVect> layersToSnap =
598 366 llmarques
            getMapControl().getMapContext().getLayersToSnap();
599
        if (layersToSnap.contains(currentLayer)) {
600
            layersToSnap.remove(currentLayer);
601
        }
602
    }
603
604 245 llmarques
    private void changeSelectedTool(String name) {
605 316 llmarques
        if (name.equalsIgnoreCase(DEFAULT_TOOL)) {
606 3430 jjdelcerro
            name = DEFAULT_ACTION_NAME;
607
            this.getMapControl().setTool(DEFAULT_TOOL_NAME);
608 2611 jjdelcerro
//            notifyChangeSelectedTool();
609 303 fdiaz
        }
610 2611 jjdelcerro
    }
611
612
    private void notifyChangeSelectedTool() {
613
        Notification notification = new BaseNotification(
614
            EditingContext.CHANGE_SELECTED_TOOL_NOTIFICATION,
615
            null
616
        );
617 303 fdiaz
        this.observableHelper.notifyObservers(this, notification);
618 245 llmarques
    }
619
620 3430 jjdelcerro
    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 227 llmarques
    private void cleanEditingContext() {
630
        serviceStack.clear();
631
        currentParam = null;
632 3430 jjdelcerro
633
        I18nManager i18n = ToolsLocator.getI18nManager();
634
        showConsoleMessage("\n" + i18n.getTranslation("select_new_tool") + "\n");
635 89 llmarques
636 3430 jjdelcerro
        changeSelectedTool(DEFAULT_TOOL);
637
        notifyChangeSelectedTool(DEFAULT_ACTION_NAME);
638 227 llmarques
    }
639 127 llmarques
640 2109 fdiaz
    @Override
641 227 llmarques
    public void deleteObserver(Observer o) {
642
        this.observableHelper.deleteObserver(o);
643 109 llmarques
    }
644 89 llmarques
645 2109 fdiaz
    @Override
646 227 llmarques
    public void deleteObservers() {
647
        this.observableHelper.deleteObservers();
648 142 llmarques
    }
649
650 109 llmarques
    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 89 llmarques
        }
657
    }
658
659 109 llmarques
    private void doAction(FLyrVect layer, int option) {
660 1234 jjdelcerro
        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
661
        I18nManager i18n = ToolsLocator.getI18nManager();
662
663 109 llmarques
        switch (option) {
664
        case SAVE_CHANGES:
665
            try {
666
                saveChanges(layer);
667
            } catch (VectorEditingException e) {
668 130 llmarques
                String msg =
669
                    String.format("Changes can not be saved in %1$s",
670
                        layer.getName());
671 2616 fdiaz
                LOGGER.info(msg, e);
672 1234 jjdelcerro
                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 161 llmarques
                return;
681 109 llmarques
            }
682
            break;
683 130 llmarques
684 109 llmarques
        case DISCARD_CHANGES:
685
            try {
686
                discardChanges(layer);
687
            } catch (VectorEditingException e) {
688 130 llmarques
                String msg =
689
                    String.format("Changes can not be discared in %1$s",
690
                        layer.getName());
691 2616 fdiaz
                LOGGER.info(msg, e);
692 1234 jjdelcerro
                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 161 llmarques
                return;
701 109 llmarques
            }
702
            break;
703 130 llmarques
704 109 llmarques
        case EXPORT_LAYER:
705
            try {
706
                exportLayer(layer);
707
            } catch (VectorEditingException e) {
708 130 llmarques
                String msg =
709
                    String.format("Changes of %1$s can not be exported",
710
                        layer.getName());
711 2616 fdiaz
                LOGGER.info(msg, e);
712 1234 jjdelcerro
                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 161 llmarques
                return;
721 109 llmarques
            }
722
            break;
723 130 llmarques
724 109 llmarques
        case CANCEL:
725 126 llmarques
            return;
726 109 llmarques
        }
727 127 llmarques
728 226 llmarques
        cleanEditingContext();
729 126 llmarques
        hideConsole();
730 366 llmarques
        disableSnapping();
731 302 fdiaz
        changeSelectedTool(DEFAULT_TOOL);
732 127 llmarques
733 126 llmarques
        FeatureStore featureStore = layer.getFeatureStore();
734 142 llmarques
        featureStore.deleteObserver(getMapControl());
735 89 llmarques
736 109 llmarques
    }
737 89 llmarques
738 226 llmarques
    private void enableSelection(boolean enableSelection) {
739 2444 fdiaz
        this.getEditingCompoundBehavior().setDrawnBehavior(
740
                EditingCompoundBehavior.SELECTION_INDEX, enableSelection);
741 89 llmarques
    }
742
743 2109 fdiaz
    @Override
744 109 llmarques
    public void endEdition(FLyrVect layer) {
745 3140 jjdelcerro
        if( this.isProcessing() ) {
746
            return;
747
        }
748 109 llmarques
        if (layer.isEditing()) {
749
            EditingNotificationManager editingNotificationManager =
750 844 jjdelcerro
                DALSwingLocator.getEditingNotificationManager();
751 89 llmarques
752 109 llmarques
            EditingNotification notification =
753
                editingNotificationManager.notifyObservers(this,
754 986 jjdelcerro
                    EditingNotification.BEFORE_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
755 89 llmarques
756 109 llmarques
            if (notification.isCanceled()) {
757 130 llmarques
                String msg =
758
                    String.format(
759
                        "Stop edit layer %1$s canceled by somme observer.",
760
                        layer.getName());
761 2616 fdiaz
                LOGGER.info(msg, new EndEditingException(msg, null));
762 89 llmarques
763 109 llmarques
            }
764 130 llmarques
765 142 llmarques
            getMapControl().getCanceldraw().setCanceled(true);
766 109 llmarques
            int option;
767
            EditingSwingManager swingManager =
768
                EditingSwingLocator.getSwingManager();
769 130 llmarques
770 842 fdiaz
771 672 jjdelcerro
            if (layer.isWritable() && getMapControl().getProjection().equals(layer.getProjection()) ) {
772 109 llmarques
                option =
773 142 llmarques
                    swingManager.showPanelSaveOrDiscard(getMapControl(),
774 109 llmarques
                        layer.getName());
775
            } else {
776
                option =
777 142 llmarques
                    swingManager.showPanelExportOrDiscard(getMapControl(),
778 109 llmarques
                        layer.getName());
779
            }
780 89 llmarques
781 109 llmarques
            doAction(layer, option);
782 89 llmarques
783 109 llmarques
            editingNotificationManager.notifyObservers(this,
784 986 jjdelcerro
                EditingNotification.AFTER_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
785 89 llmarques
786 109 llmarques
        }
787 89 llmarques
788
    }
789
790 109 llmarques
    private void exportLayer(FLyrVect layer) throws EndEditingException {
791 673 jjdelcerro
        Notification notification = new BaseNotification(EditingContext.EXPORT_LAYER_NOTIFICATION,1);
792
        notification.setValue(layer);
793
        this.observableHelper.notifyObservers(this, notification);
794 109 llmarques
    }
795 89 llmarques
796 227 llmarques
    protected void finishService() {
797 3321 fdiaz
        enqueueTask(() -> {
798 3141 fdiaz
            doFinishService();
799 3321 fdiaz
        });
800 3141 fdiaz
        refreshMenusAndToolBars();
801
    }
802
803
    private void doFinishService() {
804
        try {
805
            EditingService lastService = serviceStack.pop();
806 3140 jjdelcerro
            try {
807 3141 fdiaz
                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 3140 jjdelcerro
                    }
814 3141 fdiaz
                } else {
815
                    lastService.finishAndStore();
816
                    getMapControl().rePaintDirtyLayers();
817
                    refreshMenusAndToolBars();
818 227 llmarques
819 3140 jjdelcerro
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
820
                    showConsoleMessage("\n"
821 3141 fdiaz
                            + i18nManager.getTranslation(lastService.getName()) + "# "
822
                            + i18nManager.getTranslation("finished") + "\n");
823
//                lastService.stop();
824
                    setActiveService(lastService);
825
//                lastService.start();
826
                    lastService.restart();
827 3226 fdiaz
                    setDrawMode(DRAWMODE_NORMAL);
828 3140 jjdelcerro
                    changeSelectedTool(getActiveService().getName());
829
                }
830 227 llmarques
831 3225 fdiaz
            } catch (FinishServiceException ex) {
832
                showConsoleMessage("\n"+ex.getLocalizedMessage());
833
                cleanEditingContext();
834
                return;
835 3141 fdiaz
            } catch (InvalidEntryException ex) {
836
                I18nManager i18nManager = ToolsLocator.getI18nManager();
837
                showConsoleMessage("\n"
838
                        + i18nManager.getTranslation("invalid_option"));
839
                changeSelectedTool(getActiveService().getName());
840 3618 fdiaz
            } 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 3141 fdiaz
                cleanEditingContext();
845
                return;
846 3140 jjdelcerro
            }
847 3141 fdiaz
848
            doNextParameter();
849
        } finally {
850
            refreshMenusAndToolBars();
851
        }
852 227 llmarques
    }
853
854 2125 fdiaz
    public EditingService getActiveService() {
855 227 llmarques
        if (!serviceStack.isEmpty()) {
856
            return serviceStack.peek();
857
        }
858
        return null;
859
    }
860
861 2611 jjdelcerro
    public EditingConsole getConsolePanel() {
862 109 llmarques
        if (console == null) {
863 376 llmarques
            console = new DefaultEditingConsole(new ResponseListener() {
864
865 2109 fdiaz
                @Override
866 376 llmarques
                public void acceptResponse(String response) {
867
                    textEntered(response);
868
                }
869
            });
870 109 llmarques
        }
871
        return console;
872
    }
873 89 llmarques
874 227 llmarques
    protected FLyrVect getCurrentLayer() {
875
        return this.currentLayer;
876
    }
877
878
    protected EditingServiceParameter getCurrentParam() {
879
        return this.currentParam;
880
    }
881
882 109 llmarques
    private Component getDockConsole() {
883
        if (dockConsole == null) {
884 376 llmarques
            dockConsole = new JDockPanel((JComponent) getConsolePanel());
885 109 llmarques
        }
886
        return dockConsole;
887 89 llmarques
    }
888
889 224 llmarques
    private DefaultEditingBehavior getEditingBehavior() {
890 160 llmarques
        if (editingCompoundBehavior != null) {
891 224 llmarques
            return (DefaultEditingBehavior) editingCompoundBehavior
892 160 llmarques
                .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
893
        }
894
        return null;
895 89 llmarques
    }
896
897 109 llmarques
    private EditingCompoundBehavior getEditingCompoundBehavior() {
898
        if (editingCompoundBehavior != null) {
899
            return editingCompoundBehavior;
900
        } else {
901
            EditingCompoundBehavior editingCompoundBehavior;
902 89 llmarques
903 109 llmarques
            CompoundBehavior compoundBehavior =
904 3430 jjdelcerro
                (CompoundBehavior) getMapControl().getMapTool(VECTOREDITING_TOOL_NAME);
905 127 llmarques
906 109 llmarques
            if (compoundBehavior instanceof EditingCompoundBehavior) {
907
                editingCompoundBehavior =
908
                    (EditingCompoundBehavior) compoundBehavior;
909
            } else {
910
                editingCompoundBehavior =
911
                    (EditingCompoundBehavior) compoundBehavior.getBehavior(0);
912
            }
913 127 llmarques
914 109 llmarques
            setCompoundBehavior(editingCompoundBehavior);
915
            return editingCompoundBehavior;
916
        }
917 89 llmarques
    }
918
919 2109 fdiaz
    @Override
920 227 llmarques
    public MapControl getMapControl() {
921 323 llmarques
        return mapControlReference.get();
922 227 llmarques
    }
923
924 2125 fdiaz
925 3321 fdiaz
    @Override
926 2611 jjdelcerro
    public void nextParameter() {
927 3321 fdiaz
        enqueueTask(() -> {
928
            doNextParameter();
929
        });
930 3140 jjdelcerro
    }
931
932
    private void doNextParameter() {
933 1143 fdiaz
        if ((getMapControl().getCurrentTool() != null)
934 3430 jjdelcerro
            && !getMapControl().getCurrentTool().equals(VECTOREDITING_TOOL_NAME)) {
935
            getMapControl().setTool(VECTOREDITING_TOOL_NAME);
936 1143 fdiaz
        }
937 2444 fdiaz
        EditingService activeService = getActiveService();
938
        currentParam = activeService.next();
939 2208 fdiaz
940 226 llmarques
        if (currentParam == null) {
941 3141 fdiaz
            doFinishService();
942 226 llmarques
        } else {
943
            askQuestion(currentParam);
944
            if (currentParam.getTypes().contains(TYPE.SELECTION)) {
945
                enableSelection(true);
946 3618 fdiaz
            } else if (currentParam.getTypes().contains(TYPE.MULTILAYER_SELECTION)) {
947
                enableSelection(true);
948 226 llmarques
            } else if (currentParam.getTypes().contains(TYPE.GEOMETRY)) {
949
                refreshMenusAndToolBars();
950
            }
951
        }
952
    }
953
954 227 llmarques
    protected Stack<EditingService> getServiceStack() {
955
        return this.serviceStack;
956
    }
957
958 109 llmarques
    private void hideConsole() {
959
        isShowConsole = false;
960 876 jjdelcerro
        if( !SwingUtilities.isEventDispatchThread() ) {
961
            try {
962
                SwingUtilities.invokeAndWait(new Runnable() {
963 1095 fdiaz
964 876 jjdelcerro
                    @Override
965
                    public void run() {
966
                        hideConsole();
967
                    }
968
                });
969
                return;
970
            } catch (InterruptedException | InvocationTargetException ex) {
971 2616 fdiaz
                LOGGER.warn("Can't hide editing console.",ex);
972 876 jjdelcerro
            }
973
            return;
974 1095 fdiaz
        }
975 109 llmarques
        getDockConsole().setVisible(false);
976
    }
977 89 llmarques
978 2109 fdiaz
    @Override
979 157 llmarques
    public boolean isServiceCompatible(String name) {
980 224 llmarques
        DefaultEditingBehavior editingBehavior = getEditingBehavior();
981 157 llmarques
982
        if (editingBehavior != null) {
983
984
            try {
985 226 llmarques
                EditingManager manager = EditingLocator.getManager();
986
                EditingServiceInfo serviceInfo = manager.getServiceInfo(name);
987
                GeometryType geoType = null;
988
989
                for (EditingService editingService : getServiceStack()) {
990 316 llmarques
                    EditingServiceParameter parameter = editingService.next();
991 2444 fdiaz
                    if (parameter != null) {
992
                        if (parameter.getTypes().contains(TYPE.GEOMETRY)) {
993 226 llmarques
994 2444 fdiaz
                            int geometryType = parameter.getGeometryType();
995
                            int subType = -1;
996 316 llmarques
997 2444 fdiaz
                            try {
998
                                subType
999
                                        = getCurrentLayer().getFeatureStore()
1000
                                                .getDefaultFeatureType()
1001
                                                .getDefaultGeometryAttribute()
1002
                                                .getGeomType().getSubType();
1003 226 llmarques
1004 2444 fdiaz
                                geoType
1005
                                        = GeometryLocator.getGeometryManager()
1006
                                                .getGeometryType(geometryType, subType);
1007
                            } catch (Exception e) {
1008 226 llmarques
1009 2444 fdiaz
                                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 226 llmarques
1017 2444 fdiaz
                                throw new ServiceInformationException(msg, e);
1018
                            }
1019
1020
                            return serviceInfo.isCompatibleWith(geoType)
1021
                                    && serviceInfo.createsNewGeometries();
1022 226 llmarques
                        }
1023
                    }
1024
                }
1025
1026
                if (getCurrentLayer() != null) {
1027
                    try {
1028 2444 fdiaz
                        geoType
1029
                                = getCurrentLayer().getFeatureStore()
1030
                                        .getDefaultFeatureType()
1031
                                        .getDefaultGeometryAttribute().getGeomType();
1032
1033
                        if (serviceInfo.isCompatibleWith(geoType)) {
1034
                            return true;
1035
                        }
1036 226 llmarques
                    } catch (DataException e) {
1037 2444 fdiaz
                        String msg
1038
                                = String.format("Problems getting default "
1039
                                        + "feature type of %1$s", getCurrentLayer()
1040
                                                .getName());
1041 226 llmarques
                        throw new ServiceInformationException(msg, e);
1042
                    }
1043
                }
1044
1045
                return false;
1046 157 llmarques
            } catch (ServiceInformationException e) {
1047 2616 fdiaz
                LOGGER.warn(
1048 365 llmarques
                    "Problems getting if editing context is compatible with "
1049
                        + name, e);
1050 157 llmarques
            }
1051
        }
1052
        return false;
1053
    }
1054 2203 jjdelcerro
1055 2611 jjdelcerro
    private static final EditingContextSymbolTable contextSymbolTable = new EditingContextSymbolTable();
1056 1673 jjdelcerro
1057 2611 jjdelcerro
    @Override
1058
    public SymbolTable getContextSymbolTable() {
1059
        return contextSymbolTable;
1060
    }
1061
1062
    @Override
1063
    public Point parsePoint(String response) throws ParsePointException {
1064 2609 fdiaz
        response = fixResponseUsingBookmarks(response);
1065
1066 1673 jjdelcerro
        try {
1067 2203 jjdelcerro
            Object x = ExpressionUtils.evaluate(contextSymbolTable, response);
1068 1673 jjdelcerro
            if( x instanceof Point ) {
1069 2203 jjdelcerro
                contextSymbolTable.addPoint((Point) x);
1070 1673 jjdelcerro
                return (Point) x;
1071 227 llmarques
            }
1072 1673 jjdelcerro
        } catch(Exception ex) {
1073 2616 fdiaz
            LOGGER.debug("Can't evaluate: "+StringEscapeUtils.escapeJava(response),ex);
1074 1673 jjdelcerro
        }
1075
        String s = "ST_MakePoint("+response+")";
1076
        try {
1077 2203 jjdelcerro
            Object x = ExpressionUtils.evaluate(contextSymbolTable, s);
1078 1673 jjdelcerro
            if( x instanceof Point ) {
1079 2203 jjdelcerro
                contextSymbolTable.addPoint((Point) x);
1080 1673 jjdelcerro
                return (Point) x;
1081 227 llmarques
            }
1082 1673 jjdelcerro
        } catch(Exception ex) {
1083
            throw new ParsePointException(ex);
1084 226 llmarques
        }
1085 1673 jjdelcerro
        throw new ParsePointException(null);
1086 226 llmarques
    }
1087 1673 jjdelcerro
1088
    private Double parseValue(String response) throws ParseValueException {
1089 2609 fdiaz
        response = fixResponseUsingBookmarks(response);
1090
1091 227 llmarques
        try {
1092 2203 jjdelcerro
            Object x = ExpressionUtils.evaluate(contextSymbolTable, response);
1093 1673 jjdelcerro
            if( x instanceof Double ) {
1094
                return (Double) x;
1095
            }
1096
            if( x==null ) {
1097
                throw new ParseValueException(new NullPointerException());
1098
            }
1099 1783 jjdelcerro
            Coercion toDouble = ToolsLocator.getDataTypesManager().get(DataTypes.DOUBLE).getCoercion();
1100 1673 jjdelcerro
            return (Double) toDouble.coerce(x);
1101
        } catch(Exception ex) {
1102
            throw new ParseValueException(ex);
1103 227 llmarques
        }
1104 226 llmarques
1105
    }
1106
1107 2609 fdiaz
    protected String fixResponseUsingBookmarks(String response) throws LocatorException {
1108 2611 jjdelcerro
        if( response != null ) {
1109
            response = response.trim();
1110 2609 fdiaz
            int n = StringUtils.indexOf(response, " ");
1111
            if(n>0){
1112
                String name = StringUtils.left(response, n);
1113 2611 jjdelcerro
                Function fn = contextSymbolTable.function(name);
1114
                if(fn != null){
1115 2609 fdiaz
                    response = name+"("+response.substring(n)+")";
1116
                }
1117
            }
1118
        }
1119
        return response;
1120
    }
1121
1122 227 llmarques
    protected void refreshMenusAndToolBars() {
1123 876 jjdelcerro
        if (!SwingUtilities.isEventDispatchThread()) {
1124 3140 jjdelcerro
            SwingUtilities.invokeLater(() -> { refreshMenusAndToolBars(); });
1125 876 jjdelcerro
            return;
1126
        }
1127
        Notification notification = new BaseNotification(
1128
                EditingContext.REFRESH_TOOLS_NOTIFICATION,
1129
                null
1130
        );
1131 303 fdiaz
        this.observableHelper.notifyObservers(this, notification);
1132 226 llmarques
    }
1133
1134 227 llmarques
    private void saveChanges(FLyrVect layer) throws EndEditingException {
1135
        FeatureStore featureStore = layer.getFeatureStore();
1136 226 llmarques
        try {
1137 227 llmarques
            featureStore.finishEditing();
1138
        } catch (Exception e) {
1139
            throw new EndEditingException(e);
1140 226 llmarques
        }
1141 227 llmarques
    }
1142 226 llmarques
1143 227 llmarques
    private void setActiveService(EditingService service) {
1144 3141 fdiaz
        //Si se hace este metodo publico hay que comprobar el isProcessing
1145 227 llmarques
        serviceStack.add(service);
1146 3430 jjdelcerro
        notifyChangeSelectedTool(service.getName());
1147 226 llmarques
    }
1148
1149 227 llmarques
    private void setCompoundBehavior(EditingCompoundBehavior compoundBehavior) {
1150 3140 jjdelcerro
        if( this.isProcessing() ) {
1151
            return;
1152
        }
1153 227 llmarques
        this.editingCompoundBehavior = compoundBehavior;
1154
    }
1155
1156 226 llmarques
    private void setCurrentLayer(FLyrVect layer) {
1157 3140 jjdelcerro
        if( this.isProcessing() ) {
1158
            return;
1159
        }
1160 226 llmarques
        if (this.currentLayer != layer) {
1161 438 fdiaz
            this.currentLayer = layer;
1162 3430 jjdelcerro
            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 226 llmarques
        }
1174
1175
    }
1176
1177 2109 fdiaz
    @Override
1178 227 llmarques
    public void setMapControl(MapControl mapControl) {
1179 3140 jjdelcerro
        if( this.isProcessing() ) {
1180
            return;
1181
        }
1182 226 llmarques
1183 2109 fdiaz
        this.mapControlReference = new WeakReference<>(mapControl);
1184 383 llmarques
        this.mapContextReference =
1185 2109 fdiaz
            new WeakReference<>(mapControl.getMapContext());
1186 227 llmarques
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 2616 fdiaz
                LOGGER.info("Problems adding behaviors to editing context", e1);
1194 227 llmarques
                getMapControl().setTool("pan");
1195
            }
1196
        }
1197 226 llmarques
    }
1198
1199 227 llmarques
    private void showConsole() {
1200
        if (isShowConsole) {
1201
            return;
1202
        }
1203 876 jjdelcerro
        if( !SwingUtilities.isEventDispatchThread() ) {
1204
            try {
1205
                SwingUtilities.invokeAndWait(new Runnable() {
1206 1095 fdiaz
1207 876 jjdelcerro
                    @Override
1208
                    public void run() {
1209
                        showConsole();
1210
                    }
1211
                });
1212
                return;
1213
            } catch (InterruptedException | InvocationTargetException ex) {
1214 2616 fdiaz
                LOGGER.warn("Can't show editing console.",ex);
1215 876 jjdelcerro
            }
1216
            return;
1217 1095 fdiaz
        }
1218 227 llmarques
        isShowConsole = true;
1219
        getMapControl().remove(getDockConsole());
1220
        getMapControl().setLayout(new BorderLayout());
1221
        getMapControl().add(getDockConsole(), BorderLayout.SOUTH);
1222
        getDockConsole().setVisible(true);
1223 226 llmarques
    }
1224
1225 876 jjdelcerro
    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 376 llmarques
        getConsolePanel().addText(text);
1237 227 llmarques
    }
1238
1239 2611 jjdelcerro
    @Override
1240
    public void cancelActiveService() {
1241
        this.textEntered(null);
1242
    }
1243
1244 3140 jjdelcerro
//    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 2723 fdiaz
1264 226 llmarques
    protected void textEntered(String response) {
1265 3140 jjdelcerro
        if( this.isProcessing() ) {
1266
            return;
1267
        }
1268
        FeatureStore featureStore = getCurrentLayer().getFeatureStore();
1269 226 llmarques
        if (response == null) {
1270 3140 jjdelcerro
            EditingService activeService = getActiveService();
1271 842 fdiaz
            if (activeService != null) {
1272 226 llmarques
                try {
1273 842 fdiaz
                    activeService.stop();
1274 302 fdiaz
                    serviceStack.pop();
1275 316 llmarques
                    if (serviceStack.isEmpty()) {
1276 472 fdiaz
                        featureStore
1277 302 fdiaz
                            .getFeatureSelection().deselectAll();
1278
                        changeSelectedTool(DEFAULT_TOOL);
1279
                    } else {
1280 842 fdiaz
                        changeSelectedTool(activeService.getName());
1281 302 fdiaz
                    }
1282 226 llmarques
1283 245 llmarques
                    refreshMenusAndToolBars();
1284 842 fdiaz
                    activeService = getActiveService();
1285
                    if (activeService != null) {
1286 2125 fdiaz
                        nextParameter();
1287 302 fdiaz
                    } else {
1288
                        cleanEditingContext();
1289
                    }
1290 245 llmarques
1291 226 llmarques
                } catch (StopServiceException e) {
1292 2616 fdiaz
                    LOGGER
1293 842 fdiaz
                        .info("Can't stop " + activeService.getName(), e);
1294 245 llmarques
                } catch (DataException e) {
1295 2616 fdiaz
                    LOGGER.info("Can't get selection of "
1296 472 fdiaz
                        + featureStore.getFullName(), e);
1297 226 llmarques
                }
1298
            }
1299
        } else {
1300 3321 fdiaz
            enqueueTask(() -> {
1301 3140 jjdelcerro
                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 226 llmarques
1314 3140 jjdelcerro
                    activeService = getActiveService();
1315
                    if (activeService != null) {
1316
                        doNextParameter();
1317
                    } else {
1318
                        cleanEditingContext();
1319
                    }
1320
                } finally {
1321
                    refreshMenusAndToolBars();
1322 2125 fdiaz
                }
1323 3321 fdiaz
            });
1324 3140 jjdelcerro
            refreshMenusAndToolBars();
1325 2125 fdiaz
        }
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 3618 fdiaz
//            boolean insertedValue = false;
1338
            if ((types.contains(TYPE.POSITION))
1339 226 llmarques
                    || types.contains(TYPE.LIST_POSITIONS)) {
1340
1341 3141 fdiaz
                if(defaultValue instanceof Point){
1342
                    defaultPoint = (Point) defaultValue;
1343
                }
1344 2125 fdiaz
                try {
1345
                    if (StringUtils.isEmpty(input.replace("\n", ""))) {
1346
                        point = defaultPoint;
1347
                    } else {
1348
                        point = parsePoint(input);
1349 226 llmarques
                    }
1350
1351 2125 fdiaz
                    if (point != null) {
1352
                        return point;
1353 226 llmarques
                    }
1354
1355 2125 fdiaz
                } catch (ParsePointException e) {
1356
                    // Do nothing to try other types
1357 226 llmarques
                }
1358 2125 fdiaz
            }
1359
            if (types.contains(TYPE.VALUE)) {
1360 226 llmarques
1361 2125 fdiaz
                try {
1362
                    value = parseValue(input);
1363
                    if (value != null) {
1364
                        return value;
1365
                    }
1366 226 llmarques
1367 2125 fdiaz
                } catch (ParseValueException e) {
1368
                    // Do nothing to try other types
1369 226 llmarques
                }
1370
1371 2125 fdiaz
            }
1372
            if (types.contains(TYPE.OPTION)) {
1373
                input = input.replace("\n", "");
1374
                return input;
1375
            }
1376 2444 fdiaz
1377 3618 fdiaz
            if (types.contains(TYPE.SELECTION)) {
1378 2125 fdiaz
                if (input.equalsIgnoreCase("\n")) {
1379
                    enableSelection(false);
1380 226 llmarques
1381 2125 fdiaz
                    FeatureSelection clonedSelection;
1382
                    try {
1383
                        clonedSelection = (FeatureSelection) featureStore
1384 1143 fdiaz
                                .getFeatureSelection().clone();
1385 3618 fdiaz
                        if (!clonedSelection.isEmpty()) {
1386
                            return clonedSelection;
1387 226 llmarques
                        }
1388 2125 fdiaz
                    } catch (Exception e) {
1389 2616 fdiaz
                        LOGGER.warn("Can't access to selection.", e);
1390 2125 fdiaz
                        throw new InvalidEntryException(e);
1391 226 llmarques
                    }
1392
                }
1393
            }
1394 3618 fdiaz
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 226 llmarques
        }
1413 2125 fdiaz
        return null;
1414 226 llmarques
    }
1415 3618 fdiaz
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 438 fdiaz
1446 2109 fdiaz
    @Override
1447 438 fdiaz
    public void setDefaultBehaviors(Behavior[] defaultBehaviors) {
1448 3140 jjdelcerro
        if( this.isProcessing() ) {
1449
            return;
1450
        }
1451 438 fdiaz
        this.defaultBehaviors = defaultBehaviors;
1452 546 llmarques
        try {
1453
            addBehaviors(defaultBehaviors);
1454
        } catch (CreateEditingBehaviorException e1) {
1455 2616 fdiaz
            LOGGER.info("Problems adding behaviors to editing context", e1);
1456 546 llmarques
            getMapControl().setTool("pan");
1457
        }
1458 438 fdiaz
    }
1459
1460 2109 fdiaz
    @Override
1461 438 fdiaz
    public Behavior[] getDefaultBehaviors() {
1462
        return this.defaultBehaviors;
1463
    }
1464 2125 fdiaz
1465
    @Override
1466 2204 fdiaz
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
1467 3321 fdiaz
        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 3140 jjdelcerro
        }
1479 3321 fdiaz
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 2204 fdiaz
        if( value instanceof CharSequence){
1534
            value = coerceInputParameter(parameter, value.toString());
1535
        } else if( value instanceof Point) {
1536
            contextSymbolTable.addPoint((Point) value);
1537
        }
1538 3140 jjdelcerro
        Object v = value;
1539 3321 fdiaz
        Runnable task = () -> {
1540 3140 jjdelcerro
            try {
1541
                getActiveService().setValue(parameter, v);
1542 3321 fdiaz
                if(next){
1543
                    doNextParameter();
1544
                }
1545 3140 jjdelcerro
            } catch (InvalidEntryException ex) {
1546
                I18nManager i18nManager = ToolsLocator.getI18nManager();
1547 3289 fdiaz
                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 3837 fdiaz
                doNextParameter();
1554 3618 fdiaz
            } catch (Exception ex) {
1555
                LOGGER.warn("Can't set value", ex);
1556
                cleanEditingContext();
1557
                return;
1558 3140 jjdelcerro
            } finally {
1559
                refreshMenusAndToolBars();
1560
            }
1561 3321 fdiaz
        };
1562
        enqueueTask(task);
1563 3140 jjdelcerro
        refreshMenusAndToolBars();
1564
1565
1566 2125 fdiaz
    }
1567 2611 jjdelcerro
1568 3321 fdiaz
    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 2611 jjdelcerro
    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 2125 fdiaz
1595 3140 jjdelcerro
    public boolean isProcessing() {
1596 3321 fdiaz
        if(this.tasksDispatcher == null){
1597
            return false;
1598
        }
1599
        return this.tasksDispatcher.isProcessing();
1600 3140 jjdelcerro
    }
1601
1602 3226 fdiaz
    @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 89 llmarques
}