Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / impl / DefaultFeatureSelection.java @ 46672

History | View | Annotate | Download (25.5 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
6 43089 jjdelcerro
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 40435 jjdelcerro
 *
11 43089 jjdelcerro
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 40435 jjdelcerro
 *
16 43089 jjdelcerro
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 40435 jjdelcerro
 *
20 43089 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40435 jjdelcerro
 */
23
package org.gvsig.fmap.dal.feature.impl;
24
25
import java.util.ArrayList;
26
import java.util.HashMap;
27 42834 dmartinezizquierdo
import java.util.Iterator;
28 40435 jjdelcerro
import java.util.List;
29
import java.util.Map;
30
import java.util.Map.Entry;
31
32
import org.gvsig.fmap.dal.DataStoreNotification;
33
import org.gvsig.fmap.dal.exception.DataException;
34 42821 dmartinezizquierdo
import org.gvsig.fmap.dal.exception.DataRuntimeException;
35 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeature;
36
import org.gvsig.fmap.dal.feature.Feature;
37 44113 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureQuery;
38 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureReference;
39
import org.gvsig.fmap.dal.feature.FeatureSelection;
40
import org.gvsig.fmap.dal.feature.FeatureSet;
41
import org.gvsig.fmap.dal.feature.FeatureStore;
42 44113 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
43 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
44
import org.gvsig.fmap.dal.feature.exception.ReversedSelectionIteratorException;
45 43089 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureReferenceSelection.SelectionData;
46
import org.gvsig.fmap.dal.feature.impl.featureset.AbstractFeatureSet;
47 44113 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
48 43089 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
49 40435 jjdelcerro
import org.gvsig.tools.ToolsLocator;
50
import org.gvsig.tools.dispose.DisposableIterator;
51 43088 jjdelcerro
import org.gvsig.tools.dispose.DisposeUtils;
52 40435 jjdelcerro
import org.gvsig.tools.dynobject.DynStruct;
53
import org.gvsig.tools.exception.BaseException;
54 43089 jjdelcerro
import org.gvsig.tools.observer.Observable;
55
import org.gvsig.tools.observer.Observer;
56 40435 jjdelcerro
import org.gvsig.tools.persistence.PersistenceManager;
57
import org.gvsig.tools.persistence.PersistentState;
58
import org.gvsig.tools.persistence.exception.PersistenceException;
59 43358 jjdelcerro
import org.gvsig.tools.visitor.Visitor;
60 42834 dmartinezizquierdo
import org.slf4j.Logger;
61
import org.slf4j.LoggerFactory;
62 40435 jjdelcerro
63
/**
64
 * Default implementation of the FeatureSelection interface. Internally, only
65
 * FeatureReference values are stored.
66 42821 dmartinezizquierdo
 *
67 40435 jjdelcerro
 * This implementation performs better if used with the selection related
68
 * methods: select, deselect and isSelected ones.
69 42821 dmartinezizquierdo
 *
70 40435 jjdelcerro
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
71
 */
72 43089 jjdelcerro
public class DefaultFeatureSelection extends AbstractFeatureSet
73
        implements FeatureSelection {
74 40435 jjdelcerro
75 43089 jjdelcerro
    public class RemoveFromFeatureSelectionException extends DataRuntimeException {
76 40435 jjdelcerro
77 43089 jjdelcerro
        /**
78
         *
79
         */
80
        private static final long serialVersionUID = 2636692469445838928L;
81
        private final static String MESSAGE_FORMAT = "Can't remove feature from reversed selection.";
82
        private final static String MESSAGE_KEY = "_RemoveFromFeatureSelectionException";
83 40435 jjdelcerro
84 43089 jjdelcerro
        public RemoveFromFeatureSelectionException(Throwable cause) {
85
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
86
            //setValue("store", store);
87
        }
88
    }
89 40435 jjdelcerro
90 43089 jjdelcerro
    /**
91
     * Facade over a Iterator of FeatureReferences, to return Features instead.
92
     *
93
     * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
94
     */
95
    private class FeatureIteratorFacade implements DisposableIterator {
96 40435 jjdelcerro
97 43089 jjdelcerro
        private final Logger LOGGER = LoggerFactory
98
                .getLogger(FeatureIteratorFacade.class);
99 40435 jjdelcerro
100 43089 jjdelcerro
        private java.util.Iterator refIterator;
101 40435 jjdelcerro
102 43089 jjdelcerro
        private FeatureStore featureStore;
103
        private Feature currentFeature = null;
104 40435 jjdelcerro
105 43089 jjdelcerro
        public FeatureIteratorFacade(java.util.Iterator iter,
106
                FeatureStore featureStore) {
107
            this.refIterator = iter;
108
            this.featureStore = featureStore;
109
        }
110 40435 jjdelcerro
111 43089 jjdelcerro
        @Override
112
        public boolean hasNext() {
113
            return refIterator.hasNext();
114
        }
115 40435 jjdelcerro
116 43089 jjdelcerro
        @Override
117
        public Object next() {
118
            FeatureReference ref = nextFeatureReference();
119
            try {
120
                currentFeature = featureStore.getFeatureByReference(ref);
121
                return currentFeature;
122
            } catch (DataException ex) {
123
                LOGGER.error(
124
                        "Error loading the Feature with FeatureReference: "
125
                        + ref, ex);
126
                return null;
127
            }
128
        }
129 42821 dmartinezizquierdo
130 43089 jjdelcerro
        /**
131
         * Returns the next FeatureReference.
132
         *
133
         * @return the next FeatureReference
134
         */
135
        public FeatureReference nextFeatureReference() {
136
            return (FeatureReference) refIterator.next();
137
        }
138 40435 jjdelcerro
139 43089 jjdelcerro
        @Override
140
        public void remove() {
141
            try {
142
                featureStore.delete(currentFeature);
143
                refIterator.remove();
144
            } catch (DataException e) {
145
                throw new RemoveFromFeatureSelectionException(e);
146
            }
147
        }
148 40435 jjdelcerro
149 43089 jjdelcerro
        public class RemoveFromFeatureSelectionException extends DataRuntimeException {
150 40435 jjdelcerro
151 43089 jjdelcerro
            /**
152
             *
153
             */
154
            private static final long serialVersionUID = 2636692469445838928L;
155
            private final static String MESSAGE_FORMAT = "Can't remove feature from selection.";
156
            private final static String MESSAGE_KEY = "_RemoveFromFeatureSelectionException";
157 40435 jjdelcerro
158 43089 jjdelcerro
            public RemoveFromFeatureSelectionException(Throwable cause) {
159
                super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
160
                //setValue("store", store);
161
            }
162
        }
163 40435 jjdelcerro
164 43089 jjdelcerro
        @Override
165
        public void dispose() {
166
            if (refIterator instanceof DisposableIterator) {
167
                ((DisposableIterator) refIterator).dispose();
168
            }
169
            refIterator = null;
170
            featureStore = null;
171
        }
172
    }
173 40435 jjdelcerro
174 43089 jjdelcerro
    /**
175
     * Facade over a Iterator of FeatureReferences, to return Features instead,
176
     * when the Selection is reversed
177
     *
178
     * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
179
     */
180
    private class ReversedFeatureIteratorFacade implements DisposableIterator {
181 40435 jjdelcerro
182 43089 jjdelcerro
        private SelectionData selectionData;
183 40435 jjdelcerro
184 43089 jjdelcerro
        private DisposableIterator iterator;
185 40435 jjdelcerro
186 43089 jjdelcerro
        private Feature nextFeature = null;
187
        private Feature currentFeature = null;
188 40435 jjdelcerro
189 43089 jjdelcerro
        private FeatureSet featureSet;
190 40435 jjdelcerro
191 43089 jjdelcerro
        public ReversedFeatureIteratorFacade(SelectionData selectionData,
192
                FeatureStore featureStore, boolean fastIterator) {
193
            this.selectionData = selectionData;
194 40435 jjdelcerro
195 43089 jjdelcerro
            // Load a Set with all the store features
196
            try {
197 44113 jjdelcerro
                featureSet = new IgnoreInsertAndUpdateFeatureSet(
198
                        (DefaultFeatureStore) featureStore,
199
                        new DefaultFeatureQuery(featureStore.getDefaultFeatureType())
200
                );
201 43089 jjdelcerro
                iterator = featureSet.fastIterator();
202
            } catch (DataException ex) {
203
                throw new ReversedSelectionIteratorException(ex);
204
            }
205 40435 jjdelcerro
206 43089 jjdelcerro
            // Filter the features not selected and position in the next
207
            // selected feature
208
            positionInNextElement();
209
        }
210 40435 jjdelcerro
211 43089 jjdelcerro
        @Override
212
        public boolean hasNext() {
213
            return nextFeature != null;
214
        }
215 40435 jjdelcerro
216 43089 jjdelcerro
        @Override
217
        public Object next() {
218
            featureIterators.remove(currentFeature);
219
            currentFeature = nextFeature.getCopy();
220
            featureIterators.put(currentFeature, this);
221
            positionInNextElement();
222
            return currentFeature;
223
        }
224 40435 jjdelcerro
225 43089 jjdelcerro
        @Override
226
        public void remove() {
227
            try {
228
                featureSet.delete(currentFeature);
229
            } catch (DataException e) {
230
                throw new RemoveFromFeatureSelectionException(e);
231 40435 jjdelcerro
232 43089 jjdelcerro
            }
233
        }
234 40435 jjdelcerro
235 43089 jjdelcerro
        private void positionInNextElement() {
236
            nextFeature = null;
237
            while (iterator.hasNext()) {
238
                nextFeature = (Feature) iterator.next();
239
                if (selectionData.contains(nextFeature.getReference())) {
240
                    nextFeature = null;
241
                } else {
242
                    break;
243 43088 jjdelcerro
                }
244
            }
245
        }
246 40435 jjdelcerro
247 43089 jjdelcerro
        @Override
248
        public void dispose() {
249
            this.featureSet.dispose();
250
            this.iterator.dispose();
251
            this.selectionData = null;
252
            this.nextFeature = null;
253
        }
254
    }
255 40435 jjdelcerro
256 43089 jjdelcerro
    private Map featureTypeCounts = new HashMap(1);
257
    private final Map<Feature, Iterator> featureIterators = new HashMap<>();
258
    private final DefaultFeatureReferenceSelection featureReferenceSelection;
259 40435 jjdelcerro
260 43089 jjdelcerro
    /**
261
     * Creates a DefaultFeatureSelection, with a FeatureStore.
262
     *
263
     * @param featureStore the FeatureStore to load Features from
264
     * @throws DataException if there is an error while getting the total number
265
     * of Features of the Store.
266
     * @see AbstractSetBasedDataSelection#DefaultSelection(int)
267
     */
268
    public DefaultFeatureSelection(DefaultFeatureStore featureStore)
269
            throws DataException {
270
        this.featureReferenceSelection = new DefaultFeatureReferenceSelection(featureStore);
271
    }
272 40435 jjdelcerro
273 43089 jjdelcerro
    /**
274
     * Creates a new Selection with the total size of Features from which the
275
     * selection will be performed.
276
     *
277
     * @param featureStore the FeatureStore of the selected FeatureReferences
278
     * @param helper to get some information of the Store
279
     * @throws DataException if there is an error while getting the total number
280
     * of Features of the Store.
281
     */
282
    public DefaultFeatureSelection(FeatureStore featureStore,
283
            FeatureSelectionHelper helper) throws DataException {
284
        this.featureReferenceSelection = new DefaultFeatureReferenceSelection(featureStore, helper);
285
    }
286 40435 jjdelcerro
287 43089 jjdelcerro
    /**
288
     * Constructor used by the persistence manager. Don't use directly. After to
289
     * invoke this method, the persistence manager calls the the method
290
     * {@link #loadFromState(PersistentState)} to set the values of the internal
291
     * attributes that this class needs to work.
292
     */
293
    public DefaultFeatureSelection() {
294
        this.featureReferenceSelection = new DefaultFeatureReferenceSelection();
295
    }
296 40435 jjdelcerro
297 43089 jjdelcerro
    @Override
298
    public FeatureStore getFeatureStore() {
299
        return this.featureReferenceSelection.getFeatureStore();
300
    }
301 40435 jjdelcerro
302 43089 jjdelcerro
    private void notifyObservers(String notificationType) {
303
        this.featureReferenceSelection.notifyObservers(notificationType);
304
    }
305 40435 jjdelcerro
306 43089 jjdelcerro
    public FeatureCommandsStack getCommands() {
307
        return this.featureReferenceSelection.getCommands();
308
    }
309 40435 jjdelcerro
310 43089 jjdelcerro
    @Override
311
    public void enableNotifications() {
312
        this.featureReferenceSelection.enableNotifications();
313
    }
314 40435 jjdelcerro
315 43089 jjdelcerro
    @Override
316
    public void disableNotifications() {
317
        this.featureReferenceSelection.disableNotifications();
318
    }
319 40435 jjdelcerro
320 43089 jjdelcerro
    public boolean isReversed() {
321
        return this.featureReferenceSelection.isReversed();
322
    }
323 40435 jjdelcerro
324 43089 jjdelcerro
    @Override
325
    public long getSelectedCount() {
326
        return this.featureReferenceSelection.getSelectedCount();
327
    }
328 40435 jjdelcerro
329 43089 jjdelcerro
    public DefaultFeatureReferenceSelection.SelectionData getData() {
330
        return this.featureReferenceSelection.getData();
331
    }
332 40435 jjdelcerro
333 43089 jjdelcerro
    @Override
334
    public boolean select(FeatureReference reference) {
335
        return this.featureReferenceSelection.select(reference);
336
    }
337 40435 jjdelcerro
338 43089 jjdelcerro
    public boolean select(FeatureReference reference, boolean undoable) {
339
        return this.featureReferenceSelection.select(reference, undoable);
340
    }
341 40435 jjdelcerro
342 43089 jjdelcerro
    @Override
343
    public boolean deselect(FeatureReference reference) {
344
        return this.featureReferenceSelection.deselect(reference);
345
    }
346 40435 jjdelcerro
347 43089 jjdelcerro
    public boolean deselect(FeatureReference reference, boolean undoable) {
348
        return this.featureReferenceSelection.deselect(reference, undoable);
349
    }
350 42834 dmartinezizquierdo
351 43089 jjdelcerro
    @Override
352 46309 jjdelcerro
    public Iterator<FeatureReference> referenceIterator() {
353 43089 jjdelcerro
        return this.featureReferenceSelection.referenceIterator();
354
    }
355 42834 dmartinezizquierdo
356 43089 jjdelcerro
    @Override
357 46309 jjdelcerro
    public Iterable<FeatureReference> referenceIterable() {
358
        return this.featureReferenceSelection.referenceIterable();
359
    }
360
361
    @Override
362 43089 jjdelcerro
    public void selectAll() throws DataException {
363
        this.featureReferenceSelection.selectAll();
364
    }
365 42834 dmartinezizquierdo
366 43089 jjdelcerro
    @Override
367
    public void deselectAll() throws DataException {
368
        this.featureReferenceSelection.deselectAll();
369
    }
370
371
    public void deselectAll(boolean undoable) throws DataException {
372
        this.featureReferenceSelection.deselectAll(undoable);
373
    }
374
375
    @Override
376
    public boolean isSelected(FeatureReference reference) {
377
        return this.featureReferenceSelection.isSelected(reference);
378
    }
379 40435 jjdelcerro
380 43089 jjdelcerro
    @Override
381
    public void reverse() {
382
        this.featureReferenceSelection.reverse();
383
    }
384 40435 jjdelcerro
385 43089 jjdelcerro
    @Override
386
    public void dispose() {
387
        this.featureReferenceSelection.dispose();
388
    }
389 40435 jjdelcerro
390 43089 jjdelcerro
    @Override
391
    public void update(Observable o, Object o1) {
392
        this.featureReferenceSelection.update(o, o1);
393
    }
394 40435 jjdelcerro
395 43089 jjdelcerro
    @Override
396
    public void addObserver(Observer obsrvr) {
397
        this.featureReferenceSelection.addObserver(obsrvr);
398
    }
399 40435 jjdelcerro
400 43089 jjdelcerro
    @Override
401
    public void deleteObserver(Observer obsrvr) {
402
        this.featureReferenceSelection.deleteObserver(obsrvr);
403
    }
404 40435 jjdelcerro
405 43089 jjdelcerro
    @Override
406
    public void deleteObservers() {
407
        this.featureReferenceSelection.deleteObservers();
408
    }
409 40435 jjdelcerro
410 43089 jjdelcerro
    @Override
411
    public void beginComplexNotification() {
412
        this.featureReferenceSelection.beginComplexNotification();
413
    }
414 40435 jjdelcerro
415 43089 jjdelcerro
    @Override
416
    public void endComplexNotification() {
417
        this.featureReferenceSelection.endComplexNotification();
418
    }
419 40435 jjdelcerro
420 43089 jjdelcerro
    @Override
421
    public void saveToState(PersistentState ps) throws PersistenceException {
422
        this.featureReferenceSelection.saveToState(ps);
423
    }
424 40435 jjdelcerro
425 43089 jjdelcerro
    @Override
426
    public boolean select(Feature feature) {
427
        return select(feature, true);
428
    }
429 40435 jjdelcerro
430 43089 jjdelcerro
    /**
431
     * @param feature
432
     * @return
433
     * @see #select(Feature)
434
     * @param undoable if the action must be undoable
435
     */
436
    public boolean select(Feature feature, boolean undoable) {
437
        // TODO: should we check if the feature is from the same FeatureStore??
438
        if (feature == null) {
439
            return false;
440
        }
441 42821 dmartinezizquierdo
442 43089 jjdelcerro
        // LOGGER.debug("Selected feature: {}", feature);
443
        if (isReversed()) {
444
            removeFeatureTypeCount(feature.getType());
445
        } else {
446
            addFeatureTypeCount(feature.getType());
447
        }
448
        return select(feature.getReference(), undoable);
449
    }
450
451
    @Override
452
    public boolean select(FeatureSet features) throws DataException {
453
        return select(features, true);
454
    }
455
456
    /**
457
     * @param features
458
     * @return
459
     * @throws org.gvsig.fmap.dal.exception.DataException
460
     * @see #select(FeatureSet)
461
     * @param undoable if the action must be undoable
462
     */
463
    public boolean select(FeatureSet features, boolean undoable)
464
            throws DataException {
465
        boolean change = false;
466
        boolean inComplex = false;
467
        if (undoable && this.featureReferenceSelection.getFeatureStore().isEditing()
468
                && !this.featureReferenceSelection.getCommands().inComplex()) {
469
470
            this.featureReferenceSelection.getCommands().startComplex("_selectionSelectFeatureSet");
471
            inComplex = this.featureReferenceSelection.getCommands().inComplex();
472
        }
473
474
        disableNotifications();
475
        DisposableIterator iter = null;
476
        try {
477
            for (iter = features.fastIterator(); iter.hasNext();) {
478
                change |= select((Feature) iter.next(), undoable);
479 42821 dmartinezizquierdo
            }
480 43089 jjdelcerro
        } finally {
481
            DisposeUtils.disposeQuietly(iter);
482
        }
483
        enableNotifications();
484
        if (undoable && getFeatureStore().isEditing() && inComplex) {
485
            getCommands().endComplex();
486
        }
487
        if (change) {
488
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
489
        }
490
        return change;
491
    }
492 40435 jjdelcerro
493 43089 jjdelcerro
    @Override
494
    public boolean deselect(Feature feature) {
495
        return deselect(feature, true);
496
    }
497 42821 dmartinezizquierdo
498 43089 jjdelcerro
    /**
499
     * @param feature
500
     * @return
501
     * @see #deselect(Feature)
502
     * @param undoable if the action must be undoable
503
     */
504
    public boolean deselect(Feature feature, boolean undoable) {
505
        if (feature == null) {
506
            return false;
507
        }
508 42821 dmartinezizquierdo
509 43089 jjdelcerro
        LOG.debug("Deselected feature: {}", feature);
510 42821 dmartinezizquierdo
511 43089 jjdelcerro
        if (isReversed()) {
512
            addFeatureTypeCount(feature.getType());
513
        } else {
514
            removeFeatureTypeCount(feature.getType());
515
        }
516
        return deselect(feature.getReference(), undoable);
517
    }
518 42821 dmartinezizquierdo
519 43089 jjdelcerro
    @Override
520
    public boolean deselect(FeatureSet features) throws DataException {
521
        return deselect(features, true);
522
    }
523 40435 jjdelcerro
524 43089 jjdelcerro
    /**
525
     * @param features
526
     * @return
527
     * @throws org.gvsig.fmap.dal.exception.DataException
528
     * @see #deselect(FeatureSet)
529
     * @param undoable if the action must be undoable
530
     */
531
    public boolean deselect(FeatureSet features, boolean undoable)
532
            throws DataException {
533
        boolean change = false;
534
        if (undoable && getFeatureStore().isEditing()) {
535
            getCommands().startComplex("_selectionDeselectFeatureSet");
536
        }
537
        disableNotifications();
538
        DisposableIterator iter = null;
539
        try {
540
            for (iter = features.fastIterator(); iter.hasNext();) {
541
                change |= deselect((Feature) iter.next(), undoable);
542
            }
543
        } finally {
544
            DisposeUtils.disposeQuietly(iter);
545
        }
546
        enableNotifications();
547
        if (undoable && getFeatureStore().isEditing()) {
548
            getCommands().endComplex();
549
        }
550
        if (change) {
551
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
552
        }
553
        return change;
554
    }
555 40435 jjdelcerro
556 43089 jjdelcerro
    @Override
557
    public boolean isSelected(Feature feature) {
558
        if (feature == null) {
559
            return false;
560
        }
561 43646 jjdelcerro
        if( this.featureReferenceSelection.isEmpty() ) {
562
            return false;
563
        }
564 43089 jjdelcerro
        // Use the selection data size as a small optimization for the most
565
        // common case, when nothing is selected and every feature is checked
566
        // while drawing or painting the table document.
567
        if (getData().isReversed()) {
568
            return getData().getSize() == 0
569
                    || !getData().contains(feature.getReference());
570
        } else {
571
            return getData().getSize() > 0
572
                    && getData().contains(feature.getReference());
573
        }
574 42834 dmartinezizquierdo
    }
575 40435 jjdelcerro
576 43089 jjdelcerro
    @Override
577
    public FeatureType getDefaultFeatureType() {
578
        try {
579
            return getFeatureStore().getDefaultFeatureType();
580
        } catch (DataException ex) {
581
            LOG.error("Error getting the default feature type "
582
                    + "of the FeatureStore: " + getFeatureStore(), ex);
583
        }
584
        return null;
585 42834 dmartinezizquierdo
    }
586 40435 jjdelcerro
587 43089 jjdelcerro
    @Override
588
    public List getFeatureTypes() {
589
        // Go through the map of FeatureTypes, and return only the ones that
590
        // have at least a Feature.
591
        List types = new ArrayList();
592
        for (java.util.Iterator iterator = featureTypeCounts.entrySet()
593
                .iterator(); iterator.hasNext();) {
594
            Map.Entry entry = (Entry) iterator.next();
595
            FeatureType type = (FeatureType) entry.getKey();
596
            Long count = (Long) entry.getValue();
597 40435 jjdelcerro
598 43089 jjdelcerro
            if (count > 0) {
599
                types.add(type);
600
            }
601
        }
602 40435 jjdelcerro
603 43089 jjdelcerro
        return types;
604
    }
605 40435 jjdelcerro
606 43089 jjdelcerro
    @Override
607
    public long getSize() throws DataException {
608
        return getSelectedCount();
609
    }
610 40435 jjdelcerro
611 43089 jjdelcerro
    /**
612
     * Returns the list of selected values, or the deselected ones if the
613
     * selection has been reversed.
614
     *
615
     * WARN: not very good performance implementation.
616
     */
617
    @Override
618 43358 jjdelcerro
        public DisposableIterator iterator(long index) {
619
                return iterator(index, 0, false);
620
        }
621 40435 jjdelcerro
622 43358 jjdelcerro
    @Override
623
        public DisposableIterator iterator(long index, long elements) {
624
                return iterator(index, elements, false);
625
        }
626
627 43089 jjdelcerro
    /**
628
     * Returns the list of selected values, or the deselected ones if the
629
     * selection has been reversed.
630
     *
631
     * WARN: not really a fast implementation.
632
     */
633
    @Override
634 43358 jjdelcerro
        public DisposableIterator fastIterator(long index) {
635
            return fastIterator(index, 0);
636
        }
637
638
    @Override
639
    public DisposableIterator fastIterator(long index, long elements) {
640
        return iterator(index, elements, true);
641 43089 jjdelcerro
    }
642 40435 jjdelcerro
643 43358 jjdelcerro
644 43089 jjdelcerro
    protected void clearFeatureReferences() {
645
        this.featureReferenceSelection.clearFeatureReferences();
646
        featureTypeCounts.clear();
647
    }
648 40435 jjdelcerro
649 43089 jjdelcerro
    /**
650
     * Creates an iterator for the Selection.
651
     */
652 43358 jjdelcerro
    private DisposableIterator iterator(long index, long elements, boolean fastIterator) {
653 43089 jjdelcerro
        if (isReversed()) {
654
            DisposableIterator iter = new ReversedFeatureIteratorFacade(
655
                    getData(), getFeatureStore(), fastIterator);
656
            for (long l = 0; l < index && iter.hasNext(); l++) {
657
                iter.next();
658
            }
659
            return iter;
660 40435 jjdelcerro
661 43089 jjdelcerro
        } else {
662
            // TODO: maybe we could add a new referenceIterator(int index)
663
            // method that could be implemented in a more performant way
664 40435 jjdelcerro
665 43089 jjdelcerro
            java.util.Iterator iter = getData().getSelected().iterator();
666
            for (long l = 0; l < index && iter.hasNext(); l++) {
667
                iter.next();
668
            }
669
            return new FeatureIteratorFacade(iter, getFeatureStore());
670
        }
671
    }
672 40435 jjdelcerro
673 43089 jjdelcerro
    private Long removeFeatureTypeCount(FeatureType featureType) {
674
        Long count = (Long) featureTypeCounts.get(featureType);
675
        if (count == null) {
676
            count = new Long(-1);
677
        } else {
678
            count = count - 1;
679
        }
680
        featureTypeCounts.put(featureType, count);
681
        return count;
682
    }
683 40435 jjdelcerro
684 43089 jjdelcerro
    private Long addFeatureTypeCount(FeatureType featureType) {
685
        Long count = (Long) featureTypeCounts.get(featureType);
686
        if (count == null) {
687
            count = new Long(1);
688
        } else {
689
            count = count + 1;
690
        }
691
        featureTypeCounts.put(featureType, count);
692
        return count;
693 40435 jjdelcerro
    }
694
695 43089 jjdelcerro
    @Override
696
    public void delete(Feature feature) throws DataException {
697
        Iterator it = this.featureIterators.get(feature);
698
        if (it != null) {
699
            it.remove();
700
            return;
701
        }
702
        feature.getStore().delete(feature);
703 40435 jjdelcerro
    }
704
705 43089 jjdelcerro
    @Override
706
    public void insert(EditableFeature feature) throws DataException {
707
        feature.getStore().insert(feature);
708
    }
709
710
    @Override
711
    public void update(EditableFeature feature) throws DataException {
712
        feature.getStore().update(feature);
713
    }
714 44097 omartinez
715
716
    @Override
717
    public void commitChanges() throws DataException {
718
    }
719 43089 jjdelcerro
720
    /*
721
     * (non-Javadoc)
722
     *
723
     * @seeorg.gvsig.fmap.dal.feature.impl.DefaultFeatureReferenceSelection#
724
     * loadFromState(org.gvsig.tools.persistence.PersistentState)
725
     */
726
    @Override
727
    public void loadFromState(PersistentState state)
728
            throws PersistenceException {
729
        this.featureReferenceSelection.loadFromState(state);
730
    }
731
732
    protected void doDispose() throws BaseException {
733
        this.featureReferenceSelection.doDispose();
734
        featureTypeCounts.clear();
735
    }
736
737
    public static void registerPersistent() {
738
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
739
        DynStruct definition = manager.addDefinition(
740
                DefaultFeatureSelection.class, "DefaultFeatureSelection",
741
                "DefaultFeatureSelection Persistent definition", null, null);
742
743
        definition.extend(manager.getDefinition(DefaultFeatureReferenceSelection.DYNCLASS_PERSISTENT_NAME));
744
        definition.addDynFieldMap("featureTypeCounts")
745
                .setClassOfItems(Long.class).setMandatory(false);
746
747
    }
748
749
    @Override
750
    public Object clone() throws CloneNotSupportedException {
751
        DefaultFeatureSelection clone = (DefaultFeatureSelection) super.clone();
752
        clone.featureTypeCounts = new HashMap(featureTypeCounts);
753
        return clone;
754
    }
755
756 43358 jjdelcerro
    @Override
757
    protected void doAccept(Visitor visitor, long firstValueIndex, long elements) throws BaseException {
758 43646 jjdelcerro
        if( this.featureReferenceSelection.isEmpty() ) {
759
            return;
760
        }
761 43358 jjdelcerro
        DisposableIterator iterator = fastIterator(firstValueIndex, elements);
762
        if (iterator != null) {
763
            try {
764
                while (iterator.hasNext()) {
765
                    Feature feature = (Feature) iterator.next();
766
                    visitor.visit(feature);
767
                }
768
            } finally {
769
                iterator.dispose();
770
            }
771
        }
772
    }
773
774 44113 jjdelcerro
    private static class IgnoreInsertAndUpdateFeatureSet extends DefaultFeatureSet {
775
776
        public IgnoreInsertAndUpdateFeatureSet(DefaultFeatureStore store, FeatureQuery query) throws DataException {
777
            super(store, query);
778
        }
779
780
        public void update(Observable obsevable, Object notification) {
781
            String type = ((FeatureStoreNotification) notification).getType();
782
            if (type.equalsIgnoreCase(FeatureStoreNotification.AFTER_INSERT)
783
                    || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE)) {
784
                return;
785
            }
786
            super.update(obsevable, notification);
787
        }
788
789
    }
790
791 44435 jjdelcerro
    @Override
792
    public boolean isAvailable() {
793
        return this.featureReferenceSelection.isAvailable();
794
    }
795 44113 jjdelcerro
796 40767 jjdelcerro
}