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

History | View | Annotate | Download (26 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * 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
 *
11
 * 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
 *
16
 * 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
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.dal.feature.impl;
24

    
25
import java.util.ArrayList;
26
import java.util.HashMap;
27
import java.util.Iterator;
28
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
import org.gvsig.fmap.dal.exception.DataRuntimeException;
35
import org.gvsig.fmap.dal.feature.EditableFeature;
36
import org.gvsig.fmap.dal.feature.Feature;
37
import org.gvsig.fmap.dal.feature.FeatureQuery;
38
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
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
43
import org.gvsig.fmap.dal.feature.FeatureType;
44
import org.gvsig.fmap.dal.feature.exception.ReversedSelectionIteratorException;
45
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureReferenceSelection.SelectionData;
46
import org.gvsig.fmap.dal.feature.impl.featureset.AbstractFeatureSet;
47
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
48
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
49
import org.gvsig.tools.ToolsLocator;
50
import org.gvsig.tools.dispose.DisposableIterator;
51
import org.gvsig.tools.dispose.DisposeUtils;
52
import org.gvsig.tools.dynobject.DynStruct;
53
import org.gvsig.tools.exception.BaseException;
54
import org.gvsig.tools.observer.Observable;
55
import org.gvsig.tools.observer.Observer;
56
import org.gvsig.tools.persistence.PersistenceManager;
57
import org.gvsig.tools.persistence.PersistentState;
58
import org.gvsig.tools.persistence.exception.PersistenceException;
59
import org.gvsig.tools.visitor.Visitor;
60
import org.slf4j.Logger;
61
import org.slf4j.LoggerFactory;
62

    
63
/**
64
 * Default implementation of the FeatureSelection interface. Internally, only
65
 * FeatureReference values are stored.
66
 *
67
 * This implementation performs better if used with the selection related
68
 * methods: select, deselect and isSelected ones.
69
 *
70
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
71
 */
72
public class DefaultFeatureSelection extends AbstractFeatureSet
73
        implements FeatureSelection {
74

    
75
    public class RemoveFromFeatureSelectionException extends DataRuntimeException {
76

    
77
        /**
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

    
84
        public RemoveFromFeatureSelectionException(Throwable cause) {
85
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
86
            //setValue("store", store);
87
        }
88
    }
89

    
90
    /**
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

    
97
        private final Logger LOGGER = LoggerFactory
98
                .getLogger(FeatureIteratorFacade.class);
99

    
100
        private java.util.Iterator refIterator;
101

    
102
        private FeatureStore featureStore;
103
        private Feature currentFeature = null;
104

    
105
        public FeatureIteratorFacade(java.util.Iterator iter,
106
                FeatureStore featureStore) {
107
            this.refIterator = iter;
108
            this.featureStore = featureStore;
109
        }
110

    
111
        @Override
112
        public boolean hasNext() {
113
            return refIterator.hasNext();
114
        }
115

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

    
130
        /**
131
         * Returns the next FeatureReference.
132
         *
133
         * @return the next FeatureReference
134
         */
135
        public FeatureReference nextFeatureReference() {
136
            return (FeatureReference) refIterator.next();
137
        }
138

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

    
149
        public class RemoveFromFeatureSelectionException extends DataRuntimeException {
150

    
151
            /**
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

    
158
            public RemoveFromFeatureSelectionException(Throwable cause) {
159
                super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
160
                //setValue("store", store);
161
            }
162
        }
163

    
164
        @Override
165
        public void dispose() {
166
            if (refIterator instanceof DisposableIterator) {
167
                ((DisposableIterator) refIterator).dispose();
168
            }
169
            refIterator = null;
170
            featureStore = null;
171
        }
172
    }
173

    
174
    /**
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

    
182
        private SelectionData selectionData;
183

    
184
        private DisposableIterator iterator;
185

    
186
        private Feature nextFeature = null;
187
        private Feature currentFeature = null;
188

    
189
        private FeatureSet featureSet;
190

    
191
        public ReversedFeatureIteratorFacade(SelectionData selectionData,
192
                FeatureStore featureStore, boolean fastIterator) {
193
            this.selectionData = selectionData;
194

    
195
            // Load a Set with all the store features
196
            try {
197
                featureSet = new IgnoreInsertAndUpdateFeatureSet(
198
                        (DefaultFeatureStore) featureStore, 
199
                        new DefaultFeatureQuery(featureStore.getDefaultFeatureType())
200
                );
201
                iterator = featureSet.fastIterator();
202
            } catch (DataException ex) {
203
                throw new ReversedSelectionIteratorException(ex);
204
            }
205

    
206
            // Filter the features not selected and position in the next
207
            // selected feature
208
            positionInNextElement();
209
        }
210

    
211
        @Override
212
        public boolean hasNext() {
213
            return nextFeature != null;
214
        }
215

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

    
225
        @Override
226
        public void remove() {
227
            try {
228
                featureSet.delete(currentFeature);
229
            } catch (DataException e) {
230
                throw new RemoveFromFeatureSelectionException(e);
231

    
232
            }
233
        }
234

    
235
        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
                }
244
            }
245
        }
246

    
247
        @Override
248
        public void dispose() {
249
            this.featureSet.dispose();
250
            this.iterator.dispose();
251
            this.selectionData = null;
252
            this.nextFeature = null;
253
        }
254
    }
255

    
256
    private Map featureTypeCounts = new HashMap(1);
257
    private final Map<Feature, Iterator> featureIterators = new HashMap<>();
258
    private final DefaultFeatureReferenceSelection featureReferenceSelection;
259
    private boolean disposed = false;
260

    
261
    /**
262
     * Creates a DefaultFeatureSelection, with a FeatureStore.
263
     *
264
     * @param featureStore the FeatureStore to load Features from
265
     * @throws DataException if there is an error while getting the total number
266
     * of Features of the Store.
267
     * @see AbstractSetBasedDataSelection#DefaultSelection(int)
268
     */
269
    public DefaultFeatureSelection(DefaultFeatureStore featureStore)
270
            throws DataException {
271
        DisposeUtils.bind(this);
272
        this.featureReferenceSelection = new DefaultFeatureReferenceSelection(featureStore);
273
    }
274

    
275
    /**
276
     * Creates a new Selection with the total size of Features from which the
277
     * selection will be performed.
278
     *
279
     * @param featureStore the FeatureStore of the selected FeatureReferences
280
     * @param helper to get some information of the Store
281
     * @throws DataException if there is an error while getting the total number
282
     * of Features of the Store.
283
     */
284
    public DefaultFeatureSelection(FeatureStore featureStore,
285
            FeatureSelectionHelper helper) throws DataException {
286
        DisposeUtils.bind(this);
287
        this.featureReferenceSelection = new DefaultFeatureReferenceSelection(featureStore, helper);
288
    }
289

    
290
    /**
291
     * Constructor used by the persistence manager. Don't use directly. After to
292
     * invoke this method, the persistence manager calls the the method
293
     * {@link #loadFromState(PersistentState)} to set the values of the internal
294
     * attributes that this class needs to work.
295
     */
296
    public DefaultFeatureSelection() {
297
        DisposeUtils.bind(this);
298
        this.featureReferenceSelection = new DefaultFeatureReferenceSelection();
299
    }
300

    
301
    @Override
302
    public FeatureStore getFeatureStore() {
303
        return this.featureReferenceSelection.getFeatureStore();
304
    }
305

    
306
    private void notifyObservers(String notificationType) {
307
        this.featureReferenceSelection.notifyObservers(notificationType);
308
    }
309

    
310
    public FeatureCommandsStack getCommands() {
311
        return this.featureReferenceSelection.getCommands();
312
    }
313

    
314
    @Override
315
    public void enableNotifications() {
316
        this.featureReferenceSelection.enableNotifications();
317
    }
318

    
319
    @Override
320
    public void disableNotifications() {
321
        this.featureReferenceSelection.disableNotifications();
322
    }
323

    
324
    public boolean isReversed() {
325
        return this.featureReferenceSelection.isReversed();
326
    }
327

    
328
    @Override
329
    public long getSelectedCount() {
330
        return this.featureReferenceSelection.getSelectedCount();
331
    }
332

    
333
    public DefaultFeatureReferenceSelection.SelectionData getData() {
334
        return this.featureReferenceSelection.getData();
335
    }
336

    
337
    @Override
338
    public boolean select(FeatureReference reference) {
339
        return this.featureReferenceSelection.select(reference);
340
    }
341

    
342
    public boolean select(FeatureReference reference, boolean undoable) {
343
        return this.featureReferenceSelection.select(reference, undoable);
344
    }
345

    
346
    @Override
347
    public boolean deselect(FeatureReference reference) {
348
        return this.featureReferenceSelection.deselect(reference);
349
    }
350

    
351
    public boolean deselect(FeatureReference reference, boolean undoable) {
352
        return this.featureReferenceSelection.deselect(reference, undoable);
353
    }
354

    
355
    @Override
356
    public Iterator<FeatureReference> referenceIterator() {
357
        return this.featureReferenceSelection.referenceIterator();
358
    }
359

    
360
    @Override
361
    public Iterable<FeatureReference> referenceIterable() {
362
        return this.featureReferenceSelection.referenceIterable();
363
    }
364

    
365
    @Override
366
    public void selectAll() throws DataException {
367
        this.featureReferenceSelection.selectAll();
368
    }
369

    
370
    @Override
371
    public void deselectAll() throws DataException {
372
        this.featureReferenceSelection.deselectAll();
373
    }
374
    
375
    public void deselectAll(boolean undoable) throws DataException {
376
        this.featureReferenceSelection.deselectAll(undoable);
377
    }
378
    
379
    @Override
380
    public boolean isSelected(FeatureReference reference) {
381
        return this.featureReferenceSelection.isSelected(reference);
382
    }
383

    
384
    @Override
385
    public void reverse() {
386
        this.featureReferenceSelection.reverse();
387
    }
388

    
389
    @Override
390
    public synchronized final void dispose() {
391
        // Check if we have already been disposed, and don't do it again
392
        if (!disposed) {
393
            if (DisposeUtils.release(this)) {
394
                try {
395
                    doDispose();
396
                } catch (Exception ex) {
397
                    LOG.error("Error performing dispose", ex);
398
                } finally {
399
                    disposed = true;
400
                }
401
            }
402
        }
403
    }
404

    
405

    
406

    
407
    @Override
408
    public void update(Observable o, Object o1) {
409
        this.featureReferenceSelection.update(o, o1);
410
    }
411

    
412
    @Override
413
    public void addObserver(Observer obsrvr) {
414
        this.featureReferenceSelection.addObserver(obsrvr);
415
    }
416

    
417
    @Override
418
    public void deleteObserver(Observer obsrvr) {
419
        this.featureReferenceSelection.deleteObserver(obsrvr);
420
    }
421

    
422
    @Override
423
    public void deleteObservers() {
424
        this.featureReferenceSelection.deleteObservers();
425
    }
426

    
427
    @Override
428
    public void beginComplexNotification() {
429
        this.featureReferenceSelection.beginComplexNotification();
430
    }
431

    
432
    @Override
433
    public void endComplexNotification() {
434
        this.featureReferenceSelection.endComplexNotification();
435
    }
436

    
437
    @Override
438
    public void saveToState(PersistentState ps) throws PersistenceException {
439
        this.featureReferenceSelection.saveToState(ps);
440
    }
441

    
442
    @Override
443
    public boolean select(Feature feature) {
444
        return select(feature, true);
445
    }
446

    
447
    /**
448
     * @param feature
449
     * @return
450
     * @see #select(Feature)
451
     * @param undoable if the action must be undoable
452
     */
453
    public boolean select(Feature feature, boolean undoable) {
454
        // TODO: should we check if the feature is from the same FeatureStore??
455
        if (feature == null) {
456
            return false;
457
        }
458

    
459
        // LOGGER.debug("Selected feature: {}", feature);
460
        if (isReversed()) {
461
            removeFeatureTypeCount(feature.getType());
462
        } else {
463
            addFeatureTypeCount(feature.getType());
464
        }
465
        return select(feature.getReference(), undoable);
466
    }
467

    
468
    @Override
469
    public boolean select(FeatureSet features) throws DataException {
470
        return select(features, true);
471
    }
472

    
473
    /**
474
     * @param features
475
     * @return
476
     * @throws org.gvsig.fmap.dal.exception.DataException
477
     * @see #select(FeatureSet)
478
     * @param undoable if the action must be undoable
479
     */
480
    public boolean select(FeatureSet features, boolean undoable)
481
            throws DataException {
482
        boolean change = false;
483
        boolean inComplex = false;
484
        if (undoable && this.featureReferenceSelection.getFeatureStore().isEditing()
485
                && !this.featureReferenceSelection.getCommands().inComplex()) {
486

    
487
            this.featureReferenceSelection.getCommands().startComplex("_selectionSelectFeatureSet");
488
            inComplex = this.featureReferenceSelection.getCommands().inComplex();
489
        }
490

    
491
        disableNotifications();
492
        DisposableIterator iter = null;
493
        try {
494
            for (iter = features.fastIterator(); iter.hasNext();) {
495
                change |= select((Feature) iter.next(), undoable);
496
            }
497
        } finally {
498
            DisposeUtils.disposeQuietly(iter);
499
        }
500
        enableNotifications();
501
        if (undoable && getFeatureStore().isEditing() && inComplex) {
502
            getCommands().endComplex();
503
        }
504
        if (change) {
505
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
506
        }
507
        return change;
508
    }
509

    
510
    @Override
511
    public boolean deselect(Feature feature) {
512
        return deselect(feature, true);
513
    }
514

    
515
    /**
516
     * @param feature
517
     * @return
518
     * @see #deselect(Feature)
519
     * @param undoable if the action must be undoable
520
     */
521
    public boolean deselect(Feature feature, boolean undoable) {
522
        if (feature == null) {
523
            return false;
524
        }
525

    
526
        LOG.debug("Deselected feature: {}", feature);
527

    
528
        if (isReversed()) {
529
            addFeatureTypeCount(feature.getType());
530
        } else {
531
            removeFeatureTypeCount(feature.getType());
532
        }
533
        return deselect(feature.getReference(), undoable);
534
    }
535

    
536
    @Override
537
    public boolean deselect(FeatureSet features) throws DataException {
538
        return deselect(features, true);
539
    }
540

    
541
    /**
542
     * @param features
543
     * @return
544
     * @throws org.gvsig.fmap.dal.exception.DataException
545
     * @see #deselect(FeatureSet)
546
     * @param undoable if the action must be undoable
547
     */
548
    public boolean deselect(FeatureSet features, boolean undoable)
549
            throws DataException {
550
        boolean change = false;
551
        if (undoable && getFeatureStore().isEditing()) {
552
            getCommands().startComplex("_selectionDeselectFeatureSet");
553
        }
554
        disableNotifications();
555
        DisposableIterator iter = null;
556
        try {
557
            for (iter = features.fastIterator(); iter.hasNext();) {
558
                change |= deselect((Feature) iter.next(), undoable);
559
            }
560
        } finally {
561
            DisposeUtils.disposeQuietly(iter);
562
        }
563
        enableNotifications();
564
        if (undoable && getFeatureStore().isEditing()) {
565
            getCommands().endComplex();
566
        }
567
        if (change) {
568
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
569
        }
570
        return change;
571
    }
572

    
573
    @Override
574
    public boolean isSelected(Feature feature) {
575
        if (feature == null) {
576
            return false;
577
        }
578
        if( this.featureReferenceSelection.isEmpty() ) {
579
            return false;
580
        }
581
        // Use the selection data size as a small optimization for the most
582
        // common case, when nothing is selected and every feature is checked
583
        // while drawing or painting the table document.
584
        if (getData().isReversed()) {
585
            return getData().getSize() == 0
586
                    || !getData().contains(feature.getReference());
587
        } else {
588
            return getData().getSize() > 0
589
                    && getData().contains(feature.getReference());
590
        }
591
    }
592

    
593
    @Override
594
    public FeatureType getDefaultFeatureType() {
595
        try {
596
            return getFeatureStore().getDefaultFeatureType();
597
        } catch (DataException ex) {
598
            LOG.error("Error getting the default feature type "
599
                    + "of the FeatureStore: " + getFeatureStore(), ex);
600
        }
601
        return null;
602
    }
603

    
604
    @Override
605
    public List getFeatureTypes() {
606
        // Go through the map of FeatureTypes, and return only the ones that
607
        // have at least a Feature.
608
        List types = new ArrayList();
609
        for (java.util.Iterator iterator = featureTypeCounts.entrySet()
610
                .iterator(); iterator.hasNext();) {
611
            Map.Entry entry = (Entry) iterator.next();
612
            FeatureType type = (FeatureType) entry.getKey();
613
            Long count = (Long) entry.getValue();
614

    
615
            if (count > 0) {
616
                types.add(type);
617
            }
618
        }
619

    
620
        return types;
621
    }
622

    
623
    @Override
624
    public long getSize() throws DataException {
625
        return getSelectedCount();
626
    }
627

    
628
    /**
629
     * Returns the list of selected values, or the deselected ones if the
630
     * selection has been reversed.
631
     *
632
     * WARN: not very good performance implementation.
633
     */
634
    @Override
635
        public DisposableIterator iterator(long index) {
636
                return iterator(index, 0, false);
637
        }
638

    
639
    @Override
640
        public DisposableIterator iterator(long index, long elements) {
641
                return iterator(index, elements, false);
642
        }
643

    
644
    /**
645
     * Returns the list of selected values, or the deselected ones if the
646
     * selection has been reversed.
647
     *
648
     * WARN: not really a fast implementation.
649
     */
650
    @Override
651
        public DisposableIterator fastIterator(long index) {
652
            return fastIterator(index, 0);
653
        }
654

    
655
    @Override
656
    public DisposableIterator fastIterator(long index, long elements) {
657
        return iterator(index, elements, true);
658
    }
659

    
660

    
661
    protected void clearFeatureReferences() {
662
        this.featureReferenceSelection.clearFeatureReferences();
663
        featureTypeCounts.clear();
664
    }
665

    
666
    /**
667
     * Creates an iterator for the Selection.
668
     */
669
    private DisposableIterator iterator(long index, long elements, boolean fastIterator) {
670
        if (isReversed()) {
671
            DisposableIterator iter = new ReversedFeatureIteratorFacade(
672
                    getData(), getFeatureStore(), fastIterator);
673
            for (long l = 0; l < index && iter.hasNext(); l++) {
674
                iter.next();
675
            }
676
            return iter;
677

    
678
        } else {
679
            // TODO: maybe we could add a new referenceIterator(int index)
680
            // method that could be implemented in a more performant way
681

    
682
            java.util.Iterator iter = getData().getSelected().iterator();
683
            for (long l = 0; l < index && iter.hasNext(); l++) {
684
                iter.next();
685
            }
686
            return new FeatureIteratorFacade(iter, getFeatureStore());
687
        }
688
    }
689

    
690
    private Long removeFeatureTypeCount(FeatureType featureType) {
691
        Long count = (Long) featureTypeCounts.get(featureType);
692
        if (count == null) {
693
            count = new Long(-1);
694
        } else {
695
            count = count - 1;
696
        }
697
        featureTypeCounts.put(featureType, count);
698
        return count;
699
    }
700

    
701
    private Long addFeatureTypeCount(FeatureType featureType) {
702
        Long count = (Long) featureTypeCounts.get(featureType);
703
        if (count == null) {
704
            count = new Long(1);
705
        } else {
706
            count = count + 1;
707
        }
708
        featureTypeCounts.put(featureType, count);
709
        return count;
710
    }
711

    
712
    @Override
713
    public void delete(Feature feature) throws DataException {
714
        Iterator it = this.featureIterators.get(feature);
715
        if (it != null) {
716
            it.remove();
717
            return;
718
        }
719
        feature.getStore().delete(feature);
720
    }
721

    
722
    @Override
723
    public void insert(EditableFeature feature) throws DataException {
724
        feature.getStore().insert(feature);
725
    }
726

    
727
    @Override
728
    public void update(EditableFeature feature) throws DataException {
729
        feature.getStore().update(feature);
730
    }
731
    
732
    
733
    @Override
734
    public void commitChanges() throws DataException {
735
    }
736

    
737
    /*
738
     * (non-Javadoc)
739
     *
740
     * @seeorg.gvsig.fmap.dal.feature.impl.DefaultFeatureReferenceSelection#
741
     * loadFromState(org.gvsig.tools.persistence.PersistentState)
742
     */
743
    @Override
744
    public void loadFromState(PersistentState state)
745
            throws PersistenceException {
746
        this.featureReferenceSelection.loadFromState(state);
747
    }
748

    
749
    protected void doDispose() throws BaseException {
750
        this.featureReferenceSelection.doDispose();
751
        featureTypeCounts.clear();
752
    }
753

    
754
    public static void registerPersistent() {
755
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
756
        DynStruct definition = manager.addDefinition(
757
                DefaultFeatureSelection.class, "DefaultFeatureSelection",
758
                "DefaultFeatureSelection Persistent definition", null, null);
759

    
760
        definition.extend(manager.getDefinition(DefaultFeatureReferenceSelection.DYNCLASS_PERSISTENT_NAME));
761
        definition.addDynFieldMap("featureTypeCounts")
762
                .setClassOfItems(Long.class).setMandatory(false);
763

    
764
    }
765

    
766
    @Override
767
    public Object clone() throws CloneNotSupportedException {
768
        DefaultFeatureSelection clone = (DefaultFeatureSelection) super.clone();
769
        clone.featureTypeCounts = new HashMap(featureTypeCounts);
770
        return clone;
771
    }
772

    
773
    @Override
774
    protected void doAccept(Visitor visitor, long firstValueIndex, long elements) throws BaseException {
775
        if( this.featureReferenceSelection.isEmpty() ) {
776
            return;
777
        }
778
        DisposableIterator iterator = fastIterator(firstValueIndex, elements);
779
        if (iterator != null) {
780
            try {
781
                while (iterator.hasNext()) {
782
                    Feature feature = (Feature) iterator.next();
783
                    visitor.visit(feature);
784
                }
785
            } finally {
786
                iterator.dispose();
787
            }
788
        }
789
    }
790

    
791
    private static class IgnoreInsertAndUpdateFeatureSet extends DefaultFeatureSet {
792

    
793
        public IgnoreInsertAndUpdateFeatureSet(DefaultFeatureStore store, FeatureQuery query) throws DataException {
794
            super(store, query);
795
        }
796

    
797
        public void update(Observable obsevable, Object notification) {
798
            String type = ((FeatureStoreNotification) notification).getType();
799
            if (type.equalsIgnoreCase(FeatureStoreNotification.AFTER_INSERT)
800
                    || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE)) {
801
                return;
802
            }
803
            super.update(obsevable, notification);
804
        }
805

    
806
    }
807

    
808
    @Override
809
    public boolean isAvailable() {
810
        return this.featureReferenceSelection.isAvailable();
811
    }
812

    
813
}