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

History | View | Annotate | Download (11.5 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.impl.DefaultFeatureReference;
41

    
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

    
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
    }
60

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

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

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

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

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

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

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

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

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

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

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

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

    
204
    public Iterator getDeleted() {
205
        return new DeletedIterator();
206

    
207
    }
208

    
209
    public long getPendingChangesCount() {
210
        long count = 0;
211
        if( this.added!=null ) {
212
            count += this.added.size();
213
        }
214
        if( this.deleted!=null ) {
215
            count += this.deleted.size();
216
        }
217
        if( this.modifiedFromOriginal!=null ) {
218
            count += this.modifiedFromOriginal.size();
219
        }
220
        return count;
221
    }
222

    
223
    private class DeletedIterator implements Iterator {
224

    
225
        private Boolean hasnext = null;
226
        private final Iterator iter;
227
        private DefaultFeatureReference obj;
228

    
229
        public DeletedIterator() {
230
            iter = deleted.iterator();
231
        }
232

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

    
250
        @Override
251
        public Object next() {
252
            if (!hasNext()) {
253
                throw new NoSuchElementException();
254
            }
255
            hasnext = null;
256
            return obj;
257
        }
258

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

    
264
    }
265

    
266
    public Iterator getInserted() {
267
        return new InsertedIterator();
268
    }
269

    
270
    private class InsertedIterator implements Iterator {
271

    
272
        private final Iterator addedIter;
273
        private DefaultFeature obj;
274
        private Boolean hasnext = null;
275

    
276
        public InsertedIterator() {
277
            addedIter = added.values().iterator();
278
        }
279

    
280
        @Override
281
        public boolean hasNext() {
282
            if (hasnext != null) {
283
                return hasnext;
284
            }
285
            hasnext = false;
286
            int pos;
287
            while (addedIter.hasNext()) {
288
                pos = ((Integer) addedIter.next());
289
                obj = (DefaultFeature) expansionAdapter.getObject(pos);
290
                if (!deleted.contains(obj.getReference())) {
291
                    hasnext = true;
292
                    break;
293
                }
294
            }
295
            return hasnext;
296
        }
297

    
298
        @Override
299
        public Object next() {
300
            if (!hasNext()) {
301
                throw new NoSuchElementException();
302
            }
303
            hasnext = null;
304
            return obj.getData();
305
        }
306

    
307
        @Override
308
        public void remove() {
309
            addedIter.remove();
310
        }
311

    
312
    }
313

    
314
    public Iterator getUpdated() {
315
        return new UpdatedIterator();
316
    }
317

    
318
    private class UpdatedIterator implements Iterator {
319

    
320
        private Boolean hasnext = null;
321
        private final Iterator iter;
322
        private DefaultFeature obj;
323
        private int pos;
324

    
325
        public UpdatedIterator() {
326
            iter = expansionAdapter.iterator();
327
            pos = -1;
328
        }
329

    
330
        @Override
331
        public boolean hasNext() {
332
            if (hasnext != null) {
333
                return hasnext;
334
            }
335
            hasnext = false;
336
            while (iter.hasNext()) {
337
                pos++;
338
                obj = (DefaultFeature) iter.next();
339
                if (deleted.contains(obj.getReference())) {
340
                    continue;
341
                } else if (!modifiedFromOriginal.containsValue(pos)) {
342
                    continue;
343
                } else {
344
                    hasnext = true;
345
                    break;
346
                }
347
            }
348
            return hasnext;
349
        }
350

    
351
        @Override
352
        public Object next() {
353
            if (!hasNext()) {
354
                throw new NoSuchElementException();
355
            }
356
            hasnext = null;
357
            return obj.getData();
358
        }
359

    
360
        @Override
361
        public void remove() {
362
            throw new UnsupportedOperationException();
363

    
364
        }
365
    }
366

    
367
    public boolean hasNews() {
368
        return !added.isEmpty();
369
    }
370

    
371
    public long getDeltaSize() {
372
        return deltaSize;
373
    }
374

    
375
    /**
376
     * Indicates if any operation has comprimised the selected features.
377
     *
378
     * @return
379
     */
380
    public boolean isSelectionCompromised() {
381
        //Only deleted features can change order, as added features are added at the end.
382
        return deleted.size() > 0;
383
    }
384
}