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