Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 24496

History | View | Annotate | Download (33.4 KB)

1 24496 jmvivo
package org.gvsig.fmap.dal.feature.impl;
2 23772 jjdelcerro
3 24446 jmvivo
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.Iterator;
6
import java.util.List;
7 23772 jjdelcerro
8 24496 jmvivo
import org.gvsig.fmap.dal.DALLocator;
9
import org.gvsig.fmap.dal.DataExplorer;
10
import org.gvsig.fmap.dal.DataManager;
11
import org.gvsig.fmap.dal.DataQuery;
12
import org.gvsig.fmap.dal.DataSet;
13
import org.gvsig.fmap.dal.DataStoreNotification;
14
import org.gvsig.fmap.dal.DataStoreParameters;
15
import org.gvsig.fmap.dal.exceptions.CloseException;
16
import org.gvsig.fmap.dal.exceptions.DataException;
17
import org.gvsig.fmap.dal.exceptions.InitializeException;
18
import org.gvsig.fmap.dal.exceptions.OpenException;
19
import org.gvsig.fmap.dal.exceptions.ProviderNotRegisteredException;
20
import org.gvsig.fmap.dal.exceptions.ReadException;
21
import org.gvsig.fmap.dal.feature.Command;
22
import org.gvsig.fmap.dal.feature.CommandsRecord;
23
import org.gvsig.fmap.dal.feature.EditableFeature;
24
import org.gvsig.fmap.dal.feature.EditableFeatureType;
25
import org.gvsig.fmap.dal.feature.Feature;
26
import org.gvsig.fmap.dal.feature.FeatureExplorer;
27
import org.gvsig.fmap.dal.feature.FeatureIndex;
28
import org.gvsig.fmap.dal.feature.FeatureIndexes;
29
import org.gvsig.fmap.dal.feature.FeatureQuery;
30
import org.gvsig.fmap.dal.feature.FeatureReference;
31
import org.gvsig.fmap.dal.feature.FeatureSelection;
32
import org.gvsig.fmap.dal.feature.FeatureSet;
33
import org.gvsig.fmap.dal.feature.FeatureStore;
34
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
35
import org.gvsig.fmap.dal.feature.FeatureStoreParameters;
36
import org.gvsig.fmap.dal.feature.FeatureType;
37
import org.gvsig.fmap.dal.feature.exceptions.AlreadyEditingException;
38
import org.gvsig.fmap.dal.feature.exceptions.ConcurrentDataModificationException;
39
import org.gvsig.fmap.dal.feature.exceptions.CreateFeatureException;
40
import org.gvsig.fmap.dal.feature.exceptions.DataExportException;
41
import org.gvsig.fmap.dal.feature.exceptions.FeatureIndexException;
42
import org.gvsig.fmap.dal.feature.exceptions.FinishEditingException;
43
import org.gvsig.fmap.dal.feature.exceptions.GetFeatureTypeException;
44
import org.gvsig.fmap.dal.feature.exceptions.IllegalFeatureException;
45
import org.gvsig.fmap.dal.feature.exceptions.IllegalFeatureTypeException;
46
import org.gvsig.fmap.dal.feature.exceptions.NeedEditingModeException;
47
import org.gvsig.fmap.dal.feature.exceptions.NoNewFeatureInsertException;
48
import org.gvsig.fmap.dal.feature.exceptions.NullFeatureTypeException;
49
import org.gvsig.fmap.dal.feature.exceptions.SelectionNotAllowedException;
50
import org.gvsig.fmap.dal.feature.exceptions.StoreCancelEditingException;
51
import org.gvsig.fmap.dal.feature.exceptions.StoreDeleteEditableFeatureException;
52
import org.gvsig.fmap.dal.feature.exceptions.StoreDeleteFeatureException;
53
import org.gvsig.fmap.dal.feature.exceptions.StoreEditException;
54
import org.gvsig.fmap.dal.feature.exceptions.StoreInsertFeatureException;
55
import org.gvsig.fmap.dal.feature.exceptions.StoreRedoException;
56
import org.gvsig.fmap.dal.feature.exceptions.StoreUndoException;
57
import org.gvsig.fmap.dal.feature.exceptions.StoreUpdateFeatureException;
58
import org.gvsig.fmap.dal.feature.exceptions.StoreUpdateFeatureTypeException;
59
import org.gvsig.fmap.dal.feature.exceptions.ValidateFeaturesException;
60
import org.gvsig.fmap.dal.feature.exceptions.WriteNotAllowedException;
61
import org.gvsig.fmap.dal.feature.impl.commands.AbstractCommandsRecord;
62
import org.gvsig.fmap.dal.feature.impl.commands.implementation.FeatureCommandsRecord;
63
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
64
import org.gvsig.fmap.dal.feature.impl.featureSet.DefaultFeatureSet;
65
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureData;
66
import org.gvsig.fmap.dal.feature.spi.FeatureData;
67
import org.gvsig.fmap.dal.feature.spi.FeatureLocks;
68
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
69
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
70
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
71
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
72
import org.gvsig.fmap.dal.impl.DefaultDataManager;
73 23772 jjdelcerro
import org.gvsig.fmap.geom.primitive.Envelope;
74
import org.gvsig.metadata.Metadata;
75
import org.gvsig.tools.exception.BaseException;
76 24180 jjdelcerro
import org.gvsig.tools.exception.NotYetImplemented;
77 23772 jjdelcerro
import org.gvsig.tools.observer.Observer;
78 24346 cordinyana
import org.gvsig.tools.observer.WeakReferencingObservable;
79 24268 jjdelcerro
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
80 23772 jjdelcerro
import org.gvsig.tools.operations.OperationContext;
81
import org.gvsig.tools.operations.OperationException;
82
import org.gvsig.tools.operations.OperationNotSupportedException;
83 24062 jjdelcerro
import org.gvsig.tools.persistence.AbstractPersistenceManager;
84
import org.gvsig.tools.persistence.PersistenceException;
85
import org.gvsig.tools.persistence.PersistentState;
86 23879 jjdelcerro
import org.slf4j.Logger;
87
import org.slf4j.LoggerFactory;
88 23772 jjdelcerro
89
final public class DefaultFeatureStore implements
90 23879 jjdelcerro
                FeatureStoreProviderServices,
