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

History | View | Annotate | Download (48.4 KB)

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

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

    
27
import java.awt.BorderLayout;
28
import java.awt.Component;
29
import java.lang.ref.WeakReference;
30
import java.lang.reflect.InvocationTargetException;
31
import java.util.ArrayList;
32
import java.util.HashSet;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Set;
36
import java.util.Stack;
37
import java.util.logging.Level;
38
import java.util.prefs.PreferenceChangeEvent;
39
import java.util.prefs.PreferenceChangeListener;
40
import java.util.prefs.Preferences;
41
import javax.swing.JComponent;
42
import javax.swing.JOptionPane;
43
import javax.swing.SwingUtilities;
44
import org.apache.commons.lang3.StringUtils;
45
import org.apache.commons.text.StringEscapeUtils;
46
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
47
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
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.FeatureAttributeDescriptor;
56
import org.gvsig.fmap.dal.feature.FeatureSelection;
57
import org.gvsig.fmap.dal.feature.FeatureStore;
58
import org.gvsig.fmap.dal.feature.FeatureType;
59
import org.gvsig.fmap.dal.swing.DALSwingLocator;
60
import org.gvsig.fmap.geom.Geometry;
61
import org.gvsig.fmap.geom.GeometryLocator;
62
import org.gvsig.fmap.geom.GeometryUtils;
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.bookmarksandhistory.Bookmark;
82
import org.gvsig.tools.dataTypes.Coercion;
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.utils.console.JDockPanel;
92
import org.gvsig.utils.console.ResponseListener;
93
import org.gvsig.vectorediting.lib.api.EditingLocator;
94
import org.gvsig.vectorediting.lib.api.EditingManager;
95
import org.gvsig.vectorediting.lib.api.EditingService;
96
import org.gvsig.vectorediting.lib.api.EditingServiceInfo;
97
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
98
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
99
import org.gvsig.vectorediting.lib.api.exceptions.CreateEditingBehaviorException;
100
import org.gvsig.vectorediting.lib.api.exceptions.EndEditingException;
101
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
102
import org.gvsig.vectorediting.lib.api.exceptions.ParsePointException;
103
import org.gvsig.vectorediting.lib.api.exceptions.ParseValueException;
104
import org.gvsig.vectorediting.lib.api.exceptions.ServiceInformationException;
105
import org.gvsig.vectorediting.lib.api.exceptions.StartEditingException;
106
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
107
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
108
import org.gvsig.vectorediting.lib.api.exceptions.VectorEditingException;
109
import org.gvsig.vectorediting.swing.api.EditingContext;
110
import org.gvsig.vectorediting.swing.api.EditingSwingLocator;
111
import org.gvsig.vectorediting.swing.api.EditingSwingManager;
112
import org.gvsig.vectorediting.swing.api.console.EditingConsole;
113
import org.gvsig.vectorediting.swing.impl.console.DefaultEditingConsole;
114
import org.slf4j.Logger;
115
import org.slf4j.LoggerFactory;
116

    
117
public class DefaultEditingContext implements EditingContext {
118

    
119
    private static final Logger LOGGER = LoggerFactory
120
        .getLogger(EditingManager.class);
121

    
122
    private WeakReference<MapControl> mapControlReference;
123

    
124
    private WeakReference<MapContext> mapContextReference;
125

    
126
    private EditingCompoundBehavior editingCompoundBehavior;
127

    
128
    private Behavior[] lastAdditionalBehaviors;
129

    
130
    private final ObservableHelper observableHelper;
131

    
132
    private EditingConsole console;
133

    
134
    private JDockPanel dockConsole = null;
135

    
136
    private boolean isShowConsole = false;
137

    
138
    private final Stack<EditingService> serviceStack;
139

    
140
    private FLyrVect currentLayer;
141

    
142
    private EditingServiceParameter currentParam;
143

    
144
    private Behavior[] defaultBehaviors;
145
    
146
    private Set<FLyrVect> layersSpatialCacheEnabled = new HashSet<>();
147

    
148
    private final LayerListener layerListener = new LayerListener() {
149

    
150
        @Override
151
        public void activationChanged(final LayerEvent e) {
152
            if( !SwingUtilities.isEventDispatchThread() ) {
153
                SwingUtilities.invokeLater(new Runnable() {
154

    
155
                    @Override
156
                    public void run() {
157
                        activationChanged(e);
158
                    }
159
                });
160
                return;
161
            }
162

    
163
            FLayer layer = e.getSource();
164
            final MapContext mapContext = layer.getMapContext();
165

    
166
            if (countActiveAndEditingLayers(mapContext) > 1) {
167
                hideConsole();
168
                return;
169
            }
170

    
171
            if (layer instanceof FLyrVect) {
172
                if (layer.isActive()) {
173
                    if(layer.isEditing()) {
174
                        getMapControl().setTool("VectorEditing");
175
                        setCurrentLayer((FLyrVect) layer);
176
                        showConsole();
177
                        return;
178
                    } else {
179
                        final SpatialCache spatialCache = ((FLyrVect) layer).getSpatialCache();
180
                        if(!spatialCache.isEnabled()){
181
                            spatialCache.setEnabled(true);
182
                            //We keep the list of layers whose spatial cache is enabled here.
183
                            layersSpatialCacheEnabled.add((FLyrVect) layer);
184

    
185
                        }
186
                    }
187
                } else {
188
                    if(!layer.isEditing()) {
189
                        //We disabled the spatial cache of the layers that we had enabled here.
190
                        final SpatialCache spatialCache = ((FLyrVect) layer).getSpatialCache();
191
                        if(spatialCache.isEnabled() && layersSpatialCacheEnabled.contains((FLyrVect) layer)){
192
                            spatialCache.setEnabled(false);
193
                            layersSpatialCacheEnabled.remove((FLyrVect) layer);
194
                        }
195
                    }
196
                }
197
            }
198

    
199
            FLayer[] activeLayers =
200
                layer.getMapContext().getLayers().getActives();
201
            
202
            for (FLayer activeLayer : activeLayers) {
203
                if (activeLayer instanceof FLyrVect) {
204
                    if (activeLayer.isEditing()) {
205
                        getMapControl().setTool("VectorEditing");
206
                        setCurrentLayer((FLyrVect) activeLayer);
207
                        showConsole();
208
                        return;
209
                    }
210
                }
211
            }
212

    
213
            hideConsole();
214
            if ((getMapControl().getCurrentTool() != null)
215
                && getMapControl().getCurrentTool().equals("VectorEditing")) {
216
                getMapControl().setPrevTool();
217
            }
218
        }
219

    
220
        @Override
221
        public void drawValueChanged(LayerEvent e) {
222
        }
223

    
224
        @Override
225
        public void editionChanged(final LayerEvent e) {
226
            if( !SwingUtilities.isEventDispatchThread() ) {
227
                SwingUtilities.invokeLater(new Runnable() {
228

    
229
                    @Override
230
                    public void run() {
231
                        editionChanged(e);
232
                    }
233
                });
234
                return;
235
            }
236
            FLayer layer = e.getSource();
237

    
238
            if (layer instanceof FLyrVect) {
239
                if (layer.isEditing()) {
240
                    synchronized (DefaultEditingContext.this) {
241
                        beginEdition((FLyrVect) layer);
242
                        showConsole();
243
                    }
244
                } else {
245
                    hideConsole();
246
                }
247
            }
248

    
249
        }
250

    
251
        @Override
252
        public void nameChanged(LayerEvent e) {
253
        }
254

    
255
        @Override
256
        public void visibilityChanged(LayerEvent e) {
257
        }
258
    };
259
    
260
    private int countActiveAndEditingLayers(MapContext mapcontext){
261
        int count = 0;
262
        
263
        FLayer[] activeLayers =
264
                mapcontext.getLayers().getActives();
265
            
266
        for (FLayer activeLayer : activeLayers) {
267
            if (activeLayer instanceof FLyrVect) {
268
                if (activeLayer.isEditing()) {
269
                    count++;
270
                }
271
            }
272
        }
273
        
274
        return count;
275
    }
276

    
277
    private final PreferenceChangeListener preferenceChangeListener =
278
        new PreferenceChangeListener() {
279

    
280
            @Override
281
            public void preferenceChange(PreferenceChangeEvent evt) {
282
                String key = evt.getKey();
283
                if (key.equalsIgnoreCase("apply-snappers")) {
284
                    boolean newValue = Boolean.parseBoolean(evt.getNewValue());
285
                    getMapControl().setRefentEnabled(newValue);
286
                }
287
            }
288
        };
289

    
290
    public DefaultEditingContext(MapControl mapControl) {
291

    
292
        this.mapControlReference = new WeakReference<>(mapControl);
293
        this.mapContextReference =
294
            new WeakReference<>(mapControl.getMapContext());
295
        this.observableHelper = new ObservableHelper();
296

    
297
        this.serviceStack = new Stack<>();
298

    
299
        addLayerListeners();
300
        addPreferenceListener();
301
    }
302

    
303
    private void addPreferenceListener() {
304
        Preferences prefs = Preferences.userRoot().node("snappers");
305
        prefs.addPreferenceChangeListener(preferenceChangeListener);
306
    }
307

    
308
    @Override
309
    public void activateService(String name) {
310

    
311
        if ((getMapControl() != null)
312
            && getMapControl().hasTool("VectorEditing")) {
313

    
314
            CompoundBehavior editingCompoundBehavior =
315
                getEditingCompoundBehavior();
316
            getMapControl().setTool("VectorEditing");
317
            editingCompoundBehavior.setDrawnBehavior(
318
                EditingCompoundBehavior.EDITING_INDEX, true);
319

    
320
            EditingManager manager = EditingLocator.getManager();
321

    
322
            if (currentLayer != null) {
323
                IVectorLegend legend = null;
324
                try {
325
                    legend = (IVectorLegend) currentLayer.getLegend();
326
                } catch (Exception e) {
327
                    LOGGER.trace("Can't retrieve legend from layer.");
328
                    //DO NOTHING
329
                }
330

    
331
//                EditingService activeService = getActiveService();
332
//                if(activeService != null && !activeService.next().getTypes().contains(TYPE.GEOMETRY)) {
333
//                    activeService.setShowPreviewSymbol(true);
334
//                }
335
                EditingService service =
336
                    manager.getEditingService(name,
337
                        currentLayer.getFeatureStore(),
338
                        mapContextReference.get(), 
339
                        legend);
340

    
341
                if (service != null) {
342
//                     if(!serviceStack.isEmpty()) { service.setShowPreviewSymbol(false); }
343
                    this.enableSelection(false);
344

    
345
                    try {
346
                        service.activate();
347
                        service.start();                       
348
                    } catch (StartServiceException e) {
349

    
350
                        LOGGER.info(String.format(
351
                            "Can't start the service %1$s", service.getName()),
352
                            e);
353
                        cleanEditingContext();
354
                        return;
355

    
356
                    } catch (InvalidEntryException e) {
357

    
358
                        I18nManager i18nManager = ToolsLocator.getI18nManager();
359
                        showConsoleMessage("\n"
360
                            + i18nManager.getTranslation("invalid_option"));
361
                    }
362

    
363
                    if (!serviceStack.isEmpty()){
364
                        if(getActiveService().next().getTypes().contains(TYPE.GEOMETRY)) {
365
                            service.setShowPreviewSymbol(false);
366
                        } else {
367
//                            service.setShowPreviewSymbol(true);
368
//                            getActiveService().setShowPreviewSymbol(true);
369
                            serviceStack.pop();
370
                        }
371
                    }
372

    
373
                    setActiveService(service);
374

    
375
                    nextParameter();
376
                }
377
            }
378
        }
379
    }
380

    
381
    private void addBehaviors(Behavior[] additionalBehavior)
382
        throws CreateEditingBehaviorException {
383

    
384
        DefaultEditingBehavior editingBehavior;
385
        EditingCompoundBehavior editingCompoundBehavior;
386

    
387
        if (!getMapControl().hasTool("VectorEditing")) {
388

    
389
            editingBehavior = new DefaultEditingBehavior(this);
390
            editingCompoundBehavior =
391
                new EditingCompoundBehavior(editingBehavior);
392
            setCompoundBehavior(editingCompoundBehavior);
393

    
394
            if (additionalBehavior != null) {
395

    
396
                Behavior[] behaviors =
397
                    new Behavior[additionalBehavior.length + 1];
398
                behaviors[0] = editingCompoundBehavior;
399

    
400
                System.arraycopy(additionalBehavior, 0, behaviors, 1, additionalBehavior.length);
401

    
402
                getMapControl().addBehavior("VectorEditing", behaviors);
403

    
404
                lastAdditionalBehaviors = additionalBehavior;
405

    
406
            } else {
407
                getMapControl().addBehavior("VectorEditing",
408
                    editingCompoundBehavior);
409
            }
410

    
411
        } else {
412
            editingCompoundBehavior = getEditingCompoundBehavior();
413
            editingBehavior =
414
                (DefaultEditingBehavior) editingCompoundBehavior
415
                    .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
416
            setCompoundBehavior(editingCompoundBehavior);
417
            cleanEditingContext();
418
        }
419

    
420
    }
421

    
422
    private void addLayerListeners() {
423

    
424
        FLayers layers = mapContextReference.get().getLayers();
425

    
426
        layers.addLayerListener(layerListener);
427

    
428
        layers.addLayerCollectionListener(new LayerCollectionListener() {
429

    
430
            public void addLayer(FLayer layer) {
431
                if (layer instanceof FLayers) {
432
                    FLayers layers = (FLayers) layer;
433
                    for (int i = 0; i < layers.getLayersCount(); i++) {
434
                        addLayer(layers.getLayer(i));
435
                    }
436
                } else if (layer instanceof FLyrVect) {
437
                    ((FLyrVect) layer).addLayerListener(layerListener);
438
                }
439
            }
440

    
441
            @Override
442
            public void layerAdded(LayerCollectionEvent e) {
443
                addLayer(e.getLayers());
444
            }
445

    
446
            @Override
447
            public void layerAdding(LayerCollectionEvent e)
448
                throws CancelationException {
449
            }
450

    
451
            @Override
452
            public void layerMoved(LayerPositionEvent e) {
453
            }
454

    
455
            @Override
456
            public void layerMoving(LayerPositionEvent e)
457
                throws CancelationException {
458
            }
459

    
460
            public void removeLayer(FLayer layer) {
461
                if (layer instanceof FLayers) {
462
                    FLayers layers = (FLayers) layer;
463
                    for (int i = 0; i < layers.getLayersCount(); i++) {
464
                        addLayer(layers.getLayer(i));
465
                    }
466
                } else if (layer instanceof FLyrVect) {
467
                    ((FLyrVect) layer).removeLayerListener(layerListener);
468
                }
469
            }
470

    
471
            @Override
472
            public void layerRemoved(LayerCollectionEvent e) {
473
                removeLayer(e.getLayers());
474
            }
475

    
476
            @Override
477
            public void layerRemoving(LayerCollectionEvent e)
478
                throws CancelationException {
479
            }
480

    
481
            @Override
482
            public void visibilityChanged(LayerCollectionEvent e)
483
                throws CancelationException {
484
            }
485
        });
486
    }
487

    
488
    @Override
489
    public void addObserver(Observer o) {
490
        this.observableHelper.addObserver(o);
491
    }
492

    
493
    private void askQuestion(EditingServiceParameter param) {
494
        I18nManager i18nManager = ToolsLocator.getI18nManager();
495
        String translation = i18nManager.getTranslation(param.getDescription());
496
        String activeServiceName =
497
            i18nManager.getTranslation(getActiveService().getName());
498

    
499
        Object defaultValue = param.getDefaultValue();
500
        String strDefaultValue;
501

    
502
        if (defaultValue != null) {
503
            if (defaultValue instanceof String) {
504
                strDefaultValue =
505
                    i18nManager.getTranslation((String) defaultValue);
506
            } else {
507
                if(defaultValue instanceof Point){
508
                    Point point = (Point)defaultValue;
509
                    StringBuilder builder = new StringBuilder();
510
                    for(int i=0; i<point.getDimension(); i++){
511
                        builder.append(point.getCoordinateAt(i));
512
                        if(i < point.getDimension()-1){
513
                            builder.append(" , ");
514
                        }
515
                    }
516
                    strDefaultValue = builder.toString();
517
                } else {
518
                    strDefaultValue = defaultValue.toString();
519
                }
520
            }
521
            showConsoleMessage("\n" + activeServiceName + "# " + translation
522
                + "<" + strDefaultValue + "> : ");
523
        } else {
524
            showConsoleMessage("\n" + activeServiceName + "# " + translation
525
                + " : ");
526
        }
527
    }
528

    
529
    @Override
530
    public synchronized void beginEdition(FLyrVect layer,
531
        Behavior[] additionalBehaviors) {
532

    
533
        try{
534
            throw new Exception("Deprecated method");
535
        } catch (Exception e){
536
            LOGGER.info("Deprecated method", e);
537
        }
538

    
539
        beginEdition(layer);
540
        try {
541
            addBehaviors(additionalBehaviors);
542
        } catch (CreateEditingBehaviorException e1) {
543
            LOGGER.info("Problems adding behaviors to editing context", e1);
544
            getMapControl().setTool("pan");
545
        }
546
    }
547

    
548
    @Override
549
    public synchronized void beginEdition(FLyrVect layer) {
550

    
551
        EditingNotificationManager editingNotificationManager =
552
            DALSwingLocator.getEditingNotificationManager();
553

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

    
558
        if (notification.isCanceled()) {
559
            String msg =
560
                String.format("Edit layer %1$s canceled by somme observer.",
561
                    layer.getName());
562
            LOGGER.info(msg, new StartEditingException(msg, null));
563
            return;
564
        }
565

    
566
        setCurrentLayer(layer);
567

    
568
        FeatureStore featureStore = layer.getFeatureStore();
569
        if (!featureStore.isEditing()) {
570
            try {
571
                featureStore.edit();
572
            } catch (Exception e) {
573
                String msg =
574
                    String.format("Can't set %1$s in edit mode",
575
                        featureStore.getName());
576
                LOGGER.info(msg, new VectorEditingException(e));
577
                cleanEditingContext();
578
                return;
579
            }
580
        }
581

    
582
        featureStore.addObserver(getMapControl());
583

    
584
        editingNotificationManager.notifyObservers(this,
585
            EditingNotification.AFTER_ENTER_EDITING_STORE, null, layer, layer.getFeatureStore());
586

    
587
        enableSnapping();
588
    }
589

    
590
    @SuppressWarnings({ "rawtypes", "unchecked" })
591
    private void enableSnapping() {
592
        Preferences prefs = Preferences.userRoot().node("snappers");
593
         getMapControl().setRefentEnabled(prefs.getBoolean("apply-snappers", false));
594
         if (currentLayer != null) {
595
            ArrayList layersToSnap =
596
                getMapControl().getMapContext().getLayersToSnap();
597
            if (!layersToSnap.contains(currentLayer)) {
598
                layersToSnap.add(currentLayer);
599
            }
600
        }
601
    }
602

    
603
    @SuppressWarnings("rawtypes")
604
    private void disableSnapping() {
605
        ArrayList layersToSnap =
606
            getMapControl().getMapContext().getLayersToSnap();
607
        if (layersToSnap.contains(currentLayer)) {
608
            layersToSnap.remove(currentLayer);
609
        }
610
    }
611

    
612
    private void changeSelectedTool(String name) {
613
        if (name.equalsIgnoreCase(DEFAULT_TOOL)) {
614
            name = "selection-simple-select-view";
615
            this.getMapControl().setTool("pointSelection");
616
//            notifyChangeSelectedTool();
617
        }
618
    }
619
    
620
    private void notifyChangeSelectedTool() {
621
        Notification notification = new BaseNotification(
622
            EditingContext.CHANGE_SELECTED_TOOL_NOTIFICATION,
623
            null
624
        );
625
        this.observableHelper.notifyObservers(this, notification);
626
    }
627

    
628
    private void cleanEditingContext() {
629
        serviceStack.clear();
630
        currentParam = null;
631
        this.enableSelection(false);
632
        refreshMenusAndToolBars();
633

    
634
        I18nManager i18nManager = ToolsLocator.getI18nManager();
635
        showConsoleMessage("\n" + i18nManager.getTranslation("select_new_tool")
636
            + "\n");
637
        notifyChangeSelectedTool();
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 (layer.isEditing()) {
746
            EditingNotificationManager editingNotificationManager =
747
                DALSwingLocator.getEditingNotificationManager();
748

    
749
            EditingNotification notification =
750
                editingNotificationManager.notifyObservers(this,
751
                    EditingNotification.BEFORE_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
752

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

    
760
            }
761

    
762
            getMapControl().getCanceldraw().setCanceled(true);
763
            int option;
764
            EditingSwingManager swingManager =
765
                EditingSwingLocator.getSwingManager();
766

    
767

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

    
778
            doAction(layer, option);
779

    
780
            editingNotificationManager.notifyObservers(this,
781
                EditingNotification.AFTER_EXIT_EDITING_STORE, null, layer, layer.getFeatureStore());
782

    
783
        }
784

    
785
    }
786

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

    
793
    protected void finishService() {
794
        EditingService lastService = serviceStack.pop();
795
        try {
796

    
797
            if (!serviceStack.isEmpty()
798
                && getActiveService().next().getTypes().contains(TYPE.GEOMETRY)) {
799
                Geometry geometry = lastService.finish();
800
                lastService.setShowPreviewSymbol(true);
801
                if (geometry != null) {
802
                    getActiveService().setValue(geometry);
803
                }
804
            } else {
805
                lastService.finishAndStore();
806
                getMapControl().rePaintDirtyLayers();
807

    
808
                I18nManager i18nManager = ToolsLocator.getI18nManager();
809
                showConsoleMessage("\n"
810
                    + i18nManager.getTranslation(lastService.getName()) + "# "
811
                    + i18nManager.getTranslation("finished") + "\n");
812
                lastService.stop();
813
                setActiveService(lastService);
814
                lastService.start();
815
                changeSelectedTool(getActiveService().getName());
816
            }
817

    
818
        } catch (InvalidEntryException ex) {
819
            I18nManager i18nManager = ToolsLocator.getI18nManager();
820
            showConsoleMessage("\n"
821
                + i18nManager.getTranslation("invalid_option"));
822
            changeSelectedTool(getActiveService().getName());
823
        } catch (VectorEditingException ex) {
824
            LOGGER.info("Can't finish " + lastService.getName(), ex);
825
            cleanEditingContext();
826
            return;
827
        }
828

    
829
        nextParameter();
830
    }
831

    
832
    public EditingService getActiveService() {
833
        if (!serviceStack.isEmpty()) {
834
            return serviceStack.peek();
835
        }
836
        return null;
837
    }
838

    
839
    public EditingConsole getConsolePanel() {
840
        if (console == null) {
841
            console = new DefaultEditingConsole(new ResponseListener() {
842

    
843
                @Override
844
                public void acceptResponse(String response) {
845
                    textEntered(response);
846
                }
847
            });
848
        }
849
        return console;
850
    }
851

    
852
    protected FLyrVect getCurrentLayer() {
853
        return this.currentLayer;
854
    }
855

    
856
    protected EditingServiceParameter getCurrentParam() {
857
        return this.currentParam;
858
    }
859

    
860
    private Component getDockConsole() {
861
        if (dockConsole == null) {
862
            dockConsole = new JDockPanel((JComponent) getConsolePanel());
863
        }
864
        return dockConsole;
865
    }
866

    
867
    private DefaultEditingBehavior getEditingBehavior() {
868
        if (editingCompoundBehavior != null) {
869
            return (DefaultEditingBehavior) editingCompoundBehavior
870
                .getBehavior(EditingCompoundBehavior.EDITING_INDEX);
871
        }
872
        return null;
873
    }
874

    
875
    private EditingCompoundBehavior getEditingCompoundBehavior() {
876
        if (editingCompoundBehavior != null) {
877
            return editingCompoundBehavior;
878
        } else {
879
            EditingCompoundBehavior editingCompoundBehavior;
880

    
881
            CompoundBehavior compoundBehavior =
882
                (CompoundBehavior) getMapControl().getMapTool("VectorEditing");
883

    
884
            if (compoundBehavior instanceof EditingCompoundBehavior) {
885
                editingCompoundBehavior =
886
                    (EditingCompoundBehavior) compoundBehavior;
887
            } else {
888
                editingCompoundBehavior =
889
                    (EditingCompoundBehavior) compoundBehavior.getBehavior(0);
890
            }
891

    
892
            setCompoundBehavior(editingCompoundBehavior);
893
            return editingCompoundBehavior;
894
        }
895
    }
896

    
897
    @Override
898
    public MapControl getMapControl() {
899
        return mapControlReference.get();
900
    }
901

    
902
    
903
    public void nextParameter() {
904
        if ((getMapControl().getCurrentTool() != null)
905
            && !getMapControl().getCurrentTool().equals("VectorEditing")) {
906
            getMapControl().setTool("VectorEditing");
907
        }
908
        EditingService activeService = getActiveService();
909
        currentParam = activeService.next();
910

    
911
        if (currentParam == null) {
912
            finishService();
913
        } else {
914
            askQuestion(currentParam);
915
            if (currentParam.getTypes().contains(TYPE.SELECTION)) {
916
                enableSelection(true);
917
            } else if (currentParam.getTypes().contains(TYPE.GEOMETRY)) {
918
                refreshMenusAndToolBars();
919
            }
920
        }
921
    }
922

    
923
    protected Stack<EditingService> getServiceStack() {
924
        return this.serviceStack;
925
    }
926

    
927
    private void hideConsole() {
928
        isShowConsole = false;
929
        if( !SwingUtilities.isEventDispatchThread() ) {
930
            try {
931
                SwingUtilities.invokeAndWait(new Runnable() {
932

    
933
                    @Override
934
                    public void run() {
935
                        hideConsole();
936
                    }
937
                });
938
                return;
939
            } catch (InterruptedException | InvocationTargetException ex) {
940
                LOGGER.warn("Can't hide editing console.",ex);
941
            }
942
            return;
943
        }
944
        getDockConsole().setVisible(false);
945
    }
946

    
947
    @Override
948
    public boolean isServiceCompatible(String name) {
949
        DefaultEditingBehavior editingBehavior = getEditingBehavior();
950

    
951
        if (editingBehavior != null) {
952

    
953
            try {
954
                EditingManager manager = EditingLocator.getManager();
955
                EditingServiceInfo serviceInfo = manager.getServiceInfo(name);
956
                GeometryType geoType = null;
957

    
958
                for (EditingService editingService : getServiceStack()) {
959
                    EditingServiceParameter parameter = editingService.next();
960
                    if (parameter != null) {
961
                        if (parameter.getTypes().contains(TYPE.GEOMETRY)) {
962

    
963
                            int geometryType = parameter.getGeometryType();
964
                            int subType = -1;
965

    
966
                            try {
967
                                subType
968
                                        = getCurrentLayer().getFeatureStore()
969
                                                .getDefaultFeatureType()
970
                                                .getDefaultGeometryAttribute()
971
                                                .getGeomType().getSubType();
972

    
973
                                geoType
974
                                        = GeometryLocator.getGeometryManager()
975
                                                .getGeometryType(geometryType, subType);
976
                            } catch (Exception e) {
977

    
978
                                String msg
979
                                        = String.format(
980
                                                "Problems getting default feature"
981
                                                + " type of %1$s or getting geometry"
982
                                                + " type of %2$s %3$s",
983
                                                getCurrentLayer().getName(), geometryType,
984
                                                subType);
985

    
986
                                throw new ServiceInformationException(msg, e);
987
                            }
988

    
989
                            return serviceInfo.isCompatibleWith(geoType)
990
                                    && serviceInfo.createsNewGeometries();
991
                        }
992
                    }
993
                }
994

    
995
                if (getCurrentLayer() != null) {
996
                    try {
997
                        geoType
998
                                = getCurrentLayer().getFeatureStore()
999
                                        .getDefaultFeatureType()
1000
                                        .getDefaultGeometryAttribute().getGeomType();
1001

    
1002
                        if (serviceInfo.isCompatibleWith(geoType)) {
1003
                            return true;
1004
                        }
1005
                    } catch (DataException e) {
1006
                        String msg
1007
                                = String.format("Problems getting default "
1008
                                        + "feature type of %1$s", getCurrentLayer()
1009
                                                .getName());
1010
                        throw new ServiceInformationException(msg, e);
1011
                    }
1012
                }
1013

    
1014
                return false;
1015
            } catch (ServiceInformationException e) {
1016
                LOGGER.warn(
1017
                    "Problems getting if editing context is compatible with "
1018
                        + name, e);
1019
            }
1020
        }
1021
        return false;
1022
    }
1023
     
1024
    private static final EditingContextSymbolTable contextSymbolTable = new EditingContextSymbolTable();
1025
    
1026
    @Override
1027
    public SymbolTable getContextSymbolTable() {
1028
        return contextSymbolTable;
1029
    }
1030
    
1031
    @Override
1032
    public Point parsePoint(String response) throws ParsePointException {
1033
        response = fixResponseUsingBookmarks(response);
1034
        
1035
        try {
1036
            Object x = ExpressionUtils.evaluate(contextSymbolTable, response);
1037
            if( x instanceof Point ) {
1038
                contextSymbolTable.addPoint((Point) x);
1039
                return (Point) x;
1040
            }
1041
        } catch(Exception ex) {
1042
            LOGGER.debug("Can't evaluate: "+StringEscapeUtils.escapeJava(response),ex);
1043
        }
1044
        String s = "ST_MakePoint("+response+")";
1045
        try {
1046
            Object x = ExpressionUtils.evaluate(contextSymbolTable, s);
1047
            if( x instanceof Point ) {
1048
                contextSymbolTable.addPoint((Point) x);
1049
                return (Point) x;
1050
            }
1051
        } catch(Exception ex) {
1052
            throw new ParsePointException(ex);
1053
        }
1054
        throw new ParsePointException(null);
1055
    }
1056
    
1057
    private Double parseValue(String response) throws ParseValueException {
1058
        response = fixResponseUsingBookmarks(response);
1059

    
1060
        try {
1061
            Object x = ExpressionUtils.evaluate(contextSymbolTable, response);
1062
            if( x instanceof Double ) {
1063
                return (Double) x;
1064
            }  
1065
            if( x==null ) {
1066
                throw new ParseValueException(new NullPointerException());
1067
            }
1068
            Coercion toDouble = ToolsLocator.getDataTypesManager().get(DataTypes.DOUBLE).getCoercion();
1069
            return (Double) toDouble.coerce(x);
1070
        } catch(Exception ex) {
1071
            throw new ParseValueException(ex);
1072
        }
1073

    
1074
    }
1075

    
1076
    protected String fixResponseUsingBookmarks(String response) throws LocatorException {
1077
        if( response != null ) {
1078
            response = response.trim();
1079
            int n = StringUtils.indexOf(response, " ");
1080
            if(n>0){
1081
                String name = StringUtils.left(response, n);
1082
                Function fn = contextSymbolTable.function(name);
1083
                if(fn != null){
1084
                    response = name+"("+response.substring(n)+")";
1085
                }
1086
            }
1087
        }
1088
        return response;
1089
    }
1090

    
1091
    protected void refreshMenusAndToolBars() {
1092
        if (!SwingUtilities.isEventDispatchThread()) {
1093
            SwingUtilities.invokeLater(new Runnable() {
1094

    
1095
                @Override
1096
                public void run() {
1097
                    refreshMenusAndToolBars();
1098
                }
1099
            });
1100
            return;
1101
        }
1102
        Notification notification = new BaseNotification(
1103
                EditingContext.REFRESH_TOOLS_NOTIFICATION,
1104
                null
1105
        );
1106
        this.observableHelper.notifyObservers(this, notification);
1107
    }
1108

    
1109
    private void saveChanges(FLyrVect layer) throws EndEditingException {
1110
        FeatureStore featureStore = layer.getFeatureStore();
1111
        try {
1112
            featureStore.finishEditing();
1113
        } catch (Exception e) {
1114
            throw new EndEditingException(e);
1115
        }
1116
    }
1117

    
1118
    private void setActiveService(EditingService service) {
1119
        serviceStack.add(service);
1120
        notifyChangeSelectedTool();
1121
    }
1122

    
1123
    private void setCompoundBehavior(EditingCompoundBehavior compoundBehavior) {
1124
        this.editingCompoundBehavior = compoundBehavior;
1125
    }
1126

    
1127
    private void setCurrentLayer(FLyrVect layer) {
1128

    
1129
        if (this.currentLayer != layer) {
1130
            this.currentLayer = layer;
1131
            cleanEditingContext();
1132
        }
1133

    
1134
    }
1135

    
1136
    @Override
1137
    public void setMapControl(MapControl mapControl) {
1138

    
1139
        this.mapControlReference = new WeakReference<>(mapControl);
1140
        this.mapContextReference =
1141
            new WeakReference<>(mapControl.getMapContext());
1142

    
1143
        // When mapControl is updated we have to add older additional behaviors
1144
        // to new mapControl
1145
        if (lastAdditionalBehaviors != null) {
1146
            try {
1147
                addBehaviors(lastAdditionalBehaviors);
1148
            } catch (CreateEditingBehaviorException e1) {
1149
                LOGGER.info("Problems adding behaviors to editing context", e1);
1150
                getMapControl().setTool("pan");
1151
            }
1152
        }
1153
    }
1154

    
1155
    private void showConsole() {
1156
        if (isShowConsole) {
1157
            return;
1158
        }
1159
        if( !SwingUtilities.isEventDispatchThread() ) {
1160
            try {
1161
                SwingUtilities.invokeAndWait(new Runnable() {
1162

    
1163
                    @Override
1164
                    public void run() {
1165
                        showConsole();
1166
                    }
1167
                });
1168
                return;
1169
            } catch (InterruptedException | InvocationTargetException ex) {
1170
                LOGGER.warn("Can't show editing console.",ex);
1171
            }
1172
            return;
1173
        }
1174
        isShowConsole = true;
1175
        getMapControl().remove(getDockConsole());
1176
        getMapControl().setLayout(new BorderLayout());
1177
        getMapControl().add(getDockConsole(), BorderLayout.SOUTH);
1178
        getDockConsole().setVisible(true);
1179
    }
1180

    
1181
    protected void showConsoleMessage(final String text) {
1182
        if (!SwingUtilities.isEventDispatchThread()) {
1183
            SwingUtilities.invokeLater(new Runnable() {
1184

    
1185
                @Override
1186
                public void run() {
1187
                    showConsoleMessage(text);
1188
                }
1189
            });
1190
            return;
1191
        }
1192
        getConsolePanel().addText(text);
1193
    }
1194

    
1195
    @Override
1196
    public void cancelActiveService() {
1197
        this.textEntered(null);
1198
    }
1199
    
1200
    protected void textEntered(String response) {
1201
        FeatureStore featureStore = getCurrentLayer().getFeatureStore();
1202
        EditingService activeService = getActiveService();
1203
        if (response == null) {
1204
            if (activeService != null) {
1205
                try {
1206
                    activeService.stop();
1207
                    serviceStack.pop();
1208
                    if (serviceStack.isEmpty()) {
1209
                        featureStore
1210
                            .getFeatureSelection().deselectAll();
1211
                        changeSelectedTool(DEFAULT_TOOL);
1212
                    } else {
1213
                        changeSelectedTool(activeService.getName());
1214
                    }
1215

    
1216
                    refreshMenusAndToolBars();
1217
                    activeService = getActiveService();
1218
                    if (activeService != null) {
1219
                        nextParameter();
1220
                    } else {
1221
                        cleanEditingContext();
1222
                    }
1223

    
1224
                } catch (StopServiceException e) {
1225
                    LOGGER
1226
                        .info("Can't stop " + activeService.getName(), e);
1227
                } catch (DataException e) {
1228
                    LOGGER.info("Can't get selection of "
1229
                        + featureStore.getFullName(), e);
1230
                }
1231
            }
1232
        } else {
1233

    
1234
            I18nManager i18nManager = ToolsLocator.getI18nManager();
1235
            if (getCurrentParam() != null) {
1236
                try {
1237
                    Object coercedValue = coerceInputParameter(getCurrentParam(), response);
1238
                    activeService.setValue(coercedValue);
1239
                } catch (InvalidEntryException ex) {
1240
                    showConsoleMessage("\n"
1241
                            + i18nManager.getTranslation("invalid_option"));
1242
                }
1243
            }
1244

    
1245
            activeService = getActiveService();
1246
            if (activeService != null) {
1247
                nextParameter();
1248
            } else {
1249
                cleanEditingContext();
1250
            }
1251
        }
1252
    }
1253
    
1254
    private Object coerceInputParameter(EditingServiceParameter parameter, String input) throws InvalidEntryException {
1255
        if (parameter != null) {
1256
            FeatureStore featureStore = getCurrentLayer().getFeatureStore();
1257
            Set<TYPE> types = parameter.getTypes();
1258
            Point point = null;
1259
            Double value = null;
1260
            Point defaultPoint = null;
1261
            Object defaultValue = parameter.getDefaultValue();
1262

    
1263
            boolean insertedValue = false;
1264
            if ((!insertedValue && types.contains(TYPE.POSITION))
1265
                    || types.contains(TYPE.LIST_POSITIONS)) {
1266

    
1267
                defaultPoint = (Point) defaultValue;
1268
                try {
1269
                    if (StringUtils.isEmpty(input.replace("\n", ""))) {
1270
                        point = defaultPoint;
1271
                    } else {
1272
                        point = parsePoint(input);
1273
                    }
1274

    
1275
                    if (point != null) {
1276
                        return point;
1277
                    }
1278

    
1279
                } catch (ParsePointException e) {
1280
                    // Do nothing to try other types
1281
                }
1282
            }
1283
            if (types.contains(TYPE.VALUE)) {
1284

    
1285
                try {
1286
                    value = parseValue(input);
1287
                    if (value != null) {
1288
                        return value;
1289
                    }
1290

    
1291
                } catch (ParseValueException e) {
1292
                    // Do nothing to try other types
1293
                }
1294

    
1295
            }
1296
            if (types.contains(TYPE.OPTION)) {
1297
                input = input.replace("\n", "");
1298
                return input;
1299
            }
1300

    
1301
            if (!insertedValue && types.contains(TYPE.SELECTION)) {
1302
                if (input.equalsIgnoreCase("\n")) {
1303
                    enableSelection(false);
1304
                    insertedValue = true;
1305

    
1306
                    FeatureSelection clonedSelection;
1307
                    try {
1308
                        clonedSelection = (FeatureSelection) featureStore
1309
                                .getFeatureSelection().clone();
1310
                        if (clonedSelection.isEmpty()) {
1311
                            throw new InvalidEntryException(null);
1312
                        }
1313
                    } catch (InvalidEntryException e) {
1314
                        throw e;
1315
                    } catch (Exception e) {
1316
                        LOGGER.warn("Can't access to selection.", e);
1317
                        throw new InvalidEntryException(e);
1318
//                        cleanEditingContext();
1319
//                        return null;
1320
                    }
1321
                    
1322
                    return clonedSelection;
1323
                }
1324
            }
1325
        }
1326
        return null;
1327
    }
1328

    
1329
    @Override
1330
    public void setDefaultBehaviors(Behavior[] defaultBehaviors) {
1331
        this.defaultBehaviors = defaultBehaviors;
1332
        try {
1333
            addBehaviors(defaultBehaviors);
1334
        } catch (CreateEditingBehaviorException e1) {
1335
            LOGGER.info("Problems adding behaviors to editing context", e1);
1336
            getMapControl().setTool("pan");
1337
        }
1338
    }
1339

    
1340
    @Override
1341
    public Behavior[] getDefaultBehaviors() {
1342
        return this.defaultBehaviors;
1343
    }
1344

    
1345
    @Override
1346
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
1347
        if( value instanceof CharSequence){
1348
            value = coerceInputParameter(parameter, value.toString());
1349
        } else if( value instanceof Point) {
1350
            contextSymbolTable.addPoint((Point) value);
1351
        }
1352
        getActiveService().setValue(parameter, value);
1353
//        nextParameter();
1354
    }
1355

    
1356
    public GeometryType getGeometryType() {
1357
        if( this.currentLayer==null ) {
1358
            return null;
1359
        }
1360
        FeatureStore store = this.currentLayer.getFeatureStore();
1361
        if( store == null ) {
1362
            return null;
1363
        }
1364
        FeatureType ftype = store.getDefaultFeatureTypeQuietly();
1365
        if( ftype == null ) {
1366
            return null;
1367
        }
1368
        FeatureAttributeDescriptor geomattr = ftype.getDefaultGeometryAttribute();
1369
        if( geomattr == null ) {
1370
            return null;
1371
        }
1372
        return geomattr.getGeomType();
1373
    }    
1374
    
1375
}