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