91 24162 jjdelcerro
                Observer {
92 23772 jjdelcerro
93 24178 cordinyana
    final static private Logger logger = LoggerFactory
94
            .getLogger(DefaultFeatureStore.class);
95
96 23772 jjdelcerro
        private DataStoreParameters parameters = null;
97
        private FeatureSelection selection;
98
        private FeatureLocks locks;
99
100 24268 jjdelcerro
        private DelegateWeakReferencingObservable delegateObservable = new DelegateWeakReferencingObservable(this);
101 23772 jjdelcerro
102
        private AbstractCommandsRecord commands;
103
        private FeatureTypeManager featureTypeManager;
104
        private FeatureManager featureManager;
105
        private SpatialManager spatialManager;
106
107
        private FeatureType defaultFeatureType = null;
108
        private List featureTypes = new ArrayList();
109
110 24162 jjdelcerro
        private int mode = MODE_QUERY;
111 23772 jjdelcerro
        private long versionOfUpdate = 0;
112
        private boolean hasStrongChanges = true;
113
114
        private DefaultDataManager dataManager = null;
115
116
        private FeatureStoreProvider provider = null;
117
118 23962 jiyarza
        private DefaultFeatureIndexes indexes;
119 23894 jjdelcerro
120 23772 jjdelcerro
        /*
121
         * TODO:
122
         *
123 24396 jiyarza
         * - Comprobar que solo se pueden a�adir reglas de validacion sobre un
124 23772 jjdelcerro
         * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
125
         * featureType al que se le han cambiado las reglas de validacion cuando
126
         * hasStrongChanges=false.
127
         */
128
129
        public DefaultFeatureStore() {
130
131
        }
132
133
        public DefaultFeatureStore(DefaultDataManager manager,
134 23820 jjdelcerro
                        DataStoreParameters parameters, FeatureStoreProvider provider)
135
                        throws InitializeException {
136 23772 jjdelcerro
                initialize(manager, parameters, provider);
137
        }
138
139
        private void initialize(DefaultDataManager manager,
140 23820 jjdelcerro
                        DataStoreParameters parameters, FeatureStoreProvider provider)
141
                        throws InitializeException {
142 23772 jjdelcerro
                this.dataManager = manager;
143
                this.provider = provider;
144
                this.parameters = parameters;
145
                this.provider.initialize(this);
146
        }
147
148
        public String getName() {
149
                return this.parameters.getDataStoreName();
150
        }
151
152
        public DataStoreParameters getParameters() {
153
                return parameters;
154
        }
155
156
        public DefaultDataManager getManager() {
157
                return this.dataManager;
158
        }
159
160 24396 jiyarza
        public Iterator getChildren() {
161 23820 jjdelcerro
                return this.provider.getChilds();
162 23772 jjdelcerro
        }
163
164 23820 jjdelcerro
        public FeatureStoreProvider getProvider() {
165
                return this.provider;
166
        }
167
168
        public FeatureManager getFeatureManager() {
169
                return this.featureManager;
170
        }
171
172 23772 jjdelcerro
        public void setFeatureTypes(List types, FeatureType defaultType) {
173
                this.featureTypes = types;
174
                this.defaultFeatureType = defaultType;
175
        }
176
177
        public void open() throws OpenException {
178
                // TODO: Se puede hacer un open estando en edicion ?
179
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
180
                this.provider.open();
181
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
182
        }
183
184
        public void refresh() throws OpenException, InitializeException {
185 24180 jjdelcerro
                if (this.mode != MODE_QUERY) {
186 23772 jjdelcerro
                        throw new IllegalStateException();
187
                }
188
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
189
                this.provider.refresh();
190
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
191
        }
192
193
        public void close() throws CloseException {
194
                // TODO: Se puede hacer un close estando en edicion ?
195
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
196
                this.provider.close();
197
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
198
        }
199
200
        public void dispose() throws CloseException {
201
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
202
                this.provider.dispose();
203
                if (this.selection != null) {
204
                        this.selection.dispose();
205
                        this.selection = null;
206
                }
207
                this.commands = null;
208
209
                if (this.locks != null) {
210
                        this.locks.dispose();
211
                        this.locks = null;
212
                }
213 23820 jjdelcerro
214 23772 jjdelcerro
                this.featureManager = null;
215
                this.spatialManager = null;
216
217
                this.parameters = null;
218
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
219 24178 cordinyana
                this.delegateObservable.deleteObservers();
220
                this.delegateObservable = null;
221 23772 jjdelcerro
        }
222
223
        public boolean allowWrite() {
224
                return this.provider.allowWrite();
225
        }
226
227 24446 jmvivo
        public boolean canWriteGeometry(int geometryType) throws DataException {
228 23772 jjdelcerro
                return this.provider.canWriteGeometry(geometryType);
229
        }
230
231
        public DataExplorer getExplorer() throws ReadException {
232
                return this.provider.getExplorer();
233
        }
234
235
        public Metadata getMetadata() throws BaseException {
236
                // TODO:
237
                // Si el provider devuelbe null habria que ver de construir aqui
238
                // los metadatos basicos, como el Envelope y el SRS.
239
                return this.provider.getMetadata();
240
        }
241
242
        public Envelope getEnvelope() {
243 24180 jjdelcerro
                // FIXME: Y en edicion/append
244 23772 jjdelcerro
                return this.provider.getEnvelope();
245
        }
246
247 23894 jjdelcerro
        public FeatureIndexes getIndexes() {
248
                return this.indexes;
249
        }
250
251 24180 jjdelcerro
        /**
252
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
253
         */
254 23772 jjdelcerro
        public String getSRSDefaultGeometry() throws DataException {
255 24180 jjdelcerro
                return this.getDefaultFeatureType().getDefaultSRS();
256 23772 jjdelcerro
        }
257
258
        public FeatureSelection createDefaultFeatureSelection()
259
                        throws DataException {
260
                return new DefaultFeatureSelection(this);
261
        }
262
263
        public FeatureData createDefaultFeatureData(FeatureType type)
264
                        throws DataException {
265 23879 jjdelcerro
                return new DefaultFeatureData(type);
266 23772 jjdelcerro
        }
267
268 24062 jjdelcerro
        public PersistentState getState()
269
                        throws PersistenceException {
270
                return AbstractPersistenceManager.getState(this);
271 23772 jjdelcerro
        }
272
273 24062 jjdelcerro
        public void loadState(PersistentState state) throws PersistenceException {
274 24019 jjdelcerro
                state.setTheClass(this);
275
                state.set("dataStoreName", this.getName());
276
                state.set("parameters", this.parameters);
277
                state.set("provider", this.provider);
278
                state.set("selection", this.selection);
279
        }
280
281
        public void setState(PersistentState state) throws PersistenceException {
282
                if (this.provider != null) {
283
                        throw new PersistenceException(null);
284
                }
285
                if (this.getManager() == null) {
286
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
287
                }
288
289
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
290
                FeatureStoreProvider provider = (FeatureStoreProvider) state.get("provider");
291
292 24062 jjdelcerro
                try {
293 24019 jjdelcerro
294 24062 jjdelcerro
                        initialize(this.getManager(), params, provider);
295
                        setSelection((FeatureSelection) state.get("selection"));
296
297
                } catch (InitializeException e) {
298
                        throw new PersistenceException(e);
299
                } catch (DataException e) {
300
                        throw new PersistenceException(e);
301
                }
302
303 24019 jjdelcerro
        }
304
305 23772 jjdelcerro
        //
306
        // ====================================================================
307
        // Gestion de la seleccion
308
        //
309
310 23842 jjdelcerro
        public void setSelection(DataSet selection)
311 23772 jjdelcerro
                        throws DataException {
312 23894 jjdelcerro
                this.setSelection((FeatureSet) selection);
313 23772 jjdelcerro
        }
314
315 23842 jjdelcerro
        public DataSet createSelection() throws DataException {
316 23772 jjdelcerro
                return createFeatureSelection();
317
        }
318
319 23842 jjdelcerro
        public DataSet getSelection() throws DataException {
320 23772 jjdelcerro
                return this.getFeatureSelection();
321
        }
322
323 23842 jjdelcerro
        public void setSelection(FeatureSet selection)
324 23772 jjdelcerro
                        throws DataException {
325
                if (selection.equals(this.selection)) {
326
                        return;
327
                }
328
                if (!selection.isFromStore(this)) {
329
                        throw new SelectionNotAllowedException(getName());
330
                }
331 23894 jjdelcerro
332
                this.selection.deleteObserver(this);
333
                if (selection instanceof FeatureSelection) {
334 24194 jjdelcerro
                        if (isEditing()) {
335 24346 cordinyana
                                commands.selectionSet(this, this.selection,
336 24194 jjdelcerro
                                                (FeatureSelection) selection);
337
                        }
338 23894 jjdelcerro
                        this.selection = (FeatureSelection) selection;
339 23772 jjdelcerro
                } else {
340 24194 jjdelcerro
                        if (isEditing()) {
341 24195 jjdelcerro
                                commands.startComplex("_selectionSet");
342 24194 jjdelcerro
                        }
343 23894 jjdelcerro
                        this.selection.deselectAll();
344
                        this.selection.select(selection);
345 24194 jjdelcerro
                        if (isEditing()) {
346 24195 jjdelcerro
                                commands.endComplex();
347 24194 jjdelcerro
                        }
348 23772 jjdelcerro
                }
349 23894 jjdelcerro
                this.selection.addObserver(this);
350
351 23772 jjdelcerro
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
352
        }
353
354 23894 jjdelcerro
        public FeatureSelection createFeatureSelection() throws DataException {
355 23772 jjdelcerro
                return this.provider.createFeatureSelection();
356
        }
357
358 23894 jjdelcerro
        public FeatureSelection getFeatureSelection() throws DataException {
359 23772 jjdelcerro
                if (selection == null) {
360 23894 jjdelcerro
                        this.selection = createFeatureSelection();
361
                        this.selection.addObserver(this);
362 23772 jjdelcerro
                }
363
                return selection;
364
        }
365
366
        //
367
        // ====================================================================
368
        // Gestion de notificaciones
369
        //
370
371
        public void notifyChange(String notification) {
372 24178 cordinyana
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
373
                notification));
