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 / editing / memory / FeatureManager.java @ 44434
History | View | Annotate | Download (11.5 KB)
1 | 40559 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40435 | jjdelcerro | *
|
4 | 40559 | jjdelcerro | * Copyright (C) 2007-2013 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 | 40559 | jjdelcerro | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | * MA 02110-1301, USA.
|
||
20 | 40435 | jjdelcerro | *
|
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 | 43840 | jjdelcerro | package org.gvsig.fmap.dal.feature.impl.editing.memory; |
25 | 40435 | jjdelcerro | |
26 | import java.util.Collection; |
||
27 | import java.util.HashMap; |
||
28 | import java.util.Iterator; |
||
29 | import java.util.LinkedHashMap; |
||
30 | import java.util.LinkedHashSet; |
||
31 | import java.util.Map; |
||
32 | import java.util.NoSuchElementException; |
||
33 | |||
34 | import org.gvsig.fmap.dal.exception.DataException; |
||
35 | import org.gvsig.fmap.dal.feature.Feature; |
||
36 | import org.gvsig.fmap.dal.feature.FeatureReference; |
||
37 | import org.gvsig.fmap.dal.feature.FeatureStore; |
||
38 | import org.gvsig.fmap.dal.feature.FeatureType; |
||
39 | 43840 | jjdelcerro | import org.gvsig.fmap.dal.feature.impl.DefaultFeature; |
40 | import org.gvsig.fmap.dal.feature.impl.DefaultFeatureReference; |
||
41 | 40435 | jjdelcerro | |
42 | |||
43 | public class FeatureManager { |
||
44 | 42639 | dmartinezizquierdo | |
45 | 43840 | jjdelcerro | private int deltaSize; |
46 | 43838 | jjdelcerro | private final ExpansionAdapter expansionAdapter; |
47 | 43840 | jjdelcerro | private final Collection<FeatureReference> deleted; |
48 | private final Map<FeatureReference, Integer> added; |
||
49 | private final Map<FeatureReference, Integer> addedAndDeleted; |
||
50 | private final Map<FeatureReference, Integer> modifiedFromOriginal; |
||
51 | 43838 | jjdelcerro | |
52 | 43840 | jjdelcerro | public FeatureManager() {
|
53 | deltaSize = 0;
|
||
54 | expansionAdapter = new MemoryExpansionAdapter();
|
||
55 | deleted = new LinkedHashSet<>(); |
||
56 | added = new LinkedHashMap<>(); |
||
57 | addedAndDeleted = new LinkedHashMap<>(); |
||
58 | modifiedFromOriginal = new HashMap<>(); |
||
59 | 40435 | jjdelcerro | } |
60 | |||
61 | 43838 | jjdelcerro | /**
|
62 | * Deletes feature from this manager.
|
||
63 | *
|
||
64 | * @param id
|
||
65 | * @return The deleted feature or null if the feature had not been edited or
|
||
66 | * previously added in the editing session
|
||
67 | */
|
||
68 | 40435 | jjdelcerro | public Feature delete(FeatureReference id) {
|
69 | deleted.add(id); |
||
70 | 43838 | jjdelcerro | Integer num = added.remove(id);
|
71 | Feature feature = null;
|
||
72 | if (num == null || num == -1) { |
||
73 | num = modifiedFromOriginal.remove(id); |
||
74 | 40435 | jjdelcerro | if (num != null) { |
75 | 43838 | jjdelcerro | feature = (Feature) expansionAdapter.getObject(num); |
76 | 40435 | jjdelcerro | } |
77 | // if num is null here, method returns null
|
||
78 | 43838 | jjdelcerro | } else {
|
79 | feature = (Feature) expansionAdapter.getObject(num); |
||
80 | addedAndDeleted.put(id, num); |
||
81 | } |
||
82 | 40435 | jjdelcerro | deltaSize--; |
83 | return feature;
|
||
84 | } |
||
85 | |||
86 | public void add(Feature feature) { |
||
87 | int pos = expansionAdapter.addObject(feature);
|
||
88 | 43838 | jjdelcerro | added.put(feature.getReference(), pos); |
89 | 40435 | jjdelcerro | deleted.remove(feature.getReference()); |
90 | deltaSize++; |
||
91 | } |
||
92 | |||
93 | public Feature deleteLastFeature() {
|
||
94 | expansionAdapter.deleteLastObject(); |
||
95 | 43838 | jjdelcerro | Feature feature = (Feature) expansionAdapter.getObject(expansionAdapter.getSize() - 1);
|
96 | 40435 | jjdelcerro | added.remove(feature.getReference()); |
97 | modifiedFromOriginal.remove(feature.getReference()); |
||
98 | deltaSize--; |
||
99 | return feature;
|
||
100 | } |
||
101 | |||
102 | /**
|
||
103 | * Returns a Feature of the default type.
|
||
104 | *
|
||
105 | 43838 | jjdelcerro | * @param id the feature reference
|
106 | * @param store the store to get the feature from
|
||
107 | 40435 | jjdelcerro | * @return a Feature with the given reference
|
108 | 43838 | jjdelcerro | * @throws DataException if there is an error getting the Feature
|
109 | 40435 | jjdelcerro | */
|
110 | public Feature get(FeatureReference id, FeatureStore store)
|
||
111 | throws DataException {
|
||
112 | return get(id, store, null); |
||
113 | } |
||
114 | |||
115 | /**
|
||
116 | * Returns a Feature of the given type.
|
||
117 | *
|
||
118 | 43838 | jjdelcerro | * @param id the feature reference
|
119 | * @param store the store to get the feature from
|
||
120 | * @param featureType the type of the feature to return
|
||
121 | 40435 | jjdelcerro | * @return a Feature with the given reference
|
122 | 43838 | jjdelcerro | * @throws DataException if there is an error getting the Feature
|
123 | 40435 | jjdelcerro | */
|
124 | public Feature get(FeatureReference id, FeatureStore store,
|
||
125 | 43838 | jjdelcerro | FeatureType featureType) throws DataException {
|
126 | // FIXME: y si el featuretype que paso esta modificado.
|
||
127 | // Deberia buscarlo en el featuretypemanager ?
|
||
128 | //
|
||
129 | // Si no existe feature con ese id... ? retorna null ?
|
||
130 | // en EditedDefaultIterator se hace uso de ese comportamiento.
|
||
131 | //
|
||
132 | Integer intNum = (added.get(id));
|
||
133 | if (intNum == null) { |
||
134 | intNum = (modifiedFromOriginal.get(id)); |
||
135 | if (intNum == null) { |
||
136 | //If the feature has been added and deleted
|
||
137 | intNum = addedAndDeleted.get(id); |
||
138 | if (intNum == null) { |
||
139 | return null; |
||
140 | } |
||
141 | } |
||
142 | 40435 | jjdelcerro | } |
143 | 43838 | jjdelcerro | int num = intNum;
|
144 | if (num == -1) { |
||
145 | return null; |
||
146 | } |
||
147 | Feature feature = (Feature) expansionAdapter.getObject(num); |
||
148 | if (featureType == null) { |
||
149 | featureType = store.getDefaultFeatureType(); |
||
150 | } |
||
151 | 43729 | fdiaz | return new DefaultFeature(featureType, feature); |
152 | 40435 | jjdelcerro | } |
153 | |||
154 | public int update(Feature feature, Feature oldFeature) { |
||
155 | 43838 | jjdelcerro | int oldNum = -1; |
156 | 40435 | jjdelcerro | int num = expansionAdapter.addObject(feature);
|
157 | 43838 | jjdelcerro | FeatureReference id = feature.getReference(); |
158 | if (added.containsKey(id)) {
|
||
159 | oldNum = (added.get(id)); |
||
160 | added.put(id, num); |
||
161 | } else {
|
||
162 | if (modifiedFromOriginal.get(id) != null) { |
||
163 | oldNum = (modifiedFromOriginal.get(id)); |
||
164 | } |
||
165 | modifiedFromOriginal.put(id, num); |
||
166 | 40435 | jjdelcerro | } |
167 | return oldNum;
|
||
168 | } |
||
169 | |||
170 | public void restore(FeatureReference id) { |
||
171 | deleted.remove(id); |
||
172 | deltaSize++; |
||
173 | } |
||
174 | 43838 | jjdelcerro | |
175 | public void restore(FeatureReference id, int num) { |
||
176 | if (added.containsKey(id)) {
|
||
177 | added.put(id, num); |
||
178 | } else {
|
||
179 | modifiedFromOriginal.put(id, num); |
||
180 | 40435 | jjdelcerro | } |
181 | } |
||
182 | |||
183 | 43838 | jjdelcerro | public boolean isDeleted(Feature feature) { |
184 | return deleted.contains(feature.getReference());
|
||
185 | 40435 | jjdelcerro | } |
186 | |||
187 | public boolean isDeleted(FeatureReference featureID) { |
||
188 | 43838 | jjdelcerro | return deleted.contains(featureID);
|
189 | } |
||
190 | 40435 | jjdelcerro | |
191 | 43838 | jjdelcerro | public void clear() { |
192 | added.clear(); |
||
193 | modifiedFromOriginal.clear(); |
||
194 | expansionAdapter.close(); |
||
195 | deleted.clear(); |
||
196 | addedAndDeleted.clear(); |
||
197 | deltaSize = 0;
|
||
198 | } |
||
199 | 40435 | jjdelcerro | |
200 | 43838 | jjdelcerro | public boolean hasChanges() { |
201 | return added.size() > 0 || modifiedFromOriginal.size() > 0 || deleted.size() > 0; |
||
202 | } |
||
203 | 40435 | jjdelcerro | |
204 | 43838 | jjdelcerro | public Iterator getDeleted() { |
205 | return new DeletedIterator(); |
||
206 | 40435 | jjdelcerro | |
207 | 43838 | jjdelcerro | } |
208 | 40435 | jjdelcerro | |
209 | 44111 | jjdelcerro | public long getPendingChangesCount() { |
210 | long count = 0; |
||
211 | if( this.added!=null ) { |
||
212 | count += this.added.size();
|
||
213 | } |
||
214 | if( this.deleted!=null ) { |
||
215 | count += this.deleted.size();
|
||
216 | } |
||
217 | if( this.modifiedFromOriginal!=null ) { |
||
218 | count += this.modifiedFromOriginal.size();
|
||
219 | } |
||
220 | return count;
|
||
221 | } |
||
222 | |||
223 | 43838 | jjdelcerro | private class DeletedIterator implements Iterator { |
224 | 40435 | jjdelcerro | |
225 | 43838 | jjdelcerro | private Boolean hasnext = null; |
226 | private final Iterator iter; |
||
227 | private DefaultFeatureReference obj;
|
||
228 | 40435 | jjdelcerro | |
229 | 43838 | jjdelcerro | public DeletedIterator() {
|
230 | iter = deleted.iterator(); |
||
231 | } |
||
232 | 40435 | jjdelcerro | |
233 | 43838 | jjdelcerro | @Override
|
234 | public boolean hasNext() { |
||
235 | if (hasnext != null) { |
||
236 | return hasnext;
|
||
237 | } |
||
238 | hasnext = false;
|
||
239 | while (iter.hasNext()) {
|
||
240 | obj = (DefaultFeatureReference) iter.next(); |
||
241 | if (obj.isNewFeature()) {
|
||
242 | continue;
|
||
243 | } |
||
244 | 44434 | jjdelcerro | hasnext = true;
|
245 | 43838 | jjdelcerro | break;
|
246 | } |
||
247 | return hasnext;
|
||
248 | } |
||
249 | 40435 | jjdelcerro | |
250 | 43838 | jjdelcerro | @Override
|
251 | public Object next() { |
||
252 | if (!hasNext()) {
|
||
253 | throw new NoSuchElementException(); |
||
254 | } |
||
255 | hasnext = null;
|
||
256 | return obj;
|
||
257 | } |
||
258 | 40435 | jjdelcerro | |
259 | 43838 | jjdelcerro | @Override
|
260 | public void remove() { |
||
261 | throw new UnsupportedOperationException(); |
||
262 | } |
||
263 | 40435 | jjdelcerro | |
264 | 43838 | jjdelcerro | } |
265 | 40435 | jjdelcerro | |
266 | 43838 | jjdelcerro | public Iterator getInserted() { |
267 | return new InsertedIterator(); |
||
268 | } |
||
269 | 40435 | jjdelcerro | |
270 | 43838 | jjdelcerro | private class InsertedIterator implements Iterator { |
271 | 40435 | jjdelcerro | |
272 | 43838 | jjdelcerro | private final Iterator addedIter; |
273 | private DefaultFeature obj;
|
||
274 | private Boolean hasnext = null; |
||
275 | 40435 | jjdelcerro | |
276 | 43838 | jjdelcerro | public InsertedIterator() {
|
277 | addedIter = added.values().iterator(); |
||
278 | } |
||
279 | 40435 | jjdelcerro | |
280 | 43838 | jjdelcerro | @Override
|
281 | public boolean hasNext() { |
||
282 | if (hasnext != null) { |
||
283 | return hasnext;
|
||
284 | } |
||
285 | hasnext = false;
|
||
286 | int pos;
|
||
287 | while (addedIter.hasNext()) {
|
||
288 | pos = ((Integer) addedIter.next());
|
||
289 | obj = (DefaultFeature) expansionAdapter.getObject(pos); |
||
290 | if (!deleted.contains(obj.getReference())) {
|
||
291 | hasnext = true;
|
||
292 | break;
|
||
293 | } |
||
294 | } |
||
295 | return hasnext;
|
||
296 | } |
||
297 | 40435 | jjdelcerro | |
298 | 43838 | jjdelcerro | @Override
|
299 | public Object next() { |
||
300 | if (!hasNext()) {
|
||
301 | throw new NoSuchElementException(); |
||
302 | } |
||
303 | hasnext = null;
|
||
304 | return obj.getData();
|
||
305 | } |
||
306 | 40435 | jjdelcerro | |
307 | 43838 | jjdelcerro | @Override
|
308 | public void remove() { |
||
309 | addedIter.remove(); |
||
310 | } |
||
311 | 40435 | jjdelcerro | |
312 | 43838 | jjdelcerro | } |
313 | 40435 | jjdelcerro | |
314 | 43838 | jjdelcerro | public Iterator getUpdated() { |
315 | return new UpdatedIterator(); |
||
316 | } |
||
317 | 40435 | jjdelcerro | |
318 | 43838 | jjdelcerro | private class UpdatedIterator implements Iterator { |
319 | 40435 | jjdelcerro | |
320 | 43838 | jjdelcerro | private Boolean hasnext = null; |
321 | private final Iterator iter; |
||
322 | private DefaultFeature obj;
|
||
323 | private int pos; |
||
324 | 40435 | jjdelcerro | |
325 | 43838 | jjdelcerro | public UpdatedIterator() {
|
326 | iter = expansionAdapter.iterator(); |
||
327 | pos = -1;
|
||
328 | } |
||
329 | 40435 | jjdelcerro | |
330 | 43838 | jjdelcerro | @Override
|
331 | public boolean hasNext() { |
||
332 | if (hasnext != null) { |
||
333 | return hasnext;
|
||
334 | } |
||
335 | hasnext = false;
|
||
336 | while (iter.hasNext()) {
|
||
337 | pos++; |
||
338 | obj = (DefaultFeature) iter.next(); |
||
339 | if (deleted.contains(obj.getReference())) {
|
||
340 | continue;
|
||
341 | } else if (!modifiedFromOriginal.containsValue(pos)) { |
||
342 | continue;
|
||
343 | } else {
|
||
344 | hasnext = true;
|
||
345 | break;
|
||
346 | } |
||
347 | } |
||
348 | return hasnext;
|
||
349 | } |
||
350 | 40435 | jjdelcerro | |
351 | 43838 | jjdelcerro | @Override
|
352 | public Object next() { |
||
353 | if (!hasNext()) {
|
||
354 | throw new NoSuchElementException(); |
||
355 | } |
||
356 | hasnext = null;
|
||
357 | return obj.getData();
|
||
358 | } |
||
359 | 40435 | jjdelcerro | |
360 | 43838 | jjdelcerro | @Override
|
361 | public void remove() { |
||
362 | throw new UnsupportedOperationException(); |
||
363 | 40435 | jjdelcerro | |
364 | 43838 | jjdelcerro | } |
365 | } |
||
366 | 40435 | jjdelcerro | |
367 | 43838 | jjdelcerro | public boolean hasNews() { |
368 | return !added.isEmpty();
|
||
369 | } |
||
370 | 42639 | dmartinezizquierdo | |
371 | 43838 | jjdelcerro | public long getDeltaSize() { |
372 | return deltaSize;
|
||
373 | } |
||
374 | |||
375 | 42639 | dmartinezizquierdo | /**
|
376 | * Indicates if any operation has comprimised the selected features.
|
||
377 | 43838 | jjdelcerro | *
|
378 | 42639 | dmartinezizquierdo | * @return
|
379 | */
|
||
380 | public boolean isSelectionCompromised() { |
||
381 | //Only deleted features can change order, as added features are added at the end.
|
||
382 | 43838 | jjdelcerro | return deleted.size() > 0; |
383 | 42639 | dmartinezizquierdo | } |
384 | 40435 | jjdelcerro | } |