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

History | View | Annotate | Download (13.6 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.feature.impl.editing.memory;
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.DefaultFeature;
40
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
41

    
42
public class FeatureManager {
43

    
44
    private int deltaSize;
45
    private final ExpansionAdapter expansionAdapter;
46
    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
    private final Map<FeatureReference, Integer> original;
51

    
52
    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
        original = new HashMap<>();
60
    }
61

    
62
    /**
63
     * Deletes feature from this manager.
64
     *
65
     * @param id
66
     * @return The deleted feature or null if the feature had not been edited or
67
     * previously added in the editing session
68
     */
69
    public Feature delete(Feature feature) {
70
        FeatureReference id = feature.getReference();
71
        if(!original.containsKey(id)){
72
            int n = expansionAdapter.addObject(feature);
73
            original.put(id, n);
74
        }
75
        deleted.add(id);
76
        Integer num = added.remove(id);
77
        Feature previousFeature = null;
78
        if (num == null || num == -1) {
79
            num = modifiedFromOriginal.remove(id);
80
            if (num != null) {
81
                previousFeature = (Feature) expansionAdapter.getObject(num);
82
            }
83
            // if num is null here, method returns null
84
        } else {
85
            previousFeature = (Feature) expansionAdapter.getObject(num);
86
            addedAndDeleted.put(id, num);
87
        }
88
        deltaSize--;
89
        return previousFeature;
90
    }
91

    
92
    public void add(Feature feature) {
93
        FeatureReference id = feature.getReference();
94
        if(!original.containsKey(id)){
95
            original.put(id, null);
96
        }
97

    
98
        int pos = expansionAdapter.addObject(feature);
99
        added.put(feature.getReference(), pos);
100
        deleted.remove(feature.getReference());
101
        deltaSize++;
102
    }
103

    
104
    public Feature deleteLastFeature() {
105
        expansionAdapter.deleteLastObject();
106
        Feature feature = (Feature) expansionAdapter.getObject(expansionAdapter.getSize() - 1);
107
        added.remove(feature.getReference());
108
        modifiedFromOriginal.remove(feature.getReference());
109
        deltaSize--;
110
        return feature;
111
    }
112

    
113
    /**
114
     * Returns a Feature of the default type.
115
     *
116
     * @param id the feature reference
117
     * @param store the store to get the feature from
118
     * @return a Feature with the given reference
119
     * @throws DataException if there is an error getting the Feature
120
     */
121
    public Feature get(FeatureReference id, FeatureStore store)
122
            throws DataException {
123
        return get(id, store, null);
124
    }
125

    
126
    /**
127
     * Returns a Feature of the given type.
128
     *
129
     * @param id the feature reference
130
     * @param store the store to get the feature from
131
     * @param featureType the type of the feature to return
132
     * @return a Feature with the given reference
133
     * @throws DataException if there is an error getting the Feature
134
     */
135
    public Feature get(FeatureReference id, FeatureStore store,
136
            FeatureType featureType) throws DataException {
137
        // FIXME: y si el featuretype que paso esta modificado.
138
        //        Deberia buscarlo en el featuretypemanager ?
139
        //
140
        //        Si no existe feature con ese id... ? retorna null ?
141
        //        en EditedDefaultIterator se hace uso de ese comportamiento.
142
        //
143
        boolean isNewFeature = false;
144
        Integer intNum = (added.get(id));
145
        if (intNum == null) {
146
            intNum = (modifiedFromOriginal.get(id));
147
            if (intNum == null) {
148
                //If the feature has been added and deleted
149
                intNum = addedAndDeleted.get(id);
150
                if (intNum == null) {
151
                    return null;
152
                }
153
            }
154
        } else {
155
            isNewFeature = true;
156
        }
157
        int num = intNum;
158
        if (num == -1) {
159
            return null;
160
        }
161
        Feature feature = (Feature) expansionAdapter.getObject(num);
162
        if (featureType == null) {
163
            featureType = store.getDefaultFeatureType();
164
        }
165
        DefaultFeature feat = new DefaultFeature(featureType, feature);
166
        feat.getData().setNew(isNewFeature);
167
        return feat;
168
    }
169

    
170
    public int update(Feature feature, Feature oldFeature) {
171
        FeatureReference id = feature.getReference();
172
        if(!original.containsKey(id)){
173
            int n = expansionAdapter.addObject(oldFeature);
174
            original.put(id, n);
175
        }
176
        int oldNum = -1;
177
        int num = expansionAdapter.addObject(feature);
178
        if (added.containsKey(id)) {
179
            oldNum = (added.get(id));
180
            added.put(id, num);
181
        } else {
182
            if (modifiedFromOriginal.get(id) != null) {
183
                oldNum = (modifiedFromOriginal.get(id));
184
            }
185
            modifiedFromOriginal.put(id, num);
186
        }
187
        return oldNum;
188
    }
189

    
190
    public void restore(FeatureReference id) {
191
        deleted.remove(id);
192
        deltaSize++;
193
    }
194

    
195
    public void restore(FeatureReference id, int num) {
196
        if (added.containsKey(id)) {
197
            added.put(id, num);
198
        } else {
199
            modifiedFromOriginal.put(id, num);
200
        }
201
    }
202

    
203
    public boolean isDeleted(Feature feature) {
204
        return deleted.contains(feature.getReference());
205
    }
206

    
207
    public boolean isDeleted(FeatureReference featureID) {
208
        return deleted.contains(featureID);
209
    }
210

    
211
    public void clear() {
212
        added.clear();
213
        modifiedFromOriginal.clear();
214
        expansionAdapter.close();
215
        deleted.clear();
216
        addedAndDeleted.clear();
217
        deltaSize = 0;
218
    }
219

    
220
    public boolean hasChanges() {
221
        return added.size() > 0 || modifiedFromOriginal.size() > 0 || deleted.size() > 0;
222
    }
223

    
224
    public long getPendingChangesCount() {
225
        long count = 0;
226
        if( this.added!=null ) {
227
            count += this.added.size();
228
        }
229
        if( this.deleted!=null ) {
230
            count += this.deleted.size();
231
        }
232
        if( this.modifiedFromOriginal!=null ) {
233
            count += this.modifiedFromOriginal.size();
234
        }
235
        return count;
236
    }
237

    
238
    public Iterator<FeatureReference> getDeleted() {
239
        return new DeletedsFeatureReferencesIterator();
240

    
241
    }
242

    
243
    private class DeletedsFeatureReferencesIterator implements Iterator<FeatureReference> {
244

    
245
        private Boolean hasnext = null;
246
        private final Iterator iter;
247
        private FeatureReference reference;
248

    
249
        public DeletedsFeatureReferencesIterator() {
250
            iter = deleted.iterator();
251
        }
252

    
253
        @Override
254
        public boolean hasNext() {
255
            if (hasnext != null) {
256
                return hasnext;
257
            }
258
            hasnext = false;
259
            while (iter.hasNext()) {
260
                reference = (FeatureReference) iter.next();
261
                if (!reference.isNewFeature()) {
262
                  hasnext = true;
263
                  break;
264
                }
265
            }
266
            return hasnext;
267
        }
268

    
269
        @Override
270
        public FeatureReference next() {
271
            if (!hasNext()) {
272
                throw new NoSuchElementException();
273
            }
274
            hasnext = null;
275
            return reference;
276
        }
277

    
278
        @Override
279
        public void remove() {
280
            throw new UnsupportedOperationException();
281
        }
282

    
283
    }
284

    
285
    public Iterator<FeatureProvider> getInserted() {
286
        Iterator<Feature> it = new InsertedFeaturesIterator();
287
        return new Iterator<FeatureProvider>() {
288
          @Override
289
          public boolean hasNext() {
290
            return it.hasNext();
291
          }
292

    
293
          @Override
294
          public FeatureProvider next() {
295
            return ((DefaultFeature)it.next()).getData();
296
          }
297
        };
298
    }
299

    
300
    public Iterator<Feature> getInsertedFeatures() {
301
        return new InsertedFeaturesIterator();
302
    }
303

    
304
    private class InsertedFeaturesIterator implements Iterator<Feature> {
305

    
306
        private final Iterator addedIter;
307
        private Feature feature;
308
        private Boolean hasnext = null;
309

    
310
        public InsertedFeaturesIterator() {
311
            addedIter = added.values().iterator();
312
        }
313

    
314
        @Override
315
        public boolean hasNext() {
316
            if (hasnext != null) {
317
                return hasnext;
318
            }
319
            hasnext = false;
320
            int pos;
321
            while (addedIter.hasNext()) {
322
                pos = ((Integer) addedIter.next());
323
                feature = (Feature) expansionAdapter.getObject(pos);
324
                if (!deleted.contains(feature.getReference())) {
325
                    hasnext = true;
326
                    break;
327
                }
328
            }
329
            return hasnext;
330
        }
331

    
332
        @Override
333
        public Feature next() {
334
            if (!hasNext()) {
335
                throw new NoSuchElementException();
336
            }
337
            hasnext = null;
338
            return feature;
339
        }
340

    
341
        @Override
342
        public void remove() {
343
            addedIter.remove();
344
        }
345

    
346
    }
347

    
348
    public Iterator<Feature> getUpdatedFeatures() {
349
        return new UpdatedFeaturesIterator();
350
    }
351

    
352
    public Iterator<FeatureProvider> getUpdated() {
353
        Iterator<Feature> it = new UpdatedFeaturesIterator();
354
        return new Iterator<FeatureProvider>() {
355
          @Override
356
          public boolean hasNext() {
357
            return it.hasNext();
358
          }
359

    
360
          @Override
361
          public FeatureProvider next() {
362
            return ((DefaultFeature)it.next()).getData();
363
          }
364
        };
365
    }
366

    
367
    private class UpdatedFeaturesIterator implements Iterator<Feature> {
368

    
369
        private Boolean hasnext = null;
370
        private final Iterator iter;
371
        private Feature feature;
372
        private int pos;
373

    
374
        public UpdatedFeaturesIterator() {
375
            iter = expansionAdapter.iterator();
376
            pos = -1;
377
        }
378

    
379
        @Override
380
        public boolean hasNext() {
381
            if (hasnext != null) {
382
                return hasnext;
383
            }
384
            hasnext = false;
385
            while (iter.hasNext()) {
386
                pos++;
387
                feature = (Feature) iter.next();
388
                if ( feature != null &&
389
                     !deleted.contains(feature.getReference()) &&
390
                     modifiedFromOriginal.containsValue(pos)) {
391
                    hasnext = true;
392
                    break;
393
                }
394
            }
395
            return hasnext;
396
        }
397

    
398
        @Override
399
        public Feature next() {
400
            if (!hasNext()) {
401
                throw new NoSuchElementException();
402
            }
403
            hasnext = null;
404
            return feature;
405
        }
406

    
407
        @Override
408
        public void remove() {
409
            throw new UnsupportedOperationException();
410

    
411
        }
412
    }
413

    
414
    public boolean hasNews() {
415
        return !added.isEmpty();
416
    }
417

    
418
    public long getDeltaSize() {
419
        return deltaSize;
420
    }
421

    
422
    /**
423
     * Indicates if any operation has comprimised the selected features.
424
     *
425
     * @return
426
     */
427
    public boolean isSelectionCompromised() {
428
        //Only deleted features can change order, as added features are added at the end.
429
        return deleted.size() > 0;
430
    }
431
    
432
    public Feature getOriginal(FeatureReference id){
433
        Integer n = original.get(id);
434
        if(n == null){
435
            return null;
436
        }
437
        return (Feature) this.expansionAdapter.getObject(n);
438
    }
439
    
440
    public boolean isFeatureModified(FeatureReference id) {
441
        return original.containsKey(id);
442
    }
443
    
444
}