374 23772 jjdelcerro
375
        }
376
377
        public void notifyChange(String notification, Feature feature) {
378 24178 cordinyana
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
379 23772 jjdelcerro
                                                this, notification, feature));
380
        }
381
382
        public void notifyChange(String notification, Command command) {
383 24178 cordinyana
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
384 23772 jjdelcerro
                                                this, notification, command));
385
        }
386
387
        public void notifyChange(String notification, EditableFeatureType type) {
388 24178 cordinyana
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
389
                notification, type));
390 23772 jjdelcerro
        }
391
392
393
        //
394
        // ====================================================================
395
        // Gestion de bloqueos
396
        //
397
398
399 23842 jjdelcerro
        public FeatureSet getLocks() throws DataException {
400 23894 jjdelcerro
                if (!this.provider.isLocksSupported()) {
401
                        getLogger().warn("Locks not supporteds");
402
                        return null;
403
                }
404 23772 jjdelcerro
                if (locks == null) {
405
                        this.locks = this.provider.createFeatureLocks();
406
                }
407
                return locks;
408
        }
409
410
        //
411
        // ====================================================================
412 24178 cordinyana
    // Interface Observable
413 23772 jjdelcerro
        //
414
415 24178 cordinyana
    public void disableNotifications() {
416
        this.delegateObservable.disableNotifications();
417 23772 jjdelcerro
418 24178 cordinyana
    }
