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

History | View | Annotate | Download (12.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

    
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

    
51
    public FeatureManager() {
52
        deltaSize = 0;
53
        expansionAdapter = new MemoryExpansionAdapter();
54
        deleted = new LinkedHashSet<>();
55
        added = new LinkedHashMap<>();
56
        addedAndDeleted = new LinkedHashMap<>();
57
        modifiedFromOriginal = new HashMap<>();
58
    }
59

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

    
85
    public void add(Feature feature) {
86
        int pos = expansionAdapter.addObject(feature);
87
        added.put(feature.getReference(), pos);
88
        deleted.remove(feature.getReference());
89
        deltaSize++;
90
    }
91

    
92
    public Feature deleteLastFeature() {
93
        expansionAdapter.deleteLastObject();
94
        Feature feature = (Feature) expansionAdapter.getObject(expansionAdapter.getSize() - 1);
95
        added.remove(feature.getReference());
96
        modifiedFromOriginal.remove(feature.getReference());
97
        deltaSize--;
98
        return feature;
99
    }
100

    
101
    /**
102
     * Returns a Feature of the default type.
103
     *
104
     * @param id the feature reference
105
     * @param store the store to get the feature from
106
     * @return a Feature with the given reference
107
     * @throws DataException if there is an error getting the Feature
108
     */
109
    public Feature get(FeatureReference id, FeatureStore store)
110
            throws DataException {
111
        return get(id, store, null);
112
    }
113

    
114
    /**
115
     * Returns a Feature of the given type.
116
     *
117
     * @param id the feature reference
118
     * @param store the store to get the feature from
119
     * @param featureType the type of the feature to return
120
     * @return a Feature with the given reference
121
     * @throws DataException if there is an error getting the Feature
122
     */
123
    public Feature get(FeatureReference id, FeatureStore store,
124
            FeatureType featureType) throws DataException {
125
        // FIXME: y si el featuretype que paso esta modificado.
126
        //        Deberia buscarlo en el featuretypemanager ?
127
        //
128
        //        Si no existe feature con ese id... ? retorna null ?
129
        //        en EditedDefaultIterator se hace uso de ese comportamiento.
130
        //
131
        Integer intNum = (added.get(id));
132
        if (intNum == null) {
133
            intNum = (modifiedFromOriginal.get(id));
134
            if (intNum == null) {
135
                //If the feature has been added and deleted
136
                intNum = addedAndDeleted.get(id);
137
                if (intNum == null) {
138
                    return null;
139
                }
140
            }
141
        }
142
        int num = intNum;
143
        if (num == -1) {
144
            return null;
145
        }
146
        Feature feature = (Feature) expansionAdapter.getObject(num);
147
        if (featureType == null) {
148
            featureType = store.getDefaultFeatureType();
149
        }
150
        return new DefaultFeature(featureType, feature);
151
    }
152

    
153
    public int update(Feature feature, Feature oldFeature) {
154
        int oldNum = -1;
155
        int num = expansionAdapter.addObject(feature);
156
        FeatureReference id = feature.getReference();
157
        if (added.containsKey(id)) {
158
            oldNum = (added.get(id));
159
            added.put(id, num);
160
        } else {
161
            if (modifiedFromOriginal.get(id) != null) {
162
                oldNum = (modifiedFromOriginal.get(id));
163
            }
164
            modifiedFromOriginal.put(id, num);
165
        }
166
        return oldNum;
167
    }
168

    
169
    public void restore(FeatureReference id) {
170
        deleted.remove(id);
171
        deltaSize++;
172
    }
173

    
174
    public void restore(FeatureReference id, int num) {
175
        if (added.containsKey(id)) {
176
            added.put(id, num);
177
        } else {
178
            modifiedFromOriginal.put(id, num);
179
        }
180
    }
181

    
182
    public boolean isDeleted(Feature feature) {
183
        return deleted.contains(feature.getReference());
184
    }
185

    
186
    public boolean isDeleted(FeatureReference featureID) {
187
        return deleted.contains(featureID);
188
    }
189

    
190
    public void clear() {
191
        added.clear();
192
        modifiedFromOriginal.clear();
193
        expansionAdapter.close();
194
        deleted.clear();
195
        addedAndDeleted.clear();
196
        deltaSize = 0;
197
    }
198

    
199
    public boolean hasChanges() {
200
        return added.size() > 0 || modifiedFromOriginal.size() > 0 || deleted.size() > 0;
201
    }
202

    
203
    public long getPendingChangesCount() {
204
        long count = 0;
205
        if( this.added!=null ) {
206
            count += this.added.size();
207
        }
208
        if( this.deleted!=null ) {
209
            count += this.deleted.size();
210
        }
211
        if( this.modifiedFromOriginal!=null ) {
212
            count += this.modifiedFromOriginal.size();
213
        }
214
        return count;
215
    }
216

    
217
    public Iterator<FeatureReference> getDeleted() {
218
        return new DeletedsFeatureReferencesIterator();
219

    
220
    }
221

    
222
    private class DeletedsFeatureReferencesIterator implements Iterator<FeatureReference> {
223

    
224
        private Boolean hasnext = null;
225
        private final Iterator iter;
226
        private FeatureReference reference;
227

    
228
        public DeletedsFeatureReferencesIterator() {
229
            iter = deleted.iterator();
230
        }
231

    
232
        @Override
233
        public boolean hasNext() {
234
            if (hasnext != null) {
235
                return hasnext;
236
            }
237
            hasnext = false;
238
            while (iter.hasNext()) {
239
                reference = (FeatureReference) iter.next();
240
                if (!reference.isNewFeature()) {
241
                  hasnext = true;
242
                  break;
243
                }
244
            }
245
            return hasnext;
246
        }
247

    
248
        @Override
249
        public FeatureReference next() {
250
            if (!hasNext()) {
251
                throw new NoSuchElementException();
252
            }
253
            hasnext = null;
254
            return reference;
255
        }
256

    
257
        @Override
258
        public void remove() {
259
            throw new UnsupportedOperationException();
260
        }
261

    
262
    }
263

    
264
    public Iterator<FeatureProvider> getInserted() {
265
        Iterator<Feature> it = new InsertedFeaturesIterator();
266
        return new Iterator<FeatureProvider>() {
267
          @Override
268
          public boolean hasNext() {
269
            return it.hasNext();
270
          }
271

    
272
          @Override
273
          public FeatureProvider next() {
274
            return ((DefaultFeature)it.next()).getData();
275
          }
276
        };
277
    }
278

    
279
    public Iterator<Feature> getInsertedFeatures() {
280
        return new InsertedFeaturesIterator();
281
    }
282

    
283
    private class InsertedFeaturesIterator implements Iterator<Feature> {
284

    
285
        private final Iterator addedIter;
286
        private Feature feature;
287
        private Boolean hasnext = null;
288

    
289
        public InsertedFeaturesIterator() {
290
            addedIter = added.values().iterator();
291
        }
292

    
293
        @Override
294
        public boolean hasNext() {
295
            if (hasnext != null) {
296
                return hasnext;
297
            }
298
            hasnext = false;
299
            int pos;
300
            while (addedIter.hasNext()) {
301
                pos = ((Integer) addedIter.next());
302
                feature = (Feature) expansionAdapter.getObject(pos);
303
                if (!deleted.contains(feature.getReference())) {
304
                    hasnext = true;
305
                    break;
306
                }
307
            }
308
            return hasnext;
309
        }
310

    
311
        @Override
312
        public Feature next() {
313
            if (!hasNext()) {
314
                throw new NoSuchElementException();
315
            }
316
            hasnext = null;
317
            return feature;
318
        }
319

    
320
        @Override
321
        public void remove() {
322
            addedIter.remove();
323
        }
324

    
325
    }
326

    
327
    public Iterator<Feature> getUpdatedFeatures() {
328
        return new UpdatedFeaturesIterator();
329
    }
330

    
331
    public Iterator<FeatureProvider> getUpdated() {
332
        Iterator<Feature> it = new UpdatedFeaturesIterator();
333
        return new Iterator<FeatureProvider>() {
334
          @Override
335
          public boolean hasNext() {
336
            return it.hasNext();
337
          }
338

    
339
          @Override
340
          public FeatureProvider next() {
341
            return ((DefaultFeature)it.next()).getData();
342
          }
343
        };
344
    }
345

    
346
    private class UpdatedFeaturesIterator implements Iterator<Feature> {
347

    
348
        private Boolean hasnext = null;
349
        private final Iterator iter;
350
        private Feature feature;
351
        private int pos;
352

    
353
        public UpdatedFeaturesIterator() {
354
            iter = expansionAdapter.iterator();
355
            pos = -1;
356
        }
357

    
358
        @Override
359
        public boolean hasNext() {
360
            if (hasnext != null) {
361
                return hasnext;
362
            }
363
            hasnext = false;
364
            while (iter.hasNext()) {
365
                pos++;
366
                feature = (Feature) iter.next();
367
                if ( !deleted.contains(feature.getReference()) &&
368
                     modifiedFromOriginal.containsValue(pos)) {
369
                    hasnext = true;
370
                    break;
371
                }
372
            }
373
            return hasnext;
374
        }
375

    
376
        @Override
377
        public Feature next() {
378
            if (!hasNext()) {
379
                throw new NoSuchElementException();
380
            }
381
            hasnext = null;
382
            return feature;
383
        }
384

    
385
        @Override
386
        public void remove() {
387
            throw new UnsupportedOperationException();
388

    
389
        }
390
    }
391

    
392
    public boolean hasNews() {
393
        return !added.isEmpty();
394
    }
395

    
396
    public long getDeltaSize() {
397
        return deltaSize;
398
    }
399

    
400
    /**
401
     * Indicates if any operation has comprimised the selected features.
402
     *
403
     * @return
404
     */
405
    public boolean isSelectionCompromised() {
406
        //Only deleted features can change order, as added features are added at the end.
407
        return deleted.size() > 0;
408
    }
409
}