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 / DefaultFeatureReferenceSelection.java @ 46672

History | View | Annotate | Download (19.7 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 44976 jjdelcerro
 * Copyright (C) 2007-2020 gvSIG Association.
5 40435 jjdelcerro
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8 40559 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21 40559 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 40435 jjdelcerro
 */
24
package org.gvsig.fmap.dal.feature.impl;
25
26
import java.util.Collections;
27
import java.util.HashSet;
28
import java.util.Iterator;
29
import java.util.Set;
30
import org.gvsig.fmap.dal.DataStore;
31
import org.gvsig.fmap.dal.DataStoreNotification;
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.FeatureReference;
34
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
35
import org.gvsig.fmap.dal.feature.FeatureStore;
36
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
37 44435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
38 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
39
import org.gvsig.tools.ToolsLocator;
40
import org.gvsig.tools.dispose.impl.AbstractDisposable;
41
import org.gvsig.tools.dynobject.DynStruct;
42
import org.gvsig.tools.exception.BaseException;
43
import org.gvsig.tools.lang.Cloneable;
44
import org.gvsig.tools.observer.Observable;
45
import org.gvsig.tools.observer.Observer;
46
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
47
import org.gvsig.tools.persistence.PersistentState;
48
import org.gvsig.tools.persistence.exception.PersistenceException;
49
import org.gvsig.tools.visitor.Visitor;
50 44976 jjdelcerro
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52 40435 jjdelcerro
53
/**
54
 * Default implementation of a FeatureReferenceSelection, based on the usage of
55
 * a java.util.Set to store individual selected or not selected
56
 * FeatureReferences, depending on the usage of the {@link #reverse()} method.
57
 *
58 44976 jjdelcerro
 * @author gvSIG Team
59 40435 jjdelcerro
 */
60 44976 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
61 40435 jjdelcerro
public class DefaultFeatureReferenceSelection extends AbstractDisposable
62 44976 jjdelcerro
        implements FeatureReferenceSelection {
63 40435 jjdelcerro
64 44976 jjdelcerro
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultFeatureReferenceSelection.class);
65 40435 jjdelcerro
66 44976 jjdelcerro
    public static final String DYNCLASS_PERSISTENT_NAME = "DefaultFeatureReferenceSelection";
67
68 44435 jjdelcerro
    private Boolean available = null;
69 44976 jjdelcerro
70 43646 jjdelcerro
    protected SelectionData selectionData = null;
71 40435 jjdelcerro
72
    private FeatureStore featureStore;
73
74
    private FeatureSelectionHelper helper;
75
76 44976 jjdelcerro
    private DelegateWeakReferencingObservable delegateObservable
77
            = new DelegateWeakReferencingObservable(this);
78 40435 jjdelcerro
79 44976 jjdelcerro
    /**
80
     * Creates a new Selection with the total size of Features from which the
81
     * selection will be performed.
82
     *
83
     * @param featureStore the FeatureStore of the selected FeatureReferences
84
     * @throws DataException if there is an error while getting the total number
85
     * of Features of the Store.
86
     */
87 40435 jjdelcerro
    public DefaultFeatureReferenceSelection(DefaultFeatureStore featureStore)
88
            throws DataException {
89
        super();
90
        this.featureStore = featureStore;
91
        this.helper = new DefaultFeatureSelectionHelper(featureStore);
92
    }
93
94
    /**
95
     * Creates a new Selection with the total size of Features from which the
96
     * selection will be performed.
97
     *
98 44976 jjdelcerro
     * @param featureStore the FeatureStore of the selected FeatureReferences
99
     * @param helper to get some information of the Store
100
     * @throws DataException if there is an error while getting the total number
101
     * of Features of the Store.
102 40435 jjdelcerro
     */
103
    public DefaultFeatureReferenceSelection(FeatureStore featureStore,
104
            FeatureSelectionHelper helper)
105
            throws DataException {
106
        super();
107
        this.featureStore = featureStore;
108
        this.helper = helper;
109
    }
110
111 44976 jjdelcerro
    /**
112
     * Constructor used by the persistence manager. Don't use directly. After to
113
     * invoke this method, the persistence manager calls the the method
114
     * {@link #loadFromState(PersistentState)} to set the values of the internal
115
     * attributes that this class needs to work.
116
     */
117
    public DefaultFeatureReferenceSelection() {
118
        super();
119
    }
120 40435 jjdelcerro
121 44976 jjdelcerro
    @Override
122 40435 jjdelcerro
    public boolean select(FeatureReference reference) {
123
        return select(reference, true);
124
    }
125
126
    /**
127 44976 jjdelcerro
     * @param reference
128
     * @param undoable if the action must be undoable
129
     * @return
130 40435 jjdelcerro
     * @see #select(FeatureReference)
131
     */
132
    public boolean select(FeatureReference reference, boolean undoable) {
133
        if (reference == null) {
134
            throw new IllegalArgumentException("reference");
135
        }
136
        if (isSelected(reference)) {
137
            return false;
138
        }
139
        if (undoable && getFeatureStore().isEditing()) {
140
            getCommands().select(this, reference);
141
        }
142 44976 jjdelcerro
        boolean change;
143
        if (this.getData().isReversed()) {
144 43646 jjdelcerro
            change = this.getData().remove(reference);
145 40435 jjdelcerro
        } else {
146 43646 jjdelcerro
            change = this.getData().add(reference);
147 40435 jjdelcerro
        }
148
        if (change) {
149
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
150
        }
151
        return change;
152
    }
153
154 44976 jjdelcerro
    @Override
155 40435 jjdelcerro
    public boolean deselect(FeatureReference reference) {
156
        return deselect(reference, true);
157
    }
158
159
    /**
160 44976 jjdelcerro
     * @param reference
161
     * @param undoable if the action must be undoable
162
     * @return
163 40435 jjdelcerro
     * @see #deselect(FeatureReference)
164
     */
165
    public boolean deselect(FeatureReference reference, boolean undoable) {
166
        if (!isSelected(reference)) {
167
            return false;
168
        }
169
        if (undoable && getFeatureStore().isEditing()) {
170
            getCommands().deselect(this, reference);
171
        }
172 44976 jjdelcerro
        boolean change;
173 43646 jjdelcerro
        if (this.getData().isReversed()) {
174
            change = this.getData().add(reference);
175 40435 jjdelcerro
        } else {
176 43646 jjdelcerro
            change = this.getData().remove(reference);
177 40435 jjdelcerro
        }
178
        if (change) {
179
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
180
        }
181
        return change;
182
    }
183
184 44976 jjdelcerro
    @Override
185 40435 jjdelcerro
    public void selectAll() throws DataException {
186
        selectAll(true);
187
    }
188
189
    /**
190
     * @see #selectAll()
191 44976 jjdelcerro
     * @param undoable if the action must be undoable
192
     * @throws org.gvsig.fmap.dal.exception.DataException
193 40435 jjdelcerro
     */
194
    public void selectAll(boolean undoable) throws DataException {
195
        if (undoable && getFeatureStore().isEditing()) {
196
            getCommands().startComplex("_selectionSelectAll");
197
            getCommands().selectAll(this);
198
        }
199 43646 jjdelcerro
        if (!this.getData().isReversed()) {
200
            this.getData().setReversed(true);
201 40435 jjdelcerro
        }
202
        clearFeatureReferences();
203
        if (undoable && getFeatureStore().isEditing()) {
204
            getCommands().endComplex();
205
        }
206
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
207
    }
208
209 44976 jjdelcerro
    @Override
210 40435 jjdelcerro
    public void deselectAll() throws DataException {
211
        deselectAll(false);
212
    }
213
214
    /**
215 44976 jjdelcerro
     * @param undoable if the action must be undoable
216
     * @throws org.gvsig.fmap.dal.exception.DataException
217 40435 jjdelcerro
     * @see #deselectAll()
218
     */
219
    public void deselectAll(boolean undoable) throws DataException {
220 44976 jjdelcerro
        if (this.selectionData == null) {
221 43646 jjdelcerro
            return;
222
        }
223 40435 jjdelcerro
        if (undoable && getFeatureStore().isEditing()) {
224
            getCommands().startComplex("_selectionDeselectAll");
225
            getCommands().deselectAll(this);
226
        }
227 43646 jjdelcerro
        if (this.getData().isReversed()) {
228
            this.getData().setReversed(false);
229 40435 jjdelcerro
        }
230
        clearFeatureReferences();
231
        if (undoable && getFeatureStore().isEditing()) {
232
            getCommands().endComplex();
233
        }
234
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
235
    }
236
237 44976 jjdelcerro
    @Override
238 40435 jjdelcerro
    public boolean isSelected(FeatureReference reference) {
239 44976 jjdelcerro
        if (this.selectionData == null) {
240 43646 jjdelcerro
            return false;
241
        }
242
        if (this.getData().isReversed()) {
243
            return !this.getData().contains(reference);
244 40435 jjdelcerro
        } else {
245 43646 jjdelcerro
            return this.getData().contains(reference);
246 40435 jjdelcerro
        }
247
    }
248
249 44976 jjdelcerro
    @Override
250 40435 jjdelcerro
    public void reverse() {
251
        reverse(true);
252
    }
253
254
    /**
255
     * @see #reverse()
256 44976 jjdelcerro
     * @param undoable if the action must be undoable
257 40435 jjdelcerro
     */
258
    public void reverse(boolean undoable) {
259
        if (undoable && getFeatureStore().isEditing()) {
260
            getCommands().selectionReverse(this);
261
        }
262 43646 jjdelcerro
        this.getData().setReversed(!this.getData().isReversed());
263 40435 jjdelcerro
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
264
    }
265 44976 jjdelcerro
266 43646 jjdelcerro
    public boolean isEmpty() {
267 44976 jjdelcerro
        if (this.selectionData == null) {
268 43646 jjdelcerro
            return true;
269
        }
270 44976 jjdelcerro
        return this.getSelectedCount() == 0;
271 43646 jjdelcerro
    }
272 40435 jjdelcerro
273 44976 jjdelcerro
    @Override
274 40435 jjdelcerro
    public long getSelectedCount() {
275 44976 jjdelcerro
        if (this.selectionData == null) {
276 43646 jjdelcerro
            return 0;
277
        }
278
        if (this.getData().isReversed()) {
279 44976 jjdelcerro
            return this.getData().getTotalSize() - this.getData().getSize()
280
                    + helper.getFeatureStoreDeltaSize();
281 40435 jjdelcerro
        } else {
282 43646 jjdelcerro
            return this.getData().getSize();
283 40435 jjdelcerro
        }
284
    }
285
286 44976 jjdelcerro
    @Override
287 46309 jjdelcerro
    public Iterator<FeatureReference> referenceIterator() {
288
        return Collections.unmodifiableSet(this.getData().getSelected()).iterator();
289 40435 jjdelcerro
    }
290
291 44976 jjdelcerro
    @Override
292 46309 jjdelcerro
    public Iterable<FeatureReference> referenceIterable() {
293
        Set<FeatureReference> s = Collections.unmodifiableSet(this.getData().getSelected());
294
        return s;
295
    }
296
297
    @Override
298 44976 jjdelcerro
    protected void doDispose() throws BaseException {
299
        delegateObservable.deleteObservers();
300
        deselectAll(false);
301 40435 jjdelcerro
    }
302
303 44976 jjdelcerro
    @Override
304 40435 jjdelcerro
    public boolean isFromStore(DataStore store) {
305
        return featureStore.equals(store);
306
    }
307
308 44976 jjdelcerro
    @Override
309 40435 jjdelcerro
    public void accept(Visitor visitor) throws BaseException {
310 44976 jjdelcerro
        if (this.selectionData == null) {
311 43646 jjdelcerro
            return;
312 44976 jjdelcerro
        }
313
        for (Iterator iter = this.getData().getSelected().iterator(); iter.hasNext();) {
314 40435 jjdelcerro
            visitor.visit(iter.next());
315
        }
316
    }
317
318 44976 jjdelcerro
    @Override
319
    public void update(Observable observable, Object notification) {
320 40435 jjdelcerro
        // If a Feature is deleted, remove it from the selection Set.
321
        if (notification instanceof FeatureStoreNotification) {
322
            FeatureStoreNotification storeNotif = (FeatureStoreNotification) notification;
323
            if (FeatureStoreNotification.AFTER_DELETE
324
                    .equalsIgnoreCase(storeNotif.getType())) {
325 43646 jjdelcerro
                this.getData().remove(storeNotif.getFeature().getReference());
326 40435 jjdelcerro
            }
327
        }
328
    }
329
330
    public SelectionData getData() {
331 44976 jjdelcerro
        if (selectionData == null) {
332 43646 jjdelcerro
            selectionData = new SelectionData();
333
            try {
334
                selectionData.setTotalSize(featureStore.getFeatureCount());
335
            } catch (DataException ex) {
336 44976 jjdelcerro
                throw new RuntimeException("Can't initialize SelectionData, don't get the feature count.", ex);
337 43646 jjdelcerro
            }
338
        }
339 40435 jjdelcerro
        return selectionData;
340
    }
341
342
    public void setData(SelectionData selectionData) {
343
        this.selectionData = selectionData;
344
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
345
    }
346
347 44976 jjdelcerro
    @Override
348 40435 jjdelcerro
    public String toString() {
349
        return getClass().getName() + ": " + getSelectedCount()
350
                + " features selected, reversed = "
351 43646 jjdelcerro
                + this.getData().isReversed() + ", featureIds contained: "
352
                + this.getData().getSelected();
353 40435 jjdelcerro
    }
354
355
    protected boolean isReversed() {
356 44976 jjdelcerro
        if (this.selectionData == null) {
357 43646 jjdelcerro
            return false;
358
        }
359
        return this.getData().isReversed();
360 40435 jjdelcerro
    }
361
362
    /**
363
     * Removes all the stored FeatureRefence objects.
364
     */
365
    protected void clearFeatureReferences() {
366 44976 jjdelcerro
        if (this.selectionData == null) {
367 43646 jjdelcerro
            return;
368
        }
369
        this.getData().clear();
370 40435 jjdelcerro
    }
371
372 44976 jjdelcerro
    /**
373
     * Returns the FeatureStore of the selected FeatureReferences.
374
     *
375
     * @return the featureStore
376
     */
377 40435 jjdelcerro
    protected FeatureStore getFeatureStore() {
378
        return featureStore;
379
    }
380
381 44976 jjdelcerro
    /**
382
     * Returns the reference to the commands record.
383
     *
384
     * @return the reference to the commands record
385
     */
386 40435 jjdelcerro
    protected FeatureCommandsStack getCommands() {
387
        return helper.getFeatureStoreCommandsStack();
388
    }
389
390 44976 jjdelcerro
    public static class SelectionData implements Cloneable {
391
392 46309 jjdelcerro
        private Set<FeatureReference> selected = new HashSet();
393 40435 jjdelcerro
394
        /**
395
         * Sets how the Set of selected values has to be dealt.
396
         * <p>
397
         * If selected is FALSE, then values into the Set are the selected ones,
398
         * anything else is not selected.
399
         * </p>
400
         * <p>
401
         * If selected is TRUE, then values into the Set are values not
402
         * selected, anything else is selected.
403
         * </p>
404
         */
405
        private boolean reversed = false;
406
407
        private long totalSize;
408
409
        /**
410
         * @return the selected
411
         */
412 46309 jjdelcerro
        public Set<FeatureReference> getSelected() {
413 40435 jjdelcerro
            return selected;
414
        }
415
416
        /**
417 44976 jjdelcerro
         * @param selected the selected to set
418 40435 jjdelcerro
         */
419 46309 jjdelcerro
        public void setSelected(Set<FeatureReference> selected) {
420 40435 jjdelcerro
            this.selected = selected;
421
        }
422
423
        /**
424
         * @return the reversed
425
         */
426
        public boolean isReversed() {
427
            return reversed;
428
        }
429
430
        /**
431 44976 jjdelcerro
         * @param reversed the reversed to set
432 40435 jjdelcerro
         */
433
        public void setReversed(boolean reversed) {
434
            this.reversed = reversed;
435
        }
436
437
        /**
438
         * @return the totalSize
439
         */
440
        public long getTotalSize() {
441
            return totalSize;
442
        }
443
444
        /**
445 44976 jjdelcerro
         * @param totalSize the totalSize to set
446 40435 jjdelcerro
         */
447
        public void setTotalSize(long totalSize) {
448
            this.totalSize = totalSize;
449
        }
450
451
        public boolean add(FeatureReference reference) {
452
            return selected.add(reference);
453
        }
454
455
        public boolean remove(FeatureReference reference) {
456
            return selected.remove(reference);
457
        }
458
459
        public void clear() {
460
            selected.clear();
461
        }
462
463
        public boolean contains(FeatureReference reference) {
464
            return selected.contains(reference);
465
        }
466
467
        public int getSize() {
468
            return selected.size();
469
        }
470
471 44976 jjdelcerro
        @Override
472 40435 jjdelcerro
        public Object clone() throws CloneNotSupportedException {
473 44976 jjdelcerro
            SelectionData clone = (SelectionData) super.clone();
474
            // reversed and totalSize already cloned by parent.
475
            // clone the selected Set
476
            clone.selected = new HashSet(selected);
477 40435 jjdelcerro
            return clone;
478
        }
479
    }
480
481 44976 jjdelcerro
    @Override
482
    public void saveToState(PersistentState state) throws PersistenceException {
483
        state.set("store", featureStore);
484
        state.set("reversed", this.getData().isReversed());
485
        state.set("totalSize", this.getData().getTotalSize());
486
        state.set("selected", this.getData().getSelected().iterator());
487
    }
488 40435 jjdelcerro
489 44976 jjdelcerro
    @Override
490
    public void loadFromState(PersistentState state)
491
            throws PersistenceException {
492
        SelectionData data = new SelectionData(); // Do not use this.getData()
493
        featureStore = (FeatureStore) state.get("store");
494
        helper = new DefaultFeatureSelectionHelper((DefaultFeatureStore) featureStore);
495
        data.setReversed(state.getBoolean("reversed"));
496
        data.setTotalSize(state.getLong("totalSize"));
497
        Iterator it = state.getIterator("selected");
498
        while (it.hasNext()) {
499 45647 fdiaz
            FeatureReference ref = (FeatureReference) it.next();
500 44976 jjdelcerro
            data.add(ref);
501
        }
502 40435 jjdelcerro
503 44976 jjdelcerro
        /*
504 43725 jjdelcerro
             * If we do not do this, feature store will not listen
505
             * to changes in selection after instantiating a
506
             * persisted selection. For non-persisted instances,
507
             * this line corresponds to the line found in method:
508
             * getFeatureSelection() in DefaultFeatureStore.
509
             * This is not dangerous because "addObserver" only adds
510
             * if they were not already added, so future invocations
511
             * with same instances will have no effect.
512 44976 jjdelcerro
         */
513
        this.addObserver((DefaultFeatureStore) featureStore);
514
    }
515 40435 jjdelcerro
516 44976 jjdelcerro
    public static void registerPersistent() {
517
        DynStruct definition = ToolsLocator.getPersistenceManager().addDefinition(
518
                DefaultFeatureReferenceSelection.class,
519
                DYNCLASS_PERSISTENT_NAME,
520
                "DefaultFeatureReferenceSelection Persistent definition",
521
                null,
522
                null
523
        );
524 40435 jjdelcerro
525 44976 jjdelcerro
        definition.addDynFieldObject("store").setClassOfValue(FeatureStore.class).setMandatory(true);
526
        definition.addDynFieldBoolean("reversed").setMandatory(true);
527
        definition.addDynFieldLong("totalSize").setMandatory(true);
528 45647 fdiaz
        definition.addDynFieldList("selected").setClassOfItems(FeatureReference.class).setMandatory(true);
529 40435 jjdelcerro
530 44976 jjdelcerro
    }
531 40435 jjdelcerro
532 44976 jjdelcerro
    @Override
533
    public void addObserver(Observer observer) {
534
        delegateObservable.addObserver(observer);
535
    }
536 40435 jjdelcerro
537 44976 jjdelcerro
    @Override
538
    public void beginComplexNotification() {
539
        delegateObservable.beginComplexNotification();
540
    }
541 40435 jjdelcerro
542 44976 jjdelcerro
    @Override
543
    public void deleteObserver(Observer observer) {
544
        delegateObservable.deleteObserver(observer);
545
    }
546 40435 jjdelcerro
547 44976 jjdelcerro
    @Override
548
    public void deleteObservers() {
549
        delegateObservable.deleteObservers();
550
    }
551 40435 jjdelcerro
552 44976 jjdelcerro
    @Override
553
    public void disableNotifications() {
554
        delegateObservable.disableNotifications();
555
    }
556 40435 jjdelcerro
557 44976 jjdelcerro
    @Override
558
    public void enableNotifications() {
559
        delegateObservable.enableNotifications();
560
    }
561 40435 jjdelcerro
562 44976 jjdelcerro
    @Override
563
    public void endComplexNotification() {
564
        // We don't want to notify many times in a complex notification
565
        // scenario, so ignore notifications if in complex.
566
        // Only one notification will be sent when the complex notification
567
        // ends.
568
        delegateObservable.notifyObservers(DataStoreNotification.SELECTION_CHANGE);
569
        delegateObservable.endComplexNotification();
570
    }
571 40435 jjdelcerro
572 44976 jjdelcerro
    public boolean inComplex() {
573
        return delegateObservable.inComplex();
574
    }
575 40435 jjdelcerro
576 44976 jjdelcerro
    public boolean isEnabledNotifications() {
577
        return delegateObservable.isEnabledNotifications();
578
    }
579 40435 jjdelcerro
580 44976 jjdelcerro
    public void notifyObservers() {
581
        // We don't want to notify many times in a complex notification
582
        // scenario, so ignore notifications if in complex.
583
        // Only one notification will be sent when the complex notification
584
        // ends.
585
        if (!delegateObservable.inComplex()) {
586
            delegateObservable.notifyObservers();
587
        }
588
    }
589 40435 jjdelcerro
590 44976 jjdelcerro
    public void notifyObservers(Object arg) {
591
        if (!delegateObservable.inComplex()) {
592
            delegateObservable.notifyObservers(arg);
593
        }
594
    }
595 40435 jjdelcerro
596 43646 jjdelcerro
    @Override
597 44976 jjdelcerro
    public Object clone() throws CloneNotSupportedException {
598
        DefaultFeatureReferenceSelection clone = (DefaultFeatureReferenceSelection) super.clone();
599
        // Original observers aren't cloned
600
        clone.delegateObservable = new DelegateWeakReferencingObservable(clone);
601
        // Clone internal data
602
        clone.selectionData = (SelectionData) this.getData().clone();
603
        // featureStore and helper are already swallow cloned by our parent
604
        return clone;
605
    }
606 44435 jjdelcerro
607
    @Override
608
    public boolean isAvailable() {
609 44976 jjdelcerro
        if (this.available == null) {
610 44435 jjdelcerro
            try {
611
                FeatureType type = this.featureStore.getDefaultFeatureType();
612
                this.available = type.supportReferences();
613
            } catch (DataException ex) {
614
                this.available = false;
615
            }
616
        }
617
        return this.available;
618
    }
619 44976 jjdelcerro
620 40767 jjdelcerro
}