419 23772 jjdelcerro
420 24178 cordinyana
    public void enableNotifications() {
421
        this.delegateObservable.enableNotifications();
422
    }
423 23772 jjdelcerro
424 24178 cordinyana
    public void beginComplexNotification() {
425
        this.delegateObservable.beginComplexNotification();
426 23772 jjdelcerro
427 24178 cordinyana
    }
428 23772 jjdelcerro
429 24178 cordinyana
    public void endComplexNotification() {
430
        this.delegateObservable.endComplexNotification();
431 23772 jjdelcerro
432 24178 cordinyana
    }
433 23772 jjdelcerro
434 24178 cordinyana
        public void addObserver(Observer observer) {
435
                this.delegateObservable.addObserver(observer);
436 23772 jjdelcerro
437
        }
438
439 24178 cordinyana
        public void deleteObserver(Observer observer) {
440
        this.delegateObservable.deleteObserver(observer);
441 23772 jjdelcerro
        }
442
443
        public void deleteObservers() {
444 24178 cordinyana
                this.delegateObservable.deleteObservers();
445 23772 jjdelcerro
446
        }
447
448
        //
449
        // ====================================================================
450
        // Interface Observer
451
        //
452
        // Usado para observar:
453
        // - su seleccion
454
        // - sus bloqueos
455
        // - sus recursos
456
        //
457
458 24268 jjdelcerro
        public void update(WeakReferencingObservable observable, Object notification) {
459 23894 jjdelcerro
                if (observable instanceof FeatureSet) {
460 23772 jjdelcerro
                        if (observable == this.selection) {
461
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
462
                        } else if (observable == this.locks) {
463
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
464
                        }
465
466
                }
467
        }
468
469
470
        //
471
        // ====================================================================
472
        // Gestion de operaciones
473
        // Interface ExtendedOperations
474
        //
475
        public Object invokeOperation(int code, OperationContext context)
476
                        throws OperationException, OperationNotSupportedException {
477 24118 jiyarza
                return this.dataManager.getOperationManager().invokeOperation(this, code, context);
478 23772 jjdelcerro
        }
479
480
        public Object invokeOperation(String name, OperationContext context)
481
                        throws OperationException, OperationNotSupportedException {
482 24118 jiyarza
                return this.dataManager.getOperationManager().invokeOperation(this, name, context);
483 23772 jjdelcerro
        }
484
485 24066 jjdelcerro
        public boolean hasOperation(int code) {
486 24118 jiyarza
                return this.dataManager.getOperationManager().hasOperation(this, code);
487 23772 jjdelcerro
        }
488
489 24066 jjdelcerro
        public boolean hasOperation(String name) {
490 24118 jiyarza
                return this.dataManager.getOperationManager().hasOperation(this, name);
491 23772 jjdelcerro
        }
492
493
        public Object getOperation(int code) throws OperationException {
494 24118 jiyarza
                return this.dataManager.getOperationManager().getOperation(this, code);
495 23772 jjdelcerro
        }
496
497
        public Object getOperation(String name) throws OperationException {
498 24118 jiyarza
                return this.dataManager.getOperationManager().getOperation(this, name);
499 23772 jjdelcerro
        }
500
501
        //
502
        // ====================================================================
503
        // Edicion
504
        //
505
506
        private void newVersionOfUpdate() {
507
                this.versionOfUpdate++;
508
        }
509
510
        private long currentVersionOfUpdate() {
511
                return this.versionOfUpdate;
512
        }
513
514
        private void checkInEditingMode()
515
                        throws NeedEditingModeException {
516 24162 jjdelcerro
                if (mode != MODE_FULLEDIT) {
517 23772 jjdelcerro
                        throw new NeedEditingModeException(this.getName());
518
                }
519
        }
520
521 24180 jjdelcerro
        private void checkNotInAppendMode() throws IllegalStateException {
522
                if (mode == MODE_APPEND) {
523
                        throw new IllegalStateException(this.getName());
524
                }
525
        }
526
527 23772 jjdelcerro
        private void checkIsOwnFeature(Feature feature)
528 24017 jjdelcerro
                        throws IllegalFeatureException {
529 23772 jjdelcerro
                if (((DefaultFeature) feature).getStore() != this) {
530 24017 jjdelcerro
                        throw new IllegalFeatureException(this.getName());
531 23772 jjdelcerro
                }
532
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
533
                // fixFeatureType((DefaultFeatureType) feature.getType());
534
        }
