Statistics
| Revision:

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 @ 45647

History | View | Annotate | Download (14.2 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
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureReference;
36
import org.gvsig.fmap.dal.feature.FeatureStore;
37
import org.gvsig.fmap.dal.feature.FeatureType;
38 43840 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.DefaultFeature;
39 45647 fdiaz
import org.gvsig.fmap.dal.feature.impl.featurereference.FeatureReferenceFactory;
40 44871 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
41 40435 jjdelcerro
42
public class FeatureManager {
43 42639 dmartinezizquierdo
44 43840 jjdelcerro
    private int deltaSize;
45 43838 jjdelcerro
    private final ExpansionAdapter expansionAdapter;
46 43840 jjdelcerro
    private final Collection<FeatureReference> deleted;
47
    private final Map<FeatureReference, Integer> added;
48
    private final Map<FeatureReference, Integer> addedAndDeleted;
49
    private final Map<FeatureReference, Integer> modifiedFromOriginal;
50 45521 fdiaz
    private final Map<FeatureReference, Integer> original;
51 45647 fdiaz
    private final FeatureStore store;
52 43838 jjdelcerro
53 45647 fdiaz
    public FeatureManager(FeatureStore store) {
54 43840 jjdelcerro
        deltaSize = 0;
55
        expansionAdapter = new MemoryExpansionAdapter();
56
        deleted = new LinkedHashSet<>();
57
        added = new LinkedHashMap<>();
58
        addedAndDeleted = new LinkedHashMap<>();
59
        modifiedFromOriginal = new HashMap<>();
60 45521 fdiaz
        original = new HashMap<>();
61 45647 fdiaz
        this.store = store;
62 40435 jjdelcerro
    }
63
64 43838 jjdelcerro
    /**
65
     * Deletes feature from this manager.
66
     *
67
     * @param id
68
     * @return The deleted feature or null if the feature had not been edited or
69
     * previously added in the editing session
70
     */
71 45521 fdiaz
    public Feature delete(Feature feature) {
72
        FeatureReference id = feature.getReference();
73
        if(!original.containsKey(id)){
74
            int n = expansionAdapter.addObject(feature);
75
            original.put(id, n);
76
        }
77 40435 jjdelcerro
        deleted.add(id);
78 43838 jjdelcerro
        Integer num = added.remove(id);
79 45521 fdiaz
        Feature previousFeature = null;
80 43838 jjdelcerro
        if (num == null || num == -1) {
81
            num = modifiedFromOriginal.remove(id);
82 40435 jjdelcerro
            if (num != null) {
83 45521 fdiaz
                previousFeature = (Feature) expansionAdapter.getObject(num);
84 40435 jjdelcerro
            }
85
            // if num is null here, method returns null
86 43838 jjdelcerro
        } else {
87 45521 fdiaz
            previousFeature = (Feature) expansionAdapter.getObject(num);
88 43838 jjdelcerro
            addedAndDeleted.put(id, num);
89
        }
90 40435 jjdelcerro
        deltaSize--;
91 45521 fdiaz
        return previousFeature;
92 40435 jjdelcerro
    }
93
94
    public void add(Feature feature) {
95 45521 fdiaz
        FeatureReference id = feature.getReference();
96
        if(!original.containsKey(id)){
97
            original.put(id, null);
98
        }
99
100 40435 jjdelcerro
        int pos = expansionAdapter.addObject(feature);
101 43838 jjdelcerro
        added.put(feature.getReference(), pos);
102 40435 jjdelcerro
        deleted.remove(feature.getReference());
103
        deltaSize++;
104
    }
105
106
    public Feature deleteLastFeature() {
107
        expansionAdapter.deleteLastObject();
108 43838 jjdelcerro
        Feature feature = (Feature) expansionAdapter.getObject(expansionAdapter.getSize() - 1);
109 40435 jjdelcerro
        added.remove(feature.getReference());
110
        modifiedFromOriginal.remove(feature.getReference());
111
        deltaSize--;
112
        return feature;
113
    }
114 45647 fdiaz
115
    public DefaultFeature get(FeatureProvider data){
116
        FeatureReference ref = FeatureReferenceFactory.createFromFeatureProvider(store, data);
117
        try {
118
            return get(ref, store);
119
        } catch (DataException ex) {
120
            return null;
121
        }
122
    }
123 40435 jjdelcerro
124
    /**
125
     * Returns a Feature of the default type.
126
     *
127 43838 jjdelcerro
     * @param id the feature reference
128
     * @param store the store to get the feature from
129 40435 jjdelcerro
     * @return a Feature with the given reference
130 43838 jjdelcerro
     * @throws DataException if there is an error getting the Feature
131 40435 jjdelcerro
     */
132 45647 fdiaz
    public DefaultFeature get(FeatureReference id, FeatureStore store)
133 40435 jjdelcerro
            throws DataException {
134
        return get(id, store, null);
135
    }
136
137
    /**
138
     * Returns a Feature of the given type.
139
     *
140 43838 jjdelcerro
     * @param id the feature reference
141
     * @param store the store to get the feature from
142
     * @param featureType the type of the feature to return
143 40435 jjdelcerro
     * @return a Feature with the given reference
144 43838 jjdelcerro
     * @throws DataException if there is an error getting the Feature
145 40435 jjdelcerro
     */
146 45647 fdiaz
    public DefaultFeature get(FeatureReference id, FeatureStore store,
147 43838 jjdelcerro
            FeatureType featureType) throws DataException {
148
        // FIXME: y si el featuretype que paso esta modificado.
149
        //        Deberia buscarlo en el featuretypemanager ?
150
        //
151
        //        Si no existe feature con ese id... ? retorna null ?
152
        //        en EditedDefaultIterator se hace uso de ese comportamiento.
153
        //
154 45521 fdiaz
        boolean isNewFeature = false;
155 43838 jjdelcerro
        Integer intNum = (added.get(id));
156
        if (intNum == null) {
157
            intNum = (modifiedFromOriginal.get(id));
158
            if (intNum == null) {
159
                //If the feature has been added and deleted
160
                intNum = addedAndDeleted.get(id);
161
                if (intNum == null) {
162
                    return null;
163
                }
164
            }
165 45521 fdiaz
        } else {
166
            isNewFeature = true;
167 40435 jjdelcerro
        }
168 43838 jjdelcerro
        int num = intNum;
169
        if (num == -1) {
170
            return null;
171
        }
172
        Feature feature = (Feature) expansionAdapter.getObject(num);
173
        if (featureType == null) {
174
            featureType = store.getDefaultFeatureType();
175
        }
176 45521 fdiaz
        DefaultFeature feat = new DefaultFeature(featureType, feature);
177
        feat.getData().setNew(isNewFeature);
178
        return feat;
179 40435 jjdelcerro
    }
180
181
    public int update(Feature feature, Feature oldFeature) {
182 45521 fdiaz
        FeatureReference id = feature.getReference();
183
        if(!original.containsKey(id)){
184
            int n = expansionAdapter.addObject(oldFeature);
185
            original.put(id, n);
186
        }
187 43838 jjdelcerro
        int oldNum = -1;
188 40435 jjdelcerro
        int num = expansionAdapter.addObject(feature);
189 43838 jjdelcerro
        if (added.containsKey(id)) {
190
            oldNum = (added.get(id));
191
            added.put(id, num);
192
        } else {
193
            if (modifiedFromOriginal.get(id) != null) {
194
                oldNum = (modifiedFromOriginal.get(id));
195
            }
196
            modifiedFromOriginal.put(id, num);
197 40435 jjdelcerro
        }
198
        return oldNum;
199
    }
200
201
    public void restore(FeatureReference id) {
202
        deleted.remove(id);
203
        deltaSize++;
204
    }
205 43838 jjdelcerro
206
    public void restore(FeatureReference id, int num) {
207
        if (added.containsKey(id)) {
208
            added.put(id, num);
209
        } else {
210
            modifiedFromOriginal.put(id, num);
211 40435 jjdelcerro
        }
212
    }
213
214 43838 jjdelcerro
    public boolean isDeleted(Feature feature) {
215
        return deleted.contains(feature.getReference());
216 40435 jjdelcerro
    }
217
218 45647 fdiaz
    public boolean isDeleted(FeatureProvider data) {
219
        FeatureReference ref = FeatureReferenceFactory.createFromFeatureProvider(store, data);
220
        return deleted.contains(ref);
221
    }
222
223 40435 jjdelcerro
    public boolean isDeleted(FeatureReference featureID) {
224 43838 jjdelcerro
        return deleted.contains(featureID);
225
    }
226 40435 jjdelcerro
227 43838 jjdelcerro
    public void clear() {
228
        added.clear();
229
        modifiedFromOriginal.clear();
230
        expansionAdapter.close();
231
        deleted.clear();
232
        addedAndDeleted.clear();
233
        deltaSize = 0;
234
    }
235 40435 jjdelcerro
236 43838 jjdelcerro
    public boolean hasChanges() {
237
        return added.size() > 0 || modifiedFromOriginal.size() > 0 || deleted.size() > 0;
238
    }
239 40435 jjdelcerro
240 44111 jjdelcerro
    public long getPendingChangesCount() {
241
        long count = 0;
242
        if( this.added!=null ) {
243
            count += this.added.size();
244
        }
245
        if( this.deleted!=null ) {
246
            count += this.deleted.size();
247
        }
248
        if( this.modifiedFromOriginal!=null ) {
249
            count += this.modifiedFromOriginal.size();
250
        }
251
        return count;
252
    }
253
254 44871 jjdelcerro
    public Iterator<FeatureReference> getDeleted() {
255
        return new DeletedsFeatureReferencesIterator();
256 40435 jjdelcerro
257 44871 jjdelcerro
    }
258
259
    private class DeletedsFeatureReferencesIterator implements Iterator<FeatureReference> {
260
261 43838 jjdelcerro
        private Boolean hasnext = null;
262
        private final Iterator iter;
263 44871 jjdelcerro
        private FeatureReference reference;
264 40435 jjdelcerro
265 44871 jjdelcerro
        public DeletedsFeatureReferencesIterator() {
266 43838 jjdelcerro
            iter = deleted.iterator();
267
        }
268 40435 jjdelcerro
269 43838 jjdelcerro
        @Override
270
        public boolean hasNext() {
271
            if (hasnext != null) {
272
                return hasnext;
273
            }
274
            hasnext = false;
275
            while (iter.hasNext()) {
276 44871 jjdelcerro
                reference = (FeatureReference) iter.next();
277
                if (!reference.isNewFeature()) {
278
                  hasnext = true;
279
                  break;
280 43838 jjdelcerro
                }
281
            }
282
            return hasnext;
283
        }
284 40435 jjdelcerro
285 43838 jjdelcerro
        @Override
286 44871 jjdelcerro
        public FeatureReference next() {
287 43838 jjdelcerro
            if (!hasNext()) {
288
                throw new NoSuchElementException();
289
            }
290
            hasnext = null;
291 44871 jjdelcerro
            return reference;
292 43838 jjdelcerro
        }
293 40435 jjdelcerro
294 43838 jjdelcerro
        @Override
295
        public void remove() {
296
            throw new UnsupportedOperationException();
297
        }
298 40435 jjdelcerro
299 43838 jjdelcerro
    }
300 40435 jjdelcerro
301 44871 jjdelcerro
    public Iterator<FeatureProvider> getInserted() {
302
        Iterator<Feature> it = new InsertedFeaturesIterator();
303
        return new Iterator<FeatureProvider>() {
304
          @Override
305
          public boolean hasNext() {
306
            return it.hasNext();
307
          }
308
309
          @Override
310
          public FeatureProvider next() {
311
            return ((DefaultFeature)it.next()).getData();
312
          }
313
        };
314 43838 jjdelcerro
    }
315 40435 jjdelcerro
316 44871 jjdelcerro
    public Iterator<Feature> getInsertedFeatures() {
317
        return new InsertedFeaturesIterator();
318
    }
319 40435 jjdelcerro
320 44871 jjdelcerro
    private class InsertedFeaturesIterator implements Iterator<Feature> {
321
322 43838 jjdelcerro
        private final Iterator addedIter;
323 44871 jjdelcerro
        private Feature feature;
324 43838 jjdelcerro
        private Boolean hasnext = null;
325 40435 jjdelcerro
326 44871 jjdelcerro
        public InsertedFeaturesIterator() {
327 43838 jjdelcerro
            addedIter = added.values().iterator();
328
        }
329 40435 jjdelcerro
330 43838 jjdelcerro
        @Override
331
        public boolean hasNext() {
332
            if (hasnext != null) {
333
                return hasnext;
334
            }
335
            hasnext = false;
336
            int pos;
337
            while (addedIter.hasNext()) {
338
                pos = ((Integer) addedIter.next());
339 44871 jjdelcerro
                feature = (Feature) expansionAdapter.getObject(pos);
340
                if (!deleted.contains(feature.getReference())) {
341 43838 jjdelcerro
                    hasnext = true;
342
                    break;
343
                }
344
            }
345
            return hasnext;
346
        }
347 40435 jjdelcerro
348 43838 jjdelcerro
        @Override
349 44871 jjdelcerro
        public Feature next() {
350 43838 jjdelcerro
            if (!hasNext()) {
351
                throw new NoSuchElementException();
352
            }
353
            hasnext = null;
354 44871 jjdelcerro
            return feature;
355 43838 jjdelcerro
        }
356 40435 jjdelcerro
357 43838 jjdelcerro
        @Override
358
        public void remove() {
359
            addedIter.remove();
360
        }
361 40435 jjdelcerro
362 43838 jjdelcerro
    }
363 40435 jjdelcerro
364 44871 jjdelcerro
    public Iterator<Feature> getUpdatedFeatures() {
365
        return new UpdatedFeaturesIterator();
366 43838 jjdelcerro
    }
367 40435 jjdelcerro
368 44871 jjdelcerro
    public Iterator<FeatureProvider> getUpdated() {
369
        Iterator<Feature> it = new UpdatedFeaturesIterator();
370
        return new Iterator<FeatureProvider>() {
371
          @Override
372
          public boolean hasNext() {
373
            return it.hasNext();
374
          }
375 40435 jjdelcerro
376 44871 jjdelcerro
          @Override
377
          public FeatureProvider next() {
378
            return ((DefaultFeature)it.next()).getData();
379
          }
380
        };
381
    }
382
383
    private class UpdatedFeaturesIterator implements Iterator<Feature> {
384
385 43838 jjdelcerro
        private Boolean hasnext = null;
386
        private final Iterator iter;
387 44871 jjdelcerro
        private Feature feature;
388 43838 jjdelcerro
        private int pos;
389 40435 jjdelcerro
390 44871 jjdelcerro
        public UpdatedFeaturesIterator() {
391 43838 jjdelcerro
            iter = expansionAdapter.iterator();
392
            pos = -1;
393
        }
394 40435 jjdelcerro
395 43838 jjdelcerro
        @Override
396
        public boolean hasNext() {
397
            if (hasnext != null) {
398
                return hasnext;
399
            }
400
            hasnext = false;
401
            while (iter.hasNext()) {
402
                pos++;
403 44871 jjdelcerro
                feature = (Feature) iter.next();
404 45521 fdiaz
                if ( feature != null &&
405
                     !deleted.contains(feature.getReference()) &&
406 44871 jjdelcerro
                     modifiedFromOriginal.containsValue(pos)) {
407 43838 jjdelcerro
                    hasnext = true;
408
                    break;
409
                }
410
            }
411
            return hasnext;
412
        }
413 40435 jjdelcerro
414 43838 jjdelcerro
        @Override
415 44871 jjdelcerro
        public Feature next() {
416 43838 jjdelcerro
            if (!hasNext()) {
417
                throw new NoSuchElementException();
418
            }
419
            hasnext = null;
420 44871 jjdelcerro
            return feature;
421 43838 jjdelcerro
        }
422 40435 jjdelcerro
423 43838 jjdelcerro
        @Override
424
        public void remove() {
425
            throw new UnsupportedOperationException();
426 40435 jjdelcerro
427 43838 jjdelcerro
        }
428
    }
429 40435 jjdelcerro
430 43838 jjdelcerro
    public boolean hasNews() {
431
        return !added.isEmpty();
432
    }
433 42639 dmartinezizquierdo
434 43838 jjdelcerro
    public long getDeltaSize() {
435
        return deltaSize;
436
    }
437
438 42639 dmartinezizquierdo
    /**
439
     * Indicates if any operation has comprimised the selected features.
440 43838 jjdelcerro
     *
441 42639 dmartinezizquierdo
     * @return
442
     */
443
    public boolean isSelectionCompromised() {
444
        //Only deleted features can change order, as added features are added at the end.
445 43838 jjdelcerro
        return deleted.size() > 0;
446 42639 dmartinezizquierdo
    }
447 45521 fdiaz
448
    public Feature getOriginal(FeatureReference id){
449
        Integer n = original.get(id);
450
        if(n == null){
451
            return null;
452
        }
453
        return (Feature) this.expansionAdapter.getObject(n);
454
    }
455
456
    public boolean isFeatureModified(FeatureReference id) {
457
        return original.containsKey(id);
458
    }
459
460 40435 jjdelcerro
}