Statistics
| Revision:

root / trunk / extensions / extGeoProcessing / src / com / iver / gvsig / geoprocessing / impl / spatialjoin / SpatialJoinGeoprocess.java @ 4447

History | View | Annotate | Download (10.7 KB)

1
/*
2
 * Created on 28-feb-2006
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
 *
46
 * $Id: SpatialJoinGeoprocess.java 4447 2006-03-15 18:35:56Z azabala $
47
 * $Log$
48
 * Revision 1.5  2006-03-15 18:34:31  azabala
49
 * *** empty log message ***
50
 *
51
 * Revision 1.4  2006/03/14 18:32:46  fjp
52
 * Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n.
53
 *
54
 * Revision 1.3  2006/03/07 21:01:33  azabala
55
 * *** empty log message ***
56
 *
57
 * Revision 1.2  2006/03/06 19:48:39  azabala
58
 * *** empty log message ***
59
 *
60
 * Revision 1.1  2006/03/05 19:59:32  azabala
61
 * *** empty log message ***
62
 *
63
 *
64
 */
65
package com.iver.gvsig.geoprocessing.impl.spatialjoin;
66

    
67
import java.util.Map;
68

    
69
import com.iver.cit.gvsig.fmap.DriverException;
70
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
71
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition;
72
import com.iver.cit.gvsig.fmap.edition.EditionException;
73
import com.iver.cit.gvsig.fmap.layers.FBitSet;
74
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
75
import com.iver.cit.gvsig.fmap.operations.CancellableMonitorable;
76
import com.iver.cit.gvsig.fmap.operations.DefaultCancellableMonitorable;
77
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
78
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
79
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException;
80
import com.iver.gvsig.geoprocessing.impl.AbstractGeoprocess;
81
import com.iver.gvsig.geoprocessing.impl.difference.DifferenceVisitor;
82
import com.iver.gvsig.geoprocessing.impl.intersection.IntersectVisitor;
83
import com.iver.gvsig.geoprocessing.impl.jtsprocessors.DeferredFeaturePersisterProcessor;
84
import com.iver.gvsig.geoprocessing.impl.jtsprocessors.FeaturePersisterProcessor2;
85
import com.iver.gvsig.geoprocessing.model.GeoprocessException;
86
import com.iver.gvsig.geoprocessing.model.ITwoLayersGeoprocess;
87
import com.iver.gvsig.geoprocessing.schemabuilder.XTypes;
88
import com.iver.utiles.swing.threads.IMonitorableTask;
89

    
90
public class SpatialJoinGeoprocess extends AbstractGeoprocess
91
                                                                implements ITwoLayersGeoprocess {
92
        /**
93
         * overlay layer
94
         */
95
        private FLyrVect secondLayer;
96
        /**
97
         * Relates each numeric field of target layer with
98
         * many sumarization functions
99
         */
100
        private Map fields_sumFunctions;
101

    
102
        /**
103
         * flag to only clip selection of input layer
104
         */
105
        private boolean onlyFirstLayerSelection = false;
106

    
107
        /**
108
         * flag to only clip with selection of clipping layer
109
         */
110
        private boolean onlySecondLayerSelection = false;
111

    
112
        /**
113
         * flag to apply a nearest spatial join (1 to 1 join) or a intersect spatial
114
         * join (1 to m join)
115
         */
116
        private boolean nearestSpatialJoin = true;
117
        
118
        /**
119
         * Visitor that will do the process
120
         */
121
        private SpatialJoinVisitor visitor = null;
122
        /**
123
         * It will process results of joined features
124
         */
125
        private FeaturePersisterProcessor2 processor;
126
        
127

    
128
        public SpatialJoinGeoprocess(FLyrVect inputLayer) {
129
                setFirstOperand(inputLayer);
130
        }
131

    
132
        public void setSecondOperand(FLyrVect overlayLayer) {
133
                this.secondLayer = overlayLayer;
134

    
135
        }
136

    
137
        public void setFirstOperand(FLyrVect firstLayer) {
138
                this.firstLayer = firstLayer;
139
                
140
        }
141

    
142
        /**
143
         * PRECONDITION: We must setResultLayerProperties before
144
         * to call setParameters.
145
         * FIXME
146
         */
147
        public void setParameters(Map params) throws GeoprocessException {
148
                Boolean firstLayerSelection = (Boolean) params
149
                                .get("firstlayerselection");
150
                if (firstLayerSelection != null)
151
                        this.onlyFirstLayerSelection = firstLayerSelection.booleanValue();
152

    
153
                Boolean secondLayerSelection = (Boolean) params
154
                                .get("secondlayerselection");
155
                if (secondLayerSelection != null)
156
                        this.onlySecondLayerSelection = secondLayerSelection.booleanValue();
157

    
158
                if(writer == null)
159
                        throw new GeoprocessException("Hay que hacer setResultLayerProperties antes de hacer setParameters en el spatial join");
160
                processor =
161
                        new FeaturePersisterProcessor2(writer);
162
                
163
                processor = new FeaturePersisterProcessor2(writer);
164
                
165
                Boolean nearest = (Boolean) params
166
                                .get("nearest");
167
                if (nearest != null)
168
                        this.nearestSpatialJoin = nearest.booleanValue();
169
                if(nearestSpatialJoin){
170
                        visitor = new NearestSpatialJoinVisitor(this.firstLayer, 
171
                                                                        this.secondLayer,
172
                                                                        processor);
173
                }else{
174
                        visitor = new IntersectSpatialJoinVisitor(this.firstLayer,
175
                                                                                        this.secondLayer,
176
                                                        this.fields_sumFunctions, 
177
                                                        processor);
178
                }
179
                visitor.setFeatureProcessor(processor);
180

    
181
        }
182

    
183
        public void checkPreconditions() throws GeoprocessException {
184
                if (firstLayer == null)
185
                        throw new GeoprocessException(
186
                                        "Spatial Join: capa de entrada a null");
187
                if (secondLayer == null)
188
                        throw new GeoprocessException("Spatial Join: 2? capa a null");
189
                if (this.writer == null || this.schemaManager == null) {
190
                        throw new GeoprocessException(
191
                                        "Operacion spatial join sin especificar capa de resultados");
192
                }
193
                try {
194
                        int firstLayerType = firstLayer.getShapeType();
195
                        int secondLayerType = secondLayer.getShapeType();
196
                        if(firstLayerType == XTypes.POINT && secondLayerType == XTypes.POINT && (!nearestSpatialJoin)){
197
                                throw new GeoprocessException(
198
                                "No est? permitido el spatial join M:N entre puntos");
199
                        }        
200
                } catch (com.iver.cit.gvsig.fmap.DriverException e) {
201
                        throw new GeoprocessException(
202
                                        "Error al tratar de chequear la geometria de las capas a enlazar espacialmente");
203
                }
204
        }
205

    
206
        public void process() throws GeoprocessException {
207
                Strategy strategy =
208
                        StrategyManager.getStrategy(firstLayer);
209
                
210
                Strategy secondLyrStrategy =
211
                        StrategyManager.getStrategy(secondLayer);
212
                visitor.setCancelableStrategy(secondLyrStrategy);
213
                visitor.setOnlySecondLyrSelection(onlySecondLayerSelection);
214
                try {
215
                        if(this.onlyFirstLayerSelection){
216
                                strategy.process(visitor, 
217
                                                firstLayer.getRecordset().
218
                                                getSelection());
219
                                
220
                        }else{
221
                                strategy.process(visitor);
222
                        }
223
                        
224
                } catch (DriverException e) {
225
                        throw new GeoprocessException("Error al acceder a los datos durante un spatial join");
226
                } catch (VisitException e) {
227
                        throw new GeoprocessException("Error al procesar los datos durante un spatial join");
228
                }
229

    
230
        }
231

    
232
        public void cancel() {
233
                // TODO Auto-generated method stub
234

    
235
        }
236

    
237
        /**
238
         * FIXME Lanzar una excepcion si esto se llama antes
239
         * que el setParameters (esto me lo aseguro obligando a meter
240
         * los datos en el constructor)
241
         */
242
        public ILayerDefinition createLayerDefinition() {
243
                ILayerDefinition solution = null;
244
                try {
245
                        solution =  visitor.getResultLayerDefinition();
246
                } catch (GeoprocessException e) {
247
                        // TODO Auto-generated catch block
248
                        e.printStackTrace();
249
                }
250
                return solution;
251
        }
252

    
253
        public Map getFields_sumFunctions() {
254
                return fields_sumFunctions;
255
        }
256

    
257
        public void setFields_sumFunctions(Map fields_sumFunctions) {
258
                this.fields_sumFunctions = fields_sumFunctions;
259
        }
260

    
261
        public IMonitorableTask createTask() {
262
                try {
263
                        return new SpatialJoinMonitorableTask();
264
                } catch (DriverIOException e) {
265
                        return null;
266
                }
267
        }
268
        
269
        class SpatialJoinMonitorableTask implements IMonitorableTask {
270
                private CancellableMonitorable cancelMonitor = null;
271
                private boolean finished = false;
272

    
273
                SpatialJoinMonitorableTask() throws DriverIOException {
274
                        initialize();
275
                }
276
                void initialize() throws DriverIOException {
277
                        cancelMonitor = createCancelMonitor();
278
                }
279

    
280
                private CancellableMonitorable createCancelMonitor()
281
                                throws DriverIOException {
282
                        DefaultCancellableMonitorable monitor = new 
283
                                                        DefaultCancellableMonitorable();
284
                        monitor.setInitialStep(0);
285
                        monitor.setDeterminatedProcess(true);
286
                        int numSteps = 0;
287
                        if (onlyFirstLayerSelection) {
288
                                FBitSet selection = firstLayer.getRecordset().getSelection();
289
                                numSteps += (2 * selection.cardinality());
290
                        } else {
291
                                numSteps += 2 * firstLayer.getSource().getShapeCount();
292
                        }
293
                        monitor.setFinalStep(numSteps);
294
                        return monitor;
295
                }
296

    
297
                public int getInitialStep() {
298
                        return cancelMonitor.getInitialStep();
299
                }
300

    
301
                public int getFinishStep() {
302
                        return cancelMonitor.getFinalStep();
303
                }
304

    
305
                public int getCurrentStep() {
306
                        return cancelMonitor.getCurrentStep();
307
                }
308

    
309
                public String getStatusMessage() {
310
                        // FIXME Cambiar esto por un mecanismo de eventos,
311
                        // de forma que la tarea lo que tenga sea un escuchador
312
                        // que cambie el mensaje de estado segun los eventos
313
                        // de tareas que se est?n realizando
314
                        return "Spatial Join Geoprocess...";
315
                }
316

    
317
                public String getNote() {
318
                        // FIXME Cambiar esto por un mecanismo de eventos,
319
                        // de forma que la tarea lo que tenga sea un escuchador
320
                        // que cambie el mensaje de estado segun los eventos
321
                        // de tareas que se est?n realizando
322
                        return "Joining " + getCurrentStep() + " of " + getFinishStep();
323
                }
324

    
325
                public void cancel() {
326
                        ((DefaultCancellableMonitorable) cancelMonitor).setCanceled(true);
327
                }
328

    
329
                public void run() throws GeoprocessException {
330

    
331
                        Strategy strategy =
332
                                StrategyManager.getStrategy(firstLayer);
333
                        Strategy secondLyrStrategy =
334
                                StrategyManager.getStrategy(secondLayer);
335
                        visitor.setCancelableStrategy(secondLyrStrategy);
336
                        visitor.setOnlySecondLyrSelection(onlySecondLayerSelection);
337
                        try {
338
                                if(onlyFirstLayerSelection){
339
                                        strategy.process(visitor, 
340
                                                        firstLayer.getRecordset().
341
                                                        getSelection(),
342
                                                        cancelMonitor);
343
                                        
344
                                }else{
345
                                        strategy.process(visitor, cancelMonitor);
346
                                }
347
                                
348
                        } catch (DriverException e) {
349
                                throw new GeoprocessException("Error al acceder a los datos durante un spatial join");
350
                        } catch (VisitException e) {
351
                                throw new GeoprocessException("Error al procesar los datos durante un spatial join");
352
                        }
353
                        finally{
354
                                finished = true;
355
                        }
356
                }
357

    
358
                public boolean isDefined() {
359
                        return cancelMonitor.isDeterminatedProcess();
360
                }
361

    
362
                public boolean isCanceled() {
363
                        return cancelMonitor.isCanceled();
364
                }
365

    
366
                public boolean isFinished() {
367
                        return finished;
368
                }
369
        }
370
        
371

    
372
}