535
536
        private void exitEditingMode() {
537
                commands.clear();
538
                featureManager = null;
539
                spatialManager = null;
540
                featureTypeManager = null;
541
                commands = null;
542
543 24162 jjdelcerro
                mode = MODE_QUERY;
544 23772 jjdelcerro
                hasStrongChanges = true; // Lo deja a true por si las moscas
545
        }
546
547
        synchronized public void edit() throws DataException {
548 24162 jjdelcerro
                edit(MODE_FULLEDIT);
549
        }
550
551
        synchronized public void edit(int mode) throws DataException {
552 23772 jjdelcerro
                try {
553 24162 jjdelcerro
                        if ( this.mode != MODE_QUERY ) {
554 23772 jjdelcerro
                                throw new AlreadyEditingException(this.getName());
555
                        }
556 24185 jjdelcerro
                        if (!this.provider.supportsAppendMode()) {
557
                                mode = MODE_FULLEDIT;
558
                        }
559 24162 jjdelcerro
                        switch (mode) {
560
                        case MODE_QUERY:
561
                                throw new IllegalStateException(this.getName());
562 23772 jjdelcerro
563 24162 jjdelcerro
                        case MODE_FULLEDIT:
564
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
565
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
566
                                featureTypeManager = new FeatureTypeManager(
567
                                                new MemoryExpansionAdapter());
568
                                spatialManager = new SpatialManager();
569 23772 jjdelcerro
570 24162 jjdelcerro
                                commands = new FeatureCommandsRecord(featureManager,
571
                                                spatialManager, featureTypeManager);
572
                                this.mode = MODE_FULLEDIT;
573
                                hasStrongChanges = false;
574
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
575
                                break;
576
                        case MODE_APPEND:
577
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
578
                                this.provider.beginAppend();
579
                                this.mode = MODE_APPEND;
580
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
581
                                break;
582
                        }
583 23772 jjdelcerro
                } catch (Exception e) {
584
                        throw new StoreEditException(e, this.getName());
585
                }
586
        }
587
588
        public boolean isEditing() {
589 24162 jjdelcerro
                return mode == MODE_FULLEDIT;
590 23772 jjdelcerro
        }
591
592 24162 jjdelcerro
        public boolean isAppending() {
593
                return mode == MODE_APPEND;
594
        }
595
596 23772 jjdelcerro
        synchronized public void update(EditableFeatureType type)
597
                        throws DataException {
598
                try {
599
                        checkInEditingMode();
600
                        if (type == null) {
601
                                throw new NullFeatureTypeException(getName());
602
                        }
603
                        // FIXME: Comprobar que es un featureType aceptable.
604
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
605
                        newVersionOfUpdate();
606
607
                        FeatureType oldt = type.getSource().getCopy();
608
                        FeatureType newt = type.getNotEditableCopy();
609
                        commands.update(newt, oldt);
610
611
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
612
                                hasStrongChanges = true;
613
                        }
614
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
615
                } catch (Exception e) {
616
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
617
                }
618
        }
619
620
        synchronized public void delete(Feature feature) throws DataException {
621
                try {
622
                        checkInEditingMode();
623
                        checkIsOwnFeature(feature);
624
                        if (feature instanceof EditableFeature) {
625
                                throw new StoreDeleteEditableFeatureException(getName());
626
                        }
627
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
628
                        this.commands.delete(feature);
629
                        newVersionOfUpdate();
630
                        hasStrongChanges = true;
631
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
632
                } catch (Exception e) {
633
                        throw new StoreDeleteFeatureException(e, this.getName());
634
                }
635
        }
636
637
        private static EditableFeature lastChangedFeature = null;
638
639
        synchronized public void insert(EditableFeature feature)
640
                        throws DataException {
641
                try {
642 24162 jjdelcerro
                        switch (mode) {
643
                        case MODE_QUERY:
644
                                throw new NeedEditingModeException(this.getName());
645
646
                        case MODE_APPEND:
647
                                checkIsOwnFeature(feature);
648
                                if (feature.getSource() != null) {
649
                                        throw new NoNewFeatureInsertException(this.getName());
650
                                }
651
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
652 23772 jjdelcerro
                                feature.validate(Feature.UPDATE);
653 24162 jjdelcerro
                                provider.append(feature);
654
                                hasStrongChanges = true;
655
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
656
                                break;
657
658
                        case MODE_FULLEDIT:
659
                                checkIsOwnFeature(feature);
660
                                if (feature.getSource() != null) {
661
                                        throw new NoNewFeatureInsertException(this.getName());
662
                                }
663
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
664
                                newVersionOfUpdate();
665
                                if (lastChangedFeature.getSource() != feature.getSource()) {
666
                                        lastChangedFeature = feature;
667
                                        feature.validate(Feature.UPDATE);
668
                                        lastChangedFeature = null;
669
                                }
670
                                commands.insert(feature.getNotEditableCopy());
671
                                hasStrongChanges = true;
672
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
673
                                break;
674 23772 jjdelcerro
                        }
675
                } catch (Exception e) {
676
                        throw new StoreInsertFeatureException(e, this.getName());
677
                }
678
        }
679
680
        synchronized public void update(EditableFeature feature)
681
                        throws DataException {
682
                try {
683
                        if ((feature).getSource() == null) {
684
                                insert(feature);
685
                                return;
686
                        }
687
                        checkInEditingMode();
688
                        checkIsOwnFeature(feature);
689
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
690
                        newVersionOfUpdate();
691
                        if (lastChangedFeature.getSource() != feature.getSource()) {
692
                                lastChangedFeature = feature;
693
                                feature.validate(Feature.UPDATE);
694
                                lastChangedFeature = null;
695
                        }
696
697
                        Feature oldf = feature.getSource();
698
                        Feature newf = feature.getNotEditableCopy();
699
                        commands.update(newf, oldf);
700
701
                        hasStrongChanges = true;
702
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
703
                } catch (Exception e) {
704
                        throw new StoreUpdateFeatureException(e, this.getName());
705
                }
706
        }
