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.split / src / main / java / org / gvsig / vectorediting / lib / prov / split / SplitEditingProvider.java @ 575

History | View | Annotate | Download (14.7 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.split;
26

    
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.List;
30
import java.util.Map;
31

    
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.EditableFeature;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureSelection;
36
import org.gvsig.fmap.dal.feature.FeatureStore;
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.Geometry.TYPES;
39
import org.gvsig.fmap.geom.GeometryException;
40
import org.gvsig.fmap.geom.GeometryLocator;
41
import org.gvsig.fmap.geom.GeometryManager;
42
import org.gvsig.fmap.geom.aggregate.MultiCurve;
43
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
44
import org.gvsig.fmap.geom.operation.GeometryOperationException;
45
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
46
import org.gvsig.fmap.geom.primitive.Curve;
47
import org.gvsig.fmap.geom.primitive.Point;
48
import org.gvsig.fmap.geom.primitive.Primitive;
49
import org.gvsig.fmap.geom.type.GeometryType;
50
import org.gvsig.tools.ToolsLocator;
51
import org.gvsig.tools.dispose.DisposableIterator;
52
import org.gvsig.tools.dynobject.DynObject;
53
import org.gvsig.tools.exception.BaseException;
54
import org.gvsig.tools.service.spi.ProviderServices;
55
import org.gvsig.tools.visitor.VisitCanceledException;
56
import org.gvsig.tools.visitor.Visitor;
57
import org.gvsig.vectorediting.lib.api.DrawingStatus;
58
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
59
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
60
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
61
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
62
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
63
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
64
import org.gvsig.vectorediting.lib.api.exceptions.VectorEditingException;
65
import org.gvsig.vectorediting.lib.prov.split.operation.SplitOperation;
66
import org.gvsig.vectorediting.lib.prov.split.operation.SplitOperationUtils;
67
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
68
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
69
import org.gvsig.vectorediting.lib.spi.EditingProvider;
70
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
71
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
72

    
73
/**
74
 * @author llmarques
75
 *
76
 */
77
public class SplitEditingProvider extends AbstractEditingProvider implements
78
    EditingProvider {
79

    
80
    private EditingServiceParameter selection;
81

    
82
    private EditingServiceParameter splitGeometry;
83

    
84
    private FeatureStore featureStore;
85

    
86
    private Map<EditingServiceParameter, Object> values;
87

    
88
    /**
89
     * Default constructor.
90
     *
91
     * @param providerServices
92
     *            available services for this provider
93
     * @param parameters
94
     *            of this provider
95
     */
96
    public SplitEditingProvider(ProviderServices services, DynObject parameters) {
97
        super(services);
98

    
99
        this.featureStore =
100
            (FeatureStore) parameters
101
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
102

    
103
        this.selection =
104
            new DefaultEditingServiceParameter("selection", "selection",
105
                EditingServiceParameter.TYPE.SELECTION);
106

    
107
        this.splitGeometry =
108
            new DefaultEditingServiceParameter("draw_geometry_to_split",
109
                "draw_geometry_to_split", Geometry.TYPES.CURVE,
110
                EditingServiceParameter.TYPE.GEOMETRY);
111
    }
112

    
113
    public EditingServiceParameter next() {
114
        if (values.get(selection) == null) {
115
            return selection;
116
        } else if (values.get(splitGeometry) == null) {
117
            return splitGeometry;
118
        }
119
        return null;
120
    }
121

    
122
    public DrawingStatus getDrawingStatus(Point mousePosition)
123
        throws DrawServiceException {
124
        return null;
125
    }
126

    
127
    public void stop() throws StopServiceException {
128
        if (values != null) {
129
            values.clear();
130
        }
131
    }
132

    
133
    public List<EditingServiceParameter> getParameters() {
134
        List<EditingServiceParameter> parameters =
135
            new ArrayList<EditingServiceParameter>();
136
        parameters.add(selection);
137
        parameters.add(splitGeometry);
138
        return parameters;
139
    }
140

    
141
    public void setValue(Object value) throws InvalidEntryException {
142
        EditingServiceParameter parameter = next();
143
        validateAndInsertValue(parameter, value);
144
    }
145

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

    
149
        if (values != null && value != null) {
150

    
151
            if (value instanceof FeatureSelection) {
152

    
153
                FeatureSelection featureSelection = (FeatureSelection) value;
154

    
155
                try {
156
                    featureSelection.accept(new Visitor() {
157

    
158
                        public void visit(Object obj)
159
                            throws VisitCanceledException, BaseException {
160
                            Feature feature = (Feature) obj;
161
                            Geometry geometry = feature.getDefaultGeometry();
162
                            GeometryType geoType = geometry.getGeometryType();
163

    
164
                            if (geoType.isTypeOf(POINT)
165
                                || geoType.isTypeOf(MULTIPOINT)) {
166
                                throw new InvalidEntryException(null);
167
                            }
168
                        }
169
                    });
170

    
171
                    values.put(selection, value);
172
                    return;
173
                } catch (BaseException e) {
174
                    throw new InvalidEntryException(e);
175
                }
176

    
177
            } else if (value instanceof Geometry) {
178

    
179
                Geometry geometry = (Geometry) value;
180

    
181
                if (geometry instanceof MultiCurve) {
182
                    MultiCurve multiCurve = (MultiCurve) geometry;
183
                    for (int i = 0; i < multiCurve.getPrimitivesNumber(); i++) {
184
                        if (isValid((Curve) multiCurve.getPrimitiveAt(i))) {
185
                            values.put(splitGeometry, geometry);
186
                            return;
187
                        }
188
                    }
189

    
190
                } else if (geometry instanceof Curve) {
191
                    if (isValid((Curve) geometry)) {
192
                        values.put(splitGeometry, geometry);
193
                        return;
194
                    }
195
                }
196
            }
197
        }
198
        throw new InvalidEntryException(null);
199
    }
200

    
201
    private boolean isValid(final Curve curve) {
202
        FeatureSelection featureSelection =
203
            (FeatureSelection) values.get(selection);
204

    
205
        try {
206
            featureSelection.accept(new Visitor() {
207

    
208
                public void visit(Object obj) throws VisitCanceledException,
209
                    BaseException {
210
                    Feature feature = (Feature) obj;
211
                    Geometry geometry = feature.getDefaultGeometry();
212

    
213
                    Geometry intersection = geometry.intersection(curve);
214

    
215
                    if (intersection == null
216
                        || (!intersection.getGeometryType().isTypeOf(POINT)
217
                        && !intersection.getGeometryType().isTypeOf(MULTIPOINT)
218
                        && !intersection.getGeometryType().isTypeOf(CURVE)
219
                        && !intersection.getGeometryType().isTypeOf(MULTICURVE))) {
220
                        throw new VectorEditingException();
221
                    }
222
                }
223
            });
224
            return true;
225
        } catch (BaseException e) {
226
            return false;
227
        }
228
    }
229

    
230
    public Geometry finish() throws FinishServiceException {
231
        return null;
232
    }
233

    
234
    public void finishAndStore() throws FinishServiceException {
235

    
236
        if (values != null) {
237

    
238
            EditingProviderServices editingProviderServices =
239
                (EditingProviderServices) getProviderServices();
240

    
241
            FeatureSelection featureSelection =
242
                (FeatureSelection) values.get(selection);
243
            Geometry splitter = (Geometry) values.get(splitGeometry);
244
            ToolsLocator.getDisposableManager().bind(featureSelection);
245

    
246
            DisposableIterator it = null;
247
            try {
248
                it = featureSelection.fastIterator();
249

    
250
                while (it.hasNext()) {
251
                    Feature feature = (Feature) it.next();
252
                    Geometry geometryToBeSplitted =
253
                        feature.getDefaultGeometry();
254
                    GeometryType geoType =
255
                        geometryToBeSplitted.getGeometryType();
256

    
257
                    if (geoType.isTypeOf(TYPES.SURFACE)
258
                        || geoType.isTypeOf(TYPES.CURVE)) {
259

    
260
                        MultiPrimitive splittedGeometries =
261
                            (MultiPrimitive) split(
262
                                (Primitive) geometryToBeSplitted, splitter);
263

    
264
                        for (int j = 0; j < splittedGeometries
265
                            .getPrimitivesNumber(); j++) {
266
                            copyAlfanumericDataAndInsert(
267
                                splittedGeometries.getPrimitiveAt(j), feature);
268
                        }
269

    
270
                    } else if (geoType.isTypeOf(TYPES.MULTISURFACE)
271
                        || geoType.isTypeOf(TYPES.MULTICURVE)) {
272

    
273
                        MultiPrimitive multiPrimitive =
274
                            (MultiPrimitive) geometryToBeSplitted;
275

    
276
                        // Multigeometry composed by no splitted geometries.
277
                        GeometryManager geoManager = GeometryLocator.getGeometryManager();
278
                        MultiPrimitive multiNoSplitted;
279
                        if(geoType.isTypeOf(TYPES.MULTISURFACE)){
280
                            multiNoSplitted =
281
                                geoManager.createMultiSurface(editingProviderServices
282
                                    .getSubType(featureStore));
283
                        } else {
284
                            multiNoSplitted =
285
                                geoManager.createMultiCurve(editingProviderServices
286
                                    .getSubType(featureStore));
287
                        }
288

    
289
                        for (int i = 0; i < multiPrimitive
290
                            .getPrimitivesNumber(); i++) {
291

    
292
                            Geometry geoSplitted =
293
                                split(multiPrimitive.getPrimitiveAt(i),
294
                                    splitter);
295

    
296
                            if (geoSplitted instanceof MultiPrimitive) {
297
                                // If the result of split is a multiprimitive,
298
                                // it has splitted
299
                                MultiPrimitive multiSplitted = (MultiPrimitive) geoSplitted;
300
                                // Splitted geometries should be saved as
301
                                // primitives
302
                                for (int j = 0; j < multiSplitted
303
                                    .getPrimitivesNumber(); j++) {
304
                                    copyAlfanumericDataAndInsert(
305
                                        multiSplitted.getPrimitiveAt(j),
306
                                        feature);
307
                                }
308
                            } else {
309
                                // If the result of split is a primitive, it has
310
                                // not splitted. Add it to mulriNoSplitted to save it later.
311
                                multiNoSplitted
312
                                    .addPrimitive((Primitive) geoSplitted);
313
                            }
314
                        }
315

    
316
                        if(multiNoSplitted.getPrimitivesNumber() > 0){
317
                            // Not splitted geometries should be saved as multigeometry
318
                            copyAlfanumericDataAndInsert(multiNoSplitted,
319
                                feature);
320
                        }
321
                    }
322

    
323
                    editingProviderServices.deleteFeatureFromFeatureStore(
324
                        feature, featureStore);
325
                }
326

    
327
                featureSelection.deselectAll();
328
                featureStore.getFeatureSelection().deselectAll();
329

    
330

    
331
            } catch (BaseException e) {
332
                throw new FinishServiceException(e);
333
            } finally {
334
                it.dispose();
335
                featureSelection.dispose();
336
            }
337
        }
338
    }
339

    
340
    private void copyAlfanumericDataAndInsert(Geometry geometry, Feature feature)
341
        throws DataException {
342
        EditingProviderServices editingProviderServices =
343
            (EditingProviderServices) getProviderServices();
344

    
345
        EditableFeature eFeature =
346
            editingProviderServices.getFeatureCopyWithoutPK(featureStore,
347
                feature);
348
        eFeature.setDefaultGeometry(geometry);
349
        editingProviderServices.insertFeatureIntoFeatureStore(eFeature,
350
            featureStore);
351
    }
352

    
353
    private Geometry split(Primitive geometry, Geometry splitter)
354
        throws GeometryOperationNotSupportedException,
355
        GeometryOperationException, GeometryException {
356
        SplitOperation operation = SplitOperationUtils.getOperation(geometry);
357

    
358
        if (operation != null) {
359
            return operation.split(geometry, splitter);
360
        }
361
        return null;
362
    }
363

    
364
    public void start() throws StartServiceException, InvalidEntryException {
365
        values = new HashMap<EditingServiceParameter, Object>();
366
        FeatureSelection selected = null;
367
        if (featureStore != null) {
368
            try {
369
                selected = featureStore.getFeatureSelection();
370
            } catch (DataException e) {
371
                throw new StartServiceException(e);
372
            }
373
            if (selected.getSelectedCount() > 0) {
374
                setValue(selected);
375
            }
376
        }
377
    }
378

    
379
    public String getName() {
380
        return SplitEditingProviderFactory.PROVIDER_NAME;
381
    }
382

    
383
}