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 / FeatureManager.java @ 43838

History | View | Annotate | Download (11 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;
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.expansionadapter.ExpansionAdapter;
40

    
41

    
42
public class FeatureManager {
43

    
44
    private int deltaSize = 0;
45
    private final ExpansionAdapter expansionAdapter;
46
    private final Collection<FeatureReference> deleted = new LinkedHashSet();
47
    private final Map<FeatureReference, Integer> added = new LinkedHashMap();
48
    private final Map<FeatureReference, Integer> addedAndDeleted = new LinkedHashMap();
49
    private final Map<FeatureReference, Integer> modifiedFromOriginal = new HashMap();
50

    
51
    public FeatureManager(ExpansionAdapter expansionAdapter) {
52
        this.expansionAdapter = expansionAdapter;
53
    }
54

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

    
80
    public void add(Feature feature) {
81
        int pos = expansionAdapter.addObject(feature);
82
        added.put(feature.getReference(), pos);
83
        deleted.remove(feature.getReference());
84
        deltaSize++;
85
    }
86

    
87
    public Feature deleteLastFeature() {
88
        expansionAdapter.deleteLastObject();
89
        Feature feature = (Feature) expansionAdapter.getObject(expansionAdapter.getSize() - 1);
90
        added.remove(feature.getReference());
91
        modifiedFromOriginal.remove(feature.getReference());
92
        deltaSize--;
93
        return feature;
94
    }
95

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

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

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

    
164
    public void restore(FeatureReference id) {
165
        deleted.remove(id);
166
        deltaSize++;
167
    }
168

    
169
    public void restore(FeatureReference id, int num) {
170
        if (added.containsKey(id)) {
171
            added.put(id, num);
172
        } else {
173
            modifiedFromOriginal.put(id, num);
174
        }
175
    }
176

    
177
    public boolean isDeleted(Feature feature) {
178
        return deleted.contains(feature.getReference());
179
    }
180

    
181
    public boolean isDeleted(FeatureReference featureID) {
182
        return deleted.contains(featureID);
183
    }
184

    
185
    public void clear() {
186
        added.clear();
187
        modifiedFromOriginal.clear();
188
        expansionAdapter.close();
189
        deleted.clear();
190
        addedAndDeleted.clear();
191
        deltaSize = 0;
192
    }
193

    
194
    public boolean hasChanges() {
195
        return added.size() > 0 || modifiedFromOriginal.size() > 0 || deleted.size() > 0;
196
    }
197

    
198
    public Iterator getDeleted() {
199
        return new DeletedIterator();
200

    
201
    }
202

    
203
    private class DeletedIterator implements Iterator {
204

    
205
        private Boolean hasnext = null;
206
        private final Iterator iter;
207
        private DefaultFeatureReference obj;
208

    
209
        public DeletedIterator() {
210
            iter = deleted.iterator();
211
        }
212

    
213
        @Override
214
        public boolean hasNext() {
215
            if (hasnext != null) {
216
                return hasnext;
217
            }
218
            hasnext = false;
219
            while (iter.hasNext()) {
220
                obj = (DefaultFeatureReference) iter.next();
221
                if (obj.isNewFeature()) {
222
                    continue;
223
                }
224
                hasnext = false;
225
                break;
226
            }
227
            return hasnext;
228
        }
229

    
230
        @Override
231
        public Object next() {
232
            if (!hasNext()) {
233
                throw new NoSuchElementException();
234
            }
235
            hasnext = null;
236
            return obj;
237
        }
238

    
239
        @Override
240
        public void remove() {
241
            throw new UnsupportedOperationException();
242
        }
243

    
244
    }
245

    
246
    public Iterator getInserted() {
247
        return new InsertedIterator();
248
    }
249

    
250
    private class InsertedIterator implements Iterator {
251

    
252
        private final Iterator addedIter;
253
        private DefaultFeature obj;
254
        private Boolean hasnext = null;
255

    
256
        public InsertedIterator() {
257
            addedIter = added.values().iterator();
258
        }
259

    
260
        @Override
261
        public boolean hasNext() {
262
            if (hasnext != null) {
263
                return hasnext;
264
            }
265
            hasnext = false;
266
            int pos;
267
            while (addedIter.hasNext()) {
268
                pos = ((Integer) addedIter.next());
269
                obj = (DefaultFeature) expansionAdapter.getObject(pos);
270
                if (!deleted.contains(obj.getReference())) {
271
                    hasnext = true;
272
                    break;
273
                }
274
            }
275
            return hasnext;
276
        }
277

    
278
        @Override
279
        public Object next() {
280
            if (!hasNext()) {
281
                throw new NoSuchElementException();
282
            }
283
            hasnext = null;
284
            return obj.getData();
285
        }
286

    
287
        @Override
288
        public void remove() {
289
            addedIter.remove();
290
        }
291

    
292
    }
293

    
294
    public Iterator getUpdated() {
295
        return new UpdatedIterator();
296
    }
297

    
298
    private class UpdatedIterator implements Iterator {
299

    
300
        private Boolean hasnext = null;
301
        private final Iterator iter;
302
        private DefaultFeature obj;
303
        private int pos;
304

    
305
        public UpdatedIterator() {
306
            iter = expansionAdapter.iterator();
307
            pos = -1;
308
        }
309

    
310
        @Override
311
        public boolean hasNext() {
312
            if (hasnext != null) {
313
                return hasnext;
314
            }
315
            hasnext = false;
316
            while (iter.hasNext()) {
317
                pos++;
318
                obj = (DefaultFeature) iter.next();
319
                if (deleted.contains(obj.getReference())) {
320
                    continue;
321
                } else if (!modifiedFromOriginal.containsValue(pos)) {
322
                    continue;
323
                } else {
324
                    hasnext = true;
325
                    break;
326
                }
327
            }
328
            return hasnext;
329
        }
330

    
331
        @Override
332
        public Object next() {
333
            if (!hasNext()) {
334
                throw new NoSuchElementException();
335
            }
336
            hasnext = null;
337
            return obj.getData();
338
        }
339

    
340
        @Override
341
        public void remove() {
342
            throw new UnsupportedOperationException();
343

    
344
        }
345
    }
346

    
347
    public boolean hasNews() {
348
        return !added.isEmpty();
349
    }
350

    
351
    public long getDeltaSize() {
352
        return deltaSize;
353
    }
354

    
355
    /**
356
     * Indicates if any operation has comprimised the selected features.
357
     *
358
     * @return
359
     */
360
    public boolean isSelectionCompromised() {
361
        //Only deleted features can change order, as added features are added at the end.
362
        return deleted.size() > 0;
363
    }
364
}