707
708
        synchronized public void redo() throws DataException {
709
                try {
710
                        checkInEditingMode();
711
                        Command redo = commands.getNextRedoCommand();
712
                        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
713
                        newVersionOfUpdate();
714
                        commands.redo();
715
                        hasStrongChanges = true;
716
                        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
717
                } catch (Exception e) {
718
                        throw new StoreRedoException(e, this.getName());
719
                }
720
        }
721
722
        synchronized public void undo() throws DataException {
723
                try {
724
                        checkInEditingMode();
725
                        Command undo = commands.getNextUndoCommand();
726
                        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
727
                        newVersionOfUpdate();
728
                        commands.undo();
729
                        hasStrongChanges = true;
730
                        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
731
                } catch (Exception e) {
732
                        throw new StoreUndoException(e, this.getName());
733
                }
734
        }
735
736
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
737
                checkInEditingMode();
738
                return commands;
739
        }
740
741
        synchronized public void cancelEditing() throws DataException {
742
                try {
743
                        checkInEditingMode();
744
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
745
                        exitEditingMode();
746
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
747
                } catch (Exception e) {
748
                        throw new StoreCancelEditingException(e, this.getName());
749
                }
750
        }
751
752
        synchronized public void finishEditing() throws DataException {
753
                try {
754 24162 jjdelcerro
                        switch (mode) {
755
                        case MODE_QUERY:
756
                                throw new NeedEditingModeException(this.getName());
757
758
                        case MODE_APPEND:
759
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
760
                                provider.endAppend();
761
                                exitEditingMode();
762
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
763
                                break;
764
765
                        case MODE_FULLEDIT:
766
                                if (!hasStrongChanges) {
767
                                        performLightEditing();
768
                                        return;
769
                                }
770
                                if (!this.allowWrite()) {
771
                                        throw new WriteNotAllowedException(getName());
772
                                }
773
774
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
775
                                validateFeatures(Feature.FINISH_EDITING);
776
                                provider.performEditing(featureManager.getInserted(),
777
                                                featureManager.getUpdated(), featureManager
778
                                                                .getDeleted());
779
                                exitEditingMode();
780
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
781
                                break;
782 23772 jjdelcerro
                        }
783
                } catch (Exception e) {
784
                        throw new FinishEditingException(e);
785
                }
786
        }
787
788
        private void performLightEditing() throws DataException {
789 24180 jjdelcerro
                throw new NotYetImplemented(
790 23772 jjdelcerro
                                "lightFinishEdition not yet implemented");
791
792
                // TODO: implementar
793
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
794
                // exitEditingMode();
795
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
796
        }
797
798 24185 jjdelcerro
799
        public boolean isAppendModeSupported() {
800
                return this.provider.supportsAppendMode();
801
        }
802
803
804 24017 jjdelcerro
        public void export(FeatureExplorer explorer, FeatureStoreParameters params)
805 23772 jjdelcerro
                        throws DataException {
806
807
                if (this.getFeatureTypes().size() != 1) {
808 24180 jjdelcerro
                        throw new NotYetImplemented(
809 23772 jjdelcerro
                                        "export whith more than one type not yet implemented");
810
                }
811
                try {
812
                        FeatureType type = this.getDefaultFeatureType();
813 24017 jjdelcerro
                        params.setDefaultFeatureType(type);
814
                        explorer.add(params);
815 23772 jjdelcerro
816
                        DataManager manager = DALLocator.getDataManager();
817
                        FeatureStore target = (FeatureStore) manager
818 24062 jjdelcerro
                                        .createStore(params);
819 23772 jjdelcerro
                        target.edit();
820
821 23842 jjdelcerro
                        FeatureSet features = this.getFeatureSet();
822 23772 jjdelcerro
                        Iterator it1 = features.iterator();
823
                        while (it1.hasNext()) {
824
                                Feature feature = (Feature) it1.next();
825 24152 jjdelcerro
                                target.insert(target.createNewFeature(type, feature));
826 23772 jjdelcerro
                        }
827
                        features.dispose();
828
                        target.finishEditing();
829
                        target.dispose();
830
                } catch (Exception e) {
831
                        throw new DataExportException(e, params.toString());
832
                }
833
        }
834
835
        //
836
        // ====================================================================
837
        // Obtencion de datos
838
        // getDataCollection, getFeatureCollection
839
        //
840
841 23842 jjdelcerro
        public DataSet getDataSet() throws DataException {
842 24180 jjdelcerro
                checkNotInAppendMode();
843 23842 jjdelcerro
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
844
                return new DefaultFeatureSet(this, query);
845 23772 jjdelcerro
        }
846
847 23842 jjdelcerro
        public DataSet getDataSet(DataQuery dataQuery)
848 23820 jjdelcerro
                        throws DataException {
849 24180 jjdelcerro
                checkNotInAppendMode();
850 23842 jjdelcerro
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
851 23772 jjdelcerro
        }
852
853 23842 jjdelcerro
        public void getDataSet(Observer observer) throws DataException {
854 24180 jjdelcerro
                checkNotInAppendMode();
855 23842 jjdelcerro
                this.getFeatureSet(null, observer);
856 23772 jjdelcerro
        }
857
858 23842 jjdelcerro
        public void getDataSet(DataQuery dataQuery, Observer observer)
