Statistics
| Revision:

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

History | View | Annotate | Download (16 KB)

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

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {Implement data selection}
26
 */
27
package org.gvsig.fmap.dal.feature.impl;
28

    
29
import java.lang.ref.Reference;
30
import java.util.Collections;
31
import java.util.HashSet;
32
import java.util.Iterator;
33
import java.util.Set;
34

    
35
import org.gvsig.fmap.dal.DataStore;
36
import org.gvsig.fmap.dal.DataStoreNotification;
37
import org.gvsig.fmap.dal.exception.DataException;
38
import org.gvsig.fmap.dal.feature.FeatureReference;
39
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
42
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
43
import org.gvsig.tools.ToolsLocator;
44
import org.gvsig.tools.dispose.impl.AbstractDisposable;
45
import org.gvsig.tools.dynobject.DynClass;
46
import org.gvsig.tools.dynobject.DynObjectManager;
47
import org.gvsig.tools.exception.BaseException;
48
import org.gvsig.tools.observer.Observable;
49
import org.gvsig.tools.observer.Observer;
50
import org.gvsig.tools.observer.impl.BaseWeakReferencingObservable;
51
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
52
import org.gvsig.tools.persistence.PersistenceException;
53
import org.gvsig.tools.persistence.PersistentState;
54
import org.gvsig.tools.visitor.Visitor;
55

    
56
/**
57
 * Default implementation of a FeatureReferenceSelection, based on the usage of
58
 * a java.util.Set to store individual selected or not selected
59
 * FeatureReferences, depending on the usage of the {@link #reverse()} method.
60
 *
61
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
62
 */
