Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureReferenceSelection.java @ 28076

History | View | Annotate | Download (13.6 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (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.util.Collections;
30
import java.util.HashSet;
31
import java.util.Iterator;
32
import java.util.Set;
33

    
34
import org.gvsig.fmap.dal.DataStore;
35
import org.gvsig.fmap.dal.DataStoreNotification;
36
import org.gvsig.fmap.dal.exception.DataException;
37
import org.gvsig.fmap.dal.feature.FeatureReference;
38
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
39
import org.gvsig.fmap.dal.feature.FeatureStore;
40
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
41
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
42
import org.gvsig.tools.exception.BaseException;
43
import org.gvsig.tools.observer.Observable;
44
import org.gvsig.tools.observer.impl.BaseWeakReferencingObservable;
45
import org.gvsig.tools.persistence.PersistenceException;
46
import org.gvsig.tools.persistence.PersistentState;
47
import org.gvsig.tools.visitor.Visitor;
48
import org.slf4j.Logger;
49
import org.slf4j.LoggerFactory;
50

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

    
61
    private static final Logger LOGGER = LoggerFactory
62
            .getLogger(DefaultFeatureReferenceSelection.class);
63

    
64
    protected SelectionData selectionData = new SelectionData();
65

    
66
    private FeatureStore featureStore;
67

    
68
    private FeatureSelectionHelper helper;
69

    
70
        /**
71
         * Creates a new Selection with the total size of Features from which the
72
         * selection will be performed.
73
         *
74
         * @param featureStore
75
         *            the FeatureStore of the selected FeatureReferences
76
         * @throws DataException
77
         *             if there is an error while getting the total number of
78
         *             Features of the Store.
79
         */
80
    public DefaultFeatureReferenceSelection(DefaultFeatureStore featureStore)
81
            throws DataException {
82
        super();
83
        this.featureStore = featureStore;
84
        this.helper = new DefaultFeatureSelectionHelper(featureStore);
85
        selectionData.setTotalSize(featureStore.getFeatureCount());
86
    }
87

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

    
109
    public boolean select(FeatureReference reference) {
110
        return select(reference, true);
111
    }
112

    
113
    /**
114
     * @see #select(FeatureReference)
115
     * @param undoable
116
     *            if the action must be undoable
117
     */
118
    public boolean select(FeatureReference reference, boolean undoable) {
119
        if (isSelected(reference)) {
120
            return false;
121
        }
122

    
123
        if (undoable && getFeatureStore().isEditing()) {
124
            getCommands().select(this, reference);
125
        }
126
        boolean change = false;
127
        if (selectionData.isReversed()) {
128
            change = selectionData.remove(reference);
129
        } else {
130
            change = selectionData.add(reference);
131
        }
132

    
133
        if (change) {
134
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
135
        }
136

    
137
        return change;
138
    }
139

    
140
    public boolean deselect(FeatureReference reference) {
141
        return deselect(reference, true);
142
    }
143

    
144
    /**
145
     * @see #deselect(FeatureReference)
146
     * @param undoable
147
     *            if the action must be undoable
148
     */
149
    public boolean deselect(FeatureReference reference, boolean undoable) {
150
        if (!isSelected(reference)) {
151
            return false;
152
        }
153

    
154
        if (undoable && getFeatureStore().isEditing()) {
155
            getCommands().deselect(this, reference);
156
        }
157
        boolean change = false;
158
        if (selectionData.isReversed()) {
159
            change = selectionData.add(reference);
160
        } else {
161
            change = selectionData.remove(reference);
162
        }
163

    
164
        if (change) {
165
            notifyObservers(DataStoreNotification.SELECTION_CHANGE);
166
        }
167

    
168
        return change;
169
    }
170

    
171
    public void selectAll() throws DataException {
172
        selectAll(true);
173
    }
174

    
175
    /**
176
     * @see #selectAll()
177
     * @param undoable
178
     *            if the action must be undoable
179
     */
180
    public void selectAll(boolean undoable) throws DataException {
181
        if (undoable && getFeatureStore().isEditing()) {
182
            getCommands().startComplex("_selectionSelectAll");
183
            getCommands().selectAll(this);
184
        }
185
        if (!selectionData.isReversed()) {
186
            selectionData.setReversed(true);
187
        }
188
        clearFeatureReferences();
189
        if (undoable && getFeatureStore().isEditing()) {
190
            getCommands().endComplex();
191
        }
192
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
193
    }
194

    
195
    public void deselectAll() throws DataException {
196
        deselectAll(true);
197
    }
198

    
199
    /**
200
     * @see #deselectAll()
201
     * @param undoable
202
     *            if the action must be undoable
203
     */
204
    public void deselectAll(boolean undoable) throws DataException {
205
        if (undoable && getFeatureStore().isEditing()) {
206
            getCommands().startComplex("_selectionDeselectAll");
207
            getCommands().deselectAll(this);
208
        }
209
        if (selectionData.isReversed()) {
210
            selectionData.setReversed(false);
211
        }
212
        clearFeatureReferences();
213
        if (undoable && getFeatureStore().isEditing()) {
214
            getCommands().endComplex();
215
        }
216

    
217
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
218
    }
219

    
220
    public boolean isSelected(FeatureReference reference) {
221
        if (selectionData.isReversed()) {
222
            return !selectionData.contains(reference);
223
        } else {
224
            return selectionData.contains(reference);
225
        }
226
    }
227

    
228
    public void reverse() {
229
        reverse(true);
230
    }
231

    
232
    /**
233
     * @see #reverse()
234
     * @param undoable
235
     *            if the action must be undoable
236
     */
237
    public void reverse(boolean undoable) {
238
        if (undoable && getFeatureStore().isEditing()) {
239
            getCommands().selectionReverse(this);
240
        }
241
        selectionData.setReversed(!selectionData.isReversed());
242
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
243
    }
244

    
245
    public long getSelectedCount() {
246
        if (selectionData.isReversed()) {
247
                return selectionData.getTotalSize() - selectionData.getSize()
248
                        + helper.getFeatureStoreDeltaSize();
249
        } else {
250
            return selectionData.getSize();
251
        }
252
    }
253

    
254
    public Iterator referenceIterator() {
255
        return Collections.unmodifiableSet(selectionData.getSelected())
256
                .iterator();
257
    }
258

    
259
    public void dispose() {
260
        try {
261
            deselectAll();
262
        } catch (DataException ex) {
263
            LOGGER.error("Error on dispose(), deselecting all selected values",
264
                    ex);
265
        }
266
    }
267

    
268
    public boolean isFromStore(DataStore store) {
269
        return featureStore.equals(store);
270
    }
271

    
272
    public void accept(Visitor visitor) throws BaseException {
273
        for (Iterator iter = selectionData.getSelected().iterator(); iter
274
                .hasNext();) {
275
            visitor.visit(iter.next());
276
        }
277
    }
278

    
279
    public void update(Observable observable,
280
                        Object notification) {
281
        // If a Feature is deleted, remove it from the selection Set.
282
        if (notification instanceof FeatureStoreNotification) {
283
            FeatureStoreNotification storeNotif = (FeatureStoreNotification) notification;
284
            if (FeatureStoreNotification.AFTER_DELETE
285
                    .equalsIgnoreCase(storeNotif.getType())) {
286
                selectionData.remove(storeNotif.getFeature().getReference());
287
            }
288
        }
289
    }
290

    
291
    public void saveToState(PersistentState state) throws PersistenceException {
292
        state.set("reversed", selectionData.isReversed());
293
        state.set("totalSize", selectionData.getTotalSize());
294
        state.set("selected", selectionData.getSelected().iterator());
295
    }
296

    
297
    public void setState(PersistentState state) throws PersistenceException {
298
        selectionData.setReversed(state.getBoolean("reversed"));
299
        selectionData.setTotalSize(state.getLong("totalSize"));
300
        Iterator it = state.getIterator("selected");
301
        // FIXME: Esto no funcionara bien. Hay que darle una pensada mas.
302
        while (it.hasNext()) {
303
            DefaultFeatureReference ref = new DefaultFeatureReference(
304
                    this.featureStore);
305
            ref.setState((PersistentState) it.next());
306
            selectionData.add(ref);
307
        }
308
    }
309

    
310
    public SelectionData getData() {
311
        return selectionData;
312
    }
313

    
314
    public void setData(SelectionData selectionData) {
315
        this.selectionData = selectionData;
316
        notifyObservers(DataStoreNotification.SELECTION_CHANGE);
317
    }
318

    
319
    public String toString() {
320
        return getClass().getName() + ": " + getSelectedCount()
321
                + " features selected, reversed = "
322
                + selectionData.isReversed() + ", featureIds contained: "
323
                + selectionData.getSelected();
324
    }
325

    
326
    protected boolean isReversed() {
327
        return selectionData.isReversed();
328
    }
329

    
330
    /**
331
     * Removes all the stored FeatureRefence objects.
332
     */
333
    protected void clearFeatureReferences() {
334
        selectionData.clear();
335
    }
336

    
337
        /**
338
         * Returns the FeatureStore of the selected FeatureReferences.
339
         *
340
         * @return the featureStore
341
         */
342
    protected FeatureStore getFeatureStore() {
343
        return featureStore;
344
    }
345

    
346
        /**
347
         * Returns the reference to the commands record.
348
         *
349
         * @return the reference to the commands record
350
         */
351
    protected FeatureCommandsStack getCommands() {
352
        return helper.getFeatureStoreCommandsStack();
353
    }
354

    
355
    public static class SelectionData {
356
        private Set selected = new HashSet();
357

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

    
371
        private long totalSize;
372

    
373
        /**
374
         * @return the selected
375
         */
376
        public Set getSelected() {
377
            return selected;
378
        }
379

    
380
        /**
381
         * @param selected
382
         *            the selected to set
383
         */
384
        public void setSelected(Set selected) {
385
            this.selected = selected;
386
        }
387

    
388
        /**
389
         * @return the reversed
390
         */
391
        public boolean isReversed() {
392
            return reversed;
393
        }
394

    
395
        /**
396
         * @param reversed
397
         *            the reversed to set
398
         */
399
        public void setReversed(boolean reversed) {
400
            this.reversed = reversed;
401
        }
402

    
403
        /**
404
         * @return the totalSize
405
         */
406
        public long getTotalSize() {
407
            return totalSize;
408
        }
409

    
410
        /**
411
         * @param totalSize
412
         *            the totalSize to set
413
         */
414
        public void setTotalSize(long totalSize) {
415
            this.totalSize = totalSize;
416
        }
417

    
418
        public boolean add(FeatureReference reference) {
419
            return selected.add(reference);
420
        }
421

    
422
        public boolean remove(FeatureReference reference) {
423
            return selected.remove(reference);
424
        }
425

    
426
        public void clear() {
427
            selected.clear();
428
        }
429

    
430
        public boolean contains(FeatureReference reference) {
431
            return selected.contains(reference);
432
        }
433

    
434
        public int getSize() {
435
            return selected.size();
436
        }
437

    
438
        public Object clone() throws CloneNotSupportedException {
439
            SelectionData clone = new SelectionData();
440
            clone.setReversed(isReversed());
441
            clone.setTotalSize(getTotalSize());
442
            clone.setSelected(new HashSet(getSelected()));
443
            return clone;
444
        }
445
    }
446
}