859 23772 jjdelcerro
                        throws DataException {
860 24180 jjdelcerro
                checkNotInAppendMode();
861 23842 jjdelcerro
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
862 23772 jjdelcerro
        }
863
864 23842 jjdelcerro
        public FeatureSet getFeatureSet() throws DataException {
865 24180 jjdelcerro
                checkNotInAppendMode();
866 23842 jjdelcerro
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
867
                return new DefaultFeatureSet(this, query);
868 23772 jjdelcerro
        }
869
870 23842 jjdelcerro
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
871 23820 jjdelcerro
                        throws DataException {
872 24180 jjdelcerro
                checkNotInAppendMode();
873 23820 jjdelcerro
                fixFeatureQuery(featureQuery);
874
                return new DefaultFeatureSet(this, featureQuery);
875 23772 jjdelcerro
        }
876
877 23820 jjdelcerro
        private void fixFeatureQuery(FeatureQuery featureQuery)
878
                        throws DataException {
879
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
880
                if (featureQuery.getAttributeNames() != null){
881
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
882
                                        .getFeatureType();
883
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
884
                                        .getAttributeNames()));
885
                }
886
        }
887
888 23842 jjdelcerro
        public void getFeatureSet(Observer observer)
889 23772 jjdelcerro
                        throws DataException {
890 24180 jjdelcerro
                checkNotInAppendMode();
891 23842 jjdelcerro
                this.getFeatureSet(null, observer);
892 23772 jjdelcerro
        }
893
894 23842 jjdelcerro
        public void getFeatureSet(FeatureQuery query, Observer observer)
895 23772 jjdelcerro
                        throws DataException {
896
                class LoadInBackGround implements Runnable {
897
                        private FeatureStore store;
898
                        private FeatureQuery query;
899
                        private Observer observer;
900
901
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
902
                                        Observer observer) {
903
                                this.store = store;
904
                                this.query = query;
905
                                this.observer = observer;
906
                        }
907
908
                        public void run() {
909
                                try {
910 23842 jjdelcerro
                                        FeatureSet collection = store.getFeatureSet(query);
911 23772 jjdelcerro
                                        observer.update(
912
                                                        store,
913
                                                        new DefaultFeatureStoreNotification(
914
                                                                        store,
915
                                                                        FeatureStoreNotification.LOAD_FINISHED,
916
                                                                        collection
917
                                                                )
918
                                                );
919
                                } catch (Exception e) {
920
                                        observer.update(
921
                                                        store,
922
                                                        new DefaultFeatureStoreNotification(
923
                                                                        store,
924
                                                                        FeatureStoreNotification.LOAD_FINISHED,
925
                                                                        e
926
                                                                )
927
                                                );
928
                                }
929
                        }
930
                }
931
932 24180 jjdelcerro
                checkNotInAppendMode();
933 23772 jjdelcerro
                if (query == null) {
934
                        query = new FeatureQuery(this.getDefaultFeatureType());
935
                }
936
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
937
                Thread thread = new Thread(task);
938
                thread.run();
939
        }
940
941 23842 jjdelcerro
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
942 24180 jjdelcerro
                checkNotInAppendMode();
943 23842 jjdelcerro
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
944 23772 jjdelcerro
        }
945
946 23842 jjdelcerro
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
947 23820 jjdelcerro
                        throws DataException {
948 24180 jjdelcerro
                checkNotInAppendMode();
949 23820 jjdelcerro
                featureType = fixFeatureType((DefaultFeatureType) featureType);
950
                // TODO comprobar que el id es de este store
951
952 24162 jjdelcerro
                if (this.mode == MODE_FULLEDIT) {
953 24132 vcaballero
                        Feature f = featureManager.get(reference, this, featureType);
954
                        if (f!=null) {
955
                                return f;
956 23820 jjdelcerro
                        }
957
                }
958 24248 jjdelcerro
                return new DefaultFeature(this, this.provider
959
                                .getFeatureDataByReference((FeatureReferenceProviderServices) reference));
960 23772 jjdelcerro
        }
961
962
        //
963
        // ====================================================================
964
        // Gestion de features
965
        //
966
967
        private FeatureType fixFeatureType(DefaultFeatureType type)
968
                        throws DataException {
969
                FeatureType defaultType = this.getDefaultFeatureType();
970
                if (type == null || type.equals(defaultType)) {
971
                        return defaultType;
972
                }
973
                if (type.isSubtypeOf(defaultType)) {
974
                        return type;
975
                }
976
                Iterator iter = this.getFeatureTypes().iterator();
977
                FeatureType tmpType;
978
                while (iter.hasNext()) {
979
                        tmpType = (FeatureType) iter.next();
980
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
981
                                return type;
982
                        }
983
984
                }
985 24017 jjdelcerro
                throw new IllegalFeatureTypeException(getName());
986 23772 jjdelcerro
        }
987
988
        public void validateFeatures(int mode) throws DataException {
989
                try {
990 24180 jjdelcerro
                        checkNotInAppendMode();
991 23842 jjdelcerro
                        FeatureSet collection = this.getFeatureSet();
992 23772 jjdelcerro
                        Iterator iter = collection.iterator();
993
                        long previousVersionOfUpdate = currentVersionOfUpdate();
994
                        while (iter.hasNext()) {
995
                                ((DefaultFeature) iter.next()).validate(mode);
996
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
997
                                        throw new ConcurrentDataModificationException(getName());
998
                                }
999
                        }
1000
                } catch (Exception e) {
1001
                        throw new ValidateFeaturesException(e, getName());
1002
                }
1003
        }
