Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.lib / org.gvsig.vectorediting.lib.prov / org.gvsig.vectorediting.lib.prov.join / src / main / java / org / gvsig / vectorediting / lib / prov / combine / CombineEditingProvider.java @ 4300

History | View | Annotate | Download (20.4 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 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 2
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

    
25
package org.gvsig.vectorediting.lib.prov.combine;
26

    
27
import java.util.ArrayList;
28
import java.util.Iterator;
29
import java.util.List;
30
import org.gvsig.fmap.dal.exception.DataException;
31
import org.gvsig.fmap.dal.feature.EditableFeature;
32
import org.gvsig.fmap.dal.feature.Feature;
33
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
34
import org.gvsig.fmap.dal.feature.FeatureSelection;
35
import org.gvsig.fmap.dal.feature.FeatureStore;
36
import org.gvsig.fmap.dal.feature.FeatureType;
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.GeometryLocator;
39
import org.gvsig.fmap.geom.GeometryManager;
40
import org.gvsig.fmap.geom.aggregate.MultiCurve;
41
import org.gvsig.fmap.geom.aggregate.MultiPoint;
42
import org.gvsig.fmap.geom.aggregate.MultiSurface;
43
import org.gvsig.fmap.geom.complex.Complex;
44
import org.gvsig.fmap.geom.primitive.Point;
45
import org.gvsig.fmap.geom.type.GeometryType;
46
import org.gvsig.tools.ToolsLocator;
47
import org.gvsig.tools.dispose.DisposableIterator;
48
import org.gvsig.tools.dispose.DisposeUtils;
49
import org.gvsig.tools.dynobject.DynObject;
50
import org.gvsig.tools.exception.BaseException;
51
import org.gvsig.tools.service.spi.ProviderServices;
52
import org.gvsig.vectorediting.lib.api.DrawingStatus;
53
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
54
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
55
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
56
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
57
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
58
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
59
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
60
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
61
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
62
import org.gvsig.vectorediting.lib.spi.EditingProvider;
63
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
64
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
65

    
66
/**
67
 * @author llmarques
68
 *
69
 */
70
public class CombineEditingProvider extends AbstractEditingProvider implements EditingProvider {
71
    
72
    private static final int HAS_POINT = 1;
73
    private static final int HAS_CURVE = 2;
74
    private static final int HAS_SURFACE = 4;
75

    
76
    private final EditingServiceParameter selectionParameter;
77

    
78
    private final FeatureStore featureStore;
79

    
80
    private FeatureSelection featureSelection;
81

    
82
    /**
83
     * Default constructor.
84
     *
85
     * @param parameters
86
     *            of this provider
87
     * @param services
88
     */
89
    public CombineEditingProvider(DynObject parameters, ProviderServices services) {
90
        super(services);
91

    
92
        this.featureStore =
93
            (FeatureStore) parameters
94
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
95

    
96
        this.selectionParameter =
97
            new DefaultEditingServiceParameter("selection", "selection",
98
                TYPE.SELECTION);
99
    }
100

    
101
    @Override
102
    public EditingServiceParameter next() {
103
        if (featureSelection == null) {
104
            return selectionParameter;
105
        }
106
        return null;
107
    }
108

    
109
    @Override
110
    public boolean mustRestartAtFinish() {
111
        return false;
112
    }
113

    
114
    @Override
115
    public DrawingStatus getDrawingStatus(Point mousePosition)
116
        throws DrawServiceException {
117
        return null;
118
    }
119

    
120
    @Override
121
    public void stop() throws StopServiceException {
122
        DisposeUtils.disposeQuietly(featureSelection);
123
        featureSelection = null;
124
    }
125

    
126
    @Override
127
    public List<EditingServiceParameter> getParameters() {
128
        List<EditingServiceParameter> parameters =
129
            new ArrayList<>();
130
        parameters.add(selectionParameter);
131
        return parameters;
132
    }
133

    
134
    @Override
135
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
136
        validateAndInsertValue(parameter, value);
137
    }
138

    
139
    @Override
140
    public void setValue(Object value) throws InvalidEntryException {
141
        EditingServiceParameter parameter = next();
142
        validateAndInsertValue(parameter, value);
143

    
144
    }
145

    
146
    private void validateAndInsertValue(EditingServiceParameter parameter,
147
        Object value) throws InvalidEntryException {
148

    
149
        if (parameter == selectionParameter) {
150

    
151
            if (value instanceof FeatureSelection) {
152
                FeatureSelection fSelection = (FeatureSelection) value;
153

    
154
                if (fSelection.getSelectedCount() > 1) {
155

    
156
                    DisposableIterator it = null;
157

    
158
                    try {
159
                        it = fSelection.fastIterator();
160

    
161
                        Feature feature = (Feature) it.next();
162
                        // Gets geometry type of first selected feature
163
                        GeometryType geometryType =
164
                            feature.getDefaultGeometry().getGeometryType();
165

    
166
                        // Iterate over remaining selected features
167
                        while (it.hasNext()) {
168
                            feature = (Feature) it.next();
169

    
170
                            // Remaining selected features must be the same or
171
                            // the equivalent multigeometry type of first
172
                            // feature. If one of reamining geometries is
173
                            // different, selection is not valid.
174
                            if (geometryType.isTypeOf(CURVE)
175
                                || geometryType.isTypeOf(MULTICURVE)) {
176

    
177
                                GeometryType featureGeoType =
178
                                    feature.getDefaultGeometry()
179
                                        .getGeometryType();
180

    
181
                                if (!(featureGeoType.isTypeOf(CURVE) || featureGeoType
182
                                    .isTypeOf(MULTICURVE))) {
183
                                    throw new InvalidEntryException(null);
184
                                }
185

    
186
                            } else if (geometryType.isTypeOf(SURFACE)
187
                                || geometryType.isTypeOf(SURFACE)) {
188

    
189
                                GeometryType featureGeoType =
190
                                    feature.getDefaultGeometry()
191
                                        .getGeometryType();
192

    
193
                                if (!(featureGeoType.isTypeOf(SURFACE) || featureGeoType
194
                                    .isTypeOf(MULTISURFACE))) {
195
                                    throw new InvalidEntryException(null);
196
                                }
197
                            }
198
                        }
199
                        DisposeUtils.disposeQuietly(featureSelection);
200
                        ToolsLocator.getDisposableManager().bind(fSelection);
201
                        featureSelection = fSelection;
202
                        return;
203
                    } catch (DataException e) {
204
                        throw new InvalidEntryException(e);
205
                    } finally {
206
                        DisposeUtils.disposeQuietly(it);
207
                    }
208
                }
209
            }
210
        }
211
        throw new InvalidEntryException(null);
212
    }
213

    
214
    @Override
215
    public Geometry finish() throws FinishServiceException {
216

    
217
        if (featureSelection != null) {
218
            Geometry combinedGeometry = null;
219
            DisposableIterator it = null;
220

    
221
            EditingProviderServices editingProviderServices
222
                    = (EditingProviderServices) getProviderServices();
223

    
224
            int resultType = 0;
225
            
226
            GeometryManager geometryManager = GeometryLocator.getGeometryManager();
227
            try {
228
                int subtype = editingProviderServices.getSubType(featureStore);
229
                MultiPoint multiPoint = geometryManager.createMultiPoint(subtype);
230
                MultiCurve multiCurve = geometryManager.createMultiCurve(subtype);
231
                MultiSurface multiSurface = geometryManager.createMultiSurface(subtype);
232

    
233
                it = featureSelection.fastIterator();
234

    
235
                while (it.hasNext()) {
236
                    Feature tmpFeature = (Feature) it.next();
237
                    Geometry geom = tmpFeature.getDefaultGeometry();
238
                    if(geom.getGeometryType().isTypeOf(POINT) ||
239
                            geom.getGeometryType().isTypeOf(MULTIPOINT) ) {
240
                        multiPoint.addPrimitives(geom);
241
                        resultType |= HAS_POINT;
242
                    } else if(geom.getGeometryType().isTypeOf(CURVE) ||
243
                            geom.getGeometryType().isTypeOf(MULTICURVE) ) {
244
                        multiCurve.addPrimitives(geom);
245
                        resultType |= HAS_CURVE;
246
                    } else if(geom.getGeometryType().isTypeOf(SURFACE) ||
247
                            geom.getGeometryType().isTypeOf(MULTISURFACE) ) {
248
                        multiSurface.addPrimitives(geom);
249
                        resultType |= HAS_SURFACE;
250
                    } else if(geom.getGeometryType().isTypeOf(COMPLEX)) {
251
                        Complex complex = (Complex)geom;
252
                        Iterator<Geometry> complexIt = complex.iterator();
253
                        while (complexIt.hasNext()) {
254
                            Geometry geom1 = complexIt.next();
255
                            if (geom1.getGeometryType().isTypeOf(POINT)
256
                                    || geom1.getGeometryType().isTypeOf(MULTIPOINT)) {
257
                                multiPoint.addPrimitives(geom1);
258
                                resultType |= HAS_POINT;
259
                            } else if (geom1.getGeometryType().isTypeOf(CURVE)
260
                                    || geom1.getGeometryType().isTypeOf(MULTICURVE)) {
261
                                multiCurve.addPrimitives(geom1);
262
                                resultType |= HAS_CURVE;
263

    
264
                            } else if (geom1.getGeometryType().isTypeOf(SURFACE)
265
                                    || geom1.getGeometryType().isTypeOf(MULTISURFACE)) {
266
                                multiSurface.addPrimitives(geom1);
267
                                resultType |= HAS_SURFACE;
268
                            }
269
                        }
270
                    }
271
                }
272

    
273
                GeometryType storeGeomType = editingProviderServices.getGeomType(featureStore);
274
                if(resultType > 4 || resultType == 3){ //COMPLEX
275
                    if(storeGeomType.getType()!=COMPLEX && storeGeomType.getType()!=GEOMETRY){
276
                        throw new FinishServiceException("_The_resulting_geometry_is_not_valid_for_the_store", null);
277
                    }
278
                    combinedGeometry = geometryManager.create(COMPLEX, subtype);
279
                    Complex complex = (Complex)combinedGeometry;
280
                    if((resultType & HAS_POINT) == HAS_POINT){
281
                        complex.addPrimitives(multiPoint.union());
282
                    } else if((resultType & HAS_CURVE) == HAS_CURVE){
283
                        complex.addPrimitives(multiCurve.dissolve());
284
                    } else if((resultType & HAS_SURFACE) == HAS_SURFACE){
285
                        complex.addPrimitives(multiSurface.union());
286
                    }
287
                } else {
288
                    switch (resultType){
289
                        case HAS_POINT:
290
                            if(!storeGeomType.isTypeOf(GEOMETRY) &&
291
                               !storeGeomType.isTypeOf(POINT) &&
292
                               !storeGeomType.isTypeOf(MULTIPOINT) ){
293
                               throw new FinishServiceException("The resulting geometry is not valid for the store.", "_The_resulting_geometry_is_not_valid_for_the_store", null);
294
                            }
295
                            combinedGeometry = multiPoint.union();
296

    
297
                            if(storeGeomType.isTypeOf(POINT) && combinedGeometry.getGeometryType().isTypeOf(MULTIPOINT)){
298
                               throw new FinishServiceException("The resulting geometry is not valid for the store.", "_The_resulting_geometry_is_not_valid_for_the_store", null);
299
                            }
300
                            if(storeGeomType.isTypeOf(MULTIPOINT) && combinedGeometry.getGeometryType().isTypeOf(POINT)){
301
                                MultiPoint tmpMultiPoint = geometryManager.createMultiPoint(subtype);
302
                                tmpMultiPoint.addPrimitives(combinedGeometry);
303
                                combinedGeometry = tmpMultiPoint;
304
                            }
305
                            break;
306
                        case HAS_CURVE:
307
                            if(!storeGeomType.isTypeOf(GEOMETRY) &&
308
                               !storeGeomType.isTypeOf(CURVE) &&
309
                               !storeGeomType.isTypeOf(MULTICURVE) ){
310
                               throw new FinishServiceException("The resulting geometry is not valid for the store.", "_The_resulting_geometry_is_not_valid_for_the_store", null);
311
                            }
312
                            combinedGeometry = multiCurve.dissolve();
313
                            
314
                            if(storeGeomType.isTypeOf(CURVE) && combinedGeometry.getGeometryType().isTypeOf(MULTICURVE)){
315
                               throw new FinishServiceException("The resulting geometry is not valid for the store.", "_The_resulting_geometry_is_not_valid_for_the_store", null);
316
                            }
317
                            if(storeGeomType.isTypeOf(MULTICURVE) && combinedGeometry.getGeometryType().isTypeOf(CURVE)){
318
                                MultiCurve tmpMultiCurve = geometryManager.createMultiCurve(subtype);
319
                                tmpMultiCurve.addPrimitives(combinedGeometry);
320
                                combinedGeometry = tmpMultiCurve;
321
                            }
322
                            break;
323
                        case HAS_SURFACE:
324
                            if(!storeGeomType.isTypeOf(GEOMETRY) &&
325
                               !storeGeomType.isTypeOf(SURFACE) &&
326
                               !storeGeomType.isTypeOf(MULTISURFACE) ){
327
                               throw new FinishServiceException("The resulting geometry is not valid for the store.", "_The_resulting_geometry_is_not_valid_for_the_store", null);
328
                            }
329
                            combinedGeometry = multiSurface.union();
330
                            if(storeGeomType.isTypeOf(SURFACE) && combinedGeometry.getGeometryType().isTypeOf(MULTISURFACE)){
331
                               throw new FinishServiceException("The resulting geometry is not valid for the store.", "_The_resulting_geometry_is_not_valid_for_the_store", null);
332
                            }
333
                            if(storeGeomType.isTypeOf(MULTISURFACE) && combinedGeometry.getGeometryType().isTypeOf(SURFACE)){
334
                                MultiSurface tmpMultiSurface = geometryManager.createMultiSurface(subtype);
335
                                tmpMultiSurface.addPrimitives(combinedGeometry);
336
                                combinedGeometry = tmpMultiSurface;
337
                            }
338
                            break;
339
                    }
340
                }
341
            } catch (FinishServiceException e) {
342
                throw e;
343
            } catch (BaseException e) {
344
                throw new FinishServiceException(e);
345
            } finally {
346
                DisposeUtils.disposeQuietly(it);
347
            }
348

    
349
            return combinedGeometry;
350
        }
351
        return null;
352
    }
353
    
354
    @SuppressWarnings("rawtypes")
355
    @Override
356
    public void finishAndStore() throws FinishServiceException {
357
        Geometry geometry = finish();
358

    
359
        final EditingProviderServices editingProviderServices =
360
            (EditingProviderServices) getProviderServices();
361

    
362
        FeatureType featureType = null;
363
        EditableFeature eFeature = null;
364

    
365
        try {
366
            eFeature = featureStore.createNewFeature();
367
            featureType = featureStore.getDefaultFeatureType();
368
        } catch (DataException e) {
369
            throw new FinishServiceException(e);
370
        }
371

    
372
        Iterator typeIterator = featureType.iterator();
373
        // Iterate over feature type
374
        while (typeIterator.hasNext()) {
375
            boolean insertValue = true;
376
            FeatureAttributeDescriptor attribute =
377
                (FeatureAttributeDescriptor) typeIterator.next();
378

    
379
            // If type is a primary key do nothing
380
            if (!attribute.isPrimaryKey()) {
381

    
382
                // int type = attribute.getType();
383

    
384
                DisposableIterator featureIterator = null;
385
                try {
386
                    featureIterator = featureSelection.fastIterator();
387
                    Feature feature = (Feature) featureIterator.next();
388

    
389
                    // Restart iterator and initilize it at second position
390
                    featureIterator.dispose();
391
                    featureIterator = featureSelection.fastIterator(1);
392

    
393
                    // Gets the type value of first feature
394
                    Object value = feature.get(attribute.getName());
395

    
396
                    // Compare first value with the rest of features. If values
397
                    // are different, break bucle and don't insert value at new
398
                    // feature.
399
                    if (value != null) {
400

    
401
                        while (featureIterator.hasNext()) {
402
                            Feature nextFeature =
403
                                (Feature) featureIterator.next();
404
                            Object nextValue =
405
                                nextFeature.get(attribute.getName());
406

    
407
                            if (nextValue == null || !value.equals(nextValue)) {
408
                                insertValue = false;
409
                                break;
410
                            }
411
                        }
412

    
413
                        if (insertValue) {
414
                            eFeature.set(attribute.getName(), value);
415
                        }
416
                    }
417
                } catch (DataException e) {
418
                    throw new FinishServiceException(e);
419
                } finally {
420
                    DisposeUtils.disposeQuietly(featureIterator);
421
                }
422
            }
423
        }
424

    
425
        // Inserts new feature
426
        eFeature.setDefaultGeometry(geometry);
427
        editingProviderServices.insertFeatureIntoFeatureStore(eFeature,
428
            featureStore);
429

    
430
        // Deletes selected features
431
        try {
432
            featureSelection.accept((Object obj) -> {
433
                Feature feature = (Feature) obj;
434
                editingProviderServices.deleteFeatureFromFeatureStore(
435
                        feature, featureStore);
436
            });
437
            featureStore.getFeatureSelection().deselectAll();
438
        } catch (BaseException e) {
439
            throw new FinishServiceException(e);
440
        }
441
    }
442

    
443
    @Override
444
    public void start() throws StartServiceException, InvalidEntryException {
445
        FeatureSelection selected = null;
446
        if (featureStore != null) {
447
            try {
448
                selected = featureStore.getFeatureSelection();
449
            } catch (DataException e) {
450
                throw new StartServiceException(e);
451
            }
452
            if (selected.getSelectedCount() > 1) {
453
                try {
454
                    setValue(selected);
455
                } catch (InvalidEntryException e) {
456
                    throw new InvalidEntryException(e);
457
                }
458
            }
459
        }
460
    }
461

    
462
    @Override
463
    public String getName() {
464
        return CombineEditingProviderFactory.PROVIDER_NAME;
465
    }
466

    
467
    @Override
468
    public Object getValue(EditingServiceParameter parameter) {
469
        if(parameter == selectionParameter){
470
            return featureSelection;
471
        }
472
        return null;
473
    }
474
}