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

History | View | Annotate | Download (14.4 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
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.EditableFeature;
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.impl.featurereference.FeatureReferenceFactory;
41
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
42

    
43
public class FeatureManager {
44

    
45
    private int deltaSize;
46
    private final ExpansionAdapter expansionAdapter;
47
    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
    private final Map<FeatureReference, Integer> original;
52
    private final FeatureStore store;
53

    
54
    public FeatureManager(FeatureStore store) {
55
        deltaSize = 0;
56
        expansionAdapter = new MemoryExpansionAdapter();
57
        deleted = new LinkedHashSet<>();
58
        added = new LinkedHashMap<>();
59
        addedAndDeleted = new LinkedHashMap<>();
60
        modifiedFromOriginal = new HashMap<>();
61
        original = new HashMap<>();
62
        this.store = store;
63
    }
64

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

    
95
    public void add(EditableFeature feature) {
96
        FeatureReference id = feature.getReference();
97
        if(!original.containsKey(id)){
98
            original.put(id, null);
99
        }
100

    
101
        int pos = expansionAdapter.addObject(feature);
102
        added.put(feature.getReference(), pos);
103
        deleted.remove(feature.getReference());
104
        deltaSize++;
105
    }
106

    
107
    public Feature deleteLastFeature() {
108
        expansionAdapter.deleteLastObject();
109
        Feature feature = (Feature) expansionAdapter.getObject(expansionAdapter.getSize() - 1);
110
        added.remove(feature.getReference());
111
        modifiedFromOriginal.remove(feature.getReference());
112
        deltaSize--;
113
        return feature;
114
    }
115
    
116
    public DefaultFeature get(FeatureProvider data){
117
        FeatureReference ref = FeatureReferenceFactory.createFromFeatureProvider(store, data);
118
        try {
119
            return get(ref, store);
120
        } catch (DataException ex) {
121
            return null;
122
        }
123
    }
124

    
125
    /**
126
     * Returns a Feature of the default type.
127
     *
128
     * @param id the feature reference
129
     * @param store the store to get the feature from
130
     * @return a Feature with the given reference
131
     * @throws DataException if there is an error getting the Feature
132
     */
133
    public DefaultFeature get(FeatureReference id, FeatureStore store)
134
            throws DataException {
135
        return get(id, store, null);
136
    }
137

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

    
182
    public int update(EditableFeature feature, Feature oldFeature) {
183
        FeatureReference id = feature.getReference();
184
        if(!original.containsKey(id)){
185
            int n = expansionAdapter.addObject(oldFeature);
186
            original.put(id, n);
187
        }
188
        int oldNum = -1;
189
        int num = expansionAdapter.addObject(feature);
190
        if (added.containsKey(id)) {
191
            oldNum = (added.get(id));
192
            added.put(id, num);
193
        } else {
194
            if (modifiedFromOriginal.get(id) != null) {
195
                oldNum = (modifiedFromOriginal.get(id));
196
            }
197
            modifiedFromOriginal.put(id, num);
198
        }
199
        return oldNum;
200
    }
201

    
202
    public void restore(FeatureReference id) {
203
        deleted.remove(id);
204
        deltaSize++;
205
    }
206

    
207
    public void restore(FeatureReference id, int num) {
208
        if (added.containsKey(id)) {
209
            added.put(id, num);
210
        } else {
211
            modifiedFromOriginal.put(id, num);
212
        }
213
    }
214

    
215
    public boolean isDeleted(Feature feature) {
216
        return deleted.contains(feature.getReference());
217
    }
218

    
219
    public boolean isDeleted(FeatureProvider data) {
220
        FeatureReference ref = FeatureReferenceFactory.createFromFeatureProvider(store, data);
221
        return deleted.contains(ref);
222
    }
223

    
224
    public boolean isDeleted(FeatureReference featureID) {
225
        return deleted.contains(featureID);
226
    }
227

    
228
    public void clear() {
229
        added.clear();
230
        modifiedFromOriginal.clear();
231
        expansionAdapter.close();
232
        deleted.clear();
233
        addedAndDeleted.clear();
234
        deltaSize = 0;
235
    }
236

    
237
    public boolean hasChanges() {
238
        return added.size() > 0 || modifiedFromOriginal.size() > 0 || deleted.size() > 0;
239
    }
240

    
241
    public long getPendingChangesCount() {
242
        long count = 0;
243
        if( this.added!=null ) {
244
            count += this.added.size();
245
        }
246
        if( this.deleted!=null ) {
247
            count += this.deleted.size();
248
        }
249
        if( this.modifiedFromOriginal!=null ) {
250
            count += this.modifiedFromOriginal.size();
251
        }
252
        return count;
253
    }
254

    
255
    public Iterator<FeatureReference> getDeleted() {
256
        return new DeletedsFeatureReferencesIterator();
257

    
258
    }
259

    
260
    private class DeletedsFeatureReferencesIterator implements Iterator<FeatureReference> {
261

    
262
        private Boolean hasnext = null;
263
        private final Iterator iter;
264
        private FeatureReference reference;
265

    
266
        public DeletedsFeatureReferencesIterator() {
267
            iter = deleted.iterator();
268
        }
269

    
270
        @Override
271
        public boolean hasNext() {
272
            if (hasnext != null) {
273
                return hasnext;
274
            }
275
            hasnext = false;
276
            while (iter.hasNext()) {
277
                reference = (FeatureReference) iter.next();
278
                if (!reference.isNewFeature()) {
279
                  hasnext = true;
280
                  break;
281
                }
282
            }
283
            return hasnext;
284
        }
285

    
286
        @Override
287
        public FeatureReference next() {
288
            if (!hasNext()) {
289
                throw new NoSuchElementException();
290
            }
291
            hasnext = null;
292
            return reference;
293
        }
294

    
295
        @Override
296
        public void remove() {
297
            throw new UnsupportedOperationException();
298
        }
299

    
300
    }
301

    
302
    public Iterator<FeatureProvider> getInserted() {
303
        Iterator<EditableFeature> it = new InsertedFeaturesIterator();
304
        return new Iterator<FeatureProvider>() {
305
          @Override
306
          public boolean hasNext() {
307
            return it.hasNext();
308
          }
309

    
310
          @Override
311
          public FeatureProvider next() {
312
            return ((DefaultFeature)it.next()).getData();
313
          }
314
        };
315
    }
316

    
317
    public Iterator<EditableFeature> getInsertedFeatures() {
318
        return new InsertedFeaturesIterator();
319
    }
320

    
321
    private class InsertedFeaturesIterator implements Iterator<EditableFeature> {
322

    
323
        private final Iterator addedIter;
324
        private EditableFeature feature;
325
        private Boolean hasnext = null;
326

    
327
        public InsertedFeaturesIterator() {
328
            addedIter = added.values().iterator();
329
        }
330

    
331
        @Override
332
        public boolean hasNext() {
333
            if (hasnext != null) {
334
                return hasnext;
335
            }
336
            hasnext = false;
337
            int pos;
338
            while (addedIter.hasNext()) {
339
                pos = ((Integer) addedIter.next());
340
                feature = (EditableFeature) expansionAdapter.getObject(pos);
341
                if (!deleted.contains(feature.getReference())) {
342
                    hasnext = true;
343
                    break;
344
                }
345
            }
346
            return hasnext;
347
        }
348

    
349
        @Override
350
        public EditableFeature next() {
351
            if (!hasNext()) {
352
                throw new NoSuchElementException();
353
            }
354
            hasnext = null;
355
            return feature;
356
        }
357

    
358
        @Override
359
        public void remove() {
360
            addedIter.remove();
361
        }
362

    
363
    }
364

    
365
    public Iterator<EditableFeature> getUpdatedFeatures() {
366
        return new UpdatedFeaturesIterator();
367
    }
368

    
369
    public Iterator<FeatureProvider> getUpdated() {
370
        Iterator<EditableFeature> it = new UpdatedFeaturesIterator();
371
        return new Iterator<FeatureProvider>() {
372
          @Override
373
          public boolean hasNext() {
374
            return it.hasNext();
375
          }
376

    
377
          @Override
378
          public FeatureProvider next() {
379
            return ((DefaultFeature)it.next()).getData();
380
          }
381
        };
382
    }
383

    
384
    private class UpdatedFeaturesIterator implements Iterator<EditableFeature> {
385

    
386
        private Boolean hasnext = null;
387
        private final Iterator iter;
388
        private EditableFeature feature;
389
        private int pos;
390

    
391
        public UpdatedFeaturesIterator() {
392
            iter = expansionAdapter.iterator();
393
            pos = -1;
394
        }
395

    
396
        @Override
397
        public boolean hasNext() {
398
            if (hasnext != null) {
399
                return hasnext;
400
            }
401
            hasnext = false;
402
            while (iter.hasNext()) {
403
                pos++;
404
                Feature f = (Feature) iter.next();
405
                if ( f != null &&
406
                     !deleted.contains(f.getReference()) &&
407
                     modifiedFromOriginal.containsValue(pos)) {
408
                    hasnext = true;
409
                    feature = (EditableFeature) f;
410
                    break;
411
                }
412
            }
413
            return hasnext;
414
        }
415

    
416
        @Override
417
        public EditableFeature next() {
418
            if (!hasNext()) {
419
                throw new NoSuchElementException();
420
            }
421
            hasnext = null;
422
            return feature;
423
        }
424

    
425
        @Override
426
        public void remove() {
427
            throw new UnsupportedOperationException();
428

    
429
        }
430
    }
431

    
432
    public boolean hasNews() {
433
        return !added.isEmpty();
434
    }
435

    
436
    public long getDeltaSize() {
437
        return deltaSize;
438
    }
439

    
440
    /**
441
     * Indicates if any operation has comprimised the selected features.
442
     *
443
     * @return
444
     */
445
    public boolean isSelectionCompromised() {
446
        //Only deleted features can change order, as added features are added at the end.
447
        return !deleted.isEmpty() || !added.isEmpty();
448
    }
449
    
450
    public Feature getOriginal(FeatureReference id){
451
        Integer n = original.get(id);
452
        if(n == null){
453
            return null;
454
        }
455
        return (Feature) this.expansionAdapter.getObject(n);
456
    }
457
    
458
    public boolean isFeatureModified(FeatureReference id) {
459
        return original.containsKey(id);
460
    }
461
    
462
}