1004
1005
        public FeatureType getDefaultFeatureType() throws DataException {
1006
                try {
1007
                        if (isEditing()) {
1008 24132 vcaballero
                                return featureTypeManager.getType(defaultFeatureType.getId());
1009 23772 jjdelcerro
                        }
1010
                        return defaultFeatureType;
1011
                } catch (Exception e) {
1012
                        throw new GetFeatureTypeException(e, getName());
1013
                }
1014
        }
1015
1016
        public List getFeatureTypes() throws DataException {
1017
                try {
1018
                        List types;
1019
                        if (isEditing()) {
1020 24132 vcaballero
                                types=new ArrayList();
1021
                                Iterator it=featureTypes.iterator();
1022
                                while (it.hasNext()) {
1023
                                        FeatureType type = (FeatureType) it.next();
1024
                                        type=featureTypeManager.getType(type.getId());
1025 24162 jjdelcerro
                                        if (type!=null) {
1026 24132 vcaballero
                                                types.add(type);
1027 24162 jjdelcerro
                                        }
1028 24132 vcaballero
                                }
1029
                                it = featureTypeManager.newsIterator();
1030
                                while (it.hasNext()) {
1031
                                        FeatureType type = (FeatureType) it.next();
1032
                                        types.add(type);
1033
                                }
1034 23772 jjdelcerro
                        } else {
1035
                                types = featureTypes;
1036
                        }
1037
                        return Collections.unmodifiableList(types);
1038
                } catch (Exception e) {
1039
                        throw new GetFeatureTypeException(e, getName());
1040
                }
1041
        }
1042
1043 23879 jjdelcerro
        public Feature createFeature(FeatureData data)
1044 23772 jjdelcerro
                        throws DataException {
1045
                DefaultFeature feature = new DefaultFeature(this, data);
1046
                return feature;
1047
        }
1048
1049 24248 jjdelcerro
        public Feature createFeature(FeatureData data, FeatureType type)
1050 23879 jjdelcerro
                        throws DataException {
1051
                // FIXME: falta por implementar
1052
                // Comprobar si es un subtipo del feature de data
1053
                // y construir un feature usando el subtipo.
1054
                // Probablemente requiera generar una copia del data.
1055 24248 jjdelcerro
                throw new NotYetImplemented();
1056 23879 jjdelcerro
        }
1057
1058 24152 jjdelcerro
        public EditableFeature createNewFeature(FeatureType type,
1059 23772 jjdelcerro
                        Feature defaultValues)
1060
                        throws DataException {
1061
                try {
1062
                        type = this.fixFeatureType((DefaultFeatureType) type);
1063 24248 jjdelcerro
                        FeatureData data = this.provider.createFeatureData(type);
1064 23772 jjdelcerro
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1065
                                        data);
1066
                        feature.initializeValues(defaultValues);
1067
                        return feature;
1068
                } catch (Exception e) {
1069
                        throw new CreateFeatureException(e, getName());
1070
                }
1071
        }
1072
1073 24152 jjdelcerro
        public EditableFeature createNewFeature(FeatureType type,
1074 23772 jjdelcerro
                        boolean defaultValues)
1075
                        throws DataException {
1076
                try {
1077
                        type = this.fixFeatureType((DefaultFeatureType) type);
1078 24141 vcaballero
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, type);
1079 23772 jjdelcerro
                        if (defaultValues) {
1080
                                feature.initializeValues();
1081
                        }
1082
                        return feature;
1083
                } catch (Exception e) {
1084
                        throw new CreateFeatureException(e, getName());
1085
                }
1086
        }
1087
1088 24152 jjdelcerro
        public EditableFeature createNewFeature(boolean defaultValues)
1089 23772 jjdelcerro
                        throws DataException {
1090 24152 jjdelcerro
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1091 23772 jjdelcerro
        }
1092
1093 24152 jjdelcerro
        public EditableFeature createNewFeature() throws DataException {
1094
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1095 23772 jjdelcerro
        }
1096
1097 23879 jjdelcerro
        public EditableFeatureType createFeatureType() {
1098
                return new DefaultEditableFeatureType();
1099 23820 jjdelcerro
        }
1100 23772 jjdelcerro
1101 23879 jjdelcerro
        public boolean isLocksSupported() {
1102
                return this.provider.isLocksSupported();
1103
        }
1104
1105
        public Logger getLogger() {
1106 24066 jjdelcerro
                return DefaultFeatureStore.logger;
1107 23879 jjdelcerro
        }
1108 23894 jjdelcerro
1109 23949 jiyarza
        public FeatureIndex createIndex(FeatureType featureType,
1110
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1111 24180 jjdelcerro
                checkNotInAppendMode();
1112 23949 jiyarza
                FeatureIndexProviderServices index = null;
1113 24112 jiyarza
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1114 23949 jiyarza
                try {
1115
                        index.fill();
1116 24202 jiyarza
                } catch (FeatureIndexException e) {
1117 23949 jiyarza
                        throw new InitializeException(index.getName(), e);
1118
                }
1119 23995 jmvivo
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1120 23949 jiyarza
                return index;
1121 23894 jjdelcerro
        }
1122
1123 24195 jjdelcerro
        public void beginEditingGroup(String description)
1124
                        throws NeedEditingModeException {
1125
                checkInEditingMode();
1126 24186 vcaballero
                commands.startComplex(description);
1127
        }
1128 24185 jjdelcerro
1129 24195 jjdelcerro
        public void endEditingGroup() throws NeedEditingModeException {
1130
                checkInEditingMode();
1131 24186 vcaballero
                commands.endComplex();
1132
        }
1133 23772 jjdelcerro
}