63
public class DefaultFeatureReferenceSelection extends AbstractDisposable
64
                implements FeatureReferenceSelection {
65

    
66
        public static final String DYNCLASS_PERSISTENT_NAME =
67
                        "DefaultFeatureReferenceSelection_Persistent";
68

    
69
    protected SelectionData selectionData = new SelectionData();
70

    
71
    private FeatureStore featureStore;
72

    
73
    private FeatureSelectionHelper helper;
74

    
75
        private DelegateWeakReferencingObservable delegateObservable =
76
                        new DelegateWeakReferencingObservable(this);
77

    
78
        /**
79
         * Creates a new Selection with the total size of Features from which the
80
         * selection will be performed.
81
         *
82
         * @param featureStore
83
         *            the FeatureStore of the selected FeatureReferences
84
         * @throws DataException
85
         *             if there is an error while getting the total number of
86
         *             Features of the Store.
87
         */
88
    public DefaultFeatureReferenceSelection(DefaultFeatureStore featureStore)
89
            throws DataException {
90
        super();
91
        this.featureStore = featureStore;
92
        this.helper = new DefaultFeatureSelectionHelper(featureStore);
93
        selectionData.setTotalSize(featureStore.getFeatureCount());
94
    }
95

    
96
    /**
97
     * Creates a new Selection with the total size of Features from which the
98
     * selection will be performed.
99
     *
100
     * @param featureStore
101
     *            the FeatureStore of the selected FeatureReferences
102
     * @param helper
103
     *            to get some information of the Store
104
     * @throws DataException
105
     *             if there is an error while getting the total number of
106
     *             Features of the Store.
107
     */
108
    public DefaultFeatureReferenceSelection(FeatureStore featureStore,
109
            FeatureSelectionHelper helper)
110
            throws DataException {
111
        super();
112
        this.featureStore = featureStore;
113
        this.helper = helper;
114
        selectionData.setTotalSize(featureStore.getFeatureCount());
115
    }
116

    
117
        /**
118
         * Constructor used by the persistence manager. Don't use directly. After to
119
         * invoke this method, the persistence manager calls the the method
120
         * {@link #loadFromState(PersistentState)} to set the values of the internal
121
         * attributes that this class needs to work.
122
         */
123
        public DefaultFeatureReferenceSelection() {
124
                super();
125
        }
126

    
127
    public boolean select(FeatureReference reference) {
128
        return select(reference, true);
129
    }
130

    
131
    /**
132
     * @see #select(FeatureReference)
133
     * @param undoable
134
     *            if the action must be undoable
135
     */
136
    public boolean select(FeatureReference reference, boolean undoable) {
137
        if (isSelected(reference)) {
138
            return false;
139
        }
140

    
141
        if (undoable && getFeatureStore().isEditing()) {
142
            getCommands().select(this, reference);
143
        }
144
        boolean change = false;
145
        if (selectionData.isReversed()) {
146
            change = selectionData.remove(reference);
147
        } else {
148
            change = selectionData.add(reference);
149
        }
150

    
151
        if (change) {
152
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
153
        }
154

    
155
        return change;
156
    }
157

    
158
    public boolean deselect(FeatureReference reference) {
159
        return deselect(reference, true);
160
    }
161

    
162
    /**
163
     * @see #deselect(FeatureReference)
164
     * @param undoable
165
     *            if the action must be undoable
166
     */
167
    public boolean deselect(FeatureReference reference, boolean undoable) {
168
        if (!isSelected(reference)) {
169
            return false;
170
        }
171

    
172
        if (undoable && getFeatureStore().isEditing()) {
173
            getCommands().deselect(this, reference);
174
        }
175
        boolean change = false;
176
        if (selectionData.isReversed()) {
177
            change = selectionData.add(reference);
178
        } else {
179
            change = selectionData.remove(reference);
180
        }
181

    
182
        if (change) {
183
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
184
        }
185

    
186
        return change;
187
    }
188

    
189
    public void selectAll() throws DataException {
190
        selectAll(true);
191
    }
192

    
193
    /**
194
     * @see #selectAll()
195
     * @param undoable
196
     *            if the action must be undoable
197
     */
198
    public void selectAll(boolean undoable) throws DataException {
199
        if (undoable && getFeatureStore().isEditing()) {
200
            getCommands().startComplex("_selectionSelectAll");
201
            getCommands().selectAll(this);
202
        }
203
        if (!selectionData.isReversed()) {
204
            selectionData.setReversed(true);
205
        }
206
        clearFeatureReferences();
207
        if (undoable && getFeatureStore().isEditing()) {
208
            getCommands().endComplex();
209
        }
210
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
211
    }
212

    
213
    public void deselectAll() throws DataException {
214
        deselectAll(true);
215
    }
216

    
217
    /**
218
     * @see #deselectAll()
219
     * @param undoable
220
     *            if the action must be undoable
221
     */
222
    public void deselectAll(boolean undoable) throws DataException {
223
        if (undoable && getFeatureStore().isEditing()) {
224
            getCommands().startComplex("_selectionDeselectAll");
225
            getCommands().deselectAll(this);
226
        }
227
        if (selectionData.isReversed()) {
228
            selectionData.setReversed(false);
229
        }
230
        clearFeatureReferences();
231
        if (undoable && getFeatureStore().isEditing()) {
232
            getCommands().endComplex();
233
        }
234

    
235
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
236
    }
237

    
238
    public boolean isSelected(FeatureReference reference) {
239
        if (selectionData.isReversed()) {
240
            return !selectionData.contains(reference);
241
        } else {
242
            return selectionData.contains(reference);
243
        }
244
    }
245

    
246
    public void reverse() {
247
        reverse(true);
248
    }
249

    
250
    /**
251
     * @see #reverse()
252
     * @param undoable
253
     *            if the action must be undoable
254
     */
255
    public void reverse(boolean undoable) {
256
        if (undoable && getFeatureStore().isEditing()) {
257
            getCommands().selectionReverse(this);
258
        }
259
        selectionData.setReversed(!selectionData.isReversed());
260
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
261
    }
262

    
263
    public long getSelectedCount() {
264
        if (selectionData.isReversed()) {
265
                return selectionData.getTotalSize() - selectionData.getSize()
266
                        + helper.getFeatureStoreDeltaSize();
267
        } else {
268
            return selectionData.getSize();
269
        }
270
    }
271

    
272
    public Iterator referenceIterator() {
273
        return Collections.unmodifiableSet(selectionData.getSelected())
274
                .iterator();
275
    }
276

    
277
        protected void doDispose() throws BaseException {
278
                delegateObservable.deleteObservers();
279
                deselectAll(false);
280
    }
281

    
282
    public boolean isFromStore(DataStore store) {
283
        return featureStore.equals(store);
284
    }
285

    
286
    public void accept(Visitor visitor) throws BaseException {
287
        for (Iterator iter = selectionData.getSelected().iterator(); iter
288
                .hasNext();) {
289
            visitor.visit(iter.next());
290
        }
291
    }
292

    
293
    public void update(Observable observable,
294
                        Object notification) {
295
        // If a Feature is deleted, remove it from the selection Set.
296
        if (notification instanceof FeatureStoreNotification) {
297
            FeatureStoreNotification storeNotif = (FeatureStoreNotification) notification;
298
            if (FeatureStoreNotification.AFTER_DELETE
299
                    .equalsIgnoreCase(storeNotif.getType())) {
300
                selectionData.remove(storeNotif.getFeature().getReference());
301
            }
302
        }
303
    }
304

    
305
    public SelectionData getData() {
306
        return selectionData;
307
    }
308

    
309
    public void setData(SelectionData selectionData) {
310
        this.selectionData = selectionData;
311
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
312
    }
313

    
314
    public String toString() {
315
        return getClass().getName() + ": " + getSelectedCount()
316
                + " features selected, reversed = "
317
                + selectionData.isReversed() + ", featureIds contained: "
318
                + selectionData.getSelected();
319
    }
320

    
321
    protected boolean isReversed() {
322
        return selectionData.isReversed();
323
    }
324

    
325
    /**
326
     * Removes all the stored FeatureRefence objects.
327
     */
328
    protected void clearFeatureReferences() {
329
        selectionData.clear();
330
    }
331

    
332
        /**
333
         * Returns the FeatureStore of the selected FeatureReferences.
334
         *
335
         * @return the featureStore
336
         */
337
    protected FeatureStore getFeatureStore() {
338
        return featureStore;
339
    }
340

    
341
        /**
342
         * Returns the reference to the commands record.
343
         *
344
         * @return the reference to the commands record
345
         */
346
    protected FeatureCommandsStack getCommands() {
347
        return helper.getFeatureStoreCommandsStack();
348
    }
349

    
350
    public static class SelectionData {
351
        private Set selected = new HashSet();
352

    
353
        /**
354
         * Sets how the Set of selected values has to be dealt.
355
         * <p>
356
         * If selected is FALSE, then values into the Set are the selected ones,
357
         * anything else is not selected.
358
         * </p>
359
         * <p>
360
         * If selected is TRUE, then values into the Set are values not
361
         * selected, anything else is selected.
362
         * </p>
363
         */
364
        private boolean reversed = false;
365

    
366
        private long totalSize;
367

    
368
        /**
369
         * @return the selected
370
         */
371
        public Set getSelected() {
372
            return selected;
373
        }
374

    
375
        /**
376
         * @param selected
377
         *            the selected to set
378
         */
379
        public void setSelected(Set selected) {
380
            this.selected = selected;
381
        }
382

    
383
        /**
384
         * @return the reversed
385
         */
386
        public boolean isReversed() {
387
            return reversed;
388
        }
389

    
390
        /**
391
         * @param reversed
392
         *            the reversed to set
393
         */
394
        public void setReversed(boolean reversed) {
395
            this.reversed = reversed;
396
        }
397

    
398
        /**
399
         * @return the totalSize
400
         */
401
        public long getTotalSize() {
402
            return totalSize;
403
        }
404

    
405
        /**
406
         * @param totalSize
407
         *            the totalSize to set
408
         */
409
        public void setTotalSize(long totalSize) {
410
            this.totalSize = totalSize;
411
        }
412

    
413
        public boolean add(FeatureReference reference) {
414
            return selected.add(reference);
415
        }
416

    
417
        public boolean remove(FeatureReference reference) {
418
            return selected.remove(reference);
419
        }
420

    
421
        public void clear() {
422
            selected.clear();
423
        }
424

    
425
        public boolean contains(FeatureReference reference) {
426
            return selected.contains(reference);
427
        }
428

    
429
        public int getSize() {
430
            return selected.size();
431
        }
432

    
433
        public Object clone() throws CloneNotSupportedException {
434
            SelectionData clone = new SelectionData();
435
            clone.setReversed(isReversed());
436
            clone.setTotalSize(getTotalSize());
437
            clone.setSelected(new HashSet(getSelected()));
438
            return clone;
439
        }
440
    }
441

    
442
    // *** Persistence ***
443

    
444
        public void saveToState(PersistentState state) throws PersistenceException {
445
                state.set("store", featureStore);
446
                state.set("reversed", selectionData.isReversed());
447
                state.set("totalSize", selectionData.getTotalSize());
448
                state.set("selected", selectionData.getSelected().iterator());
449
        }
450

    
451
        public void loadFromState(PersistentState state)
452
                        throws PersistenceException {
453
                featureStore = (FeatureStore)state.get("store");
454
                selectionData.setReversed(state.getBoolean("reversed"));
455
                selectionData.setTotalSize(state.getLong("totalSize"));
456
                Iterator it = state.getIterator("selected");
457
                while (it.hasNext()) {
458
                        DefaultFeatureReference ref = (DefaultFeatureReference) it.next();
459
                        selectionData.add(ref);
460
                }
461
        }
462

    
463
        public static void registerPersistent() {
464
                DynObjectManager dynMan = ToolsLocator.getDynObjectManager();
465
                if (dynMan.get(DYNCLASS_PERSISTENT_NAME) != null) {
466
                        return;
467
                }
468
                DynClass dynClass = dynMan.add(
469
                                DYNCLASS_PERSISTENT_NAME,
470
//                                "DefaultFeatureReferenceSelection_Persistent",
471
                                "DefaultFeatureReferenceSelection Persistent definition");
472

    
473
                dynClass.addDynFieldObject("store").setMandatory(true);
474
                dynClass.addDynFieldBoolean("reversed").setMandatory(true);
475
                dynClass.addDynFieldLong("totalSize").setMandatory(true);
476
                dynClass.addDynFieldList("selected").setMandatory(true);
477

    
478
                ToolsLocator.getPersistenceManager().registerClass(
479
                                DefaultFeatureReferenceSelection.class, dynClass);
480

    
481
        }
482

    
483
        public void addObserver(Observer observer) {
484
                delegateObservable.addObserver(observer);
485
        }
486

    
487
        public void addObserver(Reference ref) {
488
                delegateObservable.addObserver(ref);
489
        }
490

    
491
        public void addObservers(BaseWeakReferencingObservable observable) {
492
                delegateObservable.addObservers(observable);
493
        }
494

    
495
        public void beginComplexNotification() {
496
                delegateObservable.beginComplexNotification();
497
        }
498

    
499
        public int countObservers() {
500
                return delegateObservable.countObservers();
501
        }
502

    
503
        public void deleteObserver(Observer observer) {
504
                delegateObservable.deleteObserver(observer);
505
        }
506

    
507
        public void deleteObserver(Reference ref) {
508
                delegateObservable.deleteObserver(ref);
509
        }
510

    
511
        public void deleteObservers() {
512
                delegateObservable.deleteObservers();
513
        }
514

    
515
        public void disableNotifications() {
516
                delegateObservable.disableNotifications();
517
        }
518

    
519
        public void enableNotifications() {
520
                delegateObservable.enableNotifications();
521
        }
522

    
523
        public void endComplexNotification() {
524
                delegateObservable.endComplexNotification();
525
        }
526

    
527
        public boolean inComplex() {
528
                return delegateObservable.inComplex();
529
        }
530

    
531
        public boolean isEnabledNotifications() {
532
                return delegateObservable.isEnabledNotifications();
533
        }
534

    
535
        public void notifyObservers() {
536
                delegateObservable.notifyObservers();
537
        }
538

    
539
        public void notifyObservers(Object arg) {
540
                delegateObservable.notifyObservers(arg);
